Compute correct height of ChatItems.
authorManuel Nickschas <sputnick@quassel-irc.org>
Fri, 13 Jun 2008 23:42:08 +0000 (01:42 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 2 Aug 2008 13:17:09 +0000 (15:17 +0200)
For this, we precompute possible wrap points and the width of words,
form which we can quickly compute the height.

src/client/messagemodel.cpp
src/client/messagemodel.h
src/qtui/chatitem.cpp
src/qtui/chatitem.h
src/qtui/chatlinemodel.h
src/qtui/chatlinemodelitem.cpp
src/qtui/chatlinemodelitem.h

index 6784c4f..76104bd 100644 (file)
@@ -34,8 +34,9 @@ MessageModel::~MessageModel() {
 }
 
 QVariant MessageModel::data(const QModelIndex &index, int role) const {
 }
 
 QVariant MessageModel::data(const QModelIndex &index, int role) const {
-  int row = index.row();
-  if(row < 0 || row >= _messageList.count()) return QVariant();
+  int row = index.row(); int column = index.column();
+  if(row < 0 || row >= _messageList.count() || column < 0) return QVariant();
+  if(role == ColumnTypeRole) return column;
   return _messageList[row]->data(index.column(), role);
 }
 
   return _messageList[row]->data(index.column(), role);
 }
 
index 5b2786a..f6e2538 100644 (file)
@@ -42,6 +42,7 @@ class MessageModel : public QAbstractItemModel {
       TimestampRole,
       DisplayRole,
       FormatRole,
       TimestampRole,
       DisplayRole,
       FormatRole,
+      ColumnTypeRole,
       UserRole
     };
 
       UserRole
     };
 
index 63d92e6..568cdcc 100644 (file)
 #include <QtGui>
 
 #include "chatitem.h"
 #include <QtGui>
 
 #include "chatitem.h"
+#include "chatlinemodel.h"
+#include "qtui.h"
 
 ChatItem::ChatItem(const QPersistentModelIndex &index_, QGraphicsItem *parent) : QGraphicsItem(parent), _index(index_) {
 
 ChatItem::ChatItem(const QPersistentModelIndex &index_, QGraphicsItem *parent) : QGraphicsItem(parent), _index(index_) {
-
+  QFontMetricsF *metrics = QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value<UiStyle::FormatList>().at(0).second);
+  _lineHeight = metrics->lineSpacing();
 }
 
 ChatItem::~ChatItem() {
 }
 
 ChatItem::~ChatItem() {
@@ -57,12 +60,33 @@ void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
   painter->drawRect(boundingRect());
 }
 
   painter->drawRect(boundingRect());
 }
 
