+ }
+}
+
+/*************************************************************************************************/
+
+/*************************************************************************************************/
+
+void SenderChatItem::updateLayout() {
+ if(!haveLayout()) setLayout(createLayout(QTextOption::WrapAnywhere, Qt::AlignRight));
+ ChatItem::updateLayout();
+}
+
+/*************************************************************************************************/
+
+ContentsChatItem::ContentsChatItem(QAbstractItemModel *model, QGraphicsItem *parent) : ChatItem(column(), model, parent),
+ _layoutData(0)
+{
+
+}
+
+ContentsChatItem::~ContentsChatItem() {
+ delete _layoutData;
+}
+
+qreal ContentsChatItem::computeHeight() {
+ int lines = 1;
+ WrapColumnFinder finder(this);
+ while(finder.nextWrapColumn() > 0) lines++;
+ return lines * fontMetrics()->lineSpacing();
+}
+
+void ContentsChatItem::setLayout(QTextLayout *layout) {
+ if(!_layoutData)
+ _layoutData = new LayoutData;
+ _layoutData->layout = layout;
+}
+
+void ContentsChatItem::clearLayout() {
+ delete _layoutData;
+ _layoutData = 0;
+}
+
+void ContentsChatItem::updateLayout() {
+ if(!haveLayout()) setLayout(createLayout(QTextOption::WrapAnywhere));
+
+ // Now layout
+ ChatLineModel::WrapList wrapList = data(ChatLineModel::WrapListRole).value<ChatLineModel::WrapList>();
+ if(!wrapList.count()) return; // empty chatitem
+
+ qreal h = 0;
+ WrapColumnFinder finder(this);
+ layout()->beginLayout();
+ forever {
+ QTextLine line = layout()->createLine();
+ if(!line.isValid())
+ break;
+
+ int col = finder.nextWrapColumn();
+ line.setNumColumns(col >= 0 ? col - line.textStart() : layout()->text().length());
+ line.setPosition(QPointF(0, h));
+ h += line.height() + fontMetrics()->leading();
+ }
+ layout()->endLayout();
+}
+
+void ContentsChatItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) {
+ // FIXME dirty and fast hack to make http:// urls klickable
+
+ QRegExp regex("\\b([hf]t{1,2}ps?://[^\\s]+)\\b");
+ QString str = data(ChatLineModel::DisplayRole).toString();
+ int idx = posToCursor(event->pos());
+ int mi = 0;
+ do {
+ mi = regex.indexIn(str, mi);
+ if(mi < 0) break;
+ if(idx >= mi && idx < mi + regex.matchedLength()) {
+ QDesktopServices::openUrl(QUrl(regex.capturedTexts()[1]));
+ break;
+ }
+ mi += regex.matchedLength();
+ } while(mi >= 0);
+ event->accept();
+}
+
+void ContentsChatItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) {
+ //qDebug() << (void*)this << "entering";
+ event->ignore();
+}
+
+void ContentsChatItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
+ //qDebug() << (void*)this << "leaving";
+ event->ignore();
+}
+
+void ContentsChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
+ //qDebug() << (void*)this << event->pos();
+ event->ignore();
+}
+
+/*************************************************************************************************/
+
+ContentsChatItem::WrapColumnFinder::WrapColumnFinder(ChatItem *_item) : item(_item) {
+ wrapList = item->data(ChatLineModel::WrapListRole).value<ChatLineModel::WrapList>();
+ wordidx = 0;
+ layout = 0;
+ lastwrapcol = 0;
+ lastwrappos = 0;
+ w = 0;
+}
+
+ContentsChatItem::WrapColumnFinder::~WrapColumnFinder() {
+ delete layout;
+}
+
+qint16 ContentsChatItem::WrapColumnFinder::nextWrapColumn() {
+ while(wordidx < wrapList.count()) {
+ w += wrapList.at(wordidx).width;
+ if(w >= item->width()) {
+ if(lastwrapcol >= wrapList.at(wordidx).start) {
+ // first word, and it doesn't fit
+ if(!line.isValid()) {
+ layout = item->createLayout(QTextOption::NoWrap);
+ layout->beginLayout();
+ line = layout->createLine();
+ line.setLineWidth(item->width());
+ layout->endLayout();
+ }
+ int idx = line.xToCursor(lastwrappos + item->width(), QTextLine::CursorOnCharacter);
+ qreal x = line.cursorToX(idx, QTextLine::Trailing);
+ w = w - wrapList.at(wordidx).width - (x - lastwrappos);
+ lastwrappos = x;
+ lastwrapcol = idx;
+ return idx;
+ }
+ // not the first word, so just wrap before this
+ lastwrapcol = wrapList.at(wordidx).start;
+ lastwrappos = lastwrappos + w - wrapList.at(wordidx).width;
+ w = 0;
+ return lastwrapcol;
+ }
+ w += wrapList.at(wordidx).trailing;
+ wordidx++;
+ }
+ return -1;