void clearLayout();
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ enum { Type = ChatScene::ChatItemType };
+ virtual inline int type() const { return Type; }
QVariant data(int role) const;
class TimestampChatItem : public ChatItem {
public:
TimestampChatItem(const qreal &width, const qreal &height, QGraphicsItem *parent) : ChatItem(width, height, QPointF(0, 0), parent) {}
+ enum { Type = ChatScene::TimestampChatItemType };
+ virtual inline int type() const { return Type; }
virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::TimestampColumn; }
};
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ enum { Type = ChatScene::SenderChatItemType };
+ virtual inline int type() const { return Type; }
virtual inline ChatItemPrivate *newPrivateData() { return new ChatItemPrivate(createLayout(QTextOption::ManualWrap, Qt::AlignRight)); }
};
public:
ContentsChatItem(const qreal &width, const QPointF &pos, QGraphicsItem *parent);
+ enum { Type = ChatScene::ContentsChatItemType };
+ virtual inline int type() const { return Type; }
+
inline ChatLineModel::ColumnType column() const { return ChatLineModel::ContentsColumn; }
inline QFontMetricsF *fontMetrics() const { return _fontMetrics; }
#include "chatlinemodel.h"
#include "chatitem.h"
+#include "chatscene.h"
class ChatLine : public QGraphicsItem {
public:
inline ContentsChatItem &contentsItem() { return _contentsItem; }
virtual void paint (QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ enum { Type = ChatScene::ChatLineType };
+ virtual inline int type() const { return Type; }
void setFirstColumn(const qreal ×tampWidth, const qreal &senderWidth, const QPointF &senderPos);
// setSecondColumn and setGeometryByWidth both also relocate the chatline.
updateSceneRect(width);
setHandleXLimits();
+ emit layoutChanged();
// clock_t endT = clock();
// qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
}
//setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+ updateSceneRect();
setHandleXLimits();
+ emit layoutChanged();
// clock_t endT = clock();
// qDebug() << "resized" << _lines.count() << "in" << (float)(endT - startT) / CLOCKS_PER_SEC << "sec";
CutoffRight
};
+ enum ItemType {
+ ChatLineType = QGraphicsItem::UserType + 1,
+ ChatItemType,
+ TimestampChatItemType,
+ SenderChatItemType,
+ ContentsChatItemType,
+ SearchHighlightType,
+ WebPreviewType
+ };
+
ChatScene(QAbstractItemModel *model, const QString &idString, qreal width, QObject *parent);
virtual ~ChatScene();
signals:
void lastLineChanged(QGraphicsItem *item, qreal offset);
+ void layoutChanged(); // indicates changes to the scenerect due to resizing of the contentsitems
protected:
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
return;
connect(_scene, SIGNAL(destroyed()), this, SLOT(sceneDestroyed()));
+ connect(_scene, SIGNAL(layoutChanged()), this, SLOT(repositionHighlights()));
updateHighlights();
}
}
}
+void ChatViewSearchController::repositionHighlights() {
+ QSet<ChatLine *> chatLines;
+ foreach(SearchHighlightItem *item, _highlightItems) {
+ ChatLine *line = qgraphicsitem_cast<ChatLine *>(item->parentItem());
+ if(line)
+ chatLines << line;
+ }
+ QList<ChatLine *> chatLineList(chatLines.toList());
+ foreach(ChatLine *line, chatLineList) {
+ repositionHighlights(line);
+ }
+}
+
+void ChatViewSearchController::repositionHighlights(ChatLine *line) {
+ QList<SearchHighlightItem *> searchHighlights;
+ foreach(QGraphicsItem *child, line->childItems()) {
+ SearchHighlightItem *highlightItem = qgraphicsitem_cast<SearchHighlightItem *>(child);
+ if(highlightItem)
+ searchHighlights << highlightItem;
+ }
+
+ if(searchHighlights.isEmpty())
+ return;
+
+ QList<QPointF> wordPos;
+ if(_searchSenders) {
+ foreach(QRectF wordRect, line->senderItem().findWords(searchString(), caseSensitive())) {
+ wordPos << QPointF(wordRect.x() + line->senderItem().x(), wordRect.y());
+ }
+ }
+ if(_searchMsgs) {
+ foreach(QRectF wordRect, line->contentsItem().findWords(searchString(), caseSensitive())) {
+ wordPos << QPointF(wordRect.x() + line->contentsItem().x(), wordRect.y());
+ }
+ }
+
+ qSort(searchHighlights.begin(), searchHighlights.end(), SearchHighlightItem::firstInLine);
+
+ Q_ASSERT(wordPos.count() == searchHighlights.count());
+ for(int i = 0; i < searchHighlights.count(); i++) {
+ searchHighlights.at(i)->setPos(wordPos.at(i));
+ }
+}
+
void ChatViewSearchController::sceneDestroyed() {
// WARNING: don't call any methods on scene!
_scene = 0;
qreal radius = boundingRect().height() * 0.30;
painter->drawRoundedRect(boundingRect(), radius, radius);
}
+
+bool SearchHighlightItem::firstInLine(QGraphicsItem *item1, QGraphicsItem *item2) {
+ if(item1->pos().y() != item2->pos().y())
+ return item1->pos().y() < item2->pos().y();
+ else
+ return item1->pos().x() < item2->pos().x();
+}
#include <QString>
#include <QTimeLine>
+#include "chatscene.h"
#include "message.h"
class QGraphicsItem;
void sceneDestroyed();
void updateHighlights(bool reuse = false);
+ void repositionHighlights();
+ void repositionHighlights(ChatLine *line);
+
signals:
void newCurrentHighlight(QGraphicsItem *highlightItem);
public:
SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent = 0);
- inline virtual QRectF boundingRect() const { return _boundingRect; }
+ virtual inline QRectF boundingRect() const { return _boundingRect; }
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+ enum { Type = ChatScene::SearchHighlightType };
+ virtual inline int type() const { return Type; }
+
void setHighlighted(bool highlighted);
+ static bool firstInLine(QGraphicsItem *item1, QGraphicsItem *item2);
+
private slots:
void updateHighlight(qreal value);