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) {
qSort(_messageBuffer);
QCoreApplication::postEvent(this, new ProcessBufferEvent());
}
- }
+// }
}
void MessageModel::insertMessageGroup(const QList<Message> &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();
}
}
int idx = indexForId((*iter).msgId());
- if(idx >= 0)
+ if(idx >= 0 && !_messageList.isEmpty())
dupeId = _messageList[idx]->msgId();
// we always compare to the previous entry...
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++;
}
// 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<MsgId>()) return 0;
- if(id > _messageList.last()->data(0, MsgIdRole).value<MsgId>()) 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<MsgId>()) end = pivot;
+ if(id <= _messageList.value(pivot)->msgId()) end = pivot;
else start = pivot;
}
}
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
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; }
clearWebPreview();
+// QModelIndex sidx = model()->index(start, 0);
+// QModelIndex eidx = model()->index(end, 0);
+// qDebug() << "rowsInserted" << start << end << "-" << sidx.data(MessageModel::MsgIdRole).value<MsgId>() << eidx.data(MessageModel::MsgIdRole).value<MsgId>();
+
qreal h = 0;
qreal y = _sceneRect.y();
qreal width = _sceneRect.width();
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();
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);
}
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;
// 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);
// 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());
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;
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);