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