From: Marcus Eggenberger Date: Tue, 30 Sep 2008 11:01:32 +0000 (+0200) Subject: properly fixing inserting and deleting chatlines at arbitrary positions in the scene X-Git-Tag: 0.3.1~219 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=46ddb293c61aeb90295fa1a14be71e8896f34ade properly fixing inserting and deleting chatlines at arbitrary positions in the scene --- diff --git a/src/client/messagefilter.cpp b/src/client/messagefilter.cpp index 17006720..c1253da8 100644 --- a/src/client/messagefilter.cpp +++ b/src/client/messagefilter.cpp @@ -53,5 +53,8 @@ bool MessageFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourcePar return true; BufferId id = sourceModel()->data(sourceModel()->index(sourceRow, 0), MessageModel::BufferIdRole).value(); + if(!id.isValid()) { + return true; + } return _validBuffers.contains(id); } diff --git a/src/client/messagemodel.cpp b/src/client/messagemodel.cpp index 21e39653..5269d0ad 100644 --- a/src/client/messagemodel.cpp +++ b/src/client/messagemodel.cpp @@ -79,9 +79,9 @@ void MessageModel::insertMessages(const QList &msglist) { if(msglist.isEmpty()) return; - if(_messageList.isEmpty()) { - insertMessageGroup(msglist); - } else { +// if(_messageList.isEmpty()) { +// insertMessageGroup(msglist); +// } else { int processedMsgs = insertMessagesGracefully(msglist); int remainingMsgs = msglist.count() - processedMsgs; if(remainingMsgs > 0) { @@ -94,18 +94,27 @@ void MessageModel::insertMessages(const QList &msglist) { qSort(_messageBuffer); QCoreApplication::postEvent(this, new ProcessBufferEvent()); } - } +// } } void MessageModel::insertMessageGroup(const QList &msglist) { int idx = indexForId(msglist.first().msgId()); + if(idx > 0) { + int prevIdx = idx - 1; + if(_messageList[prevIdx]->msgType() == Message::DayChange + && _messageList[prevIdx]->timeStamp() > msglist.value(0).timestamp()) { + beginRemoveRows(QModelIndex(), prevIdx, prevIdx); + MessageModelItem *oldItem = _messageList.takeAt(prevIdx); + delete oldItem; + endRemoveRows(); + idx--; + } + } beginInsertRows(QModelIndex(), idx, idx+msglist.count()-1); - foreach(Message msg, msglist) { _messageList.insert(idx, createMessageModelItem(msg)); idx++; } - endInsertRows(); } @@ -127,7 +136,7 @@ int MessageModel::insertMessagesGracefully(const QList &msglist) { } int idx = indexForId((*iter).msgId()); - if(idx >= 0) + if(idx >= 0 && !_messageList.isEmpty()) dupeId = _messageList[idx]->msgId(); // we always compare to the previous entry... @@ -152,20 +161,41 @@ int MessageModel::insertMessagesGracefully(const QList &msglist) { if(!fastForward && (*iter).msgId() < id) break; - if((*iter).msgId() != dupeId) + if((*iter).msgId() != dupeId) { + if(!grouplist.isEmpty()) { + QDateTime nextTs = grouplist.value(0).timestamp(); + QDateTime prevTs = (*iter).timestamp(); + nextTs.setTimeSpec(Qt::UTC); + prevTs.setTimeSpec(Qt::UTC); + uint nextDay = nextTs.toTime_t() / 86400; + uint prevDay = prevTs.toTime_t() / 86400; + if(nextDay != prevDay) { + nextTs.setTime_t(nextDay * 86400); + nextTs.setTimeSpec(Qt::LocalTime); + Message dayChangeMsg = Message::ChangeOfDay(nextTs); + dayChangeMsg.setMsgId((*iter).msgId()); + grouplist.prepend(dayChangeMsg); + dupeCount--; + } + } grouplist.prepend(*iter); - else + } else { dupeCount++; + } } } else { while(iter != msglist.constEnd()) { if(!fastForward && (*iter).msgId() < id) break; - if((*iter).msgId() != dupeId) + if((*iter).msgId() != dupeId) { + if(!grouplist.isEmpty()) { + qWarning() << "copy day change check"; + } grouplist.prepend(*iter); - else + } else { dupeCount++; + } iter++; } @@ -206,14 +236,18 @@ void MessageModel::clear() { // returns index of msg with given Id or of the next message after that (i.e., the index where we'd insert this msg) int MessageModel::indexForId(MsgId id) { - if(_messageList.isEmpty() || id <= _messageList.value(0)->data(0, MsgIdRole).value()) return 0; - if(id > _messageList.last()->data(0, MsgIdRole).value()) return _messageList.count(); + if(_messageList.isEmpty() || id <= _messageList.value(0)->msgId()) + return 0; + if(id > _messageList.last()->msgId()) + return _messageList.count(); + // binary search int start = 0; int end = _messageList.count()-1; while(1) { - if(end - start == 1) return end; + if(end - start == 1) + return end; int pivot = (end + start) / 2; - if(id <= _messageList.value(pivot)->data(0, MsgIdRole).value()) end = pivot; + if(id <= _messageList.value(pivot)->msgId()) end = pivot; else start = pivot; } } diff --git a/src/common/message.h b/src/common/message.h index 482039f2..90a6a168 100644 --- a/src/common/message.h +++ b/src/common/message.h @@ -33,19 +33,20 @@ class Message { public: /** The different types a message can have for display */ enum Type { - Plain = 0x0001, - Notice = 0x0002, - Action = 0x0004, - Nick = 0x0008, - Mode = 0x0010, - Join = 0x0020, - Part = 0x0040, - Quit = 0x0080, - Kick = 0x0100, - Kill = 0x0200, - Server = 0x0400, - Info = 0x0800, - Error = 0x1000 + Plain = 0x0001, + Notice = 0x0002, + Action = 0x0004, + Nick = 0x0008, + Mode = 0x0010, + Join = 0x0020, + Part = 0x0040, + Quit = 0x0080, + Kick = 0x0100, + Kill = 0x0200, + Server = 0x0400, + Info = 0x0800, + Error = 0x1000, + DayChange = 0x2000 }; // DO NOT CHANGE without knowing what you do, some of these flags are stored in the database @@ -63,6 +64,7 @@ public: Message(const QDateTime &ts, const BufferInfo &buffer = BufferInfo(), Type type = Plain, const QString &contents = "", const QString &sender = "", Flags flags = None); + inline static Message ChangeOfDay(const QDateTime &day) { return Message(day, BufferInfo(), DayChange, tr("Day changed to %1").arg(day.toString("dddd MMMM d yyyy"))); } inline MsgId msgId() const { return _msgId; } inline void setMsgId(MsgId id) { _msgId = id; } diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index e99509e1..10ef5d8f 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -94,6 +94,10 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { clearWebPreview(); +// QModelIndex sidx = model()->index(start, 0); +// QModelIndex eidx = model()->index(end, 0); +// qDebug() << "rowsInserted" << start << end << "-" << sidx.data(MessageModel::MsgIdRole).value() << eidx.data(MessageModel::MsgIdRole).value(); + qreal h = 0; qreal y = _sceneRect.y(); qreal width = _sceneRect.width(); @@ -101,12 +105,15 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { bool atBottom = false; bool moveTop = false; - if(start > 0) { - y = _lines.value(start - 1)->y() + _lines.value(start - 1)->height(); + if(start > 0 && start < _lines.count()) { + y = _lines.value(start)->y(); atTop = false; } - if(start == _lines.count()) + if(start == _lines.count()) { + y = _sceneRect.bottom(); + atTop = false; atBottom = true; + } qreal contentsWidth = width - secondColumnHandle()->sceneRight(); qreal senderWidth = secondColumnHandle()->sceneLeft() - firstColumnHandle()->sceneRight(); @@ -114,20 +121,14 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { QPointF contentsPos(secondColumnHandle()->sceneRight(), 0); QPointF senderPos(firstColumnHandle()->sceneRight(), 0); - - for(int i = end; i >= start; i--) { + for(int i = start; i <= end; i++) { ChatLine *line = new ChatLine(i, model(), width, timestampWidth, senderWidth, contentsWidth, senderPos, contentsPos); - if(atTop) { - h -= line->height(); - line->setPos(0, y+h); - } else { - line->setPos(0, y+h); - h += line->height(); - } - _lines.insert(start, line); + line->setPos(0, y+h); + h += line->height(); + _lines.insert(i, line); addItem(line); } @@ -150,8 +151,9 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { qreal offset = h; int moveStart = 0; int moveEnd = _lines.count() - 1; - ChatLine *line = 0; - if(end > _lines.count() - end) { + // move top means: moving 0 to end (aka: end + 1) + // move top means: moving end + 1 to _lines.count() - 1 (aka: _lines.count() - (end + 1) + if(end + 1 < _lines.count() - end - 1) { // move top part moveTop = true; offset = -offset; @@ -160,6 +162,7 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { // move bottom part moveStart = start; } + ChatLine *line = 0; for(int i = moveStart; i <= moveEnd; i++) { line = _lines.at(i); line->setPos(0, line->pos().y() + offset); @@ -168,7 +171,7 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { // update sceneRect if(atTop || moveTop) { - updateSceneRect(_sceneRect.adjusted(0, h, 0, 0)); + updateSceneRect(_sceneRect.adjusted(0, -h, 0, 0)); } else { updateSceneRect(_sceneRect.adjusted(0, 0, 0, h)); emit lastLineChanged(_lines.last()); @@ -220,8 +223,7 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e qreal offset = h; int moveStart = 0; int moveEnd = _lines.count() - 1; - ChatLine *line = 0; - if(start > _lines.count() - end) { + if(start < _lines.count() - start) { // move top part moveTop = true; moveEnd = start - 1; @@ -230,6 +232,7 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e 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);