nextpnr/gui/line_editor.cc

149 lines
4.6 KiB
C++
Raw Normal View History

2018-06-22 22:21:20 +08:00
/*
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Miodrag Milanovic <micko@yosyshq.com>
* Copyright (C) 2018 Alex Tsui
2018-06-22 22:21:20 +08:00
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
2018-06-20 15:42:47 +08:00
#include "line_editor.h"
#include <QApplication>
#include <QClipboard>
2018-06-20 15:42:47 +08:00
#include <QKeyEvent>
#include <QToolTip>
#include "ColumnFormatter.h"
#include "Utils.h"
#include "pyinterpreter.h"
2018-06-20 15:42:47 +08:00
2018-06-22 19:10:27 +08:00
NEXTPNR_NAMESPACE_BEGIN
LineEditor::LineEditor(ParseHelper *helper, QWidget *parent) : QLineEdit(parent), index(0), parseHelper(helper)
2018-06-20 15:42:47 +08:00
{
setContextMenuPolicy(Qt::CustomContextMenu);
QAction *clearAction = new QAction("Clear &history", this);
clearAction->setStatusTip("Clears line edit history");
2018-08-03 16:53:38 +08:00
connect(clearAction, &QAction::triggered, this, &LineEditor::clearHistory);
2018-06-20 15:42:47 +08:00
contextMenu = createStandardContextMenu();
contextMenu->addSeparator();
contextMenu->addAction(clearAction);
2018-08-03 16:53:38 +08:00
connect(this, &LineEditor::returnPressed, this, &LineEditor::textInserted);
connect(this, &LineEditor::customContextMenuRequested, this, &LineEditor::showContextMenu);
2018-06-20 15:42:47 +08:00
}
void LineEditor::keyPressEvent(QKeyEvent *ev)
{
if (ev->matches(QKeySequence::Paste)) {
QString clipboard = QApplication::clipboard()->text();
if (clipboard.isEmpty())
return;
if (clipboard.contains('\n')) {
QStringList clipboard_lines = clipboard.split('\n');
for (int i = 0; i < clipboard_lines.size(); i++) {
addLineToHistory(clipboard_lines[i]);
Q_EMIT textLineInserted(clipboard_lines[i]);
}
return;
}
} else if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) {
QToolTip::hideText();
2018-06-20 15:42:47 +08:00
if (lines.empty())
return;
if (ev->key() == Qt::Key_Up)
index--;
if (ev->key() == Qt::Key_Down)
index++;
if (index < 0)
index = 0;
if (index >= lines.size()) {
index = lines.size();
clear();
return;
}
setText(lines[index]);
} else if (ev->key() == Qt::Key_Escape) {
QToolTip::hideText();
2018-06-20 15:42:47 +08:00
clear();
return;
} else if (ev->key() == Qt::Key_Tab) {
autocomplete();
return;
2018-06-20 15:42:47 +08:00
}
QToolTip::hideText();
2018-06-20 15:42:47 +08:00
QLineEdit::keyPressEvent(ev);
}
// This makes TAB work
bool LineEditor::focusNextPrevChild(bool next) { return false; }
2018-06-20 15:42:47 +08:00
void LineEditor::textInserted()
{
addLineToHistory(text());
clear();
Q_EMIT textLineInserted(lines.back());
}
void LineEditor::addLineToHistory(QString line)
{
if (lines.empty() || lines.back() != line)
lines += line;
2018-06-20 15:42:47 +08:00
if (lines.size() > 100)
lines.removeFirst();
index = lines.size();
}
2018-06-23 22:06:49 +08:00
void LineEditor::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); }
2018-06-20 15:42:47 +08:00
void LineEditor::clearHistory()
{
lines.clear();
index = 0;
clear();
2018-06-22 19:10:27 +08:00
}
void LineEditor::autocomplete()
{
QString line = text();
2023-11-23 02:50:17 +08:00
const std::list<std::string> suggestions = pyinterpreter_suggest(line.toStdString());
if (suggestions.size() == 1) {
line = suggestions.back().c_str();
} else {
// try to complete to longest common prefix
std::string prefix = LongestCommonPrefix(suggestions.begin(), suggestions.end());
if (prefix.size() > (size_t)line.size()) {
line = prefix.c_str();
} else {
ColumnFormatter fmt;
fmt.setItems(suggestions.begin(), suggestions.end());
fmt.format(width() / 5);
QString out = "";
for (auto &it : fmt.formattedOutput()) {
if (!out.isEmpty())
out += "\n";
out += it.c_str();
}
QToolTip::setFont(font());
if (!out.trimmed().isEmpty())
QToolTip::showText(mapToGlobal(QPoint(0, 0)), out);
}
}
// set up the next line on the console
setText(line);
}
NEXTPNR_NAMESPACE_END