clazy: fix QString(QLatin1String(...))
[trojita.git] / src / Gui / LineEdit.cpp
blobe12537bca1128f5494e5d43bd256b09720f5ae5c
1 /****************************************************************************
2 **
3 ** Copyright (c) 2007 Trolltech ASA <info@trolltech.com>
4 ** Modified (c) 2009, 2011, 2013 by Glad Deschrijver <glad.deschrijver@gmail.com>
5 **
6 ** Use, modification and distribution is allowed without limitation,
7 ** warranty, liability or support of any kind.
8 **
9 ****************************************************************************/
11 #include "LineEdit.h"
13 #include <QAbstractItemModel>
14 #include <QAbstractItemView>
15 #include <QCompleter>
16 #include <QHBoxLayout>
17 #include <QKeyEvent>
18 #include <QToolButton>
19 #include <QStyle>
20 #include "Common/InvokeMethod.h"
21 #include "UiUtils/IconLoader.h"
23 LineEdit::LineEdit(const QString &text, QWidget *parent)
24 : QLineEdit(parent), m_historyEnabled(false), m_historyPosition(0)
26 init();
27 setText(text);
30 LineEdit::LineEdit(QWidget *parent)
31 : QLineEdit(parent), m_historyEnabled(false), m_historyPosition(0)
33 init();
36 void LineEdit::init()
38 m_clearButton = new QToolButton(this);
39 m_clearButton->setIcon(UiUtils::loadIcon(QStringLiteral("edit-clear-locationbar")));
40 m_clearButton->setCursor(Qt::ArrowCursor);
41 m_clearButton->setToolTip(tr("Clear input field"));
42 m_clearButton->setFocusPolicy(Qt::NoFocus);
43 m_clearButton->hide();
44 connect(m_clearButton, &QAbstractButton::clicked, this, &QLineEdit::clear);
45 connect(this, &QLineEdit::textChanged, this, &LineEdit::updateClearButton);
47 const int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
48 m_clearButton->setStyleSheet(QString::fromUtf8("QToolButton { border: none; padding-left: 1px; padding-top: %1px; padding-bottom: %1px; padding-right: %1px; }")
49 .arg(frameWidth + 1));
50 setStyleSheet(QString::fromUtf8("QLineEdit { padding-right: %1px; }")
51 .arg(m_clearButton->sizeHint().width()));
53 QHBoxLayout *layout = new QHBoxLayout(this);
54 layout->setContentsMargins(0, 0, 0, 0);
55 layout->addStretch();
56 layout->addWidget(m_clearButton);
58 connect(this, &QLineEdit::editingFinished, this, &LineEdit::doEmitTextEditingFinished);
61 QToolButton *LineEdit::clearButton()
63 return m_clearButton;
66 bool LineEdit::isHistoryEnabled()
68 return m_historyEnabled;
71 void LineEdit::setHistoryEnabled(bool enabled)
73 if (enabled == m_historyEnabled)
74 return;
75 m_historyEnabled = enabled;
76 if (m_historyEnabled) {
77 // queued so we learn and update the history list *after* the user selected an item from popup
78 connect(this, &QLineEdit::returnPressed, this, &LineEdit::learnEntry, Qt::QueuedConnection);
79 QCompleter *completer = new QCompleter(QStringList(), this);
80 completer->setCaseSensitivity(Qt::CaseInsensitive);
81 completer->setCompletionMode(QCompleter::InlineCompletion);
82 setCompleter(completer);
83 } else {
84 disconnect(this, &QLineEdit::returnPressed, this, &LineEdit::learnEntry);
85 delete completer();
86 setCompleter(NULL);
90 QSize LineEdit::sizeHint() const
92 const QSize defaultSize = QLineEdit::sizeHint();
93 const int minimumWidth = m_clearButton->sizeHint().width() + 2;
94 return QSize(qMax(defaultSize.width(), minimumWidth), defaultSize.height());
97 bool LineEdit::eventFilter(QObject *o, QEvent *e)
99 if (e->type() == QEvent::Hide && o == completer()->popup()) {
100 // next event cycle, the popup is deleted by the change and "return true" does not help
101 // connect queued to not manipulate the history *during* selection from popup, but *after*
102 CALL_LATER_NOARG(this, restoreInlineCompletion);
104 return false;
107 void LineEdit::keyReleaseEvent(QKeyEvent *ke)
109 if (!m_historyEnabled || completer()->completionMode() == QCompleter::UnfilteredPopupCompletion ||
110 !(ke->key() == Qt::Key_Up || ke->key() == Qt::Key_Down)) {
111 // irrelevant events -> ignore
112 QLineEdit::keyReleaseEvent(ke);
113 return;
116 // this manages the shell-a-like history and
117 // triggers a popdown (when pressing "down" arrow from current entry)
119 QAbstractItemModel *m = completer()->model();
120 int historyCount = m->rowCount();
122 if (ke->key() == Qt::Key_Up) {
123 // shell-a-like history navigation
124 if (m_historyPosition == historyCount) {
125 m_currentText = text();
126 if (historyCount && m->index(m_historyPosition - 1,0).data().toString() == m_currentText) {
127 // user still sees entry he entered (into history) last - skip that one.
128 --m_historyPosition;
131 if (--m_historyPosition < 0) {
132 m_historyPosition = historyCount;
133 setText(m_currentText);
134 } else {
135 setText(m->index(m_historyPosition,0).data().toString());
137 } else if (ke->key() == Qt::Key_Down) {
138 if (m_historyPosition + 1 < historyCount && m->index(m_historyPosition + 1,0).data().toString() == m_currentText) {
139 // user still sees entry he entered (into history) last - skip that one.
140 ++m_historyPosition;
142 if (++m_historyPosition == historyCount) {
143 // returning from shell-a-like journey
144 setText(m_currentText);
145 } else if (m_historyPosition > historyCount) {
146 // trigger pop...down ;-)
147 completer()->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
148 completer()->complete(); // make a popup
149 completer()->popup()->removeEventFilter(this); // protected against accidental double filtering
150 completer()->popup()->installEventFilter(this); // to restore inline completion when it closes
151 m_historyPosition = historyCount; // fix value to "current" (it's usually historyCount + 1 now)
152 } else {
153 // shell-a-like history navigation
154 setText(m->index(m_historyPosition,0).data().toString());
157 QLineEdit::keyReleaseEvent(ke);
160 void LineEdit::updateClearButton(const QString &text)
162 m_clearButton->setVisible(!text.isEmpty());
165 void LineEdit::learnEntry()
167 QAbstractItemModel *m = completer()->model();
168 int rows = m->rowCount();
169 for (int i = 0; i < rows; ++i) {
170 if (m->index(i,0).data() == text()) {
171 m->removeRow(i);
172 --rows;
173 break;
176 m->insertRows(rows, 1);
177 m->setData(m->index(rows, 0), text(), Qt::DisplayRole);
178 m_historyPosition = rows + 1;
181 void LineEdit::restoreInlineCompletion()
183 m_currentText = text(); // this was probably just updated by seleting from combobox
184 completer()->setCompletionMode(QCompleter::InlineCompletion);
185 CALL_LATER_NOARG(this, setFocus); // can't get in the second event cycle either
188 void LineEdit::doEmitTextEditingFinished()
190 emit textEditingFinished(text());