-
-
 int ChatItem::setWidth(int w) {
 int ChatItem::setWidth(int w) {
+  if(w == _boundingRect.width()) return _boundingRect.height();
+  int h = heightForWidth(w);
   _boundingRect.setWidth(w);
   _boundingRect.setWidth(w);
-  _boundingRect.setHeight(20); // FIXME
-  return 20;
+  _boundingRect.setHeight(h);
+  return h;
+}
+
+int ChatItem::heightForWidth(int width) {
+  if(data(ChatLineModel::ColumnTypeRole).toUInt() != ChatLineModel::ContentsColumn)
+    return _lineHeight; // only contents can be multi-line
+
+  QVariantList wrapList = data(ChatLineModel::WrapListRole).toList();
+  int lines = 1;
+  int offset = 0;
+  for(int i = 0; i < wrapList.count(); i+=2) {
+    if(wrapList.at(i+1).toUInt() - offset < width) continue;
+    lines++;
+    if(i > 0) {
+      if(offset != wrapList.at(i-1).toUInt()) offset = wrapList.at(i-1).toUInt();
+      else offset += width;
+    } else {
+      offset += width;
+    }
+    i-=2;
+  }
+  return lines * _lineHeight;
 }
 
 /*
 }
 
 /*
index 97a6fc0..55985a3 100644 (file)
@@ -18,8 +18,8 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#ifndef _CHATITEM_H_
-#define _CHATITEM_H_
+#ifndef CHATITEM_H_
+#define CHATITEM_H_
 
 #include <QGraphicsItem>
 #include <QTextLayout>
 
 #include <QGraphicsItem>
 #include <QTextLayout>
@@ -57,6 +57,9 @@ class ChatItem : public QGraphicsItem {
     //void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
 
   private:
     //void mouseMoveEvent ( QGraphicsSceneMouseEvent * event );
 
   private:
+    int heightForWidth(int width);
+
+    int _lineHeight;
     QRectF _boundingRect;
     //QTextLayout _layout;
     //QTextOption _textOption;
     QRectF _boundingRect;
     //QTextLayout _layout;
     //QTextOption _textOption;
index b61bd66..779b5f2 100644 (file)
@@ -28,7 +28,7 @@ class ChatLineModel : public MessageModel {
 
   public:
     enum ChatLineRole {
 
   public:
     enum ChatLineRole {
-      FormatRole = MessageModel::UserRole
+      WrapListRole = MessageModel::UserRole
     };
 
     ChatLineModel(QObject *parent = 0);
     };
 
     ChatLineModel(QObject *parent = 0);
index 8d15b92..b657f39 100644 (file)
@@ -37,7 +37,7 @@ ChatLineModelItem::ChatLineModelItem(const Message &msg) : MessageModelItem(msg)
   _sender.formatList = m.sender.formatList;
   _contents.formatList = m.contents.formatList;
 
   _sender.formatList = m.sender.formatList;
   _contents.formatList = m.contents.formatList;
 
-  computeWordList();
+  computeWrapList();
 }
 
 
 }
 
 
@@ -52,8 +52,16 @@ QVariant ChatLineModelItem::data(int column, int role) const {
   }
 
   switch(role) {
   }
 
   switch(role) {
-    case ChatLineModel::DisplayRole: return part->plainText;
-    case ChatLineModel::FormatRole:  return QVariant::fromValue<UiStyle::FormatList>(part->formatList);
+    case ChatLineModel::DisplayRole:
+      return part->plainText;
+    case ChatLineModel::FormatRole:
+      return QVariant::fromValue<UiStyle::FormatList>(part->formatList);
+    case ChatLineModel::WrapListRole:
+      if(column != ChatLineModel::ContentsColumn) return QVariant();
+      QVariantList wrapList;
+      typedef QPair<quint16, quint16> WrapPoint;  // foreach can't parse templated params
+      foreach(WrapPoint pair, _wrapList) wrapList << pair.first << pair.second;
+      return wrapList;
   }
 
   return MessageModelItem::data(column, role);
   }
 
   return MessageModelItem::data(column, role);
@@ -63,8 +71,8 @@ bool ChatLineModelItem::setData(int column, const QVariant &value, int role) {
   return false;
 }
 
   return false;
 }
 
-void ChatLineModelItem::computeWordList() {
-  QList<QPair<quint16, quint16> > wplist;  // use a temp list which we'll later copy into a QVector for efficiency
+void ChatLineModelItem::computeWrapList() {
+  WrapList wplist;  // use a temp list which we'll later copy into a QVector for efficiency
   QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _contents.plainText);
   int idx;
   int flistidx = -1;
   QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _contents.plainText);
   int idx;
   int flistidx = -1;
@@ -93,9 +101,9 @@ void ChatLineModelItem::computeWordList() {
   } while(idx < _contents.plainText.length());
 
   // A QVector needs less space than a QList
   } while(idx < _contents.plainText.length());
 
   // A QVector needs less space than a QList
-  _wordList.resize(wplist.count());
+  _wrapList.resize(wplist.count());
   for(int i = 0; i < wplist.count(); i++) {
   for(int i = 0; i < wplist.count(); i++) {
-    _wordList[i] = wplist.at(i);
+    _wrapList[i] = wplist.at(i);
   }
 }
 
   }
 }
 
index 24fed2b..f01b4e1 100644 (file)
@@ -37,7 +37,9 @@ class ChatLineModelItem : public MessageModelItem {
     virtual bool setData(int column, const QVariant &value, int role);
 
   private:
     virtual bool setData(int column, const QVariant &value, int role);
 
   private:
-    void computeWordList();
+    typedef QVector<QPair<quint16, quint16> > WrapList;
+
+    void computeWrapList();
 
     struct ChatLinePart {
       QString plainText;
 
     struct ChatLinePart {
       QString plainText;
@@ -45,7 +47,7 @@ class ChatLineModelItem : public MessageModelItem {
     };
     ChatLinePart _timestamp, _sender, _contents;
 
     };
     ChatLinePart _timestamp, _sender, _contents;
 
-    QVector<QPair<quint16, quint16> > _wordList;
+    WrapList _wrapList;
 };
 
 #endif
 };
 
 #endif