Mantid
Loading...
Searching...
No Matches
HintingLineEdit.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
9#include <QKeyEvent>
10#include <QLabel>
11#include <QStyle>
12#include <QToolTip>
13#include <boost/algorithm/string.hpp>
14#include <utility>
15
17HintingLineEdit::HintingLineEdit(QWidget *parent, std::vector<Hint> hints)
18 : QLineEdit(parent), m_hints(std::move(hints)), m_dontComplete(false) {
19 m_hintLabel = new QLabel(this, Qt::ToolTip);
20 m_hintLabel->setMargin(1 + style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, nullptr, m_hintLabel));
21 m_hintLabel->setFrameStyle(QFrame::StyledPanel);
22 m_hintLabel->setAlignment(Qt::AlignLeft);
23 m_hintLabel->setWordWrap(true);
24 m_hintLabel->setIndent(1);
25 m_hintLabel->setAutoFillBackground(true);
26 m_hintLabel->setForegroundRole(QPalette::ToolTipText);
27 m_hintLabel->setBackgroundRole(QPalette::ToolTipBase);
28 m_hintLabel->ensurePolished();
29
30 connect(this, SIGNAL(textEdited(const QString &)), this, SLOT(updateHints(const QString &)));
31 connect(this, SIGNAL(editingFinished()), this, SLOT(hideHints()));
32}
33
35
41 m_dontComplete = (e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete || e->key() == Qt::Key_Space);
42
43 if (e->key() == Qt::Key_Up) {
45 return;
46 }
47
48 if (e->key() == Qt::Key_Down) {
50 return;
51 }
52 QLineEdit::keyPressEvent(e);
53}
54
60void HintingLineEdit::updateHints(const QString &text) {
61 const size_t curPos = (size_t)cursorPosition();
62 const std::string line = text.toStdString();
63
64 // Get everything before the cursor
65 std::string prefix = line.substr(0, curPos);
66
67 // Now remove everything before the last ',' to give us the current word
68 std::size_t startPos = prefix.find_last_of(",");
69 if (startPos != std::string::npos)
70 prefix = prefix.substr(startPos + 1, prefix.size() - (startPos + 1));
71
72 // Remove any leading or trailing whitespace
73 boost::trim(prefix);
74
75 m_currentPrefix = prefix;
76
77 // Update our current list of matches
79
80 // Show the potential matches in a tooltip
82
83 // Suggest one of them to the user via auto-completion
85}
86
90
93 m_matches.clear();
94 std::copy_if(m_hints.cbegin(), m_hints.cend(), std::back_inserter(m_matches), [this](Hint const &hint) -> bool {
95 auto &hintWord = hint.word();
96 return hintWord.length() >= m_currentPrefix.length() &&
97 hintWord.substr(0, m_currentPrefix.length()) == m_currentPrefix;
98 });
99 m_match = m_matches.cbegin();
100}
101
104 QString hintList;
105 for (auto const &match : m_matches) {
106 hintList += "<b>" + QString::fromStdString(match.word()) + "</b><br />\n";
107 if (!match.description().empty())
108 hintList += QString::fromStdString(match.description()) + "<br />\n";
109 }
110
111 if (!hintList.trimmed().isEmpty()) {
112 m_hintLabel->show();
113 m_hintLabel->setText(hintList.trimmed());
114 m_hintLabel->adjustSize();
115 m_hintLabel->move(mapToGlobal(QPoint(0, height())));
116 } else {
117 m_hintLabel->hide();
118 }
119}
120
124 if (m_currentPrefix.empty() || m_matches.empty() || m_match == m_matches.cend() || m_dontComplete)
125 return;
126
127 QString line = text();
128 const int curPos = cursorPosition();
129
130 // Don't perform insertions mid-word
131 if (curPos + 1 < line.size() && line[curPos + 1].isLetterOrNumber())
132 return;
133
134 // Insert a suggestion under the cursor, then select it
135 line = line.left(curPos) + QString::fromStdString((*m_match).word()).mid(static_cast<int>(m_currentPrefix.size())) +
136 line.mid(curPos);
137
138 setText(line);
139 setSelection(curPos, static_cast<int>((*m_match).word().size()));
140}
141
144 if (!hasSelectedText())
145 return;
146
147 // Carefully cut out the selected text
148 QString line = text();
149 line = line.left(selectionStart()) + line.mid(selectionStart() + selectedText().length());
150 setText(line);
151}
152
156 // Find the next suggestion in the hint map
157 if (m_match != m_matches.end()) {
158 ++m_match;
159 if (m_match == m_matches.end())
160 m_match = m_matches.begin();
162 }
163}
164
168 // Find the previous suggestion in the hint map
169 if (m_match != m_matches.cend()) {
170 if (m_match == m_matches.cbegin()) {
171 m_match = m_matches.cend() - 1;
172 } else {
173 --m_match;
174 }
176 }
177}
178} // namespace MantidQt::MantidWidgets
double height
Definition: GetAllEi.cpp:155
void prevSuggestion()
Change to the previous auto completion suggestion.
std::vector< Hint >::const_iterator m_match
void clearSuggestion()
Remove any existing auto completion suggestion.
void showToolTip()
Show a tooltip with the current relevant hints.
void hideHints()
Hides the list of hints.
void keyPressEvent(QKeyEvent *e) override
Handle a key press event.
HintingLineEdit(QWidget *parent, std::vector< Hint > hints)
void nextSuggestion()
Change to the next available auto completion suggestion.
void insertSuggestion()
Insert an auto completion suggestion beneath the user's cursor and select it.
void updateMatches()
Updates the list of hints matching the user's current input.
void updateHints(const QString &text)
Rebuild a list of hints whenever the user edits the text, and use the hints to make auto completion s...
STL namespace.