X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;f=src%2Fclient%2Fmessagemodel.cpp;h=245a787090f4828be72445ca44ea05e63d343115;hb=5225cf288d73e76905f85380ec52418c3b04efee;hp=940dda2016e44dfbc80169893bb7942f93ad5f5e;hpb=756158351d58ce25857f52589f5f8c42236a1c27;p=quassel.git diff --git a/src/client/messagemodel.cpp b/src/client/messagemodel.cpp index 940dda20..245a7870 100644 --- a/src/client/messagemodel.cpp +++ b/src/client/messagemodel.cpp @@ -51,6 +51,8 @@ bool MessageModel::setData(const QModelIndex &index, const QVariant &value, int return false; } + + bool MessageModel::insertMessage(const Message &msg, bool fakeMsg) { MsgId id = msg.msgId(); int idx = indexForId(id); @@ -66,13 +68,123 @@ bool MessageModel::insertMessage(const Message &msg, bool fakeMsg) { return true; } -void MessageModel::insertMessages(const QList &msglist) { + +void MessageModel::insertMessageGroup(const QList &msglist) { if(msglist.isEmpty()) return; - // FIXME make this more efficient by grouping msgs - foreach(Message msg, msglist) - insertMessage(msg); + + int idx = indexForId(msglist.first().msgId()); + beginInsertRows(QModelIndex(), idx, idx+msglist.count()-1); + + foreach(Message msg, msglist) { + _messageList.insert(idx, createMessageModelItem(msg)); + idx++; + } + + endInsertRows(); } + +void MessageModel::insertMessages(const QList &msglist) { + if(msglist.isEmpty()) + return; + + if(_messageList.isEmpty()) { + insertMessageGroup(msglist); + return; + } + + bool inOrder = (msglist.first().msgId() < msglist.last().msgId()); + + // check if the whole bunch fits in at one position + if(indexForId(msglist.first().msgId()) == indexForId(msglist.last().msgId())) { + if(inOrder) { + insertMessageGroup(msglist); + } else { + QList messages = msglist; + qSort(messages); + insertMessageGroup(messages); + } + return; + } + + // depending on the order we have to traverse from the front to the back or vice versa + // for the sake of performance we have a little code duplication here + // if you need to do some changes here you'll probably need to change them at all + // places marked DUPE + + + // FIXME: keep scrollbars from jumping + // the somewhat bulk insert leads to a jumpy scrollbar when the user requests further backlog. + // it would probably be the best to stop processing each time we actually insert a messagegroup + // and give back controll to the eventloop (similar to what the QtUiMessageProcessor used to do) + QList grouplist; + MsgId id; + bool fastForward = false; + QList::const_iterator iter; + if(inOrder) { + iter = msglist.constEnd(); + iter--; // this op is safe as we've allready passed an empty check + } else { + iter = msglist.constBegin(); + } + + // DUPE (1 / 3) + int idx = indexForId((*iter).msgId()); + // we always compare to the previous entry... + // if there isn't, we can fastforward to the top + if(idx - 1 >= 0) // also safe as we've passed another empty check + id = _messageList[idx - 1]->msgId(); + else + fastForward = true; + grouplist << *iter; + + if(!inOrder) + iter++; + + if(inOrder) { + while(iter != msglist.constBegin()) { + iter--; + // DUPE (2 / 3) + if(!fastForward && (*iter).msgId() < id) { + insertMessageGroup(grouplist); + grouplist.clear(); + + // build new group + int idx = indexForId((*iter).msgId()); + if(idx - 1 >= 0) + id = _messageList[idx - 1]->msgId(); + else + fastForward = true; + } + grouplist.prepend(*iter); + } + } else { + while(iter != msglist.constEnd()) { + // DUPE (3 / 3) + if(!fastForward && (*iter).msgId() < id) { + insertMessageGroup(grouplist); + grouplist.clear(); + + // build new group + int idx = indexForId((*iter).msgId()); + if(idx - 1 >= 0) + id = _messageList[idx - 1]->msgId(); + else + fastForward = true; + } + grouplist.prepend(*iter); + iter++; + } + } + + if(!grouplist.isEmpty()) { + insertMessageGroup(grouplist); + } + + return; +} + + void MessageModel::clear() { beginRemoveRows(QModelIndex(), 0, rowCount() - 1); qDeleteAll(_messageList); @@ -80,6 +192,7 @@ void MessageModel::clear() { endRemoveRows(); } + // 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; @@ -119,3 +232,20 @@ QVariant MessageModelItem::data(int column, int role) const { } } + +// Stuff for later +bool MessageModelItem::lessThan(const MessageModelItem *m1, const MessageModelItem *m2){ + return (*m1) < (*m2); +} + +bool MessageModelItem::operator<(const MessageModelItem &other) const { + return _msgId < other._msgId; +} + +bool MessageModelItem::operator==(const MessageModelItem &other) const { + return _msgId == other._msgId; +} + +bool MessageModelItem::operator>(const MessageModelItem &other) const { + return _msgId > other._msgId; +}