aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/application.cc2
-rw-r--r--gui/base.qrc1
-rw-r--r--gui/basewindow.cc18
-rw-r--r--gui/basewindow.h5
-rw-r--r--gui/designwidget.cc16
-rw-r--r--gui/fpgaviewwidget.cc23
-rw-r--r--gui/generic/mainwindow.cc13
-rw-r--r--gui/pyconsole.cc17
-rw-r--r--gui/pyconsole.h1
-rw-r--r--gui/pythontab.cc5
-rw-r--r--gui/pythontab.h1
-rw-r--r--gui/resources/py.pngbin0 -> 2277 bytes
-rw-r--r--gui/worker.cc1
13 files changed, 80 insertions, 23 deletions
diff --git a/gui/application.cc b/gui/application.cc
index 9229f1cd..0a82e40b 100644
--- a/gui/application.cc
+++ b/gui/application.cc
@@ -70,7 +70,7 @@ bool Application::notify(QObject *receiver, QEvent *event)
bool retVal = true;
try {
retVal = QApplication::notify(receiver, event);
- } catch (assertion_failure ex) {
+ } catch (const assertion_failure &ex) {
QString msg;
QTextStream out(&msg);
out << ex.filename.c_str() << " at " << ex.line << "\n";
diff --git a/gui/base.qrc b/gui/base.qrc
index 8f58f585..644b16a6 100644
--- a/gui/base.qrc
+++ b/gui/base.qrc
@@ -22,5 +22,6 @@
<file>resources/route.png</file>
<file>resources/time_add.png</file>
<file>resources/open_json.png</file>
+ <file>resources/py.png</file>
</qresource>
</RCC>
diff --git a/gui/basewindow.cc b/gui/basewindow.cc
index 49c2d8d5..346efb88 100644
--- a/gui/basewindow.cc
+++ b/gui/basewindow.cc
@@ -189,6 +189,12 @@ void BaseMainWindow::createMenusAndBars()
actionRoute->setEnabled(false);
connect(actionRoute, &QAction::triggered, task, &TaskManager::route);
+ actionExecutePy = new QAction("Execute Python", this);
+ actionExecutePy->setIcon(QIcon(":/icons/resources/py.png"));
+ actionExecutePy->setStatusTip("Execute Python script");
+ actionExecutePy->setEnabled(true);
+ connect(actionExecutePy, &QAction::triggered, this, &BaseMainWindow::execute_python);
+
// Worker control toolbar actions
actionPlay = new QAction("Play", this);
actionPlay->setIcon(QIcon(":/icons/resources/control_play.png"));
@@ -249,6 +255,8 @@ void BaseMainWindow::createMenusAndBars()
menuDesign->addAction(actionAssignBudget);
menuDesign->addAction(actionPlace);
menuDesign->addAction(actionRoute);
+ menuDesign->addSeparator();
+ menuDesign->addAction(actionExecutePy);
// Add Help menu actions
menuHelp->addAction(actionAbout);
@@ -268,6 +276,7 @@ void BaseMainWindow::createMenusAndBars()
mainActionBar->addAction(actionAssignBudget);
mainActionBar->addAction(actionPlace);
mainActionBar->addAction(actionRoute);
+ mainActionBar->addAction(actionExecutePy);
// Add worker control toolbar
QToolBar *workerControlToolBar = new QToolBar("Worker");
@@ -412,6 +421,7 @@ void BaseMainWindow::disableActions()
actionAssignBudget->setEnabled(false);
actionPlace->setEnabled(false);
actionRoute->setEnabled(false);
+ actionExecutePy->setEnabled(true);
actionPlay->setEnabled(false);
actionPause->setEnabled(false);
@@ -454,6 +464,14 @@ void BaseMainWindow::open_proj()
}
}
+void BaseMainWindow::execute_python()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, QString("Execute Python"), QString(), QString("*.py"));
+ if (!fileName.isEmpty()) {
+ console->execute_python(fileName.toStdString());
+ }
+}
+
void BaseMainWindow::notifyChangeContext() { Q_EMIT contextChanged(ctx.get()); }
void BaseMainWindow::save_proj()
{
diff --git a/gui/basewindow.h b/gui/basewindow.h
index eb32033a..0b2d3fbc 100644
--- a/gui/basewindow.h
+++ b/gui/basewindow.h
@@ -78,6 +78,8 @@ class BaseMainWindow : public QMainWindow
void budget();
void place();
+ void execute_python();
+
void pack_finished(bool status);
void budget_finish(bool status);
void place_finished(bool status);
@@ -122,6 +124,9 @@ class BaseMainWindow : public QMainWindow
QAction *actionAssignBudget;
QAction *actionPlace;
QAction *actionRoute;
+
+ QAction *actionExecutePy;
+
QAction *actionPlay;
QAction *actionPause;
QAction *actionStop;
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index 235dd2cb..1617340b 100644
--- a/gui/designwidget.cc
+++ b/gui/designwidget.cc
@@ -444,9 +444,9 @@ TreeModel::Model *DesignWidget::getTreeByElementType(ElementType type)
return treeModel[1];
if (type == ElementType::PIP)
return treeModel[2];
- if (type == ElementType::NET)
- return treeModel[3];
if (type == ElementType::CELL)
+ return treeModel[3];
+ if (type == ElementType::NET)
return treeModel[4];
return nullptr;
}
@@ -460,9 +460,9 @@ int DesignWidget::getIndexByElementType(ElementType type)
return 1;
if (type == ElementType::PIP)
return 2;
- if (type == ElementType::NET)
- return 3;
if (type == ElementType::CELL)
+ return 3;
+ if (type == ElementType::NET)
return 4;
if (type == ElementType::GROUP)
return 5;
@@ -706,8 +706,12 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
- addProperty(topItem, QVariant::String, "Conflicting Wire",
- ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx), ElementType::WIRE);
+ if (ctx->getConflictingPipWire(pip) != WireId()) {
+ addProperty(topItem, QVariant::String, "Conflicting Wire",
+ ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx), ElementType::WIRE);
+ } else {
+ addProperty(topItem, QVariant::String, "Conflicting Wire", "", ElementType::NONE);
+ }
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
ElementType::NET);
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc
index e0a81486..f2929d6e 100644
--- a/gui/fpgaviewwidget.cc
+++ b/gui/fpgaviewwidget.cc
@@ -88,7 +88,7 @@ void FPGAViewWidget::newContext(Context *ctx)
pokeRenderer();
}
-QSize FPGAViewWidget::minimumSizeHint() const { return QSize(640, 480); }
+QSize FPGAViewWidget::minimumSizeHint() const { return QSize(320, 200); }
QSize FPGAViewWidget::sizeHint() const { return QSize(640, 480); }
@@ -100,7 +100,7 @@ void FPGAViewWidget::initializeGL()
initializeOpenGLFunctions();
QtImGui::initialize(this);
glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, colors_.background.blue() / 255,
- 0.0);
+ 1.0);
}
float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy) const
@@ -630,12 +630,16 @@ void FPGAViewWidget::mousePressEvent(QMouseEvent *event)
if (io.WantCaptureMouse)
return;
- if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) {
+ bool shift = QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
+ bool ctrl = QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
+ bool btn_right = event->buttons() & Qt::RightButton;
+ bool btn_mid = event->buttons() & Qt::MidButton;
+ bool btn_left = event->buttons() & Qt::LeftButton;
+
+ if (btn_right || btn_mid || (btn_left && shift)) {
lastDragPos_ = event->pos();
}
- if (event->buttons() & Qt::LeftButton) {
- bool ctrl = QApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
-
+ if (btn_left && !shift) {
auto world = mouseToWorldCoordinates(event->x(), event->y());
auto closestOr = pickElement(world.x(), world.y());
if (!closestOr) {
@@ -667,7 +671,12 @@ void FPGAViewWidget::mouseMoveEvent(QMouseEvent *event)
if (io.WantCaptureMouse)
return;
- if (event->buttons() & Qt::RightButton || event->buttons() & Qt::MidButton) {
+ bool shift = QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier);
+ bool btn_right = event->buttons() & Qt::RightButton;
+ bool btn_mid = event->buttons() & Qt::MidButton;
+ bool btn_left = event->buttons() & Qt::LeftButton;
+
+ if (btn_right || btn_mid || (btn_left && shift)) {
const int dx = event->x() - lastDragPos_.x();
const int dy = event->y() - lastDragPos_.y();
lastDragPos_ = event->pos();
diff --git a/gui/generic/mainwindow.cc b/gui/generic/mainwindow.cc
index 12912cc9..54d1f2c8 100644
--- a/gui/generic/mainwindow.cc
+++ b/gui/generic/mainwindow.cc
@@ -19,6 +19,9 @@
#include "mainwindow.h"
+#include <QMessageBox>
+#include <cstdlib>
+
static void initMainResource() { Q_INIT_RESOURCE(nextpnr); }
NEXTPNR_NAMESPACE_BEGIN
@@ -26,14 +29,8 @@ NEXTPNR_NAMESPACE_BEGIN
MainWindow::MainWindow(std::unique_ptr<Context> context, ArchArgs args, QWidget *parent)
: BaseMainWindow(std::move(context), args, parent)
{
- initMainResource();
-
- std::string title = "nextpnr-generic - [EMPTY]";
- setWindowTitle(title.c_str());
-
- connect(this, &BaseMainWindow::contextChanged, this, &MainWindow::newContext);
-
- createMenu();
+ QMessageBox::critical(0, "Error - FIXME", "No GUI support for nextpnr-generic");
+ std::exit(1);
}
MainWindow::~MainWindow() {}
diff --git a/gui/pyconsole.cc b/gui/pyconsole.cc
index 0ee393ce..d015aea2 100644
--- a/gui/pyconsole.cc
+++ b/gui/pyconsole.cc
@@ -76,4 +76,21 @@ void PythonConsole::moveCursorToEnd()
setTextCursor(cursor);
}
+void PythonConsole::execute_python(std::string filename)
+{
+ int errorCode = 0;
+ std::string res;
+ res = pyinterpreter_execute_file(filename.c_str(), &errorCode);
+ if (res.size()) {
+ if (errorCode) {
+ setTextColor(ERROR_COLOR);
+ } else {
+ setTextColor(OUTPUT_COLOR);
+ }
+ append(res.c_str());
+ setTextColor(NORMAL_COLOR);
+ moveCursorToEnd();
+ }
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/gui/pyconsole.h b/gui/pyconsole.h
index 9dbd3b95..977242f3 100644
--- a/gui/pyconsole.h
+++ b/gui/pyconsole.h
@@ -43,6 +43,7 @@ class PythonConsole : public QTextEdit, public ParseListener
void displayString(QString text);
void moveCursorToEnd();
virtual void parseEvent(const ParseMessage &message);
+ void execute_python(std::string filename);
protected:
static const QColor NORMAL_COLOR;
diff --git a/gui/pythontab.cc b/gui/pythontab.cc
index 80d731e9..c83f1ece 100644
--- a/gui/pythontab.cc
+++ b/gui/pythontab.cc
@@ -96,9 +96,10 @@ void PythonTab::newContext(Context *ctx)
console->clear();
pyinterpreter_preinit();
- init_python("nextpnr", !initialized);
+ init_python("nextpnr", true);
pyinterpreter_initialize();
pyinterpreter_aquire();
+ init_python("nextpnr", false);
python_export_global("ctx", ctx);
pyinterpreter_release();
@@ -114,4 +115,6 @@ void PythonTab::clearBuffer() { console->clear(); }
void PythonTab::info(std::string str) { console->displayString(str.c_str()); }
+void PythonTab::execute_python(std::string filename) { console->execute_python(filename); }
+
NEXTPNR_NAMESPACE_END
diff --git a/gui/pythontab.h b/gui/pythontab.h
index 134874b6..860bf1c3 100644
--- a/gui/pythontab.h
+++ b/gui/pythontab.h
@@ -45,6 +45,7 @@ class PythonTab : public QWidget
void newContext(Context *ctx);
void info(std::string str);
void clearBuffer();
+ void execute_python(std::string filename);
private:
PythonConsole *console;
diff --git a/gui/resources/py.png b/gui/resources/py.png
new file mode 100644
index 00000000..9cc6e522
--- /dev/null
+++ b/gui/resources/py.png
Binary files differ
diff --git a/gui/worker.cc b/gui/worker.cc
index b009ecd3..900883d4 100644
--- a/gui/worker.cc
+++ b/gui/worker.cc
@@ -126,6 +126,7 @@ TaskManager::TaskManager() : toTerminate(false), toPause(false)
TaskManager::~TaskManager()
{
+ log_write_function = nullptr;
if (workerThread.isRunning())
terminate_thread();
workerThread.quit();