1 #include "yacreader_search_line_edit.h"
2 
3 #include <QToolButton>
4 #include <QStyle>
5 #include <QLabel>
6 
7 #include <QRegExpValidator>
8 
9 #include "QsLog.h"
10 
YACReaderSearchLineEdit(QWidget * parent)11 YACReaderSearchLineEdit::YACReaderSearchLineEdit(QWidget *parent)
12     : QLineEdit(parent)
13 {
14     clearButton = new QToolButton(this);
15     searchLabel = new QLabel(this);
16 
17     QPixmap pixmap(":/images/clearSearch.png");
18     QPixmap pixmapIcon(":/images/iconSearch.png");
19 
20     searchLabel->setStyleSheet("QLabel { border: none; padding: 0px; }");
21     searchLabel->setPixmap(pixmapIcon);
22 
23     clearButton->setIcon(QIcon(pixmap));
24     clearButton->setIconSize(pixmap.size());
25     clearButton->setCursor(Qt::ArrowCursor);
26     clearButton->setStyleSheet("QToolButton { border: none; padding: 0px; }");
27     clearButton->hide();
28     connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
29     connect(this, SIGNAL(textChanged(const QString &)), this, SLOT(updateCloseButton(const QString &)));
30     int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
31 #ifdef Q_OS_MAC
32     setStyleSheet(QString("QLineEdit {border-top:1px solid #9F9F9F; border-bottom:1px solid #ACACAC; border-right:1px solid #ACACAC; border-left:1px solid #ACACAC; border-radius: 10px; background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #CACACA, stop: 0.15 #FFFFFF); padding-left: %1px; padding-right: %2px; padding-bottom: 1px; margin-bottom: 1px;} ").arg(searchLabel->sizeHint().width() + frameWidth + 6).arg(clearButton->sizeHint().width() + frameWidth + 2));
33 #else
34     setStyleSheet(QString("QLineEdit {color: #ABABAB; border:none; border-radius: 4px; background-color:#404040; padding-left: %1px; padding-right: %2px; padding-bottom: 1px; margin-right: 9px;} ").arg(searchLabel->sizeHint().width() + frameWidth + 6 + 5).arg(clearButton->sizeHint().width() + frameWidth + 2));
35 #endif
36     QSize msz = minimumSizeHint();
37     setMinimumSize(qMax(msz.width(), clearButton->sizeHint().height() + frameWidth * 2 + 2),
38                    qMax(msz.height(), clearButton->sizeHint().height() + frameWidth * 2 + 2));
39 
40 #ifdef Q_OS_MAC
41     setMaximumWidth(212);
42 #else
43     setMaximumWidth(255);
44     setFixedHeight(26);
45 #endif
46 
47     setAttribute(Qt::WA_MacShowFocusRect, false);
48     setPlaceholderText(tr("type to search"));
49 
50     //search modifiers
51     modifiers << "[read]"
52               << "[unread]"; //<< "[author]";
53     modifiersCompleter = new QCompleter(modifiers);
54 
55     QString regExpString;
56     foreach (QString modifier, modifiers) {
57         regExpString = regExpString + modifier.replace("[", "\\[").replace("]", "\\]") + ".*|";
58     }
59 
60     regExpString = regExpString + "[^\\[].*";
61 
62     QLOG_TRACE() << regExpString;
63 
64     QRegExp regExp(regExpString);
65     QValidator *validator = new QRegExpValidator(regExp, this);
66 
67     setValidator(validator);
68     setCompleter(modifiersCompleter);
69 
70     connect(this, SIGNAL(textChanged(QString)), this, SLOT(processText(QString)));
71 }
72 
clearText()73 void YACReaderSearchLineEdit::clearText()
74 {
75     disconnect(this, SIGNAL(textChanged(QString)), this, SLOT(processText(QString)));
76     clear();
77     connect(this, SIGNAL(textChanged(QString)), this, SLOT(processText(QString)));
78 }
79 
80 //modifiers are not returned
text()81 const QString YACReaderSearchLineEdit::text()
82 {
83     QString text = QLineEdit::text();
84 
85     QRegExp regExp("\\[.*\\]");
86     return text.remove(regExp).trimmed();
87 }
88 
resizeEvent(QResizeEvent *)89 void YACReaderSearchLineEdit::resizeEvent(QResizeEvent *)
90 {
91 #ifdef Q_OS_MAC
92     QSize sz = clearButton->sizeHint();
93     int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
94     clearButton->move(rect().right() - frameWidth - sz.width(),
95                       (rect().bottom() + 1 - sz.height()) / 2);
96 
97     QSize szl = searchLabel->sizeHint();
98     searchLabel->move(6, (rect().bottom() + 1 - szl.height()) / 2);
99 #else
100     QSize sz = clearButton->sizeHint();
101     int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
102     int marginRight = style()->pixelMetric(QStyle::PM_LayoutRightMargin);
103     clearButton->move(rect().right() - frameWidth - sz.width() - marginRight - 6,
104                       (rect().bottom() + 2 - sz.height()) / 2);
105 
106     QSize szl = searchLabel->sizeHint();
107     searchLabel->move(8, (rect().bottom() + 2 - szl.height()) / 2);
108 #endif
109 }
110 
updateCloseButton(const QString & text)111 void YACReaderSearchLineEdit::updateCloseButton(const QString &text)
112 {
113     clearButton->setVisible(!text.isEmpty());
114 }
115 
processText(const QString & text)116 void YACReaderSearchLineEdit::processText(const QString &text)
117 {
118 
119     QRegExp regExp("(\\[.*\\])(.*)");
120     if (text.startsWith("[")) {
121         if (regExp.exactMatch(text)) //avoid search while the modifiers are being written
122         {
123             QString modifier = regExp.cap(1);
124             QString searchText = regExp.cap(2).trimmed();
125 
126             int indexOfModifier = modifiers.indexOf(modifier);
127             if (indexOfModifier != -1) {
128                 QLOG_TRACE() << "modifier : " << modifier << "text : " << searchText;
129                 emit filterChanged(static_cast<YACReader::SearchModifiers>(indexOfModifier + 1), searchText); //TODO, do not use on indexOF
130             } else {
131                 QLOG_ERROR() << "invalid modifier : " << modifier;
132             }
133         }
134 
135         QLOG_TRACE() << "full text :" << text << " : " << regExp.indexIn(text);
136     } else {
137         QLOG_TRACE() << "NoModifiers : " << text;
138         emit filterChanged(YACReader::NoModifiers, text);
139     }
140 }
141