Clickable links API
Eion Robb
eion at robbmob.com
Sun Mar 27 18:07:25 EDT 2011
Couldn't you just use the 'uri-handler' core signal instead?
On 28 March 2011 10:41, Andrew Victor <avictor.za at gmail.com> wrote:
> hi,
>
> A long-time ago we discussed the clickable links in the conversation
> window that MXit uses for menus.
> <http://pidgin.im/pipermail/devel/2009-November/009045.html>
>
> We're currently overriding PurpleNotifyUiOps.notify_uri, which doesn't
> always work well (especially on Windows), doesn't seem to be supported
> by Adium, and IMHO is a hack.
>
>
> I'd like to propose an API enhancement (preferably for 2.8.0) that
> should improve this:
>
> 1. Extend PurplePluginProtocolInfo with an additional optional method:
> /**
> * A link was selected in a conversation.
> *
> * @param gc The connection
> * @param who The contact associated with the conversation
> * @param uri The URL that was selected
> *
> * @since 2.8.0
> */
> void (*link_selected)(PurpleConnection *gc, const char *who, const
> char *uri);
>
> 2. Extend the Conversation API with a
> 'purple_conversation_link_selected' function:
> /**
> * An internal link was selected in a Conversation
> *
> * @param conv The conversation
> * @param uri The selected URL
> *
> * @since 2.8.0
> */
> void purple_conversation_link_selected(PurpleConversation *conv,
> const char* uri);
>
> 3. Pidgin calls gtk_imhtml_class_register_protocol() to register a
> protocol handler for some protocol name. (I've been using
> "internal://" - but that be changed)
>
> Once GtkIMHtml detects the link-click it will call the handler, which
> calls purple_conversation_link_selected() which in-turn calls the
> prpl->link_selected().
>
>
> A patch is appended for review.
>
> Your thoughts?
>
> Regards,
> Andrew Victor
>
>
> ============================================================
> --- libpurple/conversation.c 7cede383dd7d23720d80e0517411b41e088b87cd
> +++ libpurple/conversation.c ad3f15b6b397e4332c04d871121d109718480296
> @@ -2301,6 +2301,24 @@ time_t purple_conversation_message_get_t
> return msg->when;
> }
>
> +void purple_conversation_link_selected(PurpleConversation *conv,
> const char* uri)
> +{
> + PurplePluginProtocolInfo *prpl_info = NULL;
> + PurpleConnection *gc;
> +
> + g_return_if_fail(conv != NULL);
> +
> + gc = purple_conversation_get_gc(conv);
> + if (!gc) /* no longer connected */
> + return;
> +
> + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc));
> + g_return_if_fail(prpl_info != NULL);
> +
> + if (prpl_info->link_selected != NULL)
> + prpl_info->link_selected(gc, purple_conversation_get_name(conv), uri);
> +}
> +
> gboolean
> purple_conversation_do_command(PurpleConversation *conv, const gchar *cmdline,
> const gchar *markup, gchar **error)
> ============================================================
> --- libpurple/conversation.h 1b5c4abc64bc9456e7f4d60bf23713f150e1da94
> +++ libpurple/conversation.h 51c68e3b7ffd9824798c17bd95e345d4a661c5cc
> @@ -796,6 +796,16 @@ time_t purple_conversation_message_get_t
> */
> time_t purple_conversation_message_get_timestamp(PurpleConvMessage *msg);
>
> +/**
> + * An internal link was selected in a Conversation
> + *
> + * @param conv The conversation
> + * @param uri The selected URL
> + *
> + * @since 2.8.0
> + */
> +void purple_conversation_link_selected(PurpleConversation *conv,
> const char* uri);
> +
> /*@}*/
>
>
> ============================================================
> --- libpurple/protocols/bonjour/bonjour.c 36c6d536994d7b5cbb85fb2a6a08f57586b140e0
> +++ libpurple/protocols/bonjour/bonjour.c 987996f0fb6eeacebdbd0c274c69880bafa81396
> @@ -536,7 +536,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /*
> set_public_alias */
> NULL, /*
> get_public_alias */
> NULL, /*
> add_buddy_with_invite */
> - NULL /*
> add_buddies_with_invite */
> + NULL, /*
> add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/gg/gg.c f9645a358190f517bd28e07af3eaf59b22f7cb9f
> +++ libpurple/protocols/gg/gg.c 8f170984c3b4e31d8df5f62096f6516edfc4742e
> @@ -2582,7 +2582,9 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> +
> };
>
> static PurplePluginInfo info = {
> ============================================================
> --- libpurple/protocols/irc/irc.c a7dd36a573f3e22b836727e3e2790521901e8950
> +++ libpurple/protocols/irc/irc.c 9d096e5d4710c5ccacf5413c25de62c6467cb4a9
> @@ -992,7 +992,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static gboolean load_plugin (PurplePlugin *plugin) {
> ============================================================
> --- libpurple/protocols/jabber/libxmpp.c a8d36f925713b21b21fe5aca4b62c01aaf9c207c
> +++ libpurple/protocols/jabber/libxmpp.c 7430f52c9a8d8ae574c44f503146102b8828073a
> @@ -131,7 +131,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static gboolean load_plugin(PurplePlugin *plugin)
> ============================================================
> --- libpurple/protocols/msn/msn.c 05271130bd391a7ec1d4816e41d07e4d7e6b5338
> +++ libpurple/protocols/msn/msn.c efb8790b51a05f661bbb089b371a2f52575897b1
> @@ -3000,7 +3000,8 @@ static PurplePluginProtocolInfo prpl_inf
> msn_set_public_alias, /* set_public_alias */
> msn_get_public_alias, /* get_public_alias */
> msn_add_buddy, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/mxit/markup.c 1494d9bde0b5ad7028b8171d08352176b740967e
> +++ libpurple/protocols/mxit/markup.c 739fd19cc7ba18ffc97680a9ba3c3720d54d10ad
> @@ -142,6 +142,13 @@ void mxit_add_html_link( struct RXMsgDat
> g_free( retstr64 );
>
> g_string_append_printf( mx->msg, "<a href=\"%s\">%s</a>", link, displayname );
> +#elif defined(MXIT_LINK_CLICK_NEW)
> + gchar* linkdata;
> +
> + linkdata = purple_base64_encode( (const unsigned char*) linkname,
> strlen( linkname ) );
> +
> + g_string_append_printf( mx->msg, "<a href=\"%s%s\">%s</a>",
> "internal://", linkdata, displayname );
> + g_free( linkdata );
> #else
> g_string_append_printf( mx->msg, "<b>%s</b>", linkname );
> #endif
> ============================================================
> --- libpurple/protocols/mxit/mxit.c 4d59ad8656ff2e1afd030e1b36109bee7dee7fbf
> +++ libpurple/protocols/mxit/mxit.c 9f0db9bf0f01e3a1c622ae49259b6d6173a56cf6
> @@ -661,6 +661,28 @@ static GList* mxit_blist_menu( PurpleBli
> return m;
> }
>
> +static void mxit_link_selected( PurpleConnection* gc, const char *
> who, const char *uri )
> +{
> + gchar* link = NULL;
> + gsize len;
> + gboolean is_command = FALSE;
> +
> + purple_debug_info( MXIT_PLUGIN_ID, "mxit_link_selected: who='%s'
> uri='%s'\n", who, uri );
> +
> + /* decode the base64 payload */
> + link = (gchar*) purple_base64_decode( uri + strlen( "internal://" ), &len );
> + purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link );
> +
> + /* determine if it's a command-response to send */
> + is_command = g_str_has_prefix( link, "::type=reply|" );
> +
> + /* send click message back to MXit */
> + mxit_send_message( gc->proto_data, who, link, FALSE, is_command );
> +
> + g_free( link );
> + link = NULL;
> +}
> +
> /*========================================================================================================================*/
>
> static PurplePluginProtocolInfo proto_info = {
> @@ -744,7 +766,8 @@ static PurplePluginProtocolInfo proto_in
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> mxit_add_buddy, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + mxit_link_selected /* link_selected */
> };
>
>
> ============================================================
> --- libpurple/protocols/mxit/mxit.h 285c04ee0f8a64b8c9cfe5169a49aa0909cf8189
> +++ libpurple/protocols/mxit/mxit.h 855410982f6366d0b1bc5b9d5b75e5fac145e9c4
> @@ -108,7 +108,8 @@
>
>
> /* define this to enable the link clicking support */
> -#define MXIT_LINK_CLICK
> +#undef MXIT_LINK_CLICK
> +#define MXIT_LINK_CLICK_NEW
>
> #ifdef MXIT_LINK_CLICK
> #define MXIT_LINK_PREFIX "gopher://"
> ============================================================
>
> --- libpurple/protocols/myspace/myspace.c 8b720fae9e178327c605495ac5176308e90fc288
> +++ libpurple/protocols/myspace/myspace.c 9788aaa8915ae56aca49b6c031bccb5fcd36ef88
> @@ -3099,7 +3099,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> /**
> ============================================================
> --- libpurple/protocols/novell/novell.c 068fb38ed404fd2ad79057e3ef7eaf2e50630577
> +++ libpurple/protocols/novell/novell.c 9dbb351e0912a933f16f6274deb7312a2772bad9
> @@ -3533,7 +3533,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info = {
> ============================================================
> --- libpurple/protocols/oscar/libaim.c a64b5eca261a904a5ecc60290abcaec53a3432f3
> +++ libpurple/protocols/oscar/libaim.c 65e422f2c2106d0c7903e8d86a40f45ec60f3e89
> @@ -102,7 +102,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> oscar_add_buddy, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/oscar/libicq.c 1cee78d9aad16734383b5c0b7511c58bd67026b5
> +++ libpurple/protocols/oscar/libicq.c d75d61ac08c8391297d331d85f07d1e785d82efc
> @@ -112,7 +112,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> oscar_add_buddy, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/qq/qq.c ff38ebede657d4a7a0227cada83ba03090b62797
> +++ libpurple/protocols/qq/qq.c ddd1d84638f774b3dea9674946fc64105f07fa29
> @@ -1044,7 +1044,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info = {
> ============================================================
> --- libpurple/protocols/simple/simple.c 8d392d04f8c644822f0826ee92941a8e72ed6a17
> +++ libpurple/protocols/simple/simple.c 4fff7ab30058f70b592d0221cec0c49054e0022b
> @@ -2114,7 +2114,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
>
> ============================================================
> --- libpurple/protocols/yahoo/libyahoo.c a871e3427922dc201c58b80316d86bfe4e67f5c6
> +++ libpurple/protocols/yahoo/libyahoo.c 2f8e2b6b29a958d1575b3e93c430d8c64d8a7277
> @@ -269,7 +269,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/yahoo/libyahoojp.c da89c3568e9054e458c7510b1cc67a6f5f46c190
> +++ libpurple/protocols/yahoo/libyahoojp.c b27006be02eb7477be7757e810bd9d33b45ed655
> @@ -165,7 +165,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info =
> ============================================================
> --- libpurple/protocols/zephyr/zephyr.c f236ae11f9522c76f54fce85e1df41f42cdbadbe
> +++ libpurple/protocols/zephyr/zephyr.c c4014ecfa1c304be04f6cc63e9fc45c901106fbf
> @@ -2913,7 +2913,8 @@ static PurplePluginProtocolInfo prpl_inf
> NULL, /* set_public_alias */
> NULL, /* get_public_alias */
> NULL, /* add_buddy_with_invite */
> - NULL /* add_buddies_with_invite */
> + NULL, /* add_buddies_with_invite */
> + NULL /* link_selected */
> };
>
> static PurplePluginInfo info = {
> ============================================================
> --- libpurple/prpl.h 00ddff21fbb760369b95f999cb7ead428862bfb2
> +++ libpurple/prpl.h 5df68759496d83b2f9f90a84d65226ad1753cc62
> @@ -647,6 +647,18 @@ struct _PurplePluginProtocolInfo
> */
> void (*add_buddy_with_invite)(PurpleConnection *pc, PurpleBuddy
> *buddy, PurpleGroup *group, const char *message);
> void (*add_buddies_with_invite)(PurpleConnection *pc, GList
> *buddies, GList *groups, const char *message);
> +
> + /**
> + * A link was selected in a conversation.
> + *
> + * @param gc The connection
> + * @param who The contact associated with the conversation
> + * @param uri The URL that was selected
> + *
> + * @since 2.8.0
> + */
> + void (*link_selected)(PurpleConnection *gc, const char *who, const char *uri);
> +
> };
>
> #define PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl, member) \
> ============================================================
> --- pidgin/gtkutils.c b95797e31c92492ca20a4c2d89261c7f3e17acf2
> +++ pidgin/gtkutils.c f4280e7eaa9072471560a890737074e8b767ff55
> @@ -45,6 +45,7 @@
>
> #include <gdk/gdkkeysyms.h>
>
> +
> #include "conversation.h"
> #include "debug.h"
> #include "desktopitem.h"
> @@ -3513,6 +3514,20 @@ pidgin_make_scrollable(GtkWidget *child,
> return child;
> }
>
> +static gboolean
> +internal_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
> +{
> + PidginConversation *conv = g_object_get_data(G_OBJECT(imhtml), "gtkconv");
> + const char *uri = gtk_imhtml_link_get_url(link);
> +
> + purple_debug_info("gtkutils", "Internal link clicked: '%s'\n", uri);
> +
> + if (conv)
> + purple_conversation_link_selected(conv->active_conv, uri);
> +
> + return TRUE;
> +}
> +
> void pidgin_utils_init(void)
> {
> gtk_imhtml_class_register_protocol("http://", url_clicked_cb,
> link_context_menu);
> @@ -3524,6 +3539,9 @@ void pidgin_utils_init(void)
> gtk_imhtml_class_register_protocol("file://", file_clicked_cb,
> file_context_menu);
> gtk_imhtml_class_register_protocol("audio://", audio_clicked_cb,
> audio_context_menu);
>
> + /* Internal link */
> + gtk_imhtml_class_register_protocol("internal://", internal_clicked_cb, dummy);
> +
> /* Example custom URL handler. */
> gtk_imhtml_class_register_protocol("open://", open_dialog, dummy);
>
> @@ -3554,6 +3572,8 @@ void pidgin_utils_uninit(void)
> {
> gtk_imhtml_class_register_protocol("open://", NULL, NULL);
>
> + gtk_imhtml_class_register_protocol("internal://", NULL, NULL);
> +
> /* If we have GNOME handlers registered, unregister them. */
> if (registered_url_handlers)
> {
>
> _______________________________________________
> Devel mailing list
> Devel at pidgin.im
> http://pidgin.im/cgi-bin/mailman/listinfo/devel
>
More information about the Devel
mailing list