-void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) {
- Q_UNUSED(index);
-
-
-// QModelIndex sidx = model()->index(start, 2);
-// QModelIndex eidx = model()->index(end, 2);
-// qDebug() << "rowsInserted:";
-// if(start > 0) {
-// QModelIndex ssidx = model()->index(start - 1, 2);
-// qDebug() << "Start--:" << start - 1 << ssidx.data(MessageModel::MsgIdRole).value<MsgId>()
-// << ssidx.data(Qt::DisplayRole).toString();
-// }
-// qDebug() << "Start:" << start << sidx.data(MessageModel::MsgIdRole).value<MsgId>()
-// << sidx.data(Qt::DisplayRole).toString();
-// qDebug() << "End:" << end << eidx.data(MessageModel::MsgIdRole).value<MsgId>()
-// << eidx.data(Qt::DisplayRole).toString();
-// if(end + 1 < model()->rowCount()) {
-// QModelIndex eeidx = model()->index(end + 1, 2);
-// qDebug() << "End++:" << end + 1 << eeidx.data(MessageModel::MsgIdRole).value<MsgId>()
-// << eeidx.data(Qt::DisplayRole).toString();
-// }
-
- qreal h = 0;
- qreal y = 0;
- qreal width = _sceneRect.width();
- bool atBottom = (start == _lines.count());
- bool atTop = !atBottom && (start == 0);
-
- if(start < _lines.count()) {
- y = _lines.value(start)->y();
- } else if(atBottom && !_lines.isEmpty()) {
- y = _lines.last()->y() + _lines.last()->height();
- }
-
- qreal contentsWidth = width - secondColumnHandle()->sceneRight();
- qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight();
- qreal timestampWidth = firstColumnHandle()->sceneLeft();
- QPointF contentsPos(secondColumnHandle()->sceneRight(), 0);
- QPointF senderPos(firstColumnHandle()->sceneRight(), 0);
-
- 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
- for(int i = end+1; i < _lines.count(); i++) {
- _lines[i]->setRow(i);
- }
-
- // update selection
- if(_selectionStart >= 0) {
- int offset = end - start + 1;
- int oldStart = _selectionStart;
- if(_selectionStart >= start)
- _selectionStart += offset;
- if(_selectionEnd >= start) {
- _selectionEnd += offset;
- if(_selectionStart == oldStart)
- for(int i = start; i < start + offset; i++)
- _lines[i]->setSelected(true);
- }
- if(_firstSelectionRow >= start)
- _firstSelectionRow += offset;
- }
-
- // neither pre- or append means we have to do dirty work: move items...
- if(!(atTop || atBottom)) {
- ChatLine *line = 0;
- for(int i = 0; i <= end; i++) {
- line = _lines.at(i);
- line->setPos(0, line->pos().y() - h);
- }
- }
-
- // check if all went right
- Q_ASSERT(start == 0 || _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() == _lines.at(start)->pos().y());
-// if(start != 0) {
-// if(_lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height() != _lines.at(start)->pos().y()) {
-// qDebug() << "lines:" << _lines.count() << "start:" << start << "end:" << end;
-// qDebug() << "line[start - 1]:" << _lines.at(start - 1)->pos().y() << "+" << _lines.at(start - 1)->height() << "=" << _lines.at(start - 1)->pos().y() + _lines.at(start - 1)->height();
-// qDebug() << "line[start]" << _lines.at(start)->pos().y();
-// qDebug() << "needed moving:" << !(atTop || atBottom) << moveTop << moveStart << moveEnd << offset;
-// Q_ASSERT(false)
-// }
-// }
- Q_ASSERT(end + 1 == _lines.count() || _lines.at(end)->pos().y() + _lines.at(end)->height() == _lines.at(end + 1)->pos().y());
-// if(end + 1 < _lines.count()) {
-// if(_lines.at(end)->pos().y() + _lines.at(end)->height() != _lines.at(end + 1)->pos().y()) {
-// qDebug() << "lines:" << _lines.count() << "start:" << start << "end:" << end;
-// qDebug() << "line[end]:" << _lines.at(end)->pos().y() << "+" << _lines.at(end)->height() << "=" << _lines.at(end)->pos().y() + _lines.at(end)->height();
-// qDebug() << "line[end+1]" << _lines.at(end + 1)->pos().y();
-// qDebug() << "needed moving:" << !(atTop || atBottom) << moveTop << moveStart << moveEnd << offset;
-// Q_ASSERT(false);
-// }
-// }
-
- 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(), h);
- }
-}
-
-void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) {
- Q_UNUSED(parent);
-
- qreal h = 0; // total height of removed items;
-
- bool atTop = (start == 0);
- bool atBottom = (end == _lines.count() - 1);
- bool moveTop = false;
-
- // clear selection
- if(_selectingItem) {
- int row = _selectingItem->row();
- if(row >= start && row <= end)
- setSelectingItem(0);
- }
-
- // remove items from scene
- QList<ChatLine *>::iterator lineIter = _lines.begin() + start;
- int lineCount = start;
- while(lineIter != _lines.end() && lineCount <= end) {
- 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
- moveTop = true;
- 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::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);
+bool ChatScene::containsBuffer(const BufferId& id) const
+{
+ auto* filter = qobject_cast<MessageFilter*>(model());
+ if (filter)
+ return filter->containsBuffer(id);
+ else
+ return false;
+}
+
+void ChatScene::setMarkerLineVisible(bool visible)
+{
+ _markerLineVisible = visible;
+ if (visible && _markerLineValid)
+ markerLine()->setVisible(true);
+ else
+ markerLine()->setVisible(false);
+}
+
+void ChatScene::setMarkerLine(MsgId msgId)
+{
+ if (!isSingleBufferScene())
+ return;
+
+ if (!msgId.isValid())
+ msgId = Client::markerLine(singleBufferId());
+
+ if (msgId.isValid()) {
+ ChatLine* line = chatLine(msgId, false, true);
+ if (line) {
+ markerLine()->setChatLine(line);
+ // if this was the last line, we won't see it because it's outside the sceneRect
+ // .. which is exactly what we want :)
+ markerLine()->setPos(line->pos() + QPointF(0, line->height()));
+
+ // DayChange messages might have been hidden outside the scene rect, don't make the markerline visible then!
+ if (markerLine()->pos().y() >= sceneRect().y()) {
+ _markerLineValid = true;
+ if (_markerLineVisible)
+ markerLine()->setVisible(true);
+ if (_markerLineJumpPending) {
+ _markerLineJumpPending = false;
+ if (markerLine()->isVisible()) {
+ markerLine()->ensureVisible(QRectF(), 50, 50);
+ }
+ }
+ return;
+ }
+ }
+ }
+ _markerLineValid = false;
+ markerLine()->setVisible(false);