X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fchatscene.cpp;h=6a9f926abd9a64cbbeef36c6b5944bc6bd68b5bb;hp=46cfc3ebe94a2d38ce83ff715c6e017f506affc3;hb=9cb22a9cccbdf2bd71568ec3989d41ca167326da;hpb=6e73ba4a19fd92038e1ea749125767661fb34e27 diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index 46cfc3eb..6a9f926a 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2010 by the Quassel Project * + * Copyright (C) 2005-2013 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -24,6 +24,7 @@ #include #include #include +#include #include #ifdef HAVE_KDE @@ -66,8 +67,9 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _firstLineRow(-1), _viewportHeight(0), _markerLine(new MarkerLineItem(width)), - _markerLineValid(false), _markerLineVisible(false), + _markerLineValid(false), + _markerLineJumpPending(false), _cutoffMode(CutoffRight), _selectingItem(0), _selectionStart(-1), @@ -147,7 +149,7 @@ ColumnHandleItem *ChatScene::secondColumnHandle() const { return _secondColHandle; } -ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact) const { +ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact, bool ignoreDayChange) const { if(!_lines.count()) return 0; @@ -169,27 +171,45 @@ ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact) const { } } - if(start != end && (*start)->msgId() == msgId) + if(start != end && (*start)->msgId() == msgId && (ignoreDayChange? (*start)->msgType() != Message::DayChange : true)) return *start; if(matchExact) return 0; + if(start == _lines.begin()) // not (yet?) in our scene + return 0; + // if we didn't find the exact msgId, take the next-lower one (this makes sense for lastSeen) - if(start == end) // higher than last element - return _lines.last(); - if(start == _lines.begin()) // not (yet?) in our scene + if(start == end) { // higher than last element + if(!ignoreDayChange) + return _lines.last(); + + for(int i = _lines.count() -1; i >= 0; i--) { + if(_lines.at(i)->msgType() != Message::DayChange) + return _lines.at(i); + } return 0; + } // return the next-lower line - return *(--start); + if(!ignoreDayChange) + return *(--start); + + do { + if((*(--start))->msgType() != Message::DayChange) + return *start; + } while(start != _lines.begin()); + return 0; } ChatItem *ChatScene::chatItemAt(const QPointF &scenePos) const { - ChatLine *line = qgraphicsitem_cast(itemAt(scenePos)); - if(line) - return line->itemAt(line->mapFromScene(scenePos)); + foreach(QGraphicsItem *item, items(scenePos, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder)) { + ChatLine *line = qgraphicsitem_cast(item); + if(line) + return line->itemAt(line->mapFromScene(scenePos)); + } return 0; } @@ -204,36 +224,71 @@ bool ChatScene::containsBuffer(const BufferId &id) const { void ChatScene::setMarkerLineVisible(bool visible) { _markerLineVisible = visible; if(visible && _markerLineValid) - _markerLine->setVisible(true); + markerLine()->setVisible(true); else - _markerLine->setVisible(false); + 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); + 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())); + 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()) { + if(markerLine()->pos().y() >= sceneRect().y()) { _markerLineValid = true; if(_markerLineVisible) - _markerLine->setVisible(true); + markerLine()->setVisible(true); + if(_markerLineJumpPending) { + _markerLineJumpPending = false; + if(markerLine()->isVisible()) { + markerLine()->ensureVisible(QRectF(), 50, 50); + } + } return; } } } _markerLineValid = false; - _markerLine->setVisible(false); + markerLine()->setVisible(false); +} + +void ChatScene::jumpToMarkerLine(bool requestBacklog) { + if(!isSingleBufferScene()) + return; + + if(markerLine()->isVisible()) { + markerLine()->ensureVisible(QRectF(), 50, 50); + return; + } + if(!_markerLineValid && requestBacklog) { + MsgId msgId = Client::markerLine(singleBufferId()); + if(msgId.isValid()) { + _markerLineJumpPending = true; + Client::backlogManager()->requestBacklog(singleBufferId(), msgId, -1, -1, 0); + + // If we filtered out the lastSeenMsg (by changing filters after setting it), we'd never jump because the above request + // won't fetch any prior lines. Thus, trigger a dynamic backlog request just in case, so repeated + // jump tries will eventually cause enough backlog to be fetched. + // This is a bit hackish, but not wasteful, as jumping to the top of the ChatView would trigger a dynamic fetch anyway. + this->requestBacklog(); + } + } } 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:"; @@ -321,6 +376,8 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { for(int i = 0; i <= end; i++) { line = _lines.at(i); line->setPos(0, line->pos().y() - h); + if(line == markerLine()->chatLine()) + markerLine()->setPos(line->pos() + QPointF(0, line->height())); } } @@ -362,12 +419,8 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { } // now move the marker line if necessary. we don't need to do anything if we appended lines though... - if(isSingleBufferScene()) { - if(!_markerLineValid || !atBottom) { - MsgId msgId = Client::markerLine(singleBufferId()); - setMarkerLine(msgId); - } - } + if(!_markerLineValid) + setMarkerLine(); } void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { @@ -377,7 +430,6 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e bool atTop = (start == 0); bool atBottom = (end == _lines.count() - 1); - bool moveTop = false; // clear selection if(_selectingItem) { @@ -390,6 +442,8 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e QList::iterator lineIter = _lines.begin() + start; int lineCount = start; while(lineIter != _lines.end() && lineCount <= end) { + if((*lineIter) == markerLine()->chatLine()) + markerLine()->setChatLine(0); h += (*lineIter)->height(); delete *lineIter; lineIter = _lines.erase(lineIter); @@ -405,7 +459,7 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e if(_selectionStart >= 0) { int offset = end - start + 1; if(_selectionStart >= start) - _selectionStart = qMax(_selectionStart -= offset, start); + _selectionStart = qMax(_selectionStart - offset, start); if(_selectionEnd >= start) _selectionEnd -= offset; if(_firstSelectionRow >= start) @@ -424,7 +478,6 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e int moveEnd = _lines.count() - 1; if(start < _lines.count() - start) { // move top part - moveTop = true; moveEnd = start - 1; } else { // move bottom part @@ -463,10 +516,7 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e void ChatScene::rowsRemoved() { // move the marker line if necessary - if(isSingleBufferScene()) { - MsgId msgId = Client::markerLine(singleBufferId()); - setMarkerLine(msgId); - } + setMarkerLine(); } void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br) { @@ -516,6 +566,7 @@ void ChatScene::layout(int start, int end, qreal width) { updateSceneRect(width); setHandleXLimits(); + setMarkerLine(); emit layoutChanged(); // clock_t endT = clock(); @@ -965,14 +1016,6 @@ void ChatScene::updateSceneRect(const QRectF &rect) { update(); } -bool ChatScene::event(QEvent *e) { - if(e->type() == QEvent::ApplicationPaletteChange) { - _firstColHandle->setColor(QApplication::palette().windowText().color()); - _secondColHandle->setColor(QApplication::palette().windowText().color()); - } - return QGraphicsScene::event(e); -} - // ======================================== // Webkit Only stuff // ========================================