Some cleanups, debug output--
[quassel.git] / src / qtui / chatlinemodelitem.cpp
index 2264fa5..824e9da 100644 (file)
@@ -52,9 +52,22 @@ ChatLineModelItem::ChatLineModelItem(const Message &msg)
     _styledMsg.setFlags(msg.flags() |= Message::ServerMsg);
 }
 
+bool ChatLineModelItem::setData(int column, const QVariant &value, int role) {
+  switch(role) {
+    case MessageModel::FlagsRole:
+      _styledMsg.setFlags((Message::Flags)value.toUInt());
+      return true;
+    default:
+      return MessageModelItem::setData(column, value, role);
+  }
+}
+
 QVariant ChatLineModelItem::data(int column, int role) const {
-  MessageModel::ColumnType col = (MessageModel::ColumnType)column;
+  if(role == ChatLineModel::MsgLabelRole)
+    return messageLabel();
+
   QVariant variant;
+  MessageModel::ColumnType col = (MessageModel::ColumnType)column;
   switch(col) {
   case ChatLineModel::TimestampColumn:
     variant = timestampData(role);
@@ -79,8 +92,13 @@ QVariant ChatLineModelItem::timestampData(int role) const {
     return _styledMsg.decoratedTimestamp();
   case ChatLineModel::EditRole:
     return _styledMsg.timestamp();
+  case ChatLineModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Timestamp);
+  case ChatLineModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Timestamp, true);
   case ChatLineModel::FormatRole:
-    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.timestampFormat()));
+    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList()
+                      << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp));
   }
   return QVariant();
 }
@@ -91,20 +109,26 @@ QVariant ChatLineModelItem::senderData(int role) const {
     return _styledMsg.decoratedSender();
   case ChatLineModel::EditRole:
     return _styledMsg.plainSender();
+  case ChatLineModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Sender);
+  case ChatLineModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Sender, true);
   case ChatLineModel::FormatRole:
-    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.senderFormat()));
+    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList()
+                      << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender));
   }
   return QVariant();
 }
 
 QVariant ChatLineModelItem::contentsData(int role) const {
-  if(_styledMsg.needsStyling())
-    _styledMsg.style(QtUi::style());
-
   switch(role) {
   case ChatLineModel::DisplayRole:
   case ChatLineModel::EditRole:
     return _styledMsg.plainContents();
+  case ChatLineModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Contents);
+  case ChatLineModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Contents, true);
   case ChatLineModel::FormatRole:
     return QVariant::fromValue<UiStyle::FormatList>(_styledMsg.contentsFormatList());
   case ChatLineModel::WrapListRole:
@@ -115,22 +139,34 @@ QVariant ChatLineModelItem::contentsData(int role) const {
   return QVariant();
 }
 
+quint32 ChatLineModelItem::messageLabel() const {
+  quint32 label = _styledMsg.senderHash() << 16;
+  if(_styledMsg.flags() & Message::Self)
+    label |= UiStyle::OwnMsg;
+  if(_styledMsg.flags() & Message::Highlight)
+    label |= UiStyle::Highlight;
+  return label;
+}
+
+QVariant ChatLineModelItem::backgroundBrush(UiStyle::FormatType subelement, bool selected) const {
+  QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel() | (selected ? UiStyle::Selected : 0));
+  if(fmt.hasProperty(QTextFormat::BackgroundBrush))
+    return QVariant::fromValue<QBrush>(fmt.background());
+  return QVariant();
+}
+
 void ChatLineModelItem::computeWrapList() const {
-  int length = _styledMsg.plainContents().length();
+  QString text = _styledMsg.plainContents();
+  int length = text.length();
   if(!length)
     return;
 
-  enum Mode { SearchStart, SearchEnd };
-
   QList<ChatLineModel::Word> wplist;  // use a temp list which we'll later copy into a QVector for efficiency
-  QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _styledMsg.plainContents().unicode(), length,
+  QTextBoundaryFinder finder(QTextBoundaryFinder::Line, _styledMsg.plainContents().unicode(), length,
                               TextBoundaryFinderBuffer, TextBoundaryFinderBufferSize);
 
   int idx;
   int oldidx = 0;
-  bool wordStart = false;
-  bool wordEnd = false;
-  Mode mode = SearchEnd;
   ChatLineModel::Word word;
   word.start = 0;
   qreal wordstartx = 0;
@@ -140,33 +176,27 @@ void ChatLineModelItem::computeWrapList() const {
   option.setWrapMode(QTextOption::NoWrap);
   layout.setTextOption(option);
 
-  layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length));
+  layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length, messageLabel()));
   layout.beginLayout();
   QTextLine line = layout.createLine();
   line.setNumColumns(length);
   layout.endLayout();
 
-  do {
-    idx = finder.toNextBoundary();
-    if(idx < 0) {
-      idx = length;
-      wordStart = false;
-      wordEnd = false;
-      mode = SearchStart;
-    } else {
-      wordStart = finder.boundaryReasons().testFlag(QTextBoundaryFinder::StartWord);
-      wordEnd = finder.boundaryReasons().testFlag(QTextBoundaryFinder::EndWord);
-    }
-
-    //if(flg) qDebug() << idx << mode << wordStart << wordEnd << contents->plainText.left(idx) << contents->plainText.mid(idx);
+  while((idx = finder.toNextBoundary()) >= 0 && idx <= length) {
+    if(idx < length)
+      idx++;  // the boundary is *before* the actual character
 
-    if(mode == SearchEnd || (!wordStart && wordEnd)) {
-      if(wordStart || !wordEnd) continue;
-      oldidx = idx;
-      mode = SearchStart;
+    if(idx == oldidx)
       continue;
+
+    word.start = oldidx;
+    int wordend = idx;
+    for(; wordend > word.start; wordend--) {
+      if(!text.at(wordend-1).isSpace())
+        break;
     }
-    qreal wordendx = line.cursorToX(oldidx);
+
+    qreal wordendx = line.cursorToX(wordend);
     qreal trailingendx = line.cursorToX(idx);
     word.endX = wordendx;
     word.width = wordendx - wordstartx;
@@ -174,13 +204,8 @@ void ChatLineModelItem::computeWrapList() const {
     wordstartx = trailingendx;
     wplist.append(word);
 
-    if(wordStart) {
-      word.start = idx;
-      mode = SearchEnd;
-    }
-    // the part " || (finder.position() == contents->plainText.length())" shouldn't be necessary
-    // but in rare and indeterministic cases Qt states that the end of the text is not a boundary o_O
-  } while(finder.isAtBoundary() || (finder.position() == length));
+    oldidx = idx;
+  }
 
   // A QVector needs less space than a QList
   _wrapList.resize(wplist.count());