X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fqtui%2Fchatscene.cpp;h=d78ee1c825eede84a29e4a6c9579da0c697294eb;hp=3f0b18de658647e143bf6ec1258bb51cf6b21be2;hb=894e2dd800e90ab52618fa620b1c995545506574;hpb=442f91e70e3b4422948758e696b5e3c4b323bdc1 diff --git a/src/qtui/chatscene.cpp b/src/qtui/chatscene.cpp index 3f0b18de..d78ee1c8 100644 --- a/src/qtui/chatscene.cpp +++ b/src/qtui/chatscene.cpp @@ -46,6 +46,8 @@ #include "columnhandleitem.h" #include "contextmenuactionprovider.h" #include "iconloader.h" +#include "mainwin.h" +#include "markerlineitem.h" #include "messagefilter.h" #include "qtui.h" #include "qtuistyle.h" @@ -63,6 +65,9 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _sceneRect(0, 0, width, 0), _firstLineRow(-1), _viewportHeight(0), + _markerLine(new MarkerLineItem(width)), + _markerLineValid(false), + _markerLineVisible(false), _cutoffMode(CutoffRight), _selectingItem(0), _selectionStart(-1), @@ -76,6 +81,9 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w _singleBufferId = filter->singleBufferId(); } + addItem(_markerLine); + connect(this, SIGNAL(sceneRectChanged(const QRectF &)), _markerLine, SLOT(sceneRectChanged(const QRectF &))); + ChatViewSettings defaultSettings; int defaultFirstColHandlePos = defaultSettings.value("FirstColumnHandlePos", 80).toInt(); int defaultSecondColHandlePos = defaultSettings.value("SecondColumnHandlePos", 200).toInt(); @@ -106,6 +114,8 @@ ChatScene::ChatScene(QAbstractItemModel *model, const QString &idString, qreal w this, SLOT(rowsInserted(const QModelIndex &, int, int))); connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int))); + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(rowsRemoved())); connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(dataChanged(QModelIndex, QModelIndex))); #ifdef HAVE_WEBKIT @@ -137,10 +147,51 @@ ColumnHandleItem *ChatScene::secondColumnHandle() const { return _secondColHandle; } +ChatLine *ChatScene::chatLine(MsgId msgId, bool matchExact) const { + if(!_lines.count()) + return 0; + + QList::ConstIterator start = _lines.begin(); + QList::ConstIterator end = _lines.end(); + QList::ConstIterator middle; + + int n = int(end - start); + int half; + + while(n > 0) { + half = n >> 1; + middle = start + half; + if((*middle)->msgId() < msgId) { + start = middle + 1; + n -= half + 1; + } else { + n = half; + } + } + + if(start != end && (*start)->msgId() == msgId) + return *start; + + if(matchExact) + 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 + return 0; + + // return the next-lower line + return *(--start); +} + 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; } @@ -152,6 +203,35 @@ bool ChatScene::containsBuffer(const BufferId &id) const { 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(msgId.isValid()) { + ChatLine *line = chatLine(msgId, false); + if(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); + return; + } + } + } + _markerLineValid = false; + _markerLine->setVisible(false); +} + void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { Q_UNUSED(index); @@ -282,6 +362,14 @@ void ChatScene::rowsInserted(const QModelIndex &index, int start, int end) { if(atBottom) { emit lastLineChanged(_lines.last(), h); } + + // 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); + } + } } void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { @@ -375,6 +463,14 @@ void ChatScene::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e updateSceneRect(); } +void ChatScene::rowsRemoved() { + // move the marker line if necessary + if(isSingleBufferScene()) { + MsgId msgId = Client::markerLine(singleBufferId()); + setMarkerLine(msgId); + } +} + void ChatScene::dataChanged(const QModelIndex &tl, const QModelIndex &br) { layout(tl.row(), br.row(), _sceneRect.width()); }