Spliting the functionality of setWidth into 3 separate functions for regular setWidth...
authorMarcus Eggenberger <egs@quassel-irc.org>
Thu, 16 Oct 2008 17:28:29 +0000 (19:28 +0200)
committerMarcus Eggenberger <egs@quassel-irc.org>
Thu, 16 Oct 2008 17:28:29 +0000 (19:28 +0200)
Those functions are still similar, but this allows us to fine tune the individual process and allows us to drop unneeded geometryChange propagation.

src/qtui/chatitem.cpp
src/qtui/chatitem.h
src/qtui/chatline.cpp
src/qtui/chatline.h
src/qtui/chatscene.cpp
src/qtui/chatscene.h

index e72cbdc..5d520e8 100644 (file)
@@ -272,6 +272,7 @@ ContentsChatItem::ContentsChatItem(const qreal &width, const QPointF &pos, QGrap
 
 qreal ContentsChatItem::setGeometryByWidth(qreal w) {
   if(w != width()) {
 
 qreal ContentsChatItem::setGeometryByWidth(qreal w) {
   if(w != width()) {
+    prepareGeometryChange();
     setWidth(w);
     // compute height
     int lines = 1;
     setWidth(w);
     // compute height
     int lines = 1;
index 5877040..3ed2cee 100644 (file)
@@ -80,16 +80,13 @@ protected:
   //  a) calling prepareGeometryChange() immediately before setColumns()
   //  b) calling Chatline::setPos() immediately afterwards
   inline void setGeometry(qreal width, qreal height) {
   //  a) calling prepareGeometryChange() immediately before setColumns()
   //  b) calling Chatline::setPos() immediately afterwards
   inline void setGeometry(qreal width, qreal height) {
-    prepareGeometryChange();
     _boundingRect.setWidth(width);
     _boundingRect.setHeight(height);
   }
   inline void setHeight(const qreal &height) {
     _boundingRect.setWidth(width);
     _boundingRect.setHeight(height);
   }
   inline void setHeight(const qreal &height) {
-    prepareGeometryChange();
     _boundingRect.setHeight(height);
   }
   inline void setWidth(const qreal &width) {
     _boundingRect.setHeight(height);
   }
   inline void setWidth(const qreal &width) {
-    prepareGeometryChange();
     _boundingRect.setWidth(width);
   }
 
     _boundingRect.setWidth(width);
   }
 
@@ -179,10 +176,6 @@ private:
   void showWebPreview(const Clickable &click);
   void clearWebPreview();
 
   void showWebPreview(const Clickable &click);
   void clearWebPreview();
 
-
-  // WARNING: setGeometry and setHeight should not be used without either:
-  //  a) calling prepareGeometryChange() immediately before setColumns()
-  //  b) calling Chatline::setPos() immediately afterwards
   qreal setGeometryByWidth(qreal w);
   friend class ChatLine;
   friend struct ContentsChatItemPrivate;
   qreal setGeometryByWidth(qreal w);
   friend class ChatLine;
   friend struct ContentsChatItemPrivate;
index f0772b3..1ef2f37 100644 (file)
@@ -68,43 +68,66 @@ ChatItem &ChatLine::item(ChatLineModel::ColumnType column) {
   }
 }
 
   }
 }
 
-// WARNING: setColumns should not be used without either:
-//  a) calling prepareGeometryChange() immediately before setColumns()
-//  b) calling Chatline::setPos() immediately afterwards
-//
-// NOTE: senderPos and contentsPos are in ChatLines coordinate system!
-qreal ChatLine::setColumns(const qreal &timestampWidth, const qreal &senderWidth, const qreal &contentsWidth,
-                          const QPointF &senderPos, const QPointF &contentsPos) {
-  prepareGeometryChange();
+// NOTE: senderPos is in ChatLines coordinate system!
+void ChatLine::setFirstColumn(const qreal &timestampWidth, const qreal &senderWidth, const QPointF &senderPos) {
+  _timestampItem.prepareGeometryChange();
+  _timestampItem.setGeometry(timestampWidth, _height);
+  // senderItem doesn't need a geom change as it's Pos is changed (ensured by void ChatScene::firstHandlePositionChanged(qreal xpos))
+  _senderItem.setGeometry(senderWidth, _height);
+  _senderItem.setPos(senderPos);
+
+  _timestampItem.clearLayout();
+  _senderItem.clearLayout();
+}
+
+// NOTE: contentsPos is in ChatLines coordinate system!
+void ChatLine::setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth,
+                              const QPointF &contentsPos, qreal &linePos) {
+  // contentsItem doesn't need a geom change as it's Pos is changed (ensured by void ChatScene::firstHandlePositionChanged(qreal xpos))
   qreal height = _contentsItem.setGeometryByWidth(contentsWidth);
   qreal height = _contentsItem.setGeometryByWidth(contentsWidth);
+  linePos -= height;
+  bool needGeometryChange = linePos == pos().y() && height != _height;
+
+  if(needGeometryChange) {
+    _timestampItem.prepareGeometryChange();
+    _senderItem.prepareGeometryChange();
+  }
+  _timestampItem.setHeight(height);
   _senderItem.setGeometry(senderWidth, height);
   _senderItem.setGeometry(senderWidth, height);
-  _timestampItem.setGeometry(timestampWidth, height);
 
 
-  _senderItem.setPos(senderPos);
   _contentsItem.setPos(contentsPos);
 
   _contentsItem.setPos(contentsPos);
 
-  _contentsItem.clearLayout();
-  _senderItem.clearLayout();
   _timestampItem.clearLayout();
   _timestampItem.clearLayout();
+  _senderItem.clearLayout();
 
 
+  if(needGeometryChange)
+    prepareGeometryChange();
 
   _height = height;
 
 
   _height = height;
 
-  return _height;
+  setPos(0, linePos);
 }
 
 }
 
-// WARNING: setGeometryByWidth should not be used without either:
-//  a) calling prepareGeometryChange() immediately before setColumns()
-//  b) calling Chatline::setPos() immediately afterwards
-qreal ChatLine::setGeometryByWidth(const qreal &width, const qreal &contentsWidth) {
-  prepareGeometryChange();
+void ChatLine::setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos) {
   qreal height = _contentsItem.setGeometryByWidth(contentsWidth);
   qreal height = _contentsItem.setGeometryByWidth(contentsWidth);
+  linePos -= height;
+  bool needGeometryChange = linePos == pos().y();
+
+  if(needGeometryChange) {
+    _timestampItem.prepareGeometryChange();
+    _senderItem.prepareGeometryChange();
+  }
   _timestampItem.setHeight(height);
   _senderItem.setHeight(height);
   _contentsItem.clearLayout();
   _timestampItem.setHeight(height);
   _senderItem.setHeight(height);
   _contentsItem.clearLayout();
+
+  if(needGeometryChange)
+    prepareGeometryChange();
+
   _height = height;
   _width = width;
   _height = height;
   _width = width;
-  return _height;
+
+  setPos(0, linePos); // set pos is _very_ cheap if nothing changes.
 }
 
 void ChatLine::setSelected(bool selected, ChatLineModel::ColumnType minColumn) {
 }
 
 void ChatLine::setSelected(bool selected, ChatLineModel::ColumnType minColumn) {
index dcf2e41..afdd380 100644 (file)
@@ -52,10 +52,11 @@ public:
 
   virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
 
 
   virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
 
-  // setColumns and setGeometryByWidth both return height
-  qreal setColumns(const qreal &timestampWidth, const qreal &senderWidth, const qreal &contentsWidth,
-                  const QPointF &senderPos, const QPointF &contentsPos);
-  qreal setGeometryByWidth(const qreal &width, const qreal &contentsWidth);
+  void setFirstColumn(const qreal &timestampWidth, const qreal &senderWidth, const QPointF &senderPos);
+  // setSecondColumn and setGeometryByWidth both also relocate the chatline.
+  // the _bottom_ position is passed via linePos. linePos is updated to the top of the chatLine.
+  void setSecondColumn(const qreal &senderWidth, const qreal &contentsWidth, const QPointF &contentsPos, qreal &linePos);
+  void setGeometryByWidth(const qreal &width, const qreal &contentsWidth, qreal &linePos);
 
   void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn);
   void setHighlighted(bool highlighted);
 
   void setSelected(bool selected, ChatLineModel::ColumnType minColumn = ChatLineModel::ContentsColumn);
   void setHighlighted(bool highlighted);
index ff28ea4..1adea58 100644 (file)
@@ -68,13 +68,13 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w
   _firstColHandle = new ColumnHandleItem(QtUi::style()->firstColumnSeparator());
   addItem(_firstColHandle);
   _firstColHandle->setXPos(_firstColHandlePos);
   _firstColHandle = new ColumnHandleItem(QtUi::style()->firstColumnSeparator());
   addItem(_firstColHandle);
   _firstColHandle->setXPos(_firstColHandlePos);
-  connect(_firstColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(handlePositionChanged(qreal)));
+  connect(_firstColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(firstHandlePositionChanged(qreal)));
   connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _firstColHandle, SLOT(sceneRectChanged(const QRectF &)));
 
   _secondColHandle = new ColumnHandleItem(QtUi::style()->secondColumnSeparator());
   addItem(_secondColHandle);
   _secondColHandle->setXPos(_secondColHandlePos);
   connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _firstColHandle, SLOT(sceneRectChanged(const QRectF &)));
 
   _secondColHandle = new ColumnHandleItem(QtUi::style()->secondColumnSeparator());
   addItem(_secondColHandle);
   _secondColHandle->setXPos(_secondColHandlePos);
