grim/guifications2
Clone
Summary
Browse
Changes
Graph
s/gaim/pidgin/
org.guifications.gf2
2007-05-05, Gary Kramlich
0ec7f3cb75fe
s/gaim/pidgin/
/*
* Guifications - The end all, be all, toaster popup plugin
* Copyright (C) 2003-2005 Gary Kramlich
*
* 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.
*/
#include
<gtk/gtk.h>
#include
<account.h>
#include
<blist.h>
#include
<debug.h>
#include
<gtkblist.h>
#include
<gtkconv.h>
#include
<gtkdialogs.h>
#include
<gtklog.h>
#include
<gtkpounce.h>
#include
<gtkutils.h>
#include
<pidginstock.h>
#include
<plugin.h>
#include
<version.h>
#ifdef HAVE_CONFIG_H
#
include
"../gf_config.h"
#endif
#include
"gf_action.h"
#include
"gf_display.h"
#include
"gf_event.h"
#include
"gf_event_info.h"
#include
"gf_internal.h"
#include
"gf_notification.h"
#include
"gf_preferences.h"
#include
"gf_utils.h"
struct
_GfAction
{
gchar
*
name
;
gchar
*
i18n
;
GfActionFunc
func
;
};
static
GList
*
actions
=
NULL
;
/*******************************************************************************
* API
******************************************************************************/
GfAction
*
gf_action_new
()
{
GfAction
*
action
;
action
=
g_new0
(
GfAction
,
1
);
return
action
;
}
void
gf_action_destroy
(
GfAction
*
action
)
{
g_return_if_fail
(
action
);
if
(
action
->
name
)
g_free
(
action
->
name
);
g_free
(
action
);
action
=
NULL
;
}
void
gf_action_set_name
(
GfAction
*
action
,
const
gchar
*
name
)
{
g_return_if_fail
(
action
);
g_return_if_fail
(
name
);
if
(
action
->
name
)
g_free
(
action
->
name
);
action
->
name
=
g_strdup
(
name
);
}
const
gchar
*
gf_action_get_name
(
GfAction
*
action
)
{
g_return_val_if_fail
(
action
,
NULL
);
return
action
->
name
;
}
void
gf_action_set_i18n
(
GfAction
*
action
,
const
gchar
*
i18n
)
{
g_return_if_fail
(
action
);
g_return_if_fail
(
i18n
);
if
(
action
->
i18n
)
g_free
(
action
->
i18n
);
action
->
i18n
=
g_strdup
(
i18n
);
}
const
gchar
*
gf_action_get_i18n
(
GfAction
*
action
)
{
g_return_val_if_fail
(
action
,
NULL
);
return
action
->
i18n
;
}
void
gf_action_set_func
(
GfAction
*
action
,
GfActionFunc
func
)
{
g_return_if_fail
(
action
);
g_return_if_fail
(
func
);
action
->
func
=
func
;
}
GfActionFunc
gf_action_get_func
(
GfAction
*
action
)
{
g_return_val_if_fail
(
action
,
NULL
);
return
action
->
func
;
}
void
gf_action_execute
(
GfAction
*
action
,
GfDisplay
*
display
,
GdkEventButton
*
event
)
{
g_return_if_fail
(
action
);
g_return_if_fail
(
display
);
action
->
func
(
display
,
event
);
}
GfAction
*
gf_action_find_with_name
(
const
gchar
*
name
)
{
GfAction
*
action
;
GList
*
l
;
g_return_val_if_fail
(
name
,
NULL
);
for
(
l
=
actions
;
l
;
l
=
l
->
next
)
{
action
=
GF_ACTION
(
l
->
data
);
if
(
!
g_ascii_strcasecmp
(
name
,
action
->
name
))
return
action
;
}
return
NULL
;
}
GfAction
*
gf_action_find_with_i18n
(
const
gchar
*
i18n
)
{
GfAction
*
action
;
GList
*
l
;
g_return_val_if_fail
(
i18n
,
NULL
);
for
(
l
=
actions
;
l
;
l
=
l
->
next
)
{
action
=
GF_ACTION
(
l
->
data
);
if
(
!
g_ascii_strcasecmp
(
i18n
,
action
->
i18n
))
return
action
;
}
return
NULL
;
}
gint
gf_action_get_position
(
GfAction
*
action
)
{
g_return_val_if_fail
(
action
,
-1
);
return
g_list_index
(
actions
,
action
);
}
/*******************************************************************************
* Sub System
******************************************************************************/
static
void
gf_action_add_default
(
const
gchar
*
name
,
const
gchar
*
i18n
,
GfActionFunc
func
)
{
GfAction
*
action
;
g_return_if_fail
(
name
);
g_return_if_fail
(
func
);
action
=
gf_action_new
();
gf_action_set_name
(
action
,
name
);
gf_action_set_i18n
(
action
,
i18n
);
gf_action_set_func
(
action
,
func
);
gf_actions_add_action
(
action
);
}
void
gf_actions_init
()
{
gf_action_add_default
(
"close"
,
_
(
"Close"
),
gf_action_execute_close
);
gf_action_add_default
(
"open"
,
_
(
"Open Conversation"
),
gf_action_execute_open_conv
);
gf_action_add_default
(
"context"
,
_
(
"Context Menu"
),
gf_action_execute_context
);
gf_action_add_default
(
"info"
,
_
(
"Get Info"
),
gf_action_execute_info
);
gf_action_add_default
(
"log"
,
_
(
"Display Log"
),
gf_action_execute_log
);
}
void
gf_actions_uninit
()
{
GList
*
l
,
*
ll
;
for
(
l
=
actions
;
l
;
l
=
ll
)
{
ll
=
l
->
next
;
gf_actions_remove_action
(
GF_ACTION
(
l
->
data
));
}
g_list_free
(
actions
);
actions
=
NULL
;
}
void
gf_actions_add_action
(
GfAction
*
action
)
{
g_return_if_fail
(
action
);
actions
=
g_list_append
(
actions
,
action
);
}
void
gf_actions_remove_action
(
GfAction
*
action
)
{
g_return_if_fail
(
action
);
actions
=
g_list_remove
(
actions
,
action
);
}
gint
gf_actions_count
()
{
return
g_list_length
(
actions
);
}
const
gchar
*
gf_actions_get_nth_name
(
gint
nth
)
{
GfAction
*
action
;
action
=
GF_ACTION
(
g_list_nth_data
(
actions
,
nth
));
return
action
->
name
;
}
const
gchar
*
gf_actions_get_nth_i18n
(
gint
nth
)
{
GfAction
*
action
;
action
=
GF_ACTION
(
g_list_nth_data
(
actions
,
nth
));
return
action
->
i18n
;
}
/*******************************************************************************
* Action Functions
******************************************************************************/
void
gf_action_execute_close
(
GfDisplay
*
display
,
GdkEventButton
*
gdk_event
)
{
g_return_if_fail
(
display
);
gf_display_destroy
(
display
);
}
static
gboolean
conversation_exists
(
PurpleConversation
*
conv
)
{
PurpleConversation
*
lconv
;
GList
*
l
;
for
(
l
=
purple_get_conversations
();
l
;
l
=
l
->
next
)
{
lconv
=
(
PurpleConversation
*
)
l
->
data
;
if
(
conv
==
lconv
)
return
TRUE
;
}
return
FALSE
;
}
void
gf_action_execute_open_conv
(
GfDisplay
*
display
,
GdkEventButton
*
gdk_event
)
{
GfEvent
*
event
;
GfEventInfo
*
info
;
PurpleAccount
*
account
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
const
GHashTable
*
components
=
NULL
;
const
gchar
*
n_type
,
*
target
;
g_return_if_fail
(
display
);
info
=
gf_display_get_event_info
(
display
);
event
=
gf_event_info_get_event
(
info
);
n_type
=
gf_event_get_notification_type
(
event
);
account
=
gf_event_info_get_account
(
info
);
buddy
=
gf_event_info_get_buddy
(
info
);
conv
=
gf_event_info_get_conversation
(
info
);
components
=
gf_event_info_get_components
(
info
);
target
=
gf_event_info_get_target
(
info
);
if
(
conv
)
{
/* we have a conv */
if
(
!
conversation_exists
(
conv
))
{
/* the conv we have doesn't exist anymore.. */
const
gchar
*
target
;
target
=
gf_event_info_get_target
(
info
);
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_ANY
,
target
,
account
);
}
}
else
if
(
components
)
{
/* it's a chat invite */
const
gchar
*
extra
=
gf_event_info_get_extra
(
info
);
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_CHAT
,
extra
,
account
);
if
(
!
conv
)
{
serv_join_chat
(
account
->
gc
,
(
GHashTable
*
)
components
);
gf_display_destroy
(
display
);
return
;
}
}
else
if
(
buddy
)
{
/* we have a buddy or a target */
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
buddy
->
name
,
account
);
if
(
!
conv
)
conv
=
purple_conversation_new
(
PURPLE_CONV_TYPE_IM
,
account
,
buddy
->
name
);
}
else
{
/* the only thing that _should_ be left is warnings.. */
if
(
target
)
{
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
target
,
account
);
if
(
!
conv
)
conv
=
purple_conversation_new
(
PURPLE_CONV_TYPE_IM
,
account
,
target
);
}
}
if
(
conv
)
{
purple_conversation_present
(
conv
);
gf_display_destroy
(
display
);
}
}
void
gf_action_execute_info
(
GfDisplay
*
display
,
GdkEventButton
*
gdk_event
)
{
GfEventInfo
*
info
;
const
gchar
*
target
;
PurpleAccount
*
account
;
g_return_if_fail
(
display
);
info
=
gf_display_get_event_info
(
display
);
account
=
gf_event_info_get_account
(
info
);
target
=
gf_event_info_get_target
(
info
);
/* This covers everything.
*
* We used to make a distinction between event types, but since we store
* the target for every event, and how you can't get info about a chat
* we just use the target. The target for a buddy event is the
* buddy->name, in a warning event it's the screen name of the person
* who warned you, and in a chat it's the person that said something.
*/
if
(
target
)
{
serv_get_info
(
account
->
gc
,
target
);
gf_display_destroy
(
display
);
}
}
void
gf_action_execute_log
(
GfDisplay
*
display
,
GdkEventButton
*
gdk_event
)
{
GfEvent
*
event
;
GfEventInfo
*
info
;
PurpleAccount
*
account
;
PurpleConversation
*
conv
;
const
gchar
*
n_type
,
*
target
;
g_return_if_fail
(
display
);
info
=
gf_display_get_event_info
(
display
);
account
=
gf_event_info_get_account
(
info
);
event
=
gf_event_info_get_event
(
info
);
conv
=
gf_event_info_get_conversation
(
info
);
target
=
gf_event_info_get_target
(
info
);
n_type
=
gf_event_get_notification_type
(
event
);
if
(
conv
)
{
PurpleConversationType
type
;
type
=
purple_conversation_get_type
(
conv
);
if
(
type
==
PURPLE_CONV_TYPE_IM
||
type
==
PURPLE_CONV_TYPE_CHAT
)
{
pidgin_log_show
(
type
,
(
type
==
PURPLE_CONV_TYPE_IM
)
?
target
:
conv
->
name
,
account
);
gf_display_destroy
(
display
);
}
}
else
if
(
target
)
{
pidgin_log_show
(
PURPLE_CONV_TYPE_IM
,
target
,
account
);
gf_display_destroy
(
display
);
}
}
/******************************************************************************
* Context menu stuff
*****************************************************************************/
static
gboolean
gf_action_context_destroy_cb
(
gpointer
data
)
{
GfDisplay
*
display
=
GF_DISPLAY
(
data
);
gf_display_destroy
(
display
);
return
FALSE
;
}
static
void
gf_action_context_hide_cb
(
GtkWidget
*
w
,
gpointer
data
)
{
GfDisplay
*
display
=
GF_DISPLAY
(
data
);
GfEventInfo
*
info
=
NULL
;
gint
display_time
;
guint
timeout_id
;
g_return_if_fail
(
display
);
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
display_time
=
purple_prefs_get_int
(
GF_PREF_BEHAVIOR_DISPLAY_TIME
);
timeout_id
=
g_timeout_add
(
display_time
*
500
,
gf_action_context_destroy_cb
,
display
);
gf_event_info_set_timeout_id
(
info
,
timeout_id
);
}
static
void
gf_action_context_position
(
GtkMenu
*
menu
,
gint
*
x
,
gint
*
y
,
gboolean
pushin
,
gpointer
data
)
{
/* GfDisplay *display = GF_DISPLAY(data);*/
}
static
void
gf_action_context_info_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
gf_action_execute_info
(
display
,
NULL
);
}
static
void
gf_action_context_im_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
;
PurpleAccount
*
account
;
PurpleConversation
*
conv
=
NULL
;
PidginWindow
*
win
=
NULL
;
const
gchar
*
target
;
info
=
gf_display_get_event_info
(
display
);
account
=
gf_event_info_get_account
(
info
);
target
=
gf_event_info_get_target
(
info
);
conv
=
purple_find_conversation_with_account
(
PURPLE_CONV_TYPE_IM
,
target
,
account
);
if
(
!
conv
)
{
conv
=
purple_conversation_new
(
PURPLE_CONV_TYPE_IM
,
account
,
target
);
}
if
(
conv
)
{
win
=
PIDGIN_CONVERSATION
(
conv
)
->
win
;
if
(
!
win
)
{
gf_display_destroy
(
display
);
return
;
}
pidgin_conv_window_switch_gtkconv
(
win
,
PIDGIN_CONVERSATION
(
conv
));
gtk_window_present
(
GTK_WINDOW
(
win
->
window
));
}
gf_display_destroy
(
display
);
}
static
void
gf_action_context_pounce_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
;
PurpleAccount
*
account
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
buddy
=
gf_event_info_get_buddy
(
info
);
g_return_if_fail
(
buddy
);
pidgin_pounce_editor_show
(
account
,
buddy
->
name
,
NULL
);
}
static
void
gf_action_context_log_buddy_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
const
gchar
*
target
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
target
=
gf_event_info_get_target
(
info
);
g_return_if_fail
(
target
);
pidgin_log_show
(
PURPLE_LOG_IM
,
target
,
account
);
}
static
void
gf_action_context_log_chat_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
conv
=
gf_event_info_get_conversation
(
info
);
g_return_if_fail
(
conv
);
pidgin_log_show
(
PURPLE_LOG_CHAT
,
conv
->
name
,
account
);
}
static
void
gf_action_context_alias_buddy_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
buddy
=
gf_event_info_get_buddy
(
info
);
g_return_if_fail
(
buddy
);
pidgin_dialogs_alias_buddy
(
buddy
);
}
static
void
gf_action_context_alias_chat_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleChat
*
chat
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
conv
=
gf_event_info_get_conversation
(
info
);
g_return_if_fail
(
conv
);
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
g_return_if_fail
(
chat
);
pidgin_dialogs_alias_chat
(
chat
);
}
static
void
gf_action_context_add_buddy_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
const
gchar
*
target
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
target
=
gf_event_info_get_target
(
info
);
g_return_if_fail
(
target
);
purple_blist_request_add_buddy
(
account
,
target
,
NULL
,
NULL
);
}
static
void
gf_action_context_add_chat_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
conv
=
gf_event_info_get_conversation
(
info
);
g_return_if_fail
(
conv
);
purple_blist_request_add_chat
(
account
,
NULL
,
NULL
,
conv
->
name
);
}
static
void
gf_action_context_remove_buddy_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
buddy
=
gf_event_info_get_buddy
(
info
);
g_return_if_fail
(
buddy
);
pidgin_dialogs_remove_buddy
(
buddy
);
}
static
void
gf_action_context_remove_chat_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleChat
*
chat
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
conv
=
gf_event_info_get_conversation
(
info
);
g_return_if_fail
(
conv
);
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
g_return_if_fail
(
chat
);
pidgin_dialogs_remove_chat
(
chat
);
}
static
void
gf_action_context_join_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
const
GHashTable
*
components
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
components
=
gf_event_info_get_components
(
info
);
g_return_if_fail
(
components
);
serv_join_chat
(
account
->
gc
,
(
GHashTable
*
)
components
);
}
static
void
gf_action_context_autojoin_cb
(
GtkWidget
*
menuitem
,
GfDisplay
*
display
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleChat
*
chat
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
conv
=
gf_event_info_get_conversation
(
info
);
g_return_if_fail
(
conv
);
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
g_return_if_fail
(
chat
);
purple_blist_node_set_bool
((
PurpleBlistNode
*
)
chat
,
"gtk-autojoin"
,
gtk_check_menu_item_get_active
(
GTK_CHECK_MENU_ITEM
(
menuitem
)));
}
/* This function has come from hell.. I summoned it last time I sent a wicked
* soul to it's eternal resting place.
*/
void
gf_action_execute_context
(
GfDisplay
*
display
,
GdkEventButton
*
gdk_event
)
{
GfEventInfo
*
info
=
NULL
;
PurpleAccount
*
account
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
PurpleChat
*
chat
=
NULL
;
PurpleConversation
*
conv
=
NULL
;
PurplePlugin
*
prpl
=
NULL
;
PurplePluginProtocolInfo
*
prpl_info
=
NULL
;
GtkWidget
*
menu
;
const
gchar
*
target
=
NULL
;
gboolean
chat_sep_added
=
FALSE
;
guint
timeout_id
;
g_return_if_fail
(
display
);
/* grab the stuff we need from the display and event info */
info
=
gf_display_get_event_info
(
display
);
g_return_if_fail
(
info
);
/* get the gaim stuff we need */
account
=
gf_event_info_get_account
(
info
);
g_return_if_fail
(
account
);
/* we're going to show the menu as long as the timeout is removed.
* We need to remove it otherwise the display get's destroyed when
* the menu is shown, or it'll leak if we don't clean it up later.
*/
timeout_id
=
gf_event_info_get_timeout_id
(
info
);
g_return_if_fail
(
g_source_remove
(
timeout_id
));
buddy
=
gf_event_info_get_buddy
(
info
);
conv
=
gf_event_info_get_conversation
(
info
);
target
=
gf_event_info_get_target
(
info
);
if
(
conv
)
chat
=
purple_blist_find_chat
(
account
,
conv
->
name
);
/* find the prpl and it's info */
prpl
=
purple_find_prpl
(
purple_account_get_protocol_id
(
account
));
if
(
prpl
)
prpl_info
=
PURPLE_PLUGIN_PROTOCOL_INFO
(
prpl
);
/* create the menu */
menu
=
gtk_menu_new
();
g_signal_connect
(
G_OBJECT
(
menu
),
"hide"
,
G_CALLBACK
(
gf_action_context_hide_cb
),
display
);
gtk_widget_show
(
menu
);
if
(
buddy
||
target
)
{
/* add get info if the prpl supports it */
if
(
prpl_info
&&
prpl_info
->
get_info
)
{
pidgin_new_item_from_stock
(
menu
,
_
(
"Get Info"
),
PIDGIN_STOCK_DIALOG_INFO
,
G_CALLBACK
(
gf_action_context_info_cb
),
display
,
0
,
0
,
NULL
);
}
/* we can im anyone.. so.. */
pidgin_new_item_from_stock
(
menu
,
_
(
"IM"
),
PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW
,
G_CALLBACK
(
gf_action_context_im_cb
),
display
,
0
,
0
,
NULL
);
}
/* It's pointless to add a buddy pounce for someone that isn't a buddy...
* Conversations currently allow this.. but that's because I haven't
* written a patch yet..
*/
if
(
buddy
)
{
pidgin_new_item_from_stock
(
menu
,
_
(
"Add Buddy Pounce"
),
NULL
,
G_CALLBACK
(
gf_action_context_pounce_cb
),
display
,
0
,
0
,
NULL
);
}
if
(
!
buddy
&&
target
)
buddy
=
purple_find_buddy
(
account
,
target
);
if
(
buddy
)
{
pidgin_new_item_from_stock
(
menu
,
_
(
"View IM log"
),
NULL
,
G_CALLBACK
(
gf_action_context_log_buddy_cb
),
display
,
0
,
0
,
NULL
);
/* add the protocol menu */
pidgin_append_blist_node_proto_menu
(
menu
,
account
->
gc
,
(
PurpleBlistNode
*
)
buddy
);
/* and now the extended menu */
pidgin_append_blist_node_extended_menu
(
menu
,
(
PurpleBlistNode
*
)
buddy
);
/* separate it! */
pidgin_separator
(
menu
);
}
/* we can't alias a non buddy, and we can't remove them either.. But if
* they're not a buddy we can add them!
*/
if
(
buddy
)
{
/* add the alias and remove button */
pidgin_new_item_from_stock
(
menu
,
_
(
"Alias Buddy"
),
PIDGIN_STOCK_ALIAS
,
G_CALLBACK
(
gf_action_context_alias_buddy_cb
),
display
,
0
,
0
,
NULL
);
pidgin_new_item_from_stock
(
menu
,
_
(
"Remove Buddy"
),
GTK_STOCK_REMOVE
,
G_CALLBACK
(
gf_action_context_remove_buddy_cb
),
display
,
0
,
0
,
NULL
);
}
else
if
(
target
)
{
pidgin_new_item_from_stock
(
menu
,
_
(
"Add Buddy"
),
GTK_STOCK_ADD
,
G_CALLBACK
(
gf_action_context_add_buddy_cb
),
display
,
0
,
0
,
NULL
);
}
/* Add a separtor if we have a buddy or target, and we have a chat */
if
((
buddy
||
target
)
&&
chat
)
{
pidgin_separator
(
menu
);
chat_sep_added
=
TRUE
;
}
if
(
chat
)
{
PurpleBlistNode
*
node
=
(
PurpleBlistNode
*
)
chat
;
gboolean
checked
;
checked
=
(
purple_blist_node_get_bool
(
node
,
"gtk-autojoin"
)
||
(
purple_blist_node_get_string
(
node
,
"gtk-autojoin"
)
!=
NULL
));
/* add the join item, possibly redundant.. */
pidgin_new_item_from_stock
(
menu
,
_
(
"Join"
),
PIDGIN_STOCK_CHAT
,
G_CALLBACK
(
gf_action_context_join_cb
),
display
,
0
,
0
,
NULL
);
pidgin_new_check_item
(
menu
,
_
(
"Auto-join"
),
G_CALLBACK
(
gf_action_context_autojoin_cb
),
display
,
checked
);
}
/* if we have a conversation and it's a chat, we show the view log for it.
* if we don't do this check we end up with two menu items to view the
* same log..
*/
if
(
conv
&&
conv
->
type
==
PURPLE_CONV_TYPE_CHAT
)
{
if
(
!
chat_sep_added
)
{
pidgin_separator
(
menu
);
chat_sep_added
=
TRUE
;
}
pidgin_new_item_from_stock
(
menu
,
_
(
"View Chat Log"
),
NULL
,
G_CALLBACK
(
gf_action_context_log_chat_cb
),
display
,
0
,
0
,
NULL
);
}
if
(
chat
)
{
/* add the proto menu for the chat */
pidgin_append_blist_node_proto_menu
(
menu
,
account
->
gc
,
(
PurpleBlistNode
*
)
chat
);
/* add the extended menu for the chat */
pidgin_append_blist_node_extended_menu
(
menu
,
(
PurpleBlistNode
*
)
chat
);
/* add the alias and remove buttons */
pidgin_new_item_from_stock
(
menu
,
_
(
"Alias Chat"
),
PIDGIN_STOCK_ALIAS
,
G_CALLBACK
(
gf_action_context_alias_chat_cb
),
display
,
0
,
0
,
NULL
);
pidgin_new_item_from_stock
(
menu
,
_
(
"Remove Chat"
),
GTK_STOCK_REMOVE
,
G_CALLBACK
(
gf_action_context_remove_chat_cb
),
display
,
0
,
0
,
NULL
);
}
/* add the add chat item if it's not on our blist.. */
if
(
!
chat
&&
conv
&&
conv
->
type
==
PURPLE_CONV_TYPE_CHAT
)
{
pidgin_new_item_from_stock
(
menu
,
_
(
"Add Chat"
),
GTK_STOCK_ADD
,
G_CALLBACK
(
gf_action_context_add_chat_cb
),
display
,
0
,
0
,
NULL
);
}
/* show it already */
gtk_widget_show_all
(
menu
);
gtk_menu_popup
(
GTK_MENU
(
menu
),
NULL
,
NULL
,
(
GtkMenuPositionFunc
)
gf_action_context_position
,
display
,
gdk_event
->
button
,
gdk_event
->
time
);
}