1 #include "exlineedit.h"
2 #include "iconutils.h"
3 
ClearButton(QWidget * parent)4 ClearButton::ClearButton(QWidget *parent)
5     : QAbstractButton(parent), hovered(false), mousePressed(false) {
6     setCursor(Qt::ArrowCursor);
7     setToolTip(tr("Clear"));
8     setVisible(false);
9     setFocusPolicy(Qt::NoFocus);
10 }
11 
paintEvent(QPaintEvent * e)12 void ClearButton::paintEvent(QPaintEvent *e) {
13     Q_UNUSED(e);
14     QPainter painter(this);
15     const int h = height();
16     int iconSize = 16;
17     if (h > 32) iconSize = 22;
18     QIcon::Mode iconMode = QIcon::Normal;
19     if (mousePressed) iconMode = QIcon::Active;
20     QPixmap p = IconUtils::icon("edit-clear").pixmap(iconSize, iconSize, iconMode);
21     int x = (width() - p.width()) / 2;
22     int y = (h - p.height()) / 2;
23     painter.drawPixmap(x, y, p);
24 }
25 
textChanged(const QString & text)26 void ClearButton::textChanged(const QString &text) {
27     setVisible(!text.isEmpty());
28 }
29 
enterEvent(QEvent * e)30 void ClearButton::enterEvent(QEvent *e) {
31     hovered = true;
32     QAbstractButton::enterEvent(e);
33 }
34 
leaveEvent(QEvent * e)35 void ClearButton::leaveEvent(QEvent *e) {
36     hovered = false;
37     QAbstractButton::leaveEvent(e);
38 }
39 
mousePressEvent(QMouseEvent * e)40 void ClearButton::mousePressEvent(QMouseEvent *e) {
41     mousePressed = true;
42     QAbstractButton::mousePressEvent(e);
43 }
44 
mouseReleaseEvent(QMouseEvent * e)45 void ClearButton::mouseReleaseEvent(QMouseEvent *e) {
46     mousePressed = false;
47     QAbstractButton::mouseReleaseEvent(e);
48 }
49 
ExLineEdit(QWidget * parent)50 ExLineEdit::ExLineEdit(QWidget *parent)
51     : QWidget(parent), m_leftWidget(nullptr), m_lineEdit(new QLineEdit(this)),
52       m_clearButton(new ClearButton(this)) {
53     setFocusPolicy(m_lineEdit->focusPolicy());
54     setAttribute(Qt::WA_InputMethodEnabled);
55     setSizePolicy(m_lineEdit->sizePolicy());
56     setBackgroundRole(m_lineEdit->backgroundRole());
57     setMouseTracking(true);
58     setAcceptDrops(true);
59     setAttribute(Qt::WA_MacShowFocusRect, true);
60     QPalette p = m_lineEdit->palette();
61     setPalette(p);
62 
63     // line edit
64     m_lineEdit->setFrame(false);
65     m_lineEdit->setFocusProxy(this);
66     m_lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
67     m_lineEdit->setStyleSheet("background:transparent");
68     QPalette clearPalette = m_lineEdit->palette();
69     clearPalette.setBrush(QPalette::Base, QBrush(Qt::transparent));
70     m_lineEdit->setPalette(clearPalette);
71 
72     // clearButton
73     connect(m_clearButton, SIGNAL(clicked()), m_lineEdit, SLOT(clear()));
74     connect(m_lineEdit, SIGNAL(textChanged(const QString &)), m_clearButton,
75             SLOT(textChanged(const QString &)));
76 }
77 
setFont(const QFont & font)78 void ExLineEdit::setFont(const QFont &font) {
79     m_lineEdit->setFont(font);
80     updateGeometries();
81 }
82 
setLeftWidget(QWidget * widget)83 void ExLineEdit::setLeftWidget(QWidget *widget) {
84     m_leftWidget = widget;
85 }
86 
leftWidget() const87 QWidget *ExLineEdit::leftWidget() const {
88     return m_leftWidget;
89 }
90 
clear()91 void ExLineEdit::clear() {
92     m_lineEdit->clear();
93 }
94 
text()95 QString ExLineEdit::text() {
96     return m_lineEdit->text();
97 }
98 
resizeEvent(QResizeEvent * e)99 void ExLineEdit::resizeEvent(QResizeEvent *e) {
100     Q_ASSERT(m_leftWidget);
101     updateGeometries();
102     QWidget::resizeEvent(e);
103 }
104 
updateGeometries()105 void ExLineEdit::updateGeometries() {
106     QStyleOptionFrame panel;
107     initStyleOption(&panel);
108     QRect rect = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
109 
110     int padding = 3;
111     // int height = rect.height() + padding*2;
112     int width = rect.width();
113 
114     // int m_leftWidgetHeight = m_leftWidget->height();
115     m_leftWidget->setGeometry(rect.x() + 2, 0, m_leftWidget->width(), m_leftWidget->height());
116 
117     int clearButtonWidth = this->height();
118     m_lineEdit->setGeometry(m_leftWidget->x() + m_leftWidget->width(), padding,
119                             width - clearButtonWidth - m_leftWidget->width(),
120                             this->height() - padding * 2);
121 
122     m_clearButton->setGeometry(this->width() - clearButtonWidth, 0, clearButtonWidth,
123                                this->height());
124 }
125 
initStyleOption(QStyleOptionFrame * option) const126 void ExLineEdit::initStyleOption(QStyleOptionFrame *option) const {
127     option->initFrom(this);
128     option->rect = contentsRect();
129     option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this);
130     option->midLineWidth = 0;
131     option->state |= QStyle::State_Sunken;
132     if (m_lineEdit->isReadOnly()) option->state |= QStyle::State_ReadOnly;
133 #ifdef QT_KEYPAD_NAVIGATION
134     if (hasEditFocus()) option->state |= QStyle::State_HasEditFocus;
135 #endif
136     option->features = QStyleOptionFrame::None;
137 }
138 
sizeHint() const139 QSize ExLineEdit::sizeHint() const {
140     m_lineEdit->setFrame(true);
141     QSize size = m_lineEdit->sizeHint();
142     m_lineEdit->setFrame(false);
143     size = size + QSize(3, 3);
144     return size;
145 }
146 
focusInEvent(QFocusEvent * e)147 void ExLineEdit::focusInEvent(QFocusEvent *e) {
148     m_lineEdit->event(e);
149     QWidget::focusInEvent(e);
150 }
151 
focusOutEvent(QFocusEvent * e)152 void ExLineEdit::focusOutEvent(QFocusEvent *e) {
153     m_lineEdit->event(e);
154 
155     if (m_lineEdit->completer()) {
156         connect(m_lineEdit->completer(), SIGNAL(activated(QString)), m_lineEdit,
157                 SLOT(setText(QString)));
158         connect(m_lineEdit->completer(), SIGNAL(highlighted(QString)), m_lineEdit,
159                 SLOT(_q_completionHighlighted(QString)));
160     }
161     QWidget::focusOutEvent(e);
162 }
163 
keyPressEvent(QKeyEvent * e)164 void ExLineEdit::keyPressEvent(QKeyEvent *e) {
165     if (e->key() == Qt::Key_Escape && !m_lineEdit->text().isEmpty()) {
166         m_lineEdit->clear();
167     }
168     m_lineEdit->event(e);
169     QWidget::keyPressEvent(e);
170 }
171 
event(QEvent * e)172 bool ExLineEdit::event(QEvent *e) {
173     if (e->type() == QEvent::ShortcutOverride || e->type() == QEvent::InputMethod)
174         m_lineEdit->event(e);
175     return QWidget::event(e);
176 }
177 
paintEvent(QPaintEvent * e)178 void ExLineEdit::paintEvent(QPaintEvent *e) {
179     Q_UNUSED(e);
180     if (hasFocus()) {
181         QPainter p(this);
182         QStyleOptionFrame panel;
183         initStyleOption(&panel);
184         style()->drawPrimitive(QStyle::PE_PanelLineEdit, &panel, &p, this);
185     }
186 }
187