Introducing lazy word wrap calc.
authorMarcus Eggenberger <egs@quassel-irc.org>
Mon, 25 Aug 2008 13:11:19 +0000 (15:11 +0200)
committerMarcus Eggenberger <egs@quassel-irc.org>
Mon, 25 Aug 2008 13:11:19 +0000 (15:11 +0200)
 - faster message processing
 - less mem consumption unless you really visit all buffers
 - slightly slower buffer switch if you visit that buffer the first time

src/qtui/chatlinemodel.cpp
src/qtui/chatlinemodel.h
src/qtui/chatlinemodelitem.cpp
src/qtui/chatlinemodelitem.h

index 28d77fb..6b770a8 100644 (file)
 
 #include "chatlinemodelitem.h"
 
-ChatLineModel::ChatLineModel(QObject *parent) : MessageModel(parent) {
+ChatLineModel::ChatLineModel(QObject *parent)
+  : MessageModel(parent)
+{
   qRegisterMetaType<WrapList>("ChatLineModel::WrapList");
   qRegisterMetaTypeStreamOperators<WrapList>("ChatLineModel::WrapList");
-
-}
-
-ChatLineModel::~ChatLineModel() {
-
 }
 
-
 MessageModelItem *ChatLineModel::createMessageModelItem(const Message &msg) {
   return new ChatLineModelItem(msg);
-
 }
 
 
index a1e2c69..0fb9226 100644 (file)
 class ChatLineModel : public MessageModel {
   Q_OBJECT
 
-  public:
-    enum ChatLineRole {
-      WrapListRole = MessageModel::UserRole
-    };
-
-    ChatLineModel(QObject *parent = 0);
-    virtual ~ChatLineModel();
-
-    /// Used to store information about words to be used for wrapping
-    struct Word {
-      quint16 start;
-      qreal width;
-      qreal trailing;
-    };
-
-    typedef QVector<Word> WrapList;
-  
-  protected:
-    virtual MessageModelItem *createMessageModelItem(const Message &);
+public:
+  enum ChatLineRole {
+    WrapListRole = MessageModel::UserRole
+  };
+
+  ChatLineModel(QObject *parent = 0);
+
+  /// Used to store information about words to be used for wrapping
+  struct Word {
+    quint16 start;
+    qreal width;
+    qreal trailing;
+  };
+  typedef QVector<Word> WrapList;
+
+protected:
+  virtual MessageModelItem *createMessageModelItem(const Message &);
 
 };
 
index 9b9e71c..1897e3e 100644 (file)
@@ -40,8 +40,13 @@ typedef struct {
 unsigned char *ChatLineModelItem::TextBoundaryFinderBuffer = (unsigned char *)malloc(512 * sizeof(HB_CharAttributes_Dummy));
 int ChatLineModelItem::TextBoundaryFinderBufferSize = 512 * (sizeof(HB_CharAttributes_Dummy) / sizeof(unsigned char));
 
+struct ChatLineModelItemPrivate {
+  ChatLineModel::WrapList wrapList;
+};
+
 ChatLineModelItem::ChatLineModelItem(const Message &msg)
-  : MessageModelItem(msg)
+  : MessageModelItem(msg),
+    _data(new ChatLineModelItemPrivate)
 {
   QtUiStyle::StyledMessage m = QtUi::style()->styleMessage(msg);
 
@@ -52,11 +57,8 @@ ChatLineModelItem::ChatLineModelItem(const Message &msg)
   _timestamp.formatList = m.timestamp.formatList;
   _sender.formatList = m.sender.formatList;
   _contents.formatList = m.contents.formatList;
-
-  computeWrapList();
 }
 
-
 QVariant ChatLineModelItem::data(int column, int role) const {
   const ChatLinePart *part = 0;
 
@@ -82,19 +84,20 @@ QVariant ChatLineModelItem::data(int column, int role) const {
   case ChatLineModel::WrapListRole:
     if(column != ChatLineModel::ContentsColumn)
       return QVariant();
-    return QVariant::fromValue<ChatLineModel::WrapList>(_wrapList);
+    if(_data->wrapList.isEmpty())
+      computeWrapList();
+    return QVariant::fromValue<ChatLineModel::WrapList>(_data->wrapList);
   }
   return MessageModelItem::data(column, role);
 }
 
-void ChatLineModelItem::computeWrapList() {
+void ChatLineModelItem::computeWrapList() const {
   if(_contents.plainText.isEmpty())
     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, _contents.plainText);
   QTextBoundaryFinder finder(QTextBoundaryFinder::Word, _contents.plainText.unicode(), _contents.plainText.length(), TextBoundaryFinderBuffer, TextBoundaryFinderBufferSize);
 
   int idx;
@@ -153,9 +156,9 @@ void ChatLineModelItem::computeWrapList() {
   } while(finder.isAtBoundary() || (finder.position() == _contents.plainText.length()));
 
   // A QVector needs less space than a QList
-  _wrapList.resize(wplist.count());
+  _data->wrapList.resize(wplist.count());
   for(int i = 0; i < wplist.count(); i++) {
-    _wrapList[i] = wplist.at(i);
+    _data->wrapList[i] = wplist.at(i);
   }
 }
 
index 1e9a8cc..bc32668 100644 (file)
@@ -26,6 +26,8 @@
 #include "chatlinemodel.h"
 #include "uistyle.h"
 
+class ChatLineModelItemPrivate;
+
 class ChatLineModelItem : public MessageModelItem {
 public:
   ChatLineModelItem(const Message &);
@@ -34,7 +36,7 @@ public:
   virtual inline bool setData(int column, const QVariant &value, int role) { Q_UNUSED(column); Q_UNUSED(value); Q_UNUSED(role); return false; }
 
 private:
-  void computeWrapList();
+  void computeWrapList() const;
 
   struct ChatLinePart {
     QString plainText;
@@ -42,7 +44,7 @@ private:
   };
   ChatLinePart _timestamp, _sender, _contents;
 
-  ChatLineModel::WrapList _wrapList;
+  ChatLineModelItemPrivate *_data;
 
   static unsigned char *TextBoundaryFinderBuffer;
   static int TextBoundaryFinderBufferSize;