+ // remove items from scene
+ QList<ChatLine *>::iterator lineIter = _lines.begin() + start;
+ int lineCount = start;
+ while (lineIter != _lines.end() && lineCount <= end) {
+ if ((*lineIter) == markerLine()->chatLine())
+ markerLine()->setChatLine(0);
+ h += (*lineIter)->height();
+ delete *lineIter;
+ lineIter = _lines.erase(lineIter);
+ lineCount++;
+ }
+
+ // update rows of remaining chatlines
+ for (int i = start; i < _lines.count(); i++) {
+ _lines.at(i)->setRow(i);
+ }
+
+ // update selection
+ if (_selectionStart >= 0) {
+ int offset = end - start + 1;
+ if (_selectionStart >= start)
+ _selectionStart = qMax(_selectionStart - offset, start);
+ if (_selectionEnd >= start)
+ _selectionEnd -= offset;
+ if (_firstSelectionRow >= start)
+ _firstSelectionRow -= offset;
+
+ if (_selectionEnd < _selectionStart) {
+ _isSelecting = false;
+ _selectionStart = -1;
+ }
+ }
+
+ // neither removing at bottom or top means we have to move items...
+ if (!(atTop || atBottom)) {
+ qreal offset = h;
+ int moveStart = 0;
+ int moveEnd = _lines.count() - 1;
+ if (start < _lines.count() - start) {
+ // move top part
+ moveEnd = start - 1;
+ }
+ else {
+ // move bottom part
+ moveStart = start;
+ offset = -offset;
+ }
+ ChatLine *line = 0;
+ for (int i = moveStart; i <= moveEnd; i++) {
+ line = _lines.at(i);
+ line->setPos(0, line->pos().y() + offset);
+ }
+ }
+
+ Q_ASSERT(start == 0 || start >= _lines.count() || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y());
+
+ // update sceneRect
+ // when searching for the first non-date-line we have to take into account that our
+ // model still contains the just removed lines so we cannot simply call updateSceneRect()
+ int numRows = model()->rowCount();
+ QModelIndex firstLineIdx;
+ _firstLineRow = -1;
+ bool needOffset = false;
+ do {
+ _firstLineRow++;
+ if (_firstLineRow >= start && _firstLineRow <= end) {
+ _firstLineRow = end + 1;
+ needOffset = true;
+ }
+ firstLineIdx = model()->index(_firstLineRow, 0);
+ }
+ while ((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && _firstLineRow < numRows);
+
+ if (needOffset)
+ _firstLineRow -= end - start + 1;
+ updateSceneRect();
+}
+
+
+void ChatScene::rowsRemoved()
+{
+ // move the marker line if necessary
+ setMarkerLine();
+}
+
+
+void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br)
+{
+ layout(tl.row(), br.row(), _sceneRect.width());
+}
+
+
+void ChatScene::updateForViewport(qreal width, qreal height)
+{
+ _viewportHeight = height;
+ setWidth(width);
+}
+
+
+void ChatScene::setWidth(qreal width)
+{
+ if (width == _sceneRect.width())
+ return;
+ layout(0, _lines.count()-1, width);
+}
+
+
+void ChatScene::layout(int start, int end, qreal width)
+{
+ // clock_t startT = clock();
+
+ // disabling the index while doing this complex updates is about
+ // 2 to 10 times faster!
+ //setItemIndexMethod(QGraphicsScene::NoIndex);
+
+ if (end >= 0) {
+ int row = end;
+ qreal linePos = _lines.at(row)->scenePos().y() + _lines.at(row)->height();
+ qreal contentsWidth = width - secondColumnHandle()->sceneRight();
+ while (row >= start) {
+ _lines.at(row--)->setGeometryByWidth(width, contentsWidth, linePos);
+ }
+
+ if (row >= 0) {
+ // remaining items don't need geometry changes, but maybe repositioning?
+ ChatLine *line = _lines.at(row);
+ qreal offset = linePos - (line->scenePos().y() + line->height());
+ if (offset != 0) {
+ while (row >= 0) {
+ line = _lines.at(row--);
+ line->setPos(0, line->scenePos().y() + offset);
+ }
+ }