1 /***************************************************************************
2 * Copyright (C) 2005-08 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include "chatviewsearchcontroller.h"
23 #include <QAbstractItemModel>
27 #include "chatlinemodel.h"
28 #include "chatscene.h"
29 #include "messagemodel.h"
31 ChatViewSearchController::ChatViewSearchController(QObject *parent)
34 _caseSensitive(false),
35 _searchSenders(false),
37 _searchOnlyRegularMsgs(true)
41 void ChatViewSearchController::setSearchString(const QString &searchString) {
42 QString oldSearchString = _searchString;
43 _searchString = searchString;
45 if(!searchString.startsWith(oldSearchString) || oldSearchString.isEmpty()) {
46 // we can't reuse our all findings... cler the scene and do it all over
50 updateHighlights(true);
55 void ChatViewSearchController::setScene(ChatScene *scene) {
61 disconnect(_scene, 0, this, 0);
62 qDeleteAll(_highlightItems);
63 _highlightItems.clear();
70 connect(_scene, SIGNAL(destroyed()), this, SLOT(sceneDestroyed()));
76 void ChatViewSearchController::updateHighlights(bool reuse) {
80 QAbstractItemModel *model = _scene->model();
84 QList<ChatLine *> chatLines;
86 foreach(SearchHighlightItem *highlightItem, _highlightItems) {
87 ChatLine *line = dynamic_cast<ChatLine *>(highlightItem->parentItem());
88 if(!line || chatLines.contains(line))
94 qDeleteAll(_highlightItems);
95 _highlightItems.clear();
96 Q_ASSERT(_highlightItems.isEmpty());
98 if(searchString().isEmpty() || !(_searchSenders || _searchMsgs))
103 foreach(ChatLine *line, chatLines) {
104 if(_searchOnlyRegularMsgs) {
105 index = model->index(line->row(), 0);
106 if(!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt()))
112 // we have to crawl through the data
115 int rowCount = model->rowCount();
116 for(int row = 0; row < rowCount; row++) {
117 ChatLine *line = _scene->chatLine(row);
119 if(_searchOnlyRegularMsgs) {
120 index = model->index(row, 0);
121 if(!checkType((Message::Type)index.data(MessageModel::TypeRole).toInt()))
129 void ChatViewSearchController::highlightLine(ChatLine *line) {
130 QList<ChatItem *> checkItems;
132 checkItems << &(line->item(MessageModel::SenderColumn));
135 checkItems << &(line->item(MessageModel::ContentsColumn));
137 foreach(ChatItem *item, checkItems) {
138 foreach(QRectF wordRect, item->findWords(searchString(), caseSensitive())) {
139 _highlightItems << new SearchHighlightItem(wordRect.adjusted(item->x(), 0, item->x(), 0), line);
144 void ChatViewSearchController::sceneDestroyed() {
145 // WARNING: don't call any methods on scene!
147 // the items will be automatically deleted when the scene is destroyed
148 // so we just have to clear the list;
149 _highlightItems.clear();
152 void ChatViewSearchController::setCaseSensitive(bool caseSensitive) {
153 if(_caseSensitive == caseSensitive)
156 _caseSensitive = caseSensitive;
158 // we can reuse the original search results if the new search
159 // parameters are a restriction of the original one
160 updateHighlights(caseSensitive);
163 void ChatViewSearchController::setSearchSenders(bool searchSenders) {
164 if(_searchSenders == searchSenders)
167 _searchSenders = searchSenders;
168 // we can reuse the original search results if the new search
169 // parameters are a restriction of the original one
170 updateHighlights(!searchSenders);
173 void ChatViewSearchController::setSearchMsgs(bool searchMsgs) {
174 if(_searchMsgs == searchMsgs)
177 _searchMsgs = searchMsgs;
179 // we can reuse the original search results if the new search
180 // parameters are a restriction of the original one
181 updateHighlights(!searchMsgs);
184 void ChatViewSearchController::setSearchOnlyRegularMsgs(bool searchOnlyRegularMsgs) {
185 if(_searchOnlyRegularMsgs == searchOnlyRegularMsgs)
188 _searchOnlyRegularMsgs = searchOnlyRegularMsgs;
190 // we can reuse the original search results if the new search
191 // parameters are a restriction of the original one
192 updateHighlights(searchOnlyRegularMsgs);
195 SearchHighlightItem::SearchHighlightItem(QRectF wordRect, QGraphicsItem *parent)
196 : QGraphicsItem(parent),
197 _boundingRect(QRectF(-wordRect.width() / 2, -wordRect.height() / 2, wordRect.width(), wordRect.height()))
199 setPos(wordRect.x() + wordRect.width() / 2 , wordRect.y() + wordRect.height() / 2);
203 void SearchHighlightItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
207 painter->setPen(QPen(Qt::black, 1.5));
208 //painter->setBrush(QColor(127, 133, 250));
209 painter->setBrush(QColor(254, 237, 45));
210 painter->setRenderHints(QPainter::Antialiasing);
211 painter->drawRoundedRect(boundingRect(), 30, 30, Qt::RelativeSize);