X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fchatscene.cpp;h=4734d9c9389617085f13ba5cdce68374953eea0d;hp=a5f624beda479f1bd90c3f4c9db52ec6208bc0c5;hb=8a4544df5632a46407697b6b3f172d75037ae25b;hpb=1c0eb65f8545bb444f5fb9e792b8d9587ce8cefa diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index a5f624be..4734d9c9 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -44,6 +44,7 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _model(model), _singleBufferScene(false), _sceneRect(0, 0, width, 0), + _firstLineRow(-1), _viewportHeight(0), _selectingItem(0), _selectionStart(-1), @@ -121,15 +122,28 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); QPointF senderPos(firstColumnHandle()->sceneRight(), 0); - for(int i = start; i <= end; i++) { - ChatLine *line = new ChatLine(i, model(), - width, - timestampWidth, senderWidth, contentsWidth, - senderPos, contentsPos); - line->setPos(0, y+h); - h += line->height(); - _lines.insert(i, line); - addItem(line); + if(atTop) { + for(int i = end; i >= start; i--) { + ChatLine *line = new ChatLine(i, model(), + width, + timestampWidth, senderWidth, contentsWidth, + senderPos, contentsPos); + h += line->height(); + line->setPos(0, y-h); + _lines.insert(start, line); + addItem(line); + } + } else { + for(int i = start; i <= end; i++) { + ChatLine *line = new ChatLine(i, model(), + width, + timestampWidth, senderWidth, contentsWidth, + senderPos, contentsPos); + line->setPos(0, y+h); + h += line->height(); + _lines.insert(i, line); + addItem(line); + } } // update existing items @@ -160,7 +174,7 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { moveEnd = end; } else { // move bottom part - moveStart = start; + moveStart = end + 1; } ChatLine *line = 0; for(int i = moveStart; i <= moveEnd; i++) { @@ -169,6 +183,16 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { } } + if(!atBottom) { + if(start < _firstLineRow) { + int prevFirstLineRow = _firstLineRow + (end - start + 1); + for(int i = end + 1; i < prevFirstLineRow; i++) { + _lines.at(i)->show(); + } + } + // force new search for first proper line + _firstLineRow = -1; + } updateSceneRect(); if(atBottom) { emit lastLineChanged(_lines.last()); @@ -242,24 +266,20 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e // model still contains the just removed lines so we cannot simply call updateSceneRect() int numRows = model()->rowCount(); QModelIndex firstLineIdx; - int row = -1; + _firstLineRow = -1; bool needOffset = false; do { - row++; - if(row >= start && row <= end) { - row = end + 1; + _firstLineRow++; + if(_firstLineRow >= start && _firstLineRow <= end) { + _firstLineRow = end + 1; needOffset = true; } - firstLineIdx = model()->index(row, 0); - } while((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && row < numRows); + firstLineIdx = model()->index(_firstLineRow, 0); + } while((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && _firstLineRow < numRows); if(needOffset) - row -= end - start + 1; - - ChatLine *firstLine = _lines.at(row); - ChatLine *lastLine = _lines.last(); - - updateSceneRect(QRectF(0, firstLine->pos().y(), _sceneRect.width(), lastLine->pos().y() + lastLine->height() - firstLine->pos().y())); + _firstLineRow -= end - start + 1; + updateSceneRect(); } void ChatScene::updateForViewport(qreal width, qreal height) { @@ -497,22 +517,32 @@ int ChatScene::sectionByScenePos(int x) { } void ChatScene::updateSceneRect() { - if(_lines.isEmpty()) + if(_lines.isEmpty()) { + updateSceneRect(QRectF(0, 0, _sceneRect.width(), 0)); return; + } // we hide day change messages at the top by making the scene rect smaller - int numRows = model()->rowCount(); - int row = -1; - QModelIndex firstLineIdx; - do { - row++; - firstLineIdx = model()->index(row, 0); - } while((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) == Message::DayChange && row < numRows); + // and by calling QGraphicsItem::hide() on all leading day change messages + // the first one is needed to ensure proper scrollbar ranges + // the second for cases where the viewport is larger then the set scenerect + // (in this case the items are shown anyways) + if(_firstLineRow == -1) { + int numRows = model()->rowCount(); + _firstLineRow = 0; + QModelIndex firstLineIdx; + while(_firstLineRow < numRows) { + firstLineIdx = model()->index(_firstLineRow, 0); + if((Message::Type)(model()->data(firstLineIdx, MessageModel::TypeRole).toInt()) != Message::DayChange) + break; + _lines.at(_firstLineRow)->hide(); + _firstLineRow++; + } + } // the following call should be safe. If it crashes something went wrong during insert/remove - ChatLine *firstLine = _lines.at(row); + 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())); }