Revamping ChatView/ChatScene's mouse handling
[quassel.git] / src / qtui / chatitem.cpp
index d1443a6..0900c7e 100644 (file)
@@ -136,7 +136,7 @@ void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
 //   painter->drawRect(_boundingRect.adjusted(0, 0, -1, -1));
 }
 
-qint16 ChatItem::posToCursor(const QPointF &pos) {
+qint16 ChatItem::posToCursor(const QPointF &pos) const {
   if(pos.y() > height()) return data(MessageModel::DisplayRole).toString().length();
   if(pos.y() < 0) return 0;
   for(int l = layout()->lineCount() - 1; l >= 0; l--) {
@@ -148,6 +148,23 @@ qint16 ChatItem::posToCursor(const QPointF &pos) {
   return 0;
 }
 
+bool ChatItem::hasSelection() const {
+  if(_selectionMode == NoSelection)
+    return false;
+  if(_selectionMode == FullSelection)
+    return true;
+  // partial
+  return _selectionStart != _selectionEnd;
+}
+
+QString ChatItem::selection() const {
+  if(_selectionMode == FullSelection)
+    return data(MessageModel::DisplayRole).toString();
+  if(_selectionMode == PartialSelection)
+    return data(MessageModel::DisplayRole).toString().mid(qMin(_selectionStart, _selectionEnd), qAbs(_selectionStart - _selectionEnd));
+  return QString();
+}
+
 void ChatItem::setFullSelection() {
   if(_selectionMode != FullSelection) {
     _selectionMode = FullSelection;
@@ -166,6 +183,16 @@ void ChatItem::continueSelecting(const QPointF &pos) {
   update();
 }
 
+bool ChatItem::isPosOverSelection(const QPointF &pos) const {
+  if(_selectionMode == FullSelection)
+    return true;
+  if(_selectionMode == PartialSelection) {
+    int cursor = posToCursor(pos); qDebug() << cursor << _selectionStart << _selectionEnd;
+    return cursor >= qMin(_selectionStart, _selectionEnd) && cursor <= qMax(_selectionStart, _selectionEnd);
+  }
+  return false;
+}
+
 QTextLayout::FormatRange ChatItem::selectionFormat() const {
   QTextLayout::FormatRange selectFmt;
   if(_selectionMode != NoSelection) {
@@ -215,15 +242,12 @@ QList<QRectF> ChatItem::findWords(const QString &searchWord, Qt::CaseSensitivity
   return resultList;
 }
 
-void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
-  if(event->buttons() == Qt::LeftButton) {
+void ChatItem::handleClick(const QPointF &pos, ChatScene::ClickMode clickMode) {
+  if(clickMode == ChatScene::SingleClick) {
     chatScene()->setSelectingItem(this);
-    _selectionStart = _selectionEnd = posToCursor(event->pos());
+    _selectionStart = _selectionEnd = posToCursor(pos);
     _selectionMode = NoSelection; // will be set to PartialSelection by mouseMoveEvent
     update();
-    event->accept();
-  } else {
-    event->ignore();
   }
 }
 
@@ -246,6 +270,14 @@ void ChatItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
   }
 }
 
+void ChatItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
+  if(event->buttons() == Qt::LeftButton) {
+    event->accept();
+  } else {
+    event->ignore();
+  }
+}
+
 void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
   if(_selectionMode != NoSelection && !event->buttons() & Qt::LeftButton) {
     _selectionEnd = posToCursor(event->pos());
@@ -265,7 +297,7 @@ void ChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
 void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
   Q_UNUSED(option); Q_UNUSED(widget);
 
-  //painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work
+  painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work
   qreal layoutWidth = layout()->minimumWidth();
   qreal offset = 0;
   if(chatScene()->senderCutoffMode() == ChatScene::CutoffLeft)
@@ -278,7 +310,7 @@ void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *op
   if(layoutWidth > width()) {
     // Draw a nice gradient for longer items
     // Qt's text drawing with a gradient brush sucks, so we use an alpha-channeled pixmap instead
-    QPixmap pixmap(QSize(layout()->boundingRect().width(), layout()->boundingRect().height()));
+    QPixmap pixmap(layout()->boundingRect().toRect().size());
     pixmap.fill(Qt::transparent);
     QPainter pixPainter(&pixmap);
     layout()->draw(&pixPainter, QPointF(qMax(offset, (qreal)0), 0), QVector<QTextLayout::FormatRange>() << selectFmt);
@@ -359,7 +391,7 @@ void ContentsChatItem::doLayout() {
 QList<ContentsChatItem::Clickable> ContentsChatItem::findClickables() const {
   // For matching URLs
   static QString urlEnd("(?:>|[,.;:\"]*\\s|\\b|$)");
-  static QString urlChars("(?:[,.;:]*[\\w\\-~@/?&=+$()!%#])");
+  static QString urlChars("(?:[,.;:]*[\\w\\-~@/?&=+$()!%#*|{}\\[\\]])");
 
   static QRegExp regExp[] = {
     // URL
@@ -457,7 +489,7 @@ void ContentsChatItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
         case Clickable::Url:
          if(!str.contains("://"))
            str = "http://" + str;
-          QDesktopServices::openUrl(str);
+          QDesktopServices::openUrl(QUrl::fromEncoded(str.toAscii()));
           break;
         case Clickable::Channel:
           // TODO join or whatever...
@@ -534,7 +566,9 @@ void ContentsChatItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) {
 }
 
 void ContentsChatItem::showWebPreview(const Clickable &click) {
-#ifdef HAVE_WEBKIT
+#ifndef HAVE_WEBKIT
+  Q_UNUSED(click);
+#else
   QTextLine line = layout()->lineForTextPosition(click.start);
   qreal x = line.cursorToX(click.start);
   qreal width = line.cursorToX(click.start + click.length) - x;