From 0d8c80ad5daafc02030385da90c5a57182a5d4e5 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 14 Jun 2019 11:14:18 +0200 Subject: gui for json write and proper statuses --- common/command.cc | 2 +- gui/base.qrc | 1 + gui/basewindow.cc | 71 +++++++++++++++++++++++++++++++++----------- gui/basewindow.h | 13 ++++---- gui/create_img.sh | 5 ++-- gui/ecp5/mainwindow.cc | 11 +++++-- gui/ecp5/mainwindow.h | 3 +- gui/ice40/mainwindow.cc | 8 +++-- gui/ice40/mainwindow.h | 3 +- gui/resources/save_json.png | Bin 0 -> 1546 bytes json/jsonparse.cc | 3 +- 11 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 gui/resources/save_json.png diff --git a/common/command.cc b/common/command.cc index 209f8cab..7b0b2caa 100644 --- a/common/command.cc +++ b/common/command.cc @@ -255,7 +255,7 @@ int CommandHandler::executeMain(std::unique_ptr ctx) customAfterLoad(w.getContext()); w.notifyChangeContext(); - w.updateLoaded(); + w.updateActions(); } else w.notifyChangeContext(); } catch (log_execution_error_exception) { diff --git a/gui/base.qrc b/gui/base.qrc index 644b16a6..85d1432a 100644 --- a/gui/base.qrc +++ b/gui/base.qrc @@ -22,6 +22,7 @@ resources/route.png resources/time_add.png resources/open_json.png + resources/save_json.png resources/py.png diff --git a/gui/basewindow.cc b/gui/basewindow.cc index 63e30f27..59dd6f7b 100644 --- a/gui/basewindow.cc +++ b/gui/basewindow.cc @@ -29,6 +29,7 @@ #include "designwidget.h" #include "fpgaviewwidget.h" #include "jsonparse.h" +#include "jsonwrite.h" #include "log.h" #include "mainwindow.h" #include "pythontab.h" @@ -138,13 +139,26 @@ void BaseMainWindow::createMenusAndBars() // Help menu actions QAction *actionAbout = new QAction("About", this); - // Design menu options + // Gile menu options + actionNew = new QAction("New", this); + actionNew->setIcon(QIcon(":/icons/resources/new.png")); + actionNew->setShortcuts(QKeySequence::New); + actionNew->setStatusTip("New project"); + connect(actionNew, &QAction::triggered, this, &BaseMainWindow::new_proj); + actionLoadJSON = new QAction("Open JSON", this); actionLoadJSON->setIcon(QIcon(":/icons/resources/open_json.png")); actionLoadJSON->setStatusTip("Open an existing JSON file"); actionLoadJSON->setEnabled(true); connect(actionLoadJSON, &QAction::triggered, this, &BaseMainWindow::open_json); + actionSaveJSON = new QAction("Save JSON", this); + actionSaveJSON->setIcon(QIcon(":/icons/resources/save_json.png")); + actionSaveJSON->setStatusTip("Write to JSON file"); + actionSaveJSON->setEnabled(true); + connect(actionSaveJSON, &QAction::triggered, this, &BaseMainWindow::save_json); + + // Design menu options actionPack = new QAction("Pack", this); actionPack->setIcon(QIcon(":/icons/resources/pack.png")); actionPack->setStatusTip("Pack current design"); @@ -223,10 +237,13 @@ void BaseMainWindow::createMenusAndBars() menuBar->addAction(menuHelp->menuAction()); // Add File menu actions + menuFile->addAction(actionNew); + menuFile->addAction(actionLoadJSON); + menuFile->addAction(actionSaveJSON); + menuFile->addSeparator(); menuFile->addAction(actionExit); // Add Design menu actions - menuDesign->addAction(actionLoadJSON); menuDesign->addAction(actionPack); menuDesign->addAction(actionAssignBudget); menuDesign->addAction(actionPlace); @@ -240,7 +257,10 @@ void BaseMainWindow::createMenusAndBars() // Main action bar mainActionBar = new QToolBar("Main"); addToolBar(Qt::TopToolBarArea, mainActionBar); + mainActionBar->addAction(actionNew); mainActionBar->addAction(actionLoadJSON); + mainActionBar->addAction(actionSaveJSON); + mainActionBar->addSeparator(); mainActionBar->addAction(actionPack); mainActionBar->addAction(actionAssignBudget); mainActionBar->addAction(actionPlace); @@ -280,7 +300,7 @@ void BaseMainWindow::load_json(std::string filename) if (parse_json_file(f, filename, ctx.get())) { log("Loading design successful.\n"); Q_EMIT updateTreeView(); - updateLoaded(); + updateActions(); } else { actionLoadJSON->setEnabled(true); log("Loading design failed.\n"); @@ -295,15 +315,26 @@ void BaseMainWindow::open_json() } } +void BaseMainWindow::save_json() +{ + QString fileName = QFileDialog::getSaveFileName(this, QString("Save JSON"), QString(), QString("*.json")); + if (!fileName.isEmpty()) { + std::string fn = fileName.toStdString(); + std::ofstream f(fn); + if (write_json_file(f, fn, ctx.get())) + log("Saving JSON successful.\n"); + else + log("Saving JSON failed.\n"); + } +} + void BaseMainWindow::pack_finished(bool status) { disableActions(); if (status) { log("Packing design successful.\n"); Q_EMIT updateTreeView(); - actionPlace->setEnabled(true); - actionAssignBudget->setEnabled(true); - onPackFinished(); + updateActions(); } else { log("Packing design failed.\n"); } @@ -313,9 +344,8 @@ void BaseMainWindow::budget_finish(bool status) { disableActions(); if (status) { - log("Assigning timing budget successful.\n"); - actionPlace->setEnabled(true); - onBudgetFinished(); + log("Assigning timing budget successful.\n"); + updateActions(); } else { log("Assigning timing budget failed.\n"); } @@ -327,8 +357,7 @@ void BaseMainWindow::place_finished(bool status) if (status) { log("Placing design successful.\n"); Q_EMIT updateTreeView(); - actionRoute->setEnabled(true); - onPlaceFinished(); + updateActions(); } else { log("Placing design failed.\n"); } @@ -339,7 +368,7 @@ void BaseMainWindow::route_finished(bool status) if (status) { log("Routing design successful.\n"); Q_EMIT updateTreeView(); - onRouteFinished(); + updateActions(); } else log("Routing design failed.\n"); } @@ -379,11 +408,12 @@ void BaseMainWindow::place() { Q_EMIT task->place(timing_driven); } void BaseMainWindow::disableActions() { - actionLoadJSON->setEnabled(false); + actionLoadJSON->setEnabled(true); actionPack->setEnabled(false); actionAssignBudget->setEnabled(false); actionPlace->setEnabled(false); actionRoute->setEnabled(false); + actionExecutePy->setEnabled(true); actionPlay->setEnabled(false); @@ -393,11 +423,18 @@ void BaseMainWindow::disableActions() onDisableActions(); } -void BaseMainWindow::updateLoaded() +void BaseMainWindow::updateActions() { - disableActions(); - actionPack->setEnabled(true); - onJsonLoaded(); + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionPack->setEnabled(true); + else if (ctx->settings.find(ctx->id("place"))==ctx->settings.end()) { + actionAssignBudget->setEnabled(true); + actionPlace->setEnabled(true); + } + else if (ctx->settings.find(ctx->id("route"))==ctx->settings.end()) + actionRoute->setEnabled(true); + + onUpdateActions(); } void BaseMainWindow::execute_python() diff --git a/gui/basewindow.h b/gui/basewindow.h index 91389978..d2640813 100644 --- a/gui/basewindow.h +++ b/gui/basewindow.h @@ -48,7 +48,8 @@ class BaseMainWindow : public QMainWindow explicit BaseMainWindow(std::unique_ptr context, ArchArgs args, QWidget *parent = 0); virtual ~BaseMainWindow(); Context *getContext() { return ctx.get(); } - void updateLoaded(); + void updateActions(); + void notifyChangeContext(); protected: @@ -57,11 +58,7 @@ class BaseMainWindow : public QMainWindow void load_json(std::string filename); virtual void onDisableActions(){}; - virtual void onJsonLoaded(){}; - virtual void onPackFinished(){}; - virtual void onBudgetFinished(){}; - virtual void onPlaceFinished(){}; - virtual void onRouteFinished(){}; + virtual void onUpdateActions(){}; protected Q_SLOTS: void writeInfo(std::string text); @@ -70,6 +67,7 @@ class BaseMainWindow : public QMainWindow virtual void new_proj() = 0; void open_json(); + void save_json(); void budget(); void place(); @@ -110,7 +108,10 @@ class BaseMainWindow : public QMainWindow QToolBar *mainActionBar; QProgressBar *progressBar; + QAction *actionNew; QAction *actionLoadJSON; + QAction *actionSaveJSON; + QAction *actionPack; QAction *actionAssignBudget; QAction *actionPlace; diff --git a/gui/create_img.sh b/gui/create_img.sh index 1508d023..fcce4e88 100755 --- a/gui/create_img.sh +++ b/gui/create_img.sh @@ -2,5 +2,6 @@ convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 ' convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'PCF'" resources/open.png ice40/resources/open_pcf.png convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'BASE'" resources/open.png ecp5/resources/open_base.png convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'LPF'" resources/open.png ecp5/resources/open_lpf.png -convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png -convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png \ No newline at end of file +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'ASC'" resources/save.png ice40/resources/save_asc.png +convert -font helvetica -fill red -pointsize 7 -gravity center -draw "text 2,8 'CONFIG'" resources/save.png ecp5/resources/save_config.png +convert -font helvetica -fill red -pointsize 8 -gravity center -draw "text 2,8 'JSON'" resources/save.png resources/save_json.png \ No newline at end of file diff --git a/gui/ecp5/mainwindow.cc b/gui/ecp5/mainwindow.cc index a54ab8b5..43b31f4c 100644 --- a/gui/ecp5/mainwindow.cc +++ b/gui/ecp5/mainwindow.cc @@ -188,8 +188,13 @@ void MainWindow::onDisableActions() actionSaveConfig->setEnabled(false); } -void MainWindow::onJsonLoaded() { actionLoadLPF->setEnabled(true); } - -void MainWindow::onRouteFinished() { actionLoadBase->setEnabled(true); } +void MainWindow::onUpdateActions() { + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadLPF->setEnabled(true); + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadBase->setEnabled(true); + if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) + actionSaveConfig->setEnabled(true); +} NEXTPNR_NAMESPACE_END diff --git a/gui/ecp5/mainwindow.h b/gui/ecp5/mainwindow.h index 186a7974..b47e7ec7 100644 --- a/gui/ecp5/mainwindow.h +++ b/gui/ecp5/mainwindow.h @@ -38,8 +38,7 @@ class MainWindow : public BaseMainWindow protected: void onDisableActions() override; - void onJsonLoaded() override; - void onRouteFinished() override; + void onUpdateActions() override; protected Q_SLOTS: void new_proj() override; diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc index b766734f..7c8effac 100644 --- a/gui/ice40/mainwindow.cc +++ b/gui/ice40/mainwindow.cc @@ -186,7 +186,11 @@ void MainWindow::onDisableActions() actionSaveAsc->setEnabled(false); } -void MainWindow::onJsonLoaded() { actionLoadPCF->setEnabled(true); } -void MainWindow::onRouteFinished() { actionSaveAsc->setEnabled(true); } +void MainWindow::onUpdateActions() { + if (ctx->settings.find(ctx->id("pack"))==ctx->settings.end()) + actionLoadPCF->setEnabled(true); + if (ctx->settings.find(ctx->id("route"))!=ctx->settings.end()) + actionSaveAsc->setEnabled(true); +} NEXTPNR_NAMESPACE_END diff --git a/gui/ice40/mainwindow.h b/gui/ice40/mainwindow.h index de160174..ed1b6aaf 100644 --- a/gui/ice40/mainwindow.h +++ b/gui/ice40/mainwindow.h @@ -39,8 +39,7 @@ class MainWindow : public BaseMainWindow void load_pcf(std::string filename); void onDisableActions() override; - void onJsonLoaded() override; - void onRouteFinished() override; + void onUpdateActions() override; protected Q_SLOTS: void new_proj() override; diff --git a/gui/resources/save_json.png b/gui/resources/save_json.png new file mode 100644 index 00000000..cbeb3243 Binary files /dev/null and b/gui/resources/save_json.png differ diff --git a/json/jsonparse.cc b/json/jsonparse.cc index b2597828..92bbf92f 100644 --- a/json/jsonparse.cc +++ b/json/jsonparse.cc @@ -740,7 +740,8 @@ void json_import(Context *ctx, string modname, JsonNode *node) for (int attrid = 0; attrid < GetSize(attr_node->data_dict_keys); attrid++) { json_import_top_attrib(ctx, modname, attr_node, &ctx->attrs, attrid); } - + ctx->settings[ctx->id("synth")] = "1"; + JsonNode *ports_parent = nullptr; if (node->data_dict.count("ports") > 0) ports_parent = node->data_dict.at("ports"); -- cgit v1.2.3