From c05bea12e0af7ec847043c832133cbfddfb278b1 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 13 Jul 2018 15:16:44 +0200 Subject: Add ctx->pack() API Signed-off-by: Clifford Wolf --- gui/ice40/mainwindow.cc | 1 - gui/ice40/worker.cc | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'gui') diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index b7f08104..bea5fce7 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -27,7 +27,6 @@ #include "design_utils.h" #include "jsonparse.h" #include "log.h" -#include "pack.h" #include "pcf.h" static void initMainResource() { Q_INIT_RESOURCE(nextpnr); } diff --git a/gui/ice40/worker.cc b/gui/ice40/worker.cc index 16f5fb89..09093ec8 100644 --- a/gui/ice40/worker.cc +++ b/gui/ice40/worker.cc @@ -23,7 +23,6 @@ #include "design_utils.h" #include "jsonparse.h" #include "log.h" -#include "pack.h" #include "pcf.h" #include "timing.h" @@ -97,7 +96,7 @@ void Worker::pack() { Q_EMIT taskStarted(); try { - bool res = pack_design(ctx); + bool res = ctx->pack(); print_utilisation(ctx); Q_EMIT pack_finished(res); } catch (WorkerInterruptionRequested) { -- cgit v1.2.3 From cbfb0302648771851ab386b6843fb0a60d018dad Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Jul 2018 15:40:43 +0200 Subject: remove maximum size restriction for tree/property --- gui/basewindow.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'gui') diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 6bc56c7b..fd9d36f4 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -66,7 +66,6 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr context, QWidget *parent DesignWidget *designview = new DesignWidget(); designview->setMinimumWidth(300); - designview->setMaximumWidth(300); splitter_h->addWidget(designview); connect(this, SIGNAL(contextChanged(Context *)), designview, SLOT(newContext(Context *))); -- cgit v1.2.3 From 07ff5ad8b8e4d0f87770b81b8478aa257567c504 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 13 Jul 2018 19:56:11 +0200 Subject: Made python console use edit line and better --- gui/CMakeLists.txt | 1 - gui/basewindow.cc | 2 +- gui/line_editor.cc | 56 +++++++++++++++++++++++++++++++++++-- gui/line_editor.h | 11 +++++++- gui/pyconsole.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gui/pyconsole.h | 58 ++++++++++++++++++++++++++++++++++++++ gui/pythontab.cc | 41 ++++++++++++++++++++++++--- gui/pythontab.h | 8 ++++++ 8 files changed, 249 insertions(+), 10 deletions(-) create mode 100644 gui/pyconsole.cc create mode 100644 gui/pyconsole.h (limited to 'gui') diff --git a/gui/CMakeLists.txt b/gui/CMakeLists.txt index 5ac4d955..2e8e367e 100644 --- a/gui/CMakeLists.txt +++ b/gui/CMakeLists.txt @@ -12,7 +12,6 @@ if (BUILD_PYTHON) ../3rdparty/python-console/modified/pyredirector.cc ../3rdparty/python-console/modified/pyinterpreter.cc - ../3rdparty/python-console/modified/pyconsole.cc ) endif() diff --git a/gui/basewindow.cc b/gui/basewindow.cc index fd9d36f4..b76527e1 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -76,7 +76,7 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr context, QWidget *parent tabWidget = new QTabWidget(); #ifndef NO_PYTHON PythonTab *pythontab = new PythonTab(); - tabWidget->addTab(pythontab, "Python"); + tabWidget->addTab(pythontab, "Console"); connect(this, SIGNAL(contextChanged(Context *)), pythontab, SLOT(newContext(Context *))); #endif info = new InfoTab(); diff --git a/gui/line_editor.cc b/gui/line_editor.cc index 9d9dac25..3c7ebe94 100644 --- a/gui/line_editor.cc +++ b/gui/line_editor.cc @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Miodrag Milanovic + * Copyright (C) 2018 Alex Tsui * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,12 +18,18 @@ * */ +#ifndef NO_PYTHON + #include "line_editor.h" #include +#include +#include "ColumnFormatter.h" +#include "Utils.h" +#include "pyinterpreter.h" NEXTPNR_NAMESPACE_BEGIN -LineEditor::LineEditor(QWidget *parent) : QLineEdit(parent), index(0) +LineEditor::LineEditor(ParseHelper *helper, QWidget *parent) : QLineEdit(parent), index(0), parseHelper(helper) { setContextMenuPolicy(Qt::CustomContextMenu); QAction *clearAction = new QAction("Clear &history", this); @@ -38,10 +45,12 @@ LineEditor::LineEditor(QWidget *parent) : QLineEdit(parent), index(0) void LineEditor::keyPressEvent(QKeyEvent *ev) { + if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) { + QToolTip::hideText(); if (lines.empty()) return; - + printf("Key_Up\n"); if (ev->key() == Qt::Key_Up) index--; if (ev->key() == Qt::Key_Down) @@ -56,12 +65,21 @@ void LineEditor::keyPressEvent(QKeyEvent *ev) } setText(lines[index]); } else if (ev->key() == Qt::Key_Escape) { + QToolTip::hideText(); clear(); return; + } else if (ev->key() == Qt::Key_Tab) { + autocomplete(); + return; } + QToolTip::hideText(); + QLineEdit::keyPressEvent(ev); } +// This makes TAB work +bool LineEditor::focusNextPrevChild(bool next) { return false; } + void LineEditor::textInserted() { if (lines.empty() || lines.back() != text()) @@ -82,4 +100,36 @@ void LineEditor::clearHistory() clear(); } -NEXTPNR_NAMESPACE_END \ No newline at end of file +void LineEditor::autocomplete() +{ + QString line = text(); + const std::list &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 + +#endif // NO_PYTHON diff --git a/gui/line_editor.h b/gui/line_editor.h index 91837182..5a57129b 100644 --- a/gui/line_editor.h +++ b/gui/line_editor.h @@ -2,6 +2,7 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Miodrag Milanovic + * Copyright (C) 2018 Alex Tsui * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,8 +21,11 @@ #ifndef LINE_EDITOR_H #define LINE_EDITOR_H +#ifndef NO_PYTHON + #include #include +#include "ParseHelper.h" #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN @@ -31,7 +35,7 @@ class LineEditor : public QLineEdit Q_OBJECT public: - explicit LineEditor(QWidget *parent = 0); + explicit LineEditor(ParseHelper *helper, QWidget *parent = 0); private Q_SLOTS: void textInserted(); @@ -43,13 +47,18 @@ class LineEditor : public QLineEdit protected: void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE; + bool focusNextPrevChild(bool next) Q_DECL_OVERRIDE; + void autocomplete(); private: int index; QStringList lines; QMenu *contextMenu; + ParseHelper *parseHelper; }; NEXTPNR_NAMESPACE_END +#endif // NO_PYTHON + #endif // LINE_EDITOR_H diff --git a/gui/pyconsole.cc b/gui/pyconsole.cc new file mode 100644 index 00000000..6da06b7e --- /dev/null +++ b/gui/pyconsole.cc @@ -0,0 +1,82 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * Copyright (C) 2018 Alex Tsui + * + * 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. + * + */ + +#ifndef NO_PYTHON + +#include "pyconsole.h" +#include "pyinterpreter.h" + +NEXTPNR_NAMESPACE_BEGIN + +const QColor PythonConsole::NORMAL_COLOR = QColor::fromRgbF(0, 0, 0); +const QColor PythonConsole::ERROR_COLOR = QColor::fromRgbF(1.0, 0, 0); +const QColor PythonConsole::OUTPUT_COLOR = QColor::fromRgbF(0, 0, 1.0); + +PythonConsole::PythonConsole(QWidget *parent) : QTextEdit(parent) {} + +void PythonConsole::parseEvent(const ParseMessage &message) +{ + // handle invalid user input + if (message.errorCode) { + setTextColor(ERROR_COLOR); + append(message.message.c_str()); + + setTextColor(NORMAL_COLOR); + append(""); + return; + } + // interpret valid user input + int errorCode = 0; + std::string res; + if (message.message.size()) + res = pyinterpreter_execute(message.message, &errorCode); + if (errorCode) { + setTextColor(ERROR_COLOR); + } else { + setTextColor(OUTPUT_COLOR); + } + + if (res.size()) { + append(res.c_str()); + } + setTextColor(NORMAL_COLOR); + append(""); + moveCursorToEnd(); +} + +void PythonConsole::displayString(QString text) +{ + QTextCursor cursor = textCursor(); + cursor.movePosition(QTextCursor::End); + setTextColor(NORMAL_COLOR); + cursor.insertText(text); + cursor.movePosition(QTextCursor::EndOfLine); +} + +void PythonConsole::moveCursorToEnd() +{ + QTextCursor cursor = textCursor(); + cursor.movePosition(QTextCursor::End); + setTextCursor(cursor); +} + +NEXTPNR_NAMESPACE_END + +#endif // NO_PYTHON diff --git a/gui/pyconsole.h b/gui/pyconsole.h new file mode 100644 index 00000000..60f10672 --- /dev/null +++ b/gui/pyconsole.h @@ -0,0 +1,58 @@ +/* + * nextpnr -- Next Generation Place and Route + * + * Copyright (C) 2018 Miodrag Milanovic + * Copyright (C) 2018 Alex Tsui + * + * 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. + * + */ + +#ifndef PYCONSOLE_H +#define PYCONSOLE_H + +#ifndef NO_PYTHON + +#include +#include +#include +#include "ParseHelper.h" +#include "ParseListener.h" +#include "nextpnr.h" + +class QWidget; +class QKeyEvent; + +NEXTPNR_NAMESPACE_BEGIN + +class PythonConsole : public QTextEdit, public ParseListener +{ + Q_OBJECT + + public: + PythonConsole(QWidget *parent = 0); + + void displayString(QString text); + void moveCursorToEnd(); + virtual void parseEvent(const ParseMessage &message); + + protected: + static const QColor NORMAL_COLOR; + static const QColor ERROR_COLOR; + static const QColor OUTPUT_COLOR; +}; + +NEXTPNR_NAMESPACE_END +#endif // NO_PYTHON + +#endif // PYCONSOLE_H diff --git a/gui/pythontab.cc b/gui/pythontab.cc index 897f87b3..5c349d7c 100644 --- a/gui/pythontab.cc +++ b/gui/pythontab.cc @@ -25,12 +25,20 @@ NEXTPNR_NAMESPACE_BEGIN +const QString PythonTab::PROMPT = ">>> "; +const QString PythonTab::MULTILINE_PROMPT = "... "; + PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false) { + QFont f("unexistent"); + f.setStyleHint(QFont::Monospace); + // Add text area for Python output and input line console = new PythonConsole(); console->setMinimumHeight(100); - console->setEnabled(false); + console->setReadOnly(true); + console->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard); + console->setFont(f); console->setContextMenuPolicy(Qt::CustomContextMenu); QAction *clearAction = new QAction("Clear &buffer", this); @@ -41,9 +49,21 @@ PythonTab::PythonTab(QWidget *parent) : QWidget(parent), initialized(false) contextMenu->addAction(clearAction); connect(console, SIGNAL(customContextMenuRequested(const QPoint)), this, SLOT(showContextMenu(const QPoint))); + lineEdit = new LineEditor(&parseHelper); + lineEdit->setMinimumHeight(30); + lineEdit->setMaximumHeight(30); + lineEdit->setFont(f); + lineEdit->setPlaceholderText(PythonTab::PROMPT); + connect(lineEdit, SIGNAL(textLineInserted(QString)), this, SLOT(editLineReturnPressed(QString))); + QGridLayout *mainLayout = new QGridLayout(); mainLayout->addWidget(console, 0, 0); + mainLayout->addWidget(lineEdit, 1, 0); setLayout(mainLayout); + + parseHelper.subscribe(console); + + prompt = PythonTab::PROMPT; } PythonTab::~PythonTab() @@ -54,13 +74,27 @@ PythonTab::~PythonTab() } } +void PythonTab::editLineReturnPressed(QString text) +{ + console->displayString(prompt + text + "\n"); + console->moveCursorToEnd(); + + parseHelper.process(text.toStdString()); + + if (parseHelper.buffered()) + prompt = PythonTab::MULTILINE_PROMPT; + else + prompt = PythonTab::PROMPT; + + lineEdit->setPlaceholderText(prompt); +} + void PythonTab::newContext(Context *ctx) { if (initialized) { pyinterpreter_finalize(); deinit_python(); } - console->setEnabled(true); console->clear(); pyinterpreter_preinit(); @@ -74,7 +108,6 @@ void PythonTab::newContext(Context *ctx) QString version = QString("Python %1 on %2\n").arg(Py_GetVersion(), Py_GetPlatform()); console->displayString(version); - console->displayPrompt(); } void PythonTab::showContextMenu(const QPoint &pt) { contextMenu->exec(mapToGlobal(pt)); } @@ -83,4 +116,4 @@ void PythonTab::clearBuffer() { console->clear(); } NEXTPNR_NAMESPACE_END -#endif \ No newline at end of file +#endif // NO_PYTHON diff --git a/gui/pythontab.h b/gui/pythontab.h index 4b22e6a9..3fd12981 100644 --- a/gui/pythontab.h +++ b/gui/pythontab.h @@ -25,6 +25,7 @@ #include #include #include +#include "ParseHelper.h" #include "line_editor.h" #include "nextpnr.h" #include "pyconsole.h" @@ -42,13 +43,20 @@ class PythonTab : public QWidget private Q_SLOTS: void showContextMenu(const QPoint &pt); void clearBuffer(); + void editLineReturnPressed(QString text); public Q_SLOTS: void newContext(Context *ctx); private: PythonConsole *console; + LineEditor *lineEdit; QMenu *contextMenu; bool initialized; + ParseHelper parseHelper; + QString prompt; + + static const QString PROMPT; + static const QString MULTILINE_PROMPT; }; NEXTPNR_NAMESPACE_END -- cgit v1.2.3