aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/basewindow.cc3
-rw-r--r--gui/designwidget.cc77
-rw-r--r--gui/designwidget.h22
-rw-r--r--gui/fpgaviewwidget.cc38
-rw-r--r--gui/fpgaviewwidget.h2
-rw-r--r--gui/ice40/mainwindow.cc2
6 files changed, 132 insertions, 12 deletions
diff --git a/gui/basewindow.cc b/gui/basewindow.cc
index 66df3ca4..92812285 100644
--- a/gui/basewindow.cc
+++ b/gui/basewindow.cc
@@ -109,6 +109,7 @@ BaseMainWindow::BaseMainWindow(std::unique_ptr<Context> context, ArchArgs args,
connect(designview, &DesignWidget::selected, fpgaView, &FPGAViewWidget::onSelectedArchItem);
connect(designview, &DesignWidget::zoomSelected, fpgaView, &FPGAViewWidget::zoomSelected);
connect(designview, &DesignWidget::highlight, fpgaView, &FPGAViewWidget::onHighlightGroupChanged);
+ connect(designview, &DesignWidget::hover, fpgaView, &FPGAViewWidget::onHoverItemChanged);
// Click event on device view
connect(fpgaView, &FPGAViewWidget::clickedBel, designview, &DesignWidget::onClickedBel);
@@ -420,7 +421,7 @@ void BaseMainWindow::disableActions()
actionNew->setEnabled(true);
actionOpen->setEnabled(true);
- if (ctx->settings.find(ctx->id("project/input/json")) != ctx->settings.end())
+ if (ctx->settings.find(ctx->id("input/json")) != ctx->settings.end())
actionSave->setEnabled(true);
else
actionSave->setEnabled(false);
diff --git a/gui/designwidget.cc b/gui/designwidget.cc
index 896ef071..c49df085 100644
--- a/gui/designwidget.cc
+++ b/gui/designwidget.cc
@@ -30,15 +30,34 @@
NEXTPNR_NAMESPACE_BEGIN
+TreeView::TreeView(QWidget *parent) : QTreeView(parent) {}
+
+TreeView::~TreeView() {}
+
+void TreeView::mouseMoveEvent(QMouseEvent *event)
+{
+ QModelIndex index = indexAt(event->pos());
+ if (index!=current) {
+ current = index;
+ Q_EMIT hoverIndexChanged(index);
+ }
+ QTreeView::mouseMoveEvent(event);
+}
+
+void TreeView::leaveEvent(QEvent *event)
+{
+ Q_EMIT hoverIndexChanged(QModelIndex());
+}
+
DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), selectionModel(nullptr)
{
// Add tree view
- treeView = new QTreeView();
+ treeView = new TreeView();
treeModel = new TreeModel::Model();
treeView->setModel(treeModel);
treeView->setContextMenuPolicy(Qt::CustomContextMenu);
treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
-
+ treeView->viewport()->setMouseTracking(true);
// Add property view
variantManager = new QtVariantPropertyManager(this);
readOnlyManager = new QtVariantPropertyManager(this);
@@ -50,6 +69,7 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
propertyEditor->show();
propertyEditor->treeWidget()->setContextMenuPolicy(Qt::CustomContextMenu);
propertyEditor->treeWidget()->setSelectionMode(QAbstractItemView::ExtendedSelection);
+ propertyEditor->treeWidget()->viewport()->setMouseTracking(true);
searchEdit = new QLineEdit();
searchEdit->setClearButtonEnabled(true);
@@ -158,9 +178,11 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(propertyEditor->treeWidget(), &QTreeWidget::customContextMenuRequested, this,
&DesignWidget::prepareMenuProperty);
connect(propertyEditor->treeWidget(), &QTreeWidget::itemDoubleClicked, this, &DesignWidget::onItemDoubleClicked);
+ connect(propertyEditor, &QtTreePropertyBrowser::hoverPropertyChanged, this, &DesignWidget::onHoverPropertyChanged);
- connect(treeView, &QTreeView::customContextMenuRequested, this, &DesignWidget::prepareMenuTree);
- connect(treeView, &QTreeView::doubleClicked, this, &DesignWidget::onDoubleClicked);
+ connect(treeView, &TreeView::customContextMenuRequested, this, &DesignWidget::prepareMenuTree);
+ connect(treeView, &TreeView::doubleClicked, this, &DesignWidget::onDoubleClicked);
+ connect(treeView, &TreeView::hoverIndexChanged, this, &DesignWidget::onHoverIndexChanged);
selectionModel = treeView->selectionModel();
connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &DesignWidget::onSelectionChanged);
@@ -388,7 +410,6 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
ElementType type = clickItem->type();
if (type == ElementType::NONE)
return;
- std::vector<DecalXY> decals;
addToHistory(index);
@@ -411,6 +432,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Conflicting Cell", ctx->nameOf(ctx->getConflictingBelCell(bel)),
ElementType::CELL);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getBelAttrs(bel)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
QtProperty *belpinsItem = addSubGroup(topItem, "Ports");
for (const auto &item : ctx->getBelPins(bel)) {
QtProperty *portInfoItem = addSubGroup(belpinsItem, item.c_str(ctx));
@@ -433,6 +459,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
ElementType::NET);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getWireAttrs(wire)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
DelayInfo delay = ctx->getWireDelay(wire);
QtProperty *delayItem = addSubGroup(topItem, "Delay");
@@ -492,6 +523,11 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
ElementType::WIRE);
+ QtProperty *attrsItem = addSubGroup(topItem, "Attributes");
+ for (auto &item : ctx->getPipAttrs(pip)) {
+ addProperty(attrsItem, QVariant::String, item.first.c_str(ctx), item.second.c_str());
+ }
+
DelayInfo delay = ctx->getPipDelay(pip);
QtProperty *delayItem = addSubGroup(topItem, "Delay");
@@ -785,4 +821,35 @@ void DesignWidget::onSearchInserted()
if (currentSearchIndexes.size() > 0 && currentIndex < currentSearchIndexes.size())
selectionModel->setCurrentIndex(currentSearchIndexes.at(currentIndex), QItemSelectionModel::ClearAndSelect);
}
+
+void DesignWidget::onHoverIndexChanged(QModelIndex index)
+{
+ if (index.isValid()) {
+ TreeModel::Item *item = treeModel->nodeFromIndex(index);
+ if (item->type() != ElementType::NONE) {
+ Q_EMIT hover(getDecals(item->type(), item->id()).at(0));
+ return;
+ }
+ }
+ Q_EMIT hover(DecalXY());
+}
+
+void DesignWidget::onHoverPropertyChanged(QtBrowserItem *item)
+{
+ if (item!=nullptr) {
+ QtProperty *selectedProperty = item->property();
+ ElementType type = getElementTypeByName(selectedProperty->propertyId());
+ if (type != ElementType::NONE) {
+ IdString value = ctx->id(selectedProperty->valueText().toStdString());
+ if (value!=IdString()) {
+ auto node = treeModel->nodeForIdType(type, value);
+ if (node) {
+ Q_EMIT hover(getDecals((*node)->type(), (*node)->id()).at(0));
+ return;
+ }
+ }
+ }
+ }
+ Q_EMIT hover(DecalXY());
+}
NEXTPNR_NAMESPACE_END
diff --git a/gui/designwidget.h b/gui/designwidget.h
index c78d7232..91da556a 100644
--- a/gui/designwidget.h
+++ b/gui/designwidget.h
@@ -22,6 +22,7 @@
#include <QTreeView>
#include <QVariant>
+#include <QMouseEvent>
#include "nextpnr.h"
#include "qtgroupboxpropertybrowser.h"
#include "qtpropertymanager.h"
@@ -31,6 +32,22 @@
NEXTPNR_NAMESPACE_BEGIN
+class TreeView : public QTreeView
+{
+ Q_OBJECT
+
+ public:
+ explicit TreeView(QWidget *parent = 0);
+ ~TreeView();
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void leaveEvent(QEvent *event) override;
+
+ Q_SIGNALS:
+ void hoverIndexChanged(QModelIndex index);
+ private:
+ QModelIndex current;
+};
+
class DesignWidget : public QWidget
{
Q_OBJECT
@@ -55,6 +72,7 @@ class DesignWidget : public QWidget
Q_SIGNALS:
void selected(std::vector<DecalXY> decal, bool keep);
void highlight(std::vector<DecalXY> decal, int group);
+ void hover(DecalXY decal);
void zoomSelected();
private Q_SLOTS:
@@ -64,6 +82,8 @@ class DesignWidget : public QWidget
void onItemDoubleClicked(QTreeWidgetItem *item, int column);
void onDoubleClicked(const QModelIndex &index);
void onSearchInserted();
+ void onHoverIndexChanged(QModelIndex index);
+ void onHoverPropertyChanged(QtBrowserItem *item);
public Q_SLOTS:
void newContext(Context *ctx);
void updateTree();
@@ -74,7 +94,7 @@ class DesignWidget : public QWidget
private:
Context *ctx;
- QTreeView *treeView;
+ TreeView *treeView;
QItemSelectionModel *selectionModel;
TreeModel::Model *treeModel;
QLineEdit *searchEdit;
diff --git a/gui/fpgaviewwidget.cc b/gui/fpgaviewwidget.cc
index 66739b28..53ee7282 100644
--- a/gui/fpgaviewwidget.cc
+++ b/gui/fpgaviewwidget.cc
@@ -240,9 +240,10 @@ void FPGAViewWidget::populateQuadTree(RendererData *data, const DecalXY &decal,
continue;
}
+ bool res = true;
if (el.type == GraphicElement::TYPE_BOX) {
// Boxes are bounded by themselves.
- data->qt->insert(PickQuadTree::BoundingBox(x + el.x1, y + el.y1, x + el.x2, y + el.y2), element);
+ res = data->qt->insert(PickQuadTree::BoundingBox(x + el.x1, y + el.y1, x + el.x2, y + el.y2), element);
}
if (el.type == GraphicElement::TYPE_LINE || el.type == GraphicElement::TYPE_ARROW) {
@@ -261,7 +262,11 @@ void FPGAViewWidget::populateQuadTree(RendererData *data, const DecalXY &decal,
x1 += 0.01;
y1 += 0.01;
- data->qt->insert(PickQuadTree::BoundingBox(x0, y0, x1, y1), element);
+ res = data->qt->insert(PickQuadTree::BoundingBox(x0, y0, x1, y1), element);
+ }
+
+ if (!res) {
+ NPNR_ASSERT_FALSE("populateQuadTree: could not insert element");
}
}
}
@@ -450,8 +455,17 @@ void FPGAViewWidget::renderLines(void)
NPNR_ASSERT(data->bbGlobal.w() != 0);
NPNR_ASSERT(data->bbGlobal.h() != 0);
+ // Enlarge the bounding box slightly for the picking - when we insert
+ // elements into it, we enlarge their bounding boxes slightly, so
+ // we need to give ourselves some sagery margin here.
+ auto bb = data->bbGlobal;
+ bb.setX0(bb.x0() - 1);
+ bb.setY0(bb.y0() - 1);
+ bb.setX1(bb.x1() + 1);
+ bb.setY1(bb.y1() + 1);
+
// Populate picking quadtree.
- data->qt = std::unique_ptr<PickQuadTree>(new PickQuadTree(data->bbGlobal));
+ data->qt = std::unique_ptr<PickQuadTree>(new PickQuadTree(bb));
for (auto const &decal : belDecals) {
populateQuadTree(data.get(), decal.first,
PickedElement::fromBel(decal.second, decal.first.x, decal.first.y));
@@ -545,6 +559,14 @@ void FPGAViewWidget::onHighlightGroupChanged(std::vector<DecalXY> decals, int gr
pokeRenderer();
}
+void FPGAViewWidget::onHoverItemChanged(DecalXY decal)
+{
+ QMutexLocker locked(&rendererArgsLock_);
+ rendererArgs_->hoveredDecal = decal;
+ rendererArgs_->changed = true;
+ pokeRenderer();
+}
+
void FPGAViewWidget::resizeGL(int width, int height) {}
boost::optional<FPGAViewWidget::PickedElement> FPGAViewWidget::pickElement(float worldx, float worldy)
@@ -736,7 +758,7 @@ void FPGAViewWidget::zoomOut() { zoom(-10); }
void FPGAViewWidget::zoomToBB(const PickQuadTree::BoundingBox &bb, float margin)
{
- if (bb.w() < 0.00005 && bb.h() < 0.00005)
+ if (fabs(bb.w()) < 0.00005 && fabs(bb.h()) < 0.00005)
return;
viewMove_.setToIdentity();
@@ -767,4 +789,12 @@ void FPGAViewWidget::zoomOutbound()
}
}
+void FPGAViewWidget::leaveEvent(QEvent *event)
+{
+ QMutexLocker locked(&rendererArgsLock_);
+ rendererArgs_->hoveredDecal = DecalXY();
+ rendererArgs_->changed = true;
+ pokeRenderer();
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/gui/fpgaviewwidget.h b/gui/fpgaviewwidget.h
index a40a0153..51a038fc 100644
--- a/gui/fpgaviewwidget.h
+++ b/gui/fpgaviewwidget.h
@@ -107,11 +107,13 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
QSize minimumSizeHint() const override;
QSize sizeHint() const override;
+ void leaveEvent(QEvent *event) override;
public Q_SLOTS:
void newContext(Context *ctx);
void onSelectedArchItem(std::vector<DecalXY> decals, bool keep);
void onHighlightGroupChanged(std::vector<DecalXY> decals, int group);
+ void onHoverItemChanged(DecalXY decal);
void pokeRenderer(void);
void zoomIn();
void zoomOut();
diff --git a/gui/ice40/mainwindow.cc b/gui/ice40/mainwindow.cc
index 9fe80717..f270b112 100644
--- a/gui/ice40/mainwindow.cc
+++ b/gui/ice40/mainwindow.cc
@@ -191,7 +191,7 @@ void MainWindow::onRouteFinished() { actionSaveAsc->setEnabled(true); }
void MainWindow::onProjectLoaded()
{
- if (ctx->settings.find(ctx->id("project/input/pcf")) != ctx->settings.end())
+ if (ctx->settings.find(ctx->id("input/pcf")) != ctx->settings.end())
actionLoadPCF->setEnabled(false);
}