ChatViewSearchController::ChatViewSearchController(QObject *parent)
: QObject(parent),
_scene(0),
+ _currentHighlight(0),
_caseSensitive(false),
_searchSenders(false),
_searchMsgs(true),
return;
connect(_scene, SIGNAL(destroyed()), this, SLOT(sceneDestroyed()));
+ connect(_scene, SIGNAL(layoutChanged()), this, SLOT(repositionHighlights()));
updateHighlights();
}
+void ChatViewSearchController::highlightNext() {
+ if(_highlightItems.isEmpty())
+ return;
+
+ if(_currentHighlight < _highlightItems.count()) {
+ _highlightItems.at(_currentHighlight)->setHighlighted(false);
+ }
+ _currentHighlight++;
+ if(_currentHighlight >= _highlightItems.count())
+ _currentHighlight = 0;
+ _highlightItems.at(_currentHighlight)->setHighlighted(true);
+ emit newCurrentHighlight(_highlightItems.at(_currentHighlight));
+}
+
+void ChatViewSearchController::highlightPrev() {
+ if(_highlightItems.isEmpty())
+ return;
+
+ if(_currentHighlight < _highlightItems.count()) {
+ _highlightItems.at(_currentHighlight)->setHighlighted(false);
+ }
+
+ _currentHighlight--;
+ if(_currentHighlight < 0)
+ _currentHighlight = _highlightItems.count() - 1;
+ _highlightItems.at(_currentHighlight)->setHighlighted(true);
+ emit newCurrentHighlight(_highlightItems.at(_currentHighlight));
+}
void ChatViewSearchController::updateHighlights(bool reuse) {
if(!_scene)
highlightLine(line);
}
}
+
+ if(!_highlightItems.isEmpty()) {
+ _highlightItems.last()->setHighlighted(true);
+ _currentHighlight = _highlightItems.count() - 1;
+ emit newCurrentHighlight(_highlightItems.last());
+ }
}
void ChatViewSearchController::highlightLine(ChatLine *line) {
}
}
+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;
updateHighlights(searchOnlyRegularMsgs);
}
+
+// ==================================================
+// SearchHighlightItem
+// ==================================================
SearchHighlightItem::SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent)
- : QGraphicsItem(parent),
- _boundingRect(QRectF(-wordRect.width() / 2, -wordRect.height() / 2, wordRect.width(), wordRect.height()))
+ : QObject(),
+ QGraphicsItem(parent),
+ _highlighted(false),
+ _alpha(100),
+ _timeLine(150)
{
- setPos(wordRect.x() + wordRect.width() / 2 , wordRect.y() + wordRect.height() / 2);
- scale(1.2, 1.2);
+ setPos(wordRect.x(), wordRect.y());
+ qreal sizedelta = wordRect.height() * 0.1;
+ _boundingRect = QRectF(-sizedelta, -sizedelta, wordRect.width() + 2 * sizedelta, wordRect.height() + 2 * sizedelta);
+
+ connect(&_timeLine, SIGNAL(valueChanged(qreal)), this, SLOT(updateHighlight(qreal)));
+}
+
+void SearchHighlightItem::setHighlighted(bool highlighted) {
+ _highlighted = highlighted;
+
+ if(highlighted)
+ _timeLine.setDirection(QTimeLine::Forward);
+ else
+ _timeLine.setDirection(QTimeLine::Backward);
+
+ if(_timeLine.state() != QTimeLine::Running)
+ _timeLine.start();
+
+ update();
+}
+
+void SearchHighlightItem::updateHighlight(qreal value) {
+ _alpha = 100 + 155 * value;
+ update();
}
void SearchHighlightItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
Q_UNUSED(option);
Q_UNUSED(widget);
- painter->setPen(QPen(Qt::black, 1.5));
- //painter->setBrush(QColor(127, 133, 250));
- painter->setBrush(QColor(254, 237, 45));
+ painter->setPen(QPen(QColor(0, 0, 0, _alpha), 1.5));
+ painter->setBrush(QColor(254, 237, 45, _alpha));
painter->setRenderHints(QPainter::Antialiasing);
- painter->drawRoundedRect(boundingRect(), 30, 30, Qt::RelativeSize);
+ 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();
}