URL linkification in People

url and email label are now marked as a link and open the address
in the browser/mail-app on click

Signed-off-by: Adrien Destugues <pulkomandy@pulkomandy.tk>

Fixes #3825

A few extra changes from the original patch:

- Remove "smart" parsing (detection of "ftp", etc) as it could lead to
ftp://ftp://url or other strangeness,
- Add gopher protocol, because mmu_man may have an home page there.
This commit is contained in:
Alexander Sulfrian 2012-04-06 17:08:15 +02:00 committed by Adrien Destugues
parent a5a3b2d9a3
commit 632e56d8e5
2 changed files with 128 additions and 1 deletions

View File

@ -15,13 +15,17 @@
#include <string.h>
#include <malloc.h>
#include <Font.h>
#include <Catalog.h>
#include <Cursor.h>
#include <Font.h>
#include <Roster.h>
#include <StorageKit.h>
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "People"
#define B_URL_MIME "application/x-vnd.Be.URL."
AttributeTextControl::AttributeTextControl(const char* label,
const char* attribute)
@ -42,6 +46,28 @@ AttributeTextControl::~AttributeTextControl()
{
}
void
AttributeTextControl::MouseDown(BPoint mousePosition)
{
if(_VisibleLabelBounds().Contains(mousePosition) && _ContainsUrl())
_HandleLabelClicked(Text());
else
BTextControl::MouseDown(mousePosition);
}
void
AttributeTextControl::MouseMoved(BPoint mousePosition, uint32 transit, const BMessage* dragMessage)
{
if (_VisibleLabelBounds().Contains(mousePosition) && _ContainsUrl()) {
BCursor linkCursor(B_CURSOR_ID_FOLLOW_LINK);
SetViewCursor(&linkCursor, true);
} else
SetViewCursor(B_CURSOR_SYSTEM_DEFAULT, true);
BTextControl::MouseMoved(mousePosition, transit, dragMessage);
}
bool
AttributeTextControl::HasChanged()
@ -63,3 +89,91 @@ AttributeTextControl::Update()
{
fOriginalValue = Text();
}
void
AttributeTextControl::_HandleLabelClicked(const char *text)
{
BString argument(text);
if (Attribute() == "META:url") {
_MakeUniformUrl(argument);
BString mimeType = B_URL_MIME;
_BuildMimeString(mimeType, argument);
if (mimeType != "") {
const char *args[] = {argument.String(), 0};
be_roster->Launch(mimeType.String(), 1, const_cast<char**>(args));
}
} else if (Attribute() == "META:email") {
if (argument.IFindFirst("mailto:") != 0 && argument != "")
argument.Prepend("mailto:");
// TODO: Could check for possible e-mail patterns.
if (argument != "") {
const char *args[] = {argument.String(), 0};
be_roster->Launch("text/x-email", 1, const_cast<char**>(args));
}
}
}
const BString&
AttributeTextControl::_MakeUniformUrl(BString &url) const
{
if (url.StartsWith("www"))
url.Prepend("http://");
else if (url.StartsWith("ftp."))
url.Prepend("ftp://");
return url;
}
const BString&
AttributeTextControl::_BuildMimeString(BString &mimeType, const BString &url)
const
{
if (url.IFindFirst("http://") == 0 || url.IFindFirst("ftp://") == 0
|| url.IFindFirst("https://") || url.IFindFirst("gopher://") == 0) {
mimeType.Append(url, url.FindFirst(':'));
}
if (!BMimeType::IsValid(mimeType.String()))
mimeType = "";
return mimeType;
}
bool
AttributeTextControl::_ContainsUrl() const
{
BString argument(Text());
if (Attribute() == "META:url") {
BString mimeType = B_URL_MIME;
if (_BuildMimeString(mimeType, _MakeUniformUrl(argument)) != "")
return true;
}
else if (Attribute() == "META:email") {
if (argument != "")
return true;
}
return false;
}
BRect
AttributeTextControl::_VisibleLabelBounds() const
{
// TODO: Could actually check current alignment of the label.
// The code below works only for right aligned labels.
BRect bounds(Bounds());
bounds.right = Divider();
bounds.left = bounds.right - StringWidth(Label());
return bounds;
}

View File

@ -21,6 +21,9 @@ public:
const char* attribute);
virtual ~AttributeTextControl();
virtual void MouseDown(BPoint);
virtual void MouseMoved(BPoint, uint32, const BMessage*);
bool HasChanged();
void Revert();
void Update();
@ -28,6 +31,16 @@ public:
const BString& Attribute() const
{ return fAttribute; }
private:
const BString& _MakeUniformUrl(BString &url) const;
const BString& _BuildMimeString(BString &mimeType,
const BString &url) const;
bool _ContainsUrl() const;
BRect _VisibleLabelBounds() const;
void _HandleLabelClicked(const char*);
private:
BString fAttribute;
BString fOriginalValue;