diff options
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/basewindow.cc | 3 | ||||
| -rw-r--r-- | gui/designwidget.cc | 77 | ||||
| -rw-r--r-- | gui/designwidget.h | 22 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.cc | 38 | ||||
| -rw-r--r-- | gui/fpgaviewwidget.h | 2 | ||||
| -rw-r--r-- | gui/ice40/mainwindow.cc | 2 |
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);
}
|
