+
+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
+{
+ QString text = _styledMsg.plainContents();
+ int length = text.length();
+ if (!length)
+ return;
+
+ QList<ChatLineModel::Word> wplist; // use a temp list which we'll later copy into a QVector for efficiency
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Line, _styledMsg.plainContents().unicode(), length,
+ TextBoundaryFinderBuffer, TextBoundaryFinderBufferSize);
+
+ int idx;
+ int oldidx = 0;
+ ChatLineModel::Word word;
+ word.start = 0;
+ qreal wordstartx = 0;
+
+ QTextLayout layout(_styledMsg.plainContents());
+ QTextOption option;
+ option.setWrapMode(QTextOption::NoWrap);
+ layout.setTextOption(option);
+
+ layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length, messageLabel()));
+ layout.beginLayout();
+ QTextLine line = layout.createLine();
+ line.setNumColumns(length);
+ layout.endLayout();
+
+ while ((idx = finder.toNextBoundary()) >= 0 && idx <= length) {
+ // QTextBoundaryFinder has inconsistent behavior in Qt version up to and including 4.6.3 (at least).
+ // It doesn't point to the position we should break, but to the character before that.
+ // Unfortunately Qt decided to fix this by changing the behavior of QTBF, so now we have to add a version
+ // check. At the time of this writing, I'm still trying to get this reverted upstream...
+ //
+ // cf. https://bugs.webkit.org/show_bug.cgi?id=31076 and Qt commit e6ac173
+ static int needWorkaround = -1;
+ if (needWorkaround < 0) {
+ needWorkaround = 0;
+ QStringList versions = QString(qVersion()).split('.');
+ if (versions.count() == 3 && versions.at(0).toInt() == 4) {
+ if (versions.at(1).toInt() <= 6 && versions.at(2).toInt() <= 3)
+ needWorkaround = 1;
+ }
+ }
+ if (needWorkaround == 1) {
+ if (idx < length)
+ idx++;
+ }
+
+ 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(wordend);
+ qreal trailingendx = line.cursorToX(idx);
+ word.endX = wordendx;
+ word.width = wordendx - wordstartx;
+ word.trailing = trailingendx - wordendx;
+ wordstartx = trailingendx;
+ wplist.append(word);
+
+ oldidx = idx;
+ }
+
+ // A QVector needs less space than a QList
+ _wrapList.resize(wplist.count());
+ for (int i = 0; i < wplist.count(); i++) {
+ _wrapList[i] = wplist.at(i);
+ }
+}