Use inheritance for handling the different ChatItem types
authorManuel Nickschas <sputnick@quassel-irc.org>
Mon, 18 Aug 2008 22:09:47 +0000 (00:09 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 18 Aug 2008 22:09:47 +0000 (00:09 +0200)
src/qtui/chatitem.cpp
src/qtui/chatitem.h
src/qtui/chatline.cpp
src/qtui/chatline.h

index c2f2425..6a9b143 100644 (file)
 #include "chatlinemodel.h"
 #include "qtui.h"
 
-ChatItem::ChatItem(int col, QAbstractItemModel *model, QGraphicsItem *parent)
+ChatItem::ChatItem(ChatLineModel::ColumnType col, QAbstractItemModel *model, QGraphicsItem *parent)
   : QGraphicsItem(parent),
     _fontMetrics(0),
-    _col(col),
-    _lines(0),
     _layoutData(0),
     _selectionMode(NoSelection),
     _selectionStart(-1)
@@ -71,13 +69,7 @@ qreal ChatItem::setGeometry(qreal w, qreal h) {
 }
 
 qreal ChatItem::computeHeight() {
-  if(data(ChatLineModel::ColumnTypeRole).toUInt() != ChatLineModel::ContentsColumn)
-    return fontMetrics()->lineSpacing(); // only contents can be multi-line
-
-  _lines = 1;
-  WrapColumnFinder finder(this);
-  while(finder.nextWrapColumn() > 0) _lines++;
-  return _lines * fontMetrics()->lineSpacing();
+  return fontMetrics()->lineSpacing(); // only contents can be multi-line
 }
 
 QTextLayout *ChatItem::createLayout(QTextOption::WrapMode wrapMode, Qt::Alignment alignment) {
@@ -101,46 +93,16 @@ void ChatItem::setLayout(QTextLayout *layout) {
 }
 
 void ChatItem::updateLayout() {
-  switch(data(ChatLineModel::ColumnTypeRole).toUInt()) {
-    case ChatLineModel::TimestampColumn:
-      if(!haveLayout()) setLayout(createLayout(QTextOption::WrapAnywhere, Qt::AlignLeft));
-      // fallthrough
-    case ChatLineModel::SenderColumn:
-      if(!haveLayout()) setLayout(createLayout(QTextOption::WrapAnywhere, Qt::AlignRight));
-      layout()->beginLayout();
-      {
-        QTextLine line = layout()->createLine();
-        if(line.isValid()) {
-          line.setLineWidth(width());
-          line.setPosition(QPointF(0,0));
-        }
-        layout()->endLayout();
-      }
-      break;
-    case ChatLineModel::ContentsColumn: {
-      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();
-    }
-    break;
+  if(!haveLayout())
+    setLayout(createLayout(QTextOption::WrapAnywhere, Qt::AlignLeft));
+
+  layout()->beginLayout();
+  QTextLine line = layout()->createLine();
+  if(line.isValid()) {
+    line.setLineWidth(width());
+    line.setPosition(QPointF(0,0));
   }
+  layout()->endLayout();
 }
 
 void ChatItem::clearLayoutData() {
@@ -321,10 +283,51 @@ void ChatItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
   event->ignore();
 }
 
+/*************************************************************************************************/
+
+/*************************************************************************************************/
+
+void SenderChatItem::updateLayout() {
+  if(!haveLayout()) setLayout(createLayout(QTextOption::WrapAnywhere, Qt::AlignRight));
+  ChatItem::updateLayout();
+}
+
+/*************************************************************************************************/
+
+qreal ContentsChatItem::computeHeight() {
+  int lines = 1;
+  WrapColumnFinder finder(this);
+  while(finder.nextWrapColumn() > 0) lines++;
+  return lines * fontMetrics()->lineSpacing();
+}
+
+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();
+}
+
 
 /*************************************************************************************************/
 
-ChatItem::WrapColumnFinder::WrapColumnFinder(ChatItem *_item) : item(_item) {
+ContentsChatItem::WrapColumnFinder::WrapColumnFinder(ChatItem *_item) : item(_item) {
   wrapList = item->data(ChatLineModel::WrapListRole).value<ChatLineModel::WrapList>();
   wordidx = 0;
   layout = 0;
@@ -333,11 +336,11 @@ ChatItem::WrapColumnFinder::WrapColumnFinder(ChatItem *_item) : item(_item) {
   w = 0;
 }
 
-ChatItem::WrapColumnFinder::~WrapColumnFinder() {
+ContentsChatItem::WrapColumnFinder::~WrapColumnFinder() {
   delete layout;
 }
 
-qint16 ChatItem::WrapColumnFinder::nextWrapColumn() {
+qint16 ContentsChatItem::WrapColumnFinder::nextWrapColumn() {
   while(wordidx < wrapList.count()) {
     w += wrapList.at(wordidx).width;
     if(w >= item->width()) {
index 44cbaaa..745f2d3 100644 (file)
@@ -33,70 +33,69 @@ class QTextLayout;
 
 class ChatItem : public QGraphicsItem {
 
-  public:
-    ChatItem(int col, QAbstractItemModel *, QGraphicsItem *parent);
-    virtual ~ChatItem();
+protected:
+  ChatItem(ChatLineModel::ColumnType column, QAbstractItemModel *, QGraphicsItem *parent);
+  virtual ~ChatItem();
 
-    inline const QAbstractItemModel *model() const { return chatScene() ? chatScene()->model() : 0; }
-    int row() const;
-    inline int column() const { return _col; }
-    inline ChatScene *chatScene() const { return qobject_cast<ChatScene *>(scene()); }
+public:
+  inline const QAbstractItemModel *model() const { return chatScene() ? chatScene()->model() : 0; }
+  inline int row() const;
+  virtual ChatLineModel::ColumnType column() const = 0;
+  inline ChatScene *chatScene() const { return qobject_cast<ChatScene *>(scene()); }
 
-    inline QFontMetricsF *fontMetrics() const { return _fontMetrics; }
-    inline virtual QRectF boundingRect() const { return _boundingRect; }
-    inline qreal width() const { return _boundingRect.width(); }
-    inline qreal height() const { return _boundingRect.height(); }
+  inline QFontMetricsF *fontMetrics() const { return _fontMetrics; }
+  inline QRectF boundingRect() const { return _boundingRect; }
+  inline qreal width() const { return _boundingRect.width(); }
+  inline qreal height() const { return _boundingRect.height(); }
 
-    inline bool haveLayout() const { return _layoutData != 0 && layout() != 0; }
-    void clearLayoutData();
-    void updateLayout();
-    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+  inline bool haveLayout() const { return _layoutData != 0 && layout() != 0; }
+  void clearLayoutData();
+  virtual QTextLayout *createLayout(QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft);
+  virtual void updateLayout();
+  virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
 
-    virtual QVariant data(int role) const;
+  virtual QVariant data(int role) const;
 
-    // returns height
-    qreal setGeometry(qreal width, qreal height = -1);
+  // returns height
+  qreal setGeometry(qreal width, qreal height = -1);
 
-    // selection stuff, to be called by the scene
-    void clearSelection();
-    void setFullSelection();
-    void continueSelecting(const QPointF &pos);
+  // selection stuff, to be called by the scene
+  void clearSelection();
+  void setFullSelection();
+  void continueSelecting(const QPointF &pos);
 
   QList<QRectF> findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive);
 
-  protected:
-    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
-    virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
-    virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
-    virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
+protected:
+  virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+  virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+  virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+  virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
 
-    virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
-    virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
-    virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
+  virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
+  virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
+  virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event);
 
-  private:
-    struct LayoutData;
-    class WrapColumnFinder;
+  struct LayoutData;
+  inline QTextLayout *layout() const;
+  void setLayout(QTextLayout *);
+  qint16 posToCursor(const QPointF &pos);
 
-    inline QTextLayout *layout() const;
-    void setLayout(QTextLayout *);
-    qint16 posToCursor(const QPointF &pos);
-    qreal computeHeight();
-    QTextLayout *createLayout(QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft);
+  virtual qreal computeHeight();
 
-    // internal selection stuff
-    void setSelection(int start, int length);
+  QRectF _boundingRect;
 
-    QRectF _boundingRect;
-    QFontMetricsF *_fontMetrics;
-    int _col;
-    quint8 _lines;
+private:
+  // internal selection stuff
+  void setSelection(int start, int length);
 
-    enum SelectionMode { NoSelection, PartialSelection, FullSelection };
-    SelectionMode _selectionMode;
-    qint16 _selectionStart, _selectionEnd;
+  QFontMetricsF *_fontMetrics;
 
-    LayoutData *_layoutData;
+  enum SelectionMode { NoSelection, PartialSelection, FullSelection };
+  SelectionMode _selectionMode;
+  qint16 _selectionStart, _selectionEnd;
+
+  LayoutData *_layoutData;
 };
 
 struct ChatItem::LayoutData {
@@ -106,22 +105,55 @@ struct ChatItem::LayoutData {
   ~LayoutData() { delete layout; }
 };
 
-class ChatItem::WrapColumnFinder {
-  public:
-    WrapColumnFinder(ChatItem *parent);
-    ~WrapColumnFinder();
-
-    qint16 nextWrapColumn();
-
-  private:
-    ChatItem *item;
-    QTextLayout *layout;
-    QTextLine line;
-    ChatLineModel::WrapList wrapList;
-    qint16 wordidx;
-    qint16 lastwrapcol;
-    qreal lastwrappos;
-    qreal w;
+class TimestampChatItem : public ChatItem {
+
+public:
+  TimestampChatItem(QAbstractItemModel *model, QGraphicsItem *parent) : ChatItem(column(), model, parent) {}
+  inline ChatLineModel::ColumnType column() const { return ChatLineModel::TimestampColumn; }
+
+};
+
+class SenderChatItem : public ChatItem {
+
+public:
+  SenderChatItem(QAbstractItemModel *model, QGraphicsItem *parent) : ChatItem(column(), model, parent) {}
+  inline ChatLineModel::ColumnType column() const { return ChatLineModel::SenderColumn; }
+
+  void updateLayout();
+};
+
+class ContentsChatItem : public ChatItem {
+
+public:
+  ContentsChatItem(QAbstractItemModel *model, QGraphicsItem *parent) : ChatItem(column(), model, parent) {}
+  inline ChatLineModel::ColumnType column() const { return ChatLineModel::ContentsColumn; }
+
+  void updateLayout();
+
+private:
+  qreal computeHeight();
+
+  class WrapColumnFinder;
+};
+
+
+
+class ContentsChatItem::WrapColumnFinder {
+public:
+  WrapColumnFinder(ChatItem *parent);
+  ~WrapColumnFinder();
+
+  qint16 nextWrapColumn();
+
+private:
+  ChatItem *item;
+  QTextLayout *layout;
+  QTextLine line;
+  ChatLineModel::WrapList wrapList;
+  qint16 wordidx;
+  qint16 lastwrapcol;
+  qreal lastwrappos;
+  qreal w;
 };
 
 #include "chatline.h"
index 5213be8..94820d6 100644 (file)
@@ -35,9 +35,9 @@
 ChatLine::ChatLine(int row, QAbstractItemModel *model, QGraphicsItem *parent)
   : QGraphicsItem(parent),
     _row(row), // needs to be set before the items
-    _timestampItem(ChatLineModel::TimestampColumn, model, this),
-    _senderItem(ChatLineModel::SenderColumn, model, this),
-    _contentsItem(ChatLineModel::ContentsColumn, model, this),
+    _timestampItem(model, this),
+    _senderItem(model, this),
+    _contentsItem(model, this),
     _width(0),
     _height(0),
     _selection(0)
index 15805cc..c429f02 100644 (file)
 
 class ChatLine : public QGraphicsItem {
 
-  public:
+public:
   ChatLine(int row, QAbstractItemModel *model, QGraphicsItem *parent = 0);
 
-    virtual QRectF boundingRect () const;
+  virtual QRectF boundingRect () const;
 
   inline int row() { return _row; }
   inline void setRow(int row) { _row = row; }
   inline const QAbstractItemModel *model() const { return chatScene() ? chatScene()->model() : 0; }
   inline ChatScene *chatScene() const { return qobject_cast<ChatScene *>(scene()); }
-    inline qreal width() const { return _width; }
-    inline qreal height() const { return _height; }
-    ChatItem &item(ChatLineModel::ColumnType);
+  inline qreal width() const { return _width; }
+  inline qreal height() const { return _height; }
+  ChatItem &item(ChatLineModel::ColumnType);
 
-    virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+  virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
 
-    // returns height
-    qreal setGeometry(qreal width, qreal firstColPos, qreal secondColPos);
-    void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn);
-    void setHighlighted(bool highlighted);
+  // returns height
+  qreal setGeometry(qreal width, qreal firstColPos, qreal secondColPos);
+  void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn);
+  void setHighlighted(bool highlighted);
 
-  protected:
+protected:
 
-  private:
+private:
   int _row;
-    ChatItem _timestampItem, _senderItem, _contentsItem;
-    qreal _width, _height;
+  TimestampChatItem _timestampItem;
+  SenderChatItem _senderItem;
+  ContentsChatItem _contentsItem;
+  qreal _width, _height;
 
-    enum { Selected = 0x40, Highlighted = 0x80 };
-    quint8 _selection;  // save space, so we put both the col and the flags into one byte
+  enum { Selected = 0x40, Highlighted = 0x80 };
+  quint8 _selection;  // save space, so we put both the col and the flags into one byte
 };
 
 #endif