Adjust URL RegEx to allow for domain names ending with a dot.
[quassel.git] / src / uisupport / clickable.cpp
index d19083c..0674d0e 100644 (file)
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include <QDesktopServices>
+#include <QModelIndex>
+#include <QUrl>
+
+#include "buffermodel.h"
 #include "clickable.h"
+#include "client.h"
+
+void Clickable::activate(NetworkId networkId, const QString &text) const {
+  if(!isValid())
+    return;
+
+  QString str = text.mid(start(), length());
+
+  switch(type()) {
+    case Clickable::Url:
+      if(!str.contains("://"))
+        str = "http://" + str;
+      QDesktopServices::openUrl(QUrl::fromEncoded(str.toUtf8(), QUrl::TolerantMode));
+      break;
+    case Clickable::Channel:
+      Client::bufferModel()->switchToOrJoinBuffer(networkId, str);
+      break;
+    default:
+      break;
+  }
+}
 
 // NOTE: This method is not threadsafe and not reentrant!
 //       (RegExps are not constant while matching, and they are static here for efficiency)
 ClickableList ClickableList::fromString(const QString &str) {
   // For matching URLs
+  static QString scheme("(?:(?:mailto:|(?:[+.-]?\\w)+://)|www(?=\\.\\S+\\.))");
+  static QString authority("(?:(?:[,.;@:]?[-\\w]+)+\\.?|\\[[0-9a-f:.]+\\])(?::\\d+)?");
+  static QString urlChars("(?:[,.;:]*[\\w~@/?&=+$()!%#*{}\\[\\]\\|'^-])");
   static QString urlEnd("(?:>|[,.;:\"]*\\s|\\b|$)");
-  static QString urlChars("(?:[,.;:]*[\\w\\-~@/?&=+$()!%#*|{}\\[\\]'^])");
 
   static QRegExp regExp[] = {
     // URL
     // QRegExp(QString("((?:https?://|s?ftp://|irc://|mailto:|www\\.)%1+|%1+\\.[a-z]{2,4}(?:?=/%1+|\\b))%2").arg(urlChars, urlEnd)),
-    QRegExp(QString("((?:(?:mailto:|\\w+://)|www\\.)%1+)%2").arg(urlChars, urlEnd), Qt::CaseInsensitive),
+    QRegExp(QString("\\b(%1%2(?:/%3*)?)%4").arg(scheme, authority, urlChars, urlEnd), Qt::CaseInsensitive),
 
     // Channel name
     // We don't match for channel names starting with + or &, because that gives us a lot of false positives.
@@ -84,3 +112,11 @@ ClickableList ClickableList::fromString(const QString &str) {
   } while(type >= 0);
   return result;
 }
+
+Clickable ClickableList::atCursorPos(int idx) {
+  foreach(const Clickable &click, *this) {
+    if(idx >= click.start() && idx < click.start() + click.length())
+      return click;
+  }
+  return Clickable();
+}