-  connect(_secondColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(handlePositionChanged(qreal)));
+  connect(_secondColHandle, SIGNAL(positionChanged(qreal)), this, SLOT(secondHandlePositionChanged(qreal)));
   connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _secondColHandle, SLOT(sceneRectChanged(const QRectF &)));
 
   setHandleXLimits();
   connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _secondColHandle, SLOT(sceneRectChanged(const QRectF &)));
 
   setHandleXLimits();
@@ -295,48 +295,23 @@ void ChatScene::updateForViewport(qreal width, qreal height) {
   setWidth(width);
 }
 
   setWidth(width);
 }
 
-// setWidth is used for 2 things:
-//  a) updating the scene to fit the width of the corresponding view
-//  b) to update the positions of the items if a columhandle has changed it's position
-// forceReposition is true in the second case
-// this method features some codeduplication for the sake of performance
-void ChatScene::setWidth(qreal width, bool forceReposition) {
-  if(width == _sceneRect.width() && !forceReposition)
+void ChatScene::setWidth(qreal width) {
+  if(width == _sceneRect.width())
     return;
 
     return;
 
-//   clock_t startT = clock();
+  // clock_t startT = clock();
 
   // disabling the index while doing this complex updates is about
   // 2 to 10 times faster!
   setItemIndexMethod(QGraphicsScene::NoIndex);
 
 
   // disabling the index while doing this complex updates is about
   // 2 to 10 times faster!
   setItemIndexMethod(QGraphicsScene::NoIndex);
 
-  qreal linePos = _sceneRect.y() + _sceneRect.height();
   QList<ChatLine *>::iterator lineIter = _lines.end();
   QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
   QList<ChatLine *>::iterator lineIter = _lines.end();
   QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
-  ChatLine *line = 0;
-  qreal lineHeight = 0;
+  qreal linePos = _sceneRect.y() + _sceneRect.height();
   qreal contentsWidth = width - secondColumnHandle()->sceneRight();
   qreal contentsWidth = width - secondColumnHandle()->sceneRight();
-
-  if(forceReposition) {
-    qreal timestampWidth = firstColumnHandle()->sceneLeft();
-    qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight();
-    QPointF senderPos(firstColumnHandle()->sceneRight(), 0);
-    QPointF contentsPos(secondColumnHandle()->sceneRight(), 0);
-    while(lineIter != lineIterBegin) {
-      lineIter--;
-      line = *lineIter;
-      lineHeight = line->setColumns(timestampWidth, senderWidth, contentsWidth, senderPos, contentsPos);
-      linePos -= lineHeight;
-      line->setPos(0, linePos);
-    }
-  } else {
-    while(lineIter != lineIterBegin) {
-      lineIter--;
-      line = *lineIter;
-      lineHeight = line->setGeometryByWidth(width, contentsWidth);
-      linePos -= lineHeight;
-      line->setPos(0, linePos);
-    }
+  while(lineIter != lineIterBegin) {
+    lineIter--;
+    (*lineIter)->setGeometryByWidth(width, contentsWidth, linePos);
   }
   setItemIndexMethod(QGraphicsScene::BspTreeIndex);
 
   }
   setItemIndexMethod(QGraphicsScene::BspTreeIndex);
 
@@ -347,29 +322,72 @@ void ChatScene::setWidth(qreal width, bool forceReposition) {
 //   qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
 }
 
 //   qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
 }
 
-void ChatScene::handlePositionChanged(qreal xpos) {
-  bool first = (sender() == _firstColHandle);
-  qreal oldx;
-  if(first) {
-    oldx = _firstColHandlePos;
-    _firstColHandlePos = xpos;
-  } else {
-    oldx = _secondColHandlePos;
-    _secondColHandlePos = xpos;
-  }
+void ChatScene::firstHandlePositionChanged(qreal xpos) {
+  if(_firstColHandlePos == xpos)
+    return;
 
 
+  _firstColHandlePos = xpos;
   ChatViewSettings viewSettings(this);
   viewSettings.setValue("FirstColumnHandlePos", _firstColHandlePos);
   ChatViewSettings viewSettings(this);
   viewSettings.setValue("FirstColumnHandlePos", _firstColHandlePos);
-  viewSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
-
   ChatViewSettings defaultSettings;
   defaultSettings.setValue("FirstColumnHandlePos", _firstColHandlePos);
   ChatViewSettings defaultSettings;
   defaultSettings.setValue("FirstColumnHandlePos", _firstColHandlePos);
+
+  // clock_t startT = clock();
+
+  // disabling the index while doing this complex updates is about
+  // 2 to 10 times faster!
+  setItemIndexMethod(QGraphicsScene::NoIndex);
+
+  QList<ChatLine *>::iterator lineIter = _lines.end();
+  QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
+  qreal timestampWidth = firstColumnHandle()->sceneLeft();
+  qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight();
+  QPointF senderPos(firstColumnHandle()->sceneRight(), 0);
+
+  while(lineIter != lineIterBegin) {
+    lineIter--;
+    (*lineIter)->setFirstColumn(timestampWidth, senderWidth, senderPos);
+  }
+  setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+
+  setHandleXLimits();
+
+//   clock_t endT = clock();
+//   qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
+}
+
+void ChatScene::secondHandlePositionChanged(qreal xpos) {
+  if(_secondColHandlePos == xpos)
+    return;
+
+  _secondColHandlePos = xpos;
+  ChatViewSettings viewSettings(this);
+  viewSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
+  ChatViewSettings defaultSettings;
   defaultSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
 
   defaultSettings.setValue("SecondColumnHandlePos", _secondColHandlePos);
 
-  setWidth(width(), true);  // readjust all chatlines
-  // we get ugly redraw errors if we don't update this explicitly... :(
-  // width() should be the same for both handles, so just use _firstColHandle regardless
-  //update(qMin(oldx, xpos), 0, qMax(oldx, xpos) + firstColHandle->width(), height());
+  // clock_t startT = clock();
+
+  // disabling the index while doing this complex updates is about
+  // 2 to 10 times faster!
+  setItemIndexMethod(QGraphicsScene::NoIndex);
+
+  QList<ChatLine *>::iterator lineIter = _lines.end();
+  QList<ChatLine *>::iterator lineIterBegin = _lines.begin();
+  qreal linePos = _sceneRect.y() + _sceneRect.height();
+  qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight();
+  qreal contentsWidth = _sceneRect.width() - secondColumnHandle()->sceneRight();
+  QPointF contentsPos(secondColumnHandle()->sceneRight(), 0);
+  while(lineIter != lineIterBegin) {
+    lineIter--;
+    (*lineIter)->setSecondColumn(senderWidth, contentsWidth, contentsPos, linePos);
+  }
+  setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+
+  setHandleXLimits();
+
+//   clock_t endT = clock();
+//   qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
 }
 
 void ChatScene::setHandleXLimits() {
 }
 
 void ChatScene::setHandleXLimits() {
@@ -529,9 +547,9 @@ int ChatScene::sectionByScenePos(int x) {
   return ChatLineModel::ContentsColumn;
 }
 
   return ChatLineModel::ContentsColumn;
 }
 
-void ChatScene::updateSceneRect() {
+void ChatScene::updateSceneRect(qreal width) {
   if(_lines.isEmpty()) {
   if(_lines.isEmpty()) {
-    updateSceneRect(QRectF(0, 0, _sceneRect.width(), 0));
+    updateSceneRect(QRectF(0, 0, width, 0));
     return;
   }
 
     return;
   }
 
@@ -556,12 +574,7 @@ void ChatScene::updateSceneRect() {
   // the following call should be safe. If it crashes something went wrong during insert/remove
   ChatLine *firstLine = _lines.at(_firstLineRow);
   ChatLine *lastLine = _lines.last();
   // the following call should be safe. If it crashes something went wrong during insert/remove
   ChatLine *firstLine = _lines.at(_firstLineRow);
   ChatLine *lastLine = _lines.last();
-  updateSceneRect(QRectF(0, firstLine->pos().y(), _sceneRect.width(), lastLine->pos().y() + lastLine->height() - firstLine->pos().y()));
-}
-
-void ChatScene::updateSceneRect(qreal width) {
-  _sceneRect.setWidth(width);
-  updateSceneRect();
+  updateSceneRect(QRectF(0, firstLine->pos().y(), width, lastLine->pos().y() + lastLine->height() - firstLine->pos().y()));
 }
 
 void ChatScene::updateSceneRect(const QRectF &rect) {
 }
 
 void ChatScene::updateSceneRect(const QRectF &rect) {
index 9ac653b..2f568d3 100644 (file)
@@ -56,7 +56,8 @@ public:
 
 public slots:
   void updateForViewport(qreal width, qreal height);
 
 public slots:
   void updateForViewport(qreal width, qreal height);
-  void setWidth(qreal, bool forceReposition = false);
+  //void setWidth(qreal, bool forceReposition = false);
+  void setWidth(qreal width);
 
   // these are used by the chatitems to notify the scene and manage selections
   void setSelectingItem(ChatItem *item);
 
   // these are used by the chatitems to notify the scene and manage selections
   void setSelectingItem(ChatItem *item);
@@ -83,7 +84,8 @@ protected slots:
   void rowsAboutToBeRemoved(const QModelIndex &, int, int);
 
 private slots:
   void rowsAboutToBeRemoved(const QModelIndex &, int, int);
 
 private slots:
-  void handlePositionChanged(qreal xpos);
+  void firstHandlePositionChanged(qreal xpos);
+  void secondHandlePositionChanged(qreal xpos);
   void showWebPreviewEvent();
   void deleteWebPreviewEvent();
 
   void showWebPreviewEvent();
   void deleteWebPreviewEvent();
 
@@ -101,8 +103,8 @@ private:
   // we store the size in a member variable.
   QRectF _sceneRect;
   int _firstLineRow; // the first row to display (aka: not a daychange msg)
   // we store the size in a member variable.
   QRectF _sceneRect;
   int _firstLineRow; // the first row to display (aka: not a daychange msg)
-  void updateSceneRect();
   void updateSceneRect(qreal width);
   void updateSceneRect(qreal width);
+  inline void updateSceneRect() { updateSceneRect(_sceneRect.width()); }
   void updateSceneRect(const QRectF &rect);
   qreal _viewportHeight;
 
   void updateSceneRect(const QRectF &rect);
   qreal _viewportHeight;