1 #include "searchlineedit.h"
2 #include "autocomplete.h"
3 #include "iconutils.h"
4
5 class SearchButton : public QAbstractButton {
6 public:
7 SearchButton(QWidget *parent = nullptr);
8 QMenu *m_menu;
9
10 protected:
11 void paintEvent(QPaintEvent *e);
12 void mousePressEvent(QMouseEvent *e);
13 };
14
SearchButton(QWidget * parent)15 SearchButton::SearchButton(QWidget *parent) : QAbstractButton(parent), m_menu(nullptr) {
16 setObjectName(QLatin1String("SearchButton"));
17 setCursor(Qt::ArrowCursor);
18 setFocusPolicy(Qt::NoFocus);
19 }
20
mousePressEvent(QMouseEvent * e)21 void SearchButton::mousePressEvent(QMouseEvent *e) {
22 if (m_menu && e->button() == Qt::LeftButton) {
23 QWidget *p = parentWidget();
24 if (p) {
25 QPoint r = p->mapToGlobal(QPoint(0, p->height()));
26 m_menu->exec(QPoint(r.x() + height() / 2, r.y()));
27 }
28 e->accept();
29 }
30 QAbstractButton::mousePressEvent(e);
31 }
32
paintEvent(QPaintEvent * e)33 void SearchButton::paintEvent(QPaintEvent *e) {
34 Q_UNUSED(e);
35 QPainter painter(this);
36 const int h = height();
37 int iconSize = 16;
38 if (h > 32) iconSize = 22;
39 QPixmap p = IconUtils::icon("edit-find").pixmap(iconSize, iconSize);
40 int x = (width() - p.width() / p.devicePixelRatio()) / 2;
41 int y = (h - p.height() / p.devicePixelRatio()) / 2;
42 painter.drawPixmap(x, y, p);
43 }
44
SearchLineEdit(QWidget * parent)45 SearchLineEdit::SearchLineEdit(QWidget *parent)
46 : ExLineEdit(parent), searchButton(new SearchButton(this)) {
47 connect(m_lineEdit, SIGNAL(textChanged(const QString &)), SIGNAL(textChanged(const QString &)));
48 connect(m_lineEdit, SIGNAL(textEdited(const QString &)), SIGNAL(textEdited(const QString &)));
49 connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(returnPressed()));
50
51 setLeftWidget(searchButton);
52 inactiveText = tr("Search");
53
54 QSizePolicy policy = sizePolicy();
55 setSizePolicy(QSizePolicy::Preferred, policy.verticalPolicy());
56
57 // completion
58 autoComplete = new AutoComplete(this, m_lineEdit);
59 connect(autoComplete, SIGNAL(suggestionAccepted(Suggestion *)),
60 SIGNAL(suggestionAccepted(Suggestion *)));
61 }
62
paintEvent(QPaintEvent * e)63 void SearchLineEdit::paintEvent(QPaintEvent *e) {
64 ExLineEdit::paintEvent(e);
65 if (m_lineEdit->text().isEmpty() && !hasFocus() && !inactiveText.isEmpty()) {
66 QStyleOptionFrame panel;
67 initStyleOption(&panel);
68 QRect r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
69 QFontMetrics fm = fontMetrics();
70 int horizontalMargin = m_lineEdit->x();
71 QRect lineRect(horizontalMargin + r.x(), r.y() + (r.height() - fm.height() + 1) / 2,
72 r.width() - 2 * horizontalMargin, fm.height());
73 QPainter painter(this);
74 painter.setPen(palette().brush(QPalette::Disabled, QPalette::Text).color());
75 painter.drawText(lineRect, Qt::AlignLeft | Qt::AlignVCenter, inactiveText);
76 }
77 }
78
resizeEvent(QResizeEvent * e)79 void SearchLineEdit::resizeEvent(QResizeEvent *e) {
80 updateGeometries();
81 ExLineEdit::resizeEvent(e);
82 }
83
updateGeometries()84 void SearchLineEdit::updateGeometries() {
85 int menuHeight = height();
86 int menuWidth = menuHeight + 1;
87 if (!searchButton->m_menu) menuWidth = (menuHeight / 5) * 4;
88 searchButton->resize(QSize(menuWidth, menuHeight));
89 }
90
setInactiveText(const QString & text)91 void SearchLineEdit::setInactiveText(const QString &text) {
92 inactiveText = text;
93 }
94
setText(const QString & text)95 void SearchLineEdit::setText(const QString &text) {
96 m_lineEdit->setText(text);
97 }
98
getAutoComplete()99 AutoComplete *SearchLineEdit::getAutoComplete() {
100 return autoComplete;
101 }
102
setMenu(QMenu * menu)103 void SearchLineEdit::setMenu(QMenu *menu) {
104 if (searchButton->m_menu) searchButton->m_menu->deleteLater();
105 searchButton->m_menu = menu;
106 updateGeometries();
107 }
108
menu() const109 QMenu *SearchLineEdit::menu() const {
110 if (!searchButton->m_menu) {
111 searchButton->m_menu = new QMenu(searchButton);
112 if (isVisible()) (const_cast<SearchLineEdit *>(this))->updateGeometries();
113 }
114 return searchButton->m_menu;
115 }
116
returnPressed()117 void SearchLineEdit::returnPressed() {
118 QString text = m_lineEdit->text().simplified();
119 if (!text.isEmpty()) {
120 autoComplete->preventSuggest();
121 emit search(text);
122 }
123 }
124
enableSuggest()125 void SearchLineEdit::enableSuggest() {
126 autoComplete->enableSuggest();
127 }
128
preventSuggest()129 void SearchLineEdit::preventSuggest() {
130 autoComplete->preventSuggest();
131 }
132
selectAll()133 void SearchLineEdit::selectAll() {
134 m_lineEdit->selectAll();
135 }
136
setSuggester(Suggester * suggester)137 void SearchLineEdit::setSuggester(Suggester *suggester) {
138 autoComplete->setSuggester(suggester);
139 }
140
focusInEvent(QFocusEvent * e)141 void SearchLineEdit::focusInEvent(QFocusEvent *e) {
142 ExLineEdit::focusInEvent(e);
143 enableSuggest();
144 }
145
emitTextChanged(const QString & text)146 void SearchLineEdit::emitTextChanged(const QString &text) {
147 autoComplete->enableSuggest();
148 emit textEdited(text);
149 }
150
text()151 QString SearchLineEdit::text() {
152 return m_lineEdit->text();
153 }
154
getLineEdit()155 QLineEdit *SearchLineEdit::getLineEdit() {
156 return m_lineEdit;
157 }
158
setEnabled(bool enabled)159 void SearchLineEdit::setEnabled(bool enabled) {
160 ExLineEdit::setEnabled(enabled);
161 emit enabledChanged(enabled);
162 }
163