Merge pull request #93 from YosysHQ/gui_changes

Gui changes
This commit is contained in:
Miodrag Milanović 2018-11-10 23:00:34 -08:00 committed by GitHub
commit 6b197fde72
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 325 additions and 215 deletions

View File

@ -46,15 +46,28 @@ void TreeView::mouseMoveEvent(QMouseEvent *event)
void TreeView::leaveEvent(QEvent *event) { Q_EMIT hoverIndexChanged(QModelIndex()); } void TreeView::leaveEvent(QEvent *event) { Q_EMIT hoverIndexChanged(QModelIndex()); }
DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), selectionModel(nullptr) DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr)
{ {
tabWidget = new QTabWidget();
// Add tree view // Add tree view
treeView = new TreeView(); for (int i = 0; i < 6; i++) {
treeModel = new TreeModel::Model(); treeView[i] = new TreeView();
treeView->setModel(treeModel); treeModel[i] = new TreeModel::Model();
treeView->setContextMenuPolicy(Qt::CustomContextMenu); treeView[i]->setModel(treeModel[i]);
treeView->setSelectionMode(QAbstractItemView::ExtendedSelection); treeView[i]->setContextMenuPolicy(Qt::CustomContextMenu);
treeView->viewport()->setMouseTracking(true); treeView[i]->setSelectionMode(QAbstractItemView::ExtendedSelection);
treeView[i]->viewport()->setMouseTracking(true);
selectionModel[i] = nullptr;
}
tabWidget->addTab(treeView[0], "Bels");
tabWidget->addTab(treeView[1], "Wires");
tabWidget->addTab(treeView[2], "Pips");
tabWidget->addTab(treeView[3], "Cells");
tabWidget->addTab(treeView[4], "Nets");
tabWidget->addTab(treeView[5], "Groups");
// Add property view // Add property view
variantManager = new QtVariantPropertyManager(this); variantManager = new QtVariantPropertyManager(this);
readOnlyManager = new QtVariantPropertyManager(this); readOnlyManager = new QtVariantPropertyManager(this);
@ -80,7 +93,14 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(actionFirst, &QAction::triggered, this, [this] { connect(actionFirst, &QAction::triggered, this, [this] {
history_ignore = true; history_ignore = true;
history_index = 0; history_index = 0;
selectionModel->setCurrentIndex(history.at(history_index), QItemSelectionModel::ClearAndSelect); auto h = history.at(history_index);
if (tabWidget->currentIndex() != h.first) {
selectionModel[tabWidget->currentIndex()]->clearSelection();
tabWidget->setCurrentIndex(h.first);
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::Select);
} else {
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::ClearAndSelect);
}
updateButtons(); updateButtons();
}); });
@ -90,7 +110,14 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(actionPrev, &QAction::triggered, this, [this] { connect(actionPrev, &QAction::triggered, this, [this] {
history_ignore = true; history_ignore = true;
history_index--; history_index--;
selectionModel->setCurrentIndex(history.at(history_index), QItemSelectionModel::ClearAndSelect); auto h = history.at(history_index);
if (tabWidget->currentIndex() != h.first) {
selectionModel[tabWidget->currentIndex()]->clearSelection();
tabWidget->setCurrentIndex(h.first);
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::Select);
} else {
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::ClearAndSelect);
}
updateButtons(); updateButtons();
}); });
@ -100,7 +127,14 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(actionNext, &QAction::triggered, this, [this] { connect(actionNext, &QAction::triggered, this, [this] {
history_ignore = true; history_ignore = true;
history_index++; history_index++;
selectionModel->setCurrentIndex(history.at(history_index), QItemSelectionModel::ClearAndSelect); auto h = history.at(history_index);
if (tabWidget->currentIndex() != h.first) {
selectionModel[tabWidget->currentIndex()]->clearSelection();
tabWidget->setCurrentIndex(h.first);
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::Select);
} else {
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::ClearAndSelect);
}
updateButtons(); updateButtons();
}); });
@ -110,7 +144,14 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(actionLast, &QAction::triggered, this, [this] { connect(actionLast, &QAction::triggered, this, [this] {
history_ignore = true; history_ignore = true;
history_index = int(history.size() - 1); history_index = int(history.size() - 1);
selectionModel->setCurrentIndex(history.at(history_index), QItemSelectionModel::ClearAndSelect); auto h = history.at(history_index);
if (tabWidget->currentIndex() != h.first) {
selectionModel[tabWidget->currentIndex()]->clearSelection();
tabWidget->setCurrentIndex(h.first);
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::Select);
} else {
selectionModel[h.first]->setCurrentIndex(h.second, QItemSelectionModel::ClearAndSelect);
}
updateButtons(); updateButtons();
}); });
@ -120,11 +161,14 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(actionClear, &QAction::triggered, this, [this] { connect(actionClear, &QAction::triggered, this, [this] {
history_index = -1; history_index = -1;
history.clear(); history.clear();
QModelIndex index = selectionModel->selectedIndexes().at(0); int num = tabWidget->currentIndex();
if (selectionModel[num]->selectedIndexes().size() > 0) {
QModelIndex index = selectionModel[num]->selectedIndexes().at(0);
if (index.isValid()) { if (index.isValid()) {
ElementType type = treeModel->nodeFromIndex(index)->type(); ElementType type = treeModel[num]->nodeFromIndex(index)->type();
if (type != ElementType::NONE) if (type != ElementType::NONE)
addToHistory(index); addToHistory(num, index);
}
} }
updateButtons(); updateButtons();
}); });
@ -142,7 +186,7 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
vbox1->setSpacing(5); vbox1->setSpacing(5);
vbox1->setContentsMargins(0, 0, 0, 0); vbox1->setContentsMargins(0, 0, 0, 0);
vbox1->addWidget(searchEdit); vbox1->addWidget(searchEdit);
vbox1->addWidget(treeView); vbox1->addWidget(tabWidget);
QWidget *toolbarWidget = new QWidget(); QWidget *toolbarWidget = new QWidget();
QHBoxLayout *hbox = new QHBoxLayout; QHBoxLayout *hbox = new QHBoxLayout;
@ -177,11 +221,18 @@ DesignWidget::DesignWidget(QWidget *parent) : QWidget(parent), ctx(nullptr), sel
connect(propertyEditor->treeWidget(), &QTreeWidget::itemDoubleClicked, this, &DesignWidget::onItemDoubleClicked); connect(propertyEditor->treeWidget(), &QTreeWidget::itemDoubleClicked, this, &DesignWidget::onItemDoubleClicked);
connect(propertyEditor, &QtTreePropertyBrowser::hoverPropertyChanged, this, &DesignWidget::onHoverPropertyChanged); connect(propertyEditor, &QtTreePropertyBrowser::hoverPropertyChanged, this, &DesignWidget::onHoverPropertyChanged);
connect(treeView, &TreeView::customContextMenuRequested, this, &DesignWidget::prepareMenuTree); for (int num = 0; num < 6; num++) {
connect(treeView, &TreeView::doubleClicked, this, &DesignWidget::onDoubleClicked); connect(treeView[num], &TreeView::customContextMenuRequested,
connect(treeView, &TreeView::hoverIndexChanged, this, &DesignWidget::onHoverIndexChanged); [this, num](const QPoint &pos) { prepareMenuTree(num, pos); });
selectionModel = treeView->selectionModel(); connect(treeView[num], &TreeView::doubleClicked, [this](const QModelIndex &index) { onDoubleClicked(index); });
connect(selectionModel, &QItemSelectionModel::selectionChanged, this, &DesignWidget::onSelectionChanged); connect(treeView[num], &TreeView::hoverIndexChanged,
[this, num](QModelIndex index) { onHoverIndexChanged(num, index); });
selectionModel[num] = treeView[num]->selectionModel();
connect(selectionModel[num], &QItemSelectionModel::selectionChanged,
[this, num](const QItemSelection &selected, const QItemSelection &deselected) {
onSelectionChanged(num, selected, deselected);
});
}
history_index = -1; history_index = -1;
history_ignore = false; history_ignore = false;
@ -207,13 +258,13 @@ void DesignWidget::updateButtons()
actionLast->setEnabled(history_index < (count - 1)); actionLast->setEnabled(history_index < (count - 1));
} }
void DesignWidget::addToHistory(QModelIndex item) void DesignWidget::addToHistory(int tab, QModelIndex item)
{ {
if (!history_ignore) { if (!history_ignore) {
int count = int(history.size()); int count = int(history.size());
for (int i = count - 1; i > history_index; i--) for (int i = count - 1; i > history_index; i--)
history.pop_back(); history.pop_back();
history.push_back(item); history.push_back(std::make_pair(tab, item));
history_index++; history_index++;
} }
history_ignore = false; history_ignore = false;
@ -236,7 +287,53 @@ void DesignWidget::newContext(Context *ctx)
{ {
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
treeModel->loadContext(ctx);
{
TreeModel::ElementXYRoot<BelId>::ElementMap belMap;
for (const auto& bel : ctx->getBels()) {
auto loc = ctx->getBelLocation(bel);
belMap[std::pair<int, int>(loc.x, loc.y)].push_back(bel);
}
auto belGetter = [](Context *ctx, BelId id) { return ctx->getBelName(id); };
getTreeByElementType(ElementType::BEL)
->loadData(std::unique_ptr<TreeModel::ElementXYRoot<BelId>>(
new TreeModel::ElementXYRoot<BelId>(ctx, belMap, belGetter, ElementType::BEL)));
}
#ifdef ARCH_ICE40
{
TreeModel::ElementXYRoot<WireId>::ElementMap wireMap;
for (int i = 0; i < ctx->chip_info->num_wires; i++) {
const auto wire = &ctx->chip_info->wire_data[i];
WireId wireid;
wireid.index = i;
wireMap[std::pair<int, int>(wire->x, wire->y)].push_back(wireid);
}
auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
getTreeByElementType(ElementType::WIRE)
->loadData(std::unique_ptr<TreeModel::ElementXYRoot<WireId>>(
new TreeModel::ElementXYRoot<WireId>(ctx, wireMap, wireGetter, ElementType::WIRE)));
}
{
TreeModel::ElementXYRoot<PipId>::ElementMap pipMap;
for (int i = 0; i < ctx->chip_info->num_pips; i++) {
const auto pip = &ctx->chip_info->pip_data[i];
PipId pipid;
pipid.index = i;
pipMap[std::pair<int, int>(pip->x, pip->y)].push_back(pipid);
}
auto pipGetter = [](Context *ctx, PipId id) { return ctx->getPipName(id); };
getTreeByElementType(ElementType::PIP)
->loadData(std::unique_ptr<TreeModel::ElementXYRoot<PipId>>(
new TreeModel::ElementXYRoot<PipId>(ctx, pipMap, pipGetter, ElementType::PIP)));
}
#endif
getTreeByElementType(ElementType::CELL)
->loadData(std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::CELL)));
getTreeByElementType(ElementType::NET)
->loadData(std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::NET)));
} }
updateTree(); updateTree();
} }
@ -260,7 +357,18 @@ void DesignWidget::updateTree()
{ {
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
treeModel->updateCellsNets(ctx);
std::vector<IdString> cells;
for (auto &pair : ctx->cells) {
cells.push_back(pair.first);
}
std::vector<IdString> nets;
for (auto &pair : ctx->nets) {
nets.push_back(pair.first);
}
getTreeByElementType(ElementType::CELL)->updateElements(ctx, cells);
getTreeByElementType(ElementType::NET)->updateElements(ctx, nets);
} }
} }
QtProperty *DesignWidget::addTopLevelProperty(const QString &id) QtProperty *DesignWidget::addTopLevelProperty(const QString &id)
@ -315,6 +423,40 @@ ElementType DesignWidget::getElementTypeByName(QString type)
return ElementType::NONE; return ElementType::NONE;
} }
TreeModel::Model *DesignWidget::getTreeByElementType(ElementType type)
{
if (type == ElementType::NONE)
return nullptr;
if (type == ElementType::BEL)
return treeModel[0];
if (type == ElementType::WIRE)
return treeModel[1];
if (type == ElementType::PIP)
return treeModel[2];
if (type == ElementType::NET)
return treeModel[3];
if (type == ElementType::CELL)
return treeModel[4];
return nullptr;
}
int DesignWidget::getIndexByElementType(ElementType type)
{
if (type == ElementType::NONE)
return -1;
if (type == ElementType::BEL)
return 0;
if (type == ElementType::WIRE)
return 1;
if (type == ElementType::PIP)
return 2;
if (type == ElementType::NET)
return 3;
if (type == ElementType::CELL)
return 4;
if (type == ElementType::GROUP)
return 5;
return -1;
}
void DesignWidget::addProperty(QtProperty *topItem, int propertyType, const QString &name, QVariant value, void DesignWidget::addProperty(QtProperty *topItem, int propertyType, const QString &name, QVariant value,
const ElementType &type) const ElementType &type)
{ {
@ -333,6 +475,12 @@ QtProperty *DesignWidget::addSubGroup(QtProperty *topItem, const QString &name)
return item; return item;
} }
void DesignWidget::clearAllSelectionModels()
{
for (int i = 0; i <= getIndexByElementType(ElementType::GROUP); i++)
selectionModel[i]->clearSelection();
}
void DesignWidget::onClickedBel(BelId bel, bool keep) void DesignWidget::onClickedBel(BelId bel, bool keep)
{ {
boost::optional<TreeModel::Item *> item; boost::optional<TreeModel::Item *> item;
@ -340,13 +488,19 @@ void DesignWidget::onClickedBel(BelId bel, bool keep)
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
item = treeModel->nodeForIdType(ElementType::BEL, ctx->getBelName(bel)); item = getTreeByElementType(ElementType::BEL)->nodeForId(ctx->getBelName(bel));
if (!item) if (!item)
return; return;
Q_EMIT selected(getDecals(ElementType::BEL, ctx->getBelName(bel)), keep); Q_EMIT selected(getDecals(ElementType::BEL, ctx->getBelName(bel)), keep);
} }
selectionModel->setCurrentIndex(treeModel->indexFromNode(*item), int index = getIndexByElementType(ElementType::BEL);
if (!keep)
clearAllSelectionModels();
if (tabWidget->currentIndex() != index) {
tabWidget->setCurrentIndex(index);
}
selectionModel[index]->setCurrentIndex(getTreeByElementType(ElementType::BEL)->indexFromNode(*item),
keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect); keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect);
} }
@ -357,13 +511,18 @@ void DesignWidget::onClickedWire(WireId wire, bool keep)
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
item = treeModel->nodeForIdType(ElementType::WIRE, ctx->getWireName(wire)); item = getTreeByElementType(ElementType::WIRE)->nodeForId(ctx->getWireName(wire));
if (!item) if (!item)
return; return;
Q_EMIT selected(getDecals(ElementType::WIRE, ctx->getWireName(wire)), keep); Q_EMIT selected(getDecals(ElementType::WIRE, ctx->getWireName(wire)), keep);
} }
selectionModel->setCurrentIndex(treeModel->indexFromNode(*item), int index = getIndexByElementType(ElementType::WIRE);
if (!keep)
clearAllSelectionModels();
if (tabWidget->currentIndex() != index)
tabWidget->setCurrentIndex(index);
selectionModel[index]->setCurrentIndex(getTreeByElementType(ElementType::WIRE)->indexFromNode(*item),
keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect); keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect);
} }
@ -374,41 +533,49 @@ void DesignWidget::onClickedPip(PipId pip, bool keep)
std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex); std::lock_guard<std::mutex> lock_ui(ctx->ui_mutex);
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
item = treeModel->nodeForIdType(ElementType::PIP, ctx->getPipName(pip)); item = getTreeByElementType(ElementType::PIP)->nodeForId(ctx->getPipName(pip));
if (!item) if (!item)
return; return;
Q_EMIT selected(getDecals(ElementType::PIP, ctx->getPipName(pip)), keep); Q_EMIT selected(getDecals(ElementType::PIP, ctx->getPipName(pip)), keep);
} }
selectionModel->setCurrentIndex(treeModel->indexFromNode(*item),
int index = getIndexByElementType(ElementType::PIP);
if (!keep)
clearAllSelectionModels();
if (tabWidget->currentIndex() != index)
tabWidget->setCurrentIndex(index);
selectionModel[index]->setCurrentIndex(getTreeByElementType(ElementType::PIP)->indexFromNode(*item),
keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect); keep ? QItemSelectionModel::Select : QItemSelectionModel::ClearAndSelect);
} }
void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelection &) void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QItemSelection &)
{ {
if (selectionModel->selectedIndexes().size() == 0) int num_selected = 0;
return;
if (selectionModel->selectedIndexes().size() > 1) {
std::vector<DecalXY> decals; std::vector<DecalXY> decals;
for (auto index : selectionModel->selectedIndexes()) { for (int i = 0; i <= getIndexByElementType(ElementType::GROUP); i++) {
TreeModel::Item *item = treeModel->nodeFromIndex(index); num_selected += selectionModel[i]->selectedIndexes().size();
for (auto index : selectionModel[i]->selectedIndexes()) {
TreeModel::Item *item = treeModel[i]->nodeFromIndex(index);
std::vector<DecalXY> d = getDecals(item->type(), item->id()); std::vector<DecalXY> d = getDecals(item->type(), item->id());
std::move(d.begin(), d.end(), std::back_inserter(decals)); std::move(d.begin(), d.end(), std::back_inserter(decals));
} }
}
if (num_selected > 1 || (selectionModel[num]->selectedIndexes().size() == 0)) {
Q_EMIT selected(decals, false); Q_EMIT selected(decals, false);
return; return;
} }
QModelIndex index = selectionModel->selectedIndexes().at(0);
QModelIndex index = selectionModel[num]->selectedIndexes().at(0);
if (!index.isValid()) if (!index.isValid())
return; return;
TreeModel::Item *clickItem = treeModel->nodeFromIndex(index); TreeModel::Item *clickItem = treeModel[num]->nodeFromIndex(index);
ElementType type = clickItem->type(); ElementType type = clickItem->type();
if (type == ElementType::NONE) if (type == ElementType::NONE)
return; return;
addToHistory(index); addToHistory(num, index);
clearProperties(); clearProperties();
@ -714,7 +881,7 @@ void DesignWidget::prepareMenuProperty(const QPoint &pos)
if (type == ElementType::NONE) if (type == ElementType::NONE)
continue; continue;
IdString value = ctx->id(selectedProperty->valueText().toStdString()); IdString value = ctx->id(selectedProperty->valueText().toStdString());
auto node = treeModel->nodeForIdType(type, value); auto node = getTreeByElementType(type)->nodeForId(value);
if (!node) if (!node)
continue; continue;
items.append(*node); items.append(*node);
@ -755,18 +922,20 @@ void DesignWidget::prepareMenuProperty(const QPoint &pos)
menu.exec(tree->mapToGlobal(pos)); menu.exec(tree->mapToGlobal(pos));
} }
void DesignWidget::prepareMenuTree(const QPoint &pos) void DesignWidget::prepareMenuTree(int num, const QPoint &pos)
{ {
int selectedIndex = -1; int selectedIndex = -1;
if (selectionModel->selectedIndexes().size() == 0) if (selectionModel[num]->selectedIndexes().size() == 0)
return; return;
QList<TreeModel::Item *> items; QList<TreeModel::Item *> items;
for (auto index : selectionModel->selectedIndexes()) { for (int i = 0; i <= getIndexByElementType(ElementType::GROUP); i++) {
TreeModel::Item *item = treeModel->nodeFromIndex(index); for (auto index : selectionModel[i]->selectedIndexes()) {
TreeModel::Item *item = treeModel[i]->nodeFromIndex(index);
items.append(item); items.append(item);
} }
}
if (items.size() == 1) { if (items.size() == 1) {
TreeModel::Item *item = items.at(0); TreeModel::Item *item = items.at(0);
if (highlightSelected.contains(item)) if (highlightSelected.contains(item))
@ -787,23 +956,31 @@ void DesignWidget::prepareMenuTree(const QPoint &pos)
action->setChecked(true); action->setChecked(true);
connect(action, &QAction::triggered, this, [this, i, items] { updateHighlightGroup(items, i); }); connect(action, &QAction::triggered, this, [this, i, items] { updateHighlightGroup(items, i); });
} }
menu.exec(treeView->mapToGlobal(pos)); menu.exec(treeView[num]->mapToGlobal(pos));
} }
void DesignWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column) void DesignWidget::onItemDoubleClicked(QTreeWidgetItem *item, int column)
{ {
QtProperty *selectedProperty = propertyEditor->itemToBrowserItem(item)->property(); QtProperty *selectedProperty = propertyEditor->itemToBrowserItem(item)->property();
ElementType type = getElementTypeByName(selectedProperty->propertyId()); ElementType type = getElementTypeByName(selectedProperty->propertyId());
auto it = treeModel->nodeForIdType(type, ctx->id(selectedProperty->valueText().toStdString())); if (type == ElementType::NONE)
if (it) return;
selectionModel->setCurrentIndex(treeModel->indexFromNode(*it), QItemSelectionModel::ClearAndSelect); auto it = getTreeByElementType(type)->nodeForId(ctx->id(selectedProperty->valueText().toStdString()));
if (it) {
int num = getIndexByElementType(type);
clearAllSelectionModels();
if (tabWidget->currentIndex() != num)
tabWidget->setCurrentIndex(num);
selectionModel[num]->setCurrentIndex(getTreeByElementType(type)->indexFromNode(*it),
QItemSelectionModel::ClearAndSelect);
}
} }
void DesignWidget::onDoubleClicked(const QModelIndex &index) { Q_EMIT zoomSelected(); } void DesignWidget::onDoubleClicked(const QModelIndex &index) { Q_EMIT zoomSelected(); }
void DesignWidget::onSearchInserted() void DesignWidget::onSearchInserted()
{ {
if (currentSearch == searchEdit->text()) { if (currentSearch == searchEdit->text() && currentIndexTab == tabWidget->currentIndex()) {
currentIndex++; currentIndex++;
if (currentIndex >= currentSearchIndexes.size()) if (currentIndex >= currentSearchIndexes.size())
currentIndex = 0; currentIndex = 0;
@ -812,17 +989,19 @@ void DesignWidget::onSearchInserted()
std::lock_guard<std::mutex> lock(ctx->mutex); std::lock_guard<std::mutex> lock(ctx->mutex);
currentSearch = searchEdit->text(); currentSearch = searchEdit->text();
currentSearchIndexes = treeModel->search(searchEdit->text()); currentSearchIndexes = treeModel[tabWidget->currentIndex()]->search(searchEdit->text());
currentIndex = 0; currentIndex = 0;
currentIndexTab = tabWidget->currentIndex();
} }
if (currentSearchIndexes.size() > 0 && currentIndex < currentSearchIndexes.size()) if (currentSearchIndexes.size() > 0 && currentIndex < currentSearchIndexes.size())
selectionModel->setCurrentIndex(currentSearchIndexes.at(currentIndex), QItemSelectionModel::ClearAndSelect); selectionModel[tabWidget->currentIndex()]->setCurrentIndex(currentSearchIndexes.at(currentIndex),
QItemSelectionModel::ClearAndSelect);
} }
void DesignWidget::onHoverIndexChanged(QModelIndex index) void DesignWidget::onHoverIndexChanged(int num, QModelIndex index)
{ {
if (index.isValid()) { if (index.isValid()) {
TreeModel::Item *item = treeModel->nodeFromIndex(index); TreeModel::Item *item = treeModel[num]->nodeFromIndex(index);
if (item->type() != ElementType::NONE) { if (item->type() != ElementType::NONE) {
std::vector<DecalXY> decals = getDecals(item->type(), item->id()); std::vector<DecalXY> decals = getDecals(item->type(), item->id());
if (decals.size() > 0) if (decals.size() > 0)
@ -841,7 +1020,7 @@ void DesignWidget::onHoverPropertyChanged(QtBrowserItem *item)
if (type != ElementType::NONE) { if (type != ElementType::NONE) {
IdString value = ctx->id(selectedProperty->valueText().toStdString()); IdString value = ctx->id(selectedProperty->valueText().toStdString());
if (value != IdString()) { if (value != IdString()) {
auto node = treeModel->nodeForIdType(type, value); auto node = getTreeByElementType(type)->nodeForId(value);
if (node) { if (node) {
std::vector<DecalXY> decals = getDecals((*node)->type(), (*node)->id()); std::vector<DecalXY> decals = getDecals((*node)->type(), (*node)->id());
if (decals.size() > 0) if (decals.size() > 0)

View File

@ -21,6 +21,7 @@
#define DESIGNWIDGET_H #define DESIGNWIDGET_H
#include <QMouseEvent> #include <QMouseEvent>
#include <QTabWidget>
#include <QTreeView> #include <QTreeView>
#include <QVariant> #include <QVariant>
#include "nextpnr.h" #include "nextpnr.h"
@ -65,11 +66,14 @@ class DesignWidget : public QWidget
const ElementType &type = ElementType::NONE); const ElementType &type = ElementType::NONE);
QString getElementTypeName(ElementType type); QString getElementTypeName(ElementType type);
ElementType getElementTypeByName(QString type); ElementType getElementTypeByName(QString type);
TreeModel::Model *getTreeByElementType(ElementType type);
int getIndexByElementType(ElementType type);
int getElementIndex(ElementType type); int getElementIndex(ElementType type);
void updateButtons(); void updateButtons();
void addToHistory(QModelIndex item); void addToHistory(int tab, QModelIndex item);
std::vector<DecalXY> getDecals(ElementType type, IdString value); std::vector<DecalXY> getDecals(ElementType type, IdString value);
void updateHighlightGroup(QList<TreeModel::Item *> item, int group); void updateHighlightGroup(QList<TreeModel::Item *> item, int group);
void clearAllSelectionModels();
Q_SIGNALS: Q_SIGNALS:
void selected(std::vector<DecalXY> decal, bool keep); void selected(std::vector<DecalXY> decal, bool keep);
void highlight(std::vector<DecalXY> decal, int group); void highlight(std::vector<DecalXY> decal, int group);
@ -78,12 +82,12 @@ class DesignWidget : public QWidget
private Q_SLOTS: private Q_SLOTS:
void prepareMenuProperty(const QPoint &pos); void prepareMenuProperty(const QPoint &pos);
void prepareMenuTree(const QPoint &pos); void prepareMenuTree(int num, const QPoint &pos);
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void onSelectionChanged(int num, const QItemSelection &selected, const QItemSelection &deselected);
void onItemDoubleClicked(QTreeWidgetItem *item, int column); void onItemDoubleClicked(QTreeWidgetItem *item, int column);
void onDoubleClicked(const QModelIndex &index); void onDoubleClicked(const QModelIndex &index);
void onSearchInserted(); void onSearchInserted();
void onHoverIndexChanged(QModelIndex index); void onHoverIndexChanged(int num, QModelIndex index);
void onHoverPropertyChanged(QtBrowserItem *item); void onHoverPropertyChanged(QtBrowserItem *item);
public Q_SLOTS: public Q_SLOTS:
void newContext(Context *ctx); void newContext(Context *ctx);
@ -95,9 +99,11 @@ class DesignWidget : public QWidget
private: private:
Context *ctx; Context *ctx;
TreeView *treeView; QTabWidget *tabWidget;
QItemSelectionModel *selectionModel;
TreeModel::Model *treeModel; TreeView *treeView[6];
QItemSelectionModel *selectionModel[6];
TreeModel::Model *treeModel[6];
QLineEdit *searchEdit; QLineEdit *searchEdit;
QtVariantPropertyManager *variantManager; QtVariantPropertyManager *variantManager;
QtVariantPropertyManager *readOnlyManager; QtVariantPropertyManager *readOnlyManager;
@ -108,7 +114,7 @@ class DesignWidget : public QWidget
QMap<QtProperty *, QString> propertyToId; QMap<QtProperty *, QString> propertyToId;
QMap<QString, QtProperty *> idToProperty; QMap<QString, QtProperty *> idToProperty;
std::vector<QModelIndex> history; std::vector<std::pair<int, QModelIndex>> history;
int history_index; int history_index;
bool history_ignore; bool history_ignore;
@ -124,6 +130,7 @@ class DesignWidget : public QWidget
QString currentSearch; QString currentSearch;
QList<QModelIndex> currentSearchIndexes; QList<QModelIndex> currentSearchIndexes;
int currentIndex; int currentIndex;
int currentIndexTab;
}; };
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -56,6 +56,7 @@ FPGAViewWidget::FPGAViewWidget(QWidget *parent)
colors_.highlight[7] = QColor("#da70d6"); colors_.highlight[7] = QColor("#da70d6");
rendererArgs_->changed = false; rendererArgs_->changed = false;
rendererArgs_->gridChanged = false;
rendererArgs_->flags.zoomOutbound = true; rendererArgs_->flags.zoomOutbound = true;
auto fmt = format(); auto fmt = format();
@ -86,6 +87,11 @@ FPGAViewWidget::~FPGAViewWidget() {}
void FPGAViewWidget::newContext(Context *ctx) void FPGAViewWidget::newContext(Context *ctx)
{ {
ctx_ = ctx; ctx_ = ctx;
{
QMutexLocker lock(&rendererArgsLock_);
rendererArgs_->gridChanged = true;
}
onSelectedArchItem(std::vector<DecalXY>(), false); onSelectedArchItem(std::vector<DecalXY>(), false);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
onHighlightGroupChanged(std::vector<DecalXY>(), i); onHighlightGroupChanged(std::vector<DecalXY>(), i);
@ -109,19 +115,6 @@ void FPGAViewWidget::initializeGL()
QtImGui::initialize(this); QtImGui::initialize(this);
glClearColor(colors_.background.red() / 255, colors_.background.green() / 255, glClearColor(colors_.background.red() / 255, colors_.background.green() / 255,
colors_.background.blue() / 255, 0.0); colors_.background.blue() / 255, 0.0);
{
QMutexLocker locker(&rendererDataLock_);
// Render grid.
auto grid = LineShaderData();
for (float i = -100.0f; i < 100.0f; i += 1.0f) {
PolyLine(-100.0f, i, 100.0f, i).build(grid);
PolyLine(i, -100.0f, i, 100.0f).build(grid);
}
grid.last_render = 1;
lineShader_.update_vbos(GraphicElement::STYLE_GRID, grid);
}
} }
float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy) const float FPGAViewWidget::PickedElement::distance(Context *ctx, float wx, float wy) const
@ -444,6 +437,7 @@ void FPGAViewWidget::renderLines(void)
DecalXY hoveredDecal; DecalXY hoveredDecal;
std::vector<DecalXY> highlightedDecals[8]; std::vector<DecalXY> highlightedDecals[8];
bool highlightedOrSelectedChanged; bool highlightedOrSelectedChanged;
bool gridChanged;
PassthroughFlags flags; PassthroughFlags flags;
{ {
// Take the renderer arguments lock, copy over all we need. // Take the renderer arguments lock, copy over all we need.
@ -456,7 +450,9 @@ void FPGAViewWidget::renderLines(void)
highlightedDecals[i] = rendererArgs_->highlightedDecals[i]; highlightedDecals[i] = rendererArgs_->highlightedDecals[i];
highlightedOrSelectedChanged = rendererArgs_->changed; highlightedOrSelectedChanged = rendererArgs_->changed;
gridChanged = rendererArgs_->gridChanged;
rendererArgs_->changed = false; rendererArgs_->changed = false;
rendererArgs_->gridChanged = false;
flags = rendererArgs_->flags; flags = rendererArgs_->flags;
} }
@ -528,6 +524,7 @@ void FPGAViewWidget::renderLines(void)
// If we're not re-rendering any highlights/selections, let's // If we're not re-rendering any highlights/selections, let's
// copy them over from teh current object. // copy them over from teh current object.
data->gfxGrid = rendererData_->gfxGrid;
if (!highlightedOrSelectedChanged) { if (!highlightedOrSelectedChanged) {
data->gfxSelected = rendererData_->gfxSelected; data->gfxSelected = rendererData_->gfxSelected;
data->gfxHovered = rendererData_->gfxHovered; data->gfxHovered = rendererData_->gfxHovered;
@ -539,7 +536,19 @@ void FPGAViewWidget::renderLines(void)
rendererData_ = std::move(data); rendererData_ = std::move(data);
} }
} }
if (gridChanged)
{
QMutexLocker locker(&rendererDataLock_);
rendererData_->gfxGrid.clear();
// Render grid.
for (float i = 0.0f; i < 1.0f * ctx_->getGridDimX() + 1; i += 1.0f) {
PolyLine(i, 0.0f, i, 1.0f * ctx_->getGridDimY()).build(rendererData_->gfxGrid);
}
for (float i = 0.0f; i < 1.0f * ctx_->getGridDimY() + 1; i += 1.0f) {
PolyLine(0.0f, i, 1.0f * ctx_->getGridDimX(), i).build(rendererData_->gfxGrid);
}
rendererData_->gfxGrid.last_render++;
}
if (highlightedOrSelectedChanged) { if (highlightedOrSelectedChanged) {
QMutexLocker locker(&rendererDataLock_); QMutexLocker locker(&rendererDataLock_);
@ -851,6 +860,7 @@ void FPGAViewWidget::zoomSelected()
{ {
{ {
QMutexLocker lock(&rendererDataLock_); QMutexLocker lock(&rendererDataLock_);
if (rendererData_->bbSelected.x0() != std::numeric_limits<float>::infinity())
zoomToBB(rendererData_->bbSelected, 0.5f, true); zoomToBB(rendererData_->bbSelected, 0.5f, true);
} }
update(); update();
@ -876,6 +886,8 @@ void FPGAViewWidget::leaveEvent(QEvent *event)
void FPGAViewWidget::update_vbos() void FPGAViewWidget::update_vbos()
{ {
lineShader_.update_vbos(GraphicElement::STYLE_GRID, rendererData_->gfxGrid);
for (int style = GraphicElement::STYLE_FRAME; style for (int style = GraphicElement::STYLE_FRAME; style
< GraphicElement::STYLE_HIGHLIGHTED0; < GraphicElement::STYLE_HIGHLIGHTED0;
style++) { style++) {

View File

@ -265,6 +265,8 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
DecalXY hoveredDecal; DecalXY hoveredDecal;
// Whether to render the above three or skip it. // Whether to render the above three or skip it.
bool changed; bool changed;
// Whether to render grid or skip it.
bool gridChanged;
// Flags to pass back into the RendererData. // Flags to pass back into the RendererData.
PassthroughFlags flags; PassthroughFlags flags;
@ -278,6 +280,7 @@ class FPGAViewWidget : public QOpenGLWidget, protected QOpenGLFunctions
struct RendererData struct RendererData
{ {
LineShaderData gfxGrid;
LineShaderData gfxByStyle[GraphicElement::STYLE_MAX]; LineShaderData gfxByStyle[GraphicElement::STYLE_MAX];
LineShaderData gfxSelected; LineShaderData gfxSelected;
LineShaderData gfxHovered; LineShaderData gfxHovered;

View File

@ -266,7 +266,7 @@ template <typename CoordinateT, typename ElementT> class QuadTreeNode
splitx_ = (bound_.x1_ - bound_.x0_) / 2 + bound_.x0_; splitx_ = (bound_.x1_ - bound_.x0_) / 2 + bound_.x0_;
splity_ = (bound_.y1_ - bound_.y0_) / 2 + bound_.y0_; splity_ = (bound_.y1_ - bound_.y0_) / 2 + bound_.y0_;
// Create the new children. // Create the new children.
children_ = decltype(children_)(new QuadTreeNode<CoordinateT, ElementT>[4] { children_ = decltype(children_)(new QuadTreeNode<CoordinateT, ElementT>[4]{
// Note: not using [NW] = QuadTreeNode because that seems to // Note: not using [NW] = QuadTreeNode because that seems to
// crash g++ 7.3.0. // crash g++ 7.3.0.
/* NW */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, bound_.y0_, splitx_, splity_), /* NW */ QuadTreeNode<CoordinateT, ElementT>(BoundingBox(bound_.x0_, bound_.y0_, splitx_, splity_),

View File

@ -154,80 +154,20 @@ Model::Model(QObject *parent) : QAbstractItemModel(parent), root_(new Item("Elem
Model::~Model() {} Model::~Model() {}
void Model::loadContext(Context *ctx) void Model::loadData(std::unique_ptr<Item> data)
{ {
if (!ctx)
return;
ctx_ = ctx;
beginResetModel(); beginResetModel();
root_ = std::move(data);
// Currently we lack an API to get a proper hierarchy of bels/pip/wires
// cross-arch. So we only do this for ICE40 by querying the ChipDB
// directly.
// TODO(q3k): once AnyId and the tree API land in Arch, move this over.
#ifdef ARCH_ICE40
{
std::map<std::pair<int, int>, std::vector<BelId>> belMap;
for (auto bel : ctx->getBels()) {
auto loc = ctx->getBelLocation(bel);
belMap[std::pair<int, int>(loc.x, loc.y)].push_back(bel);
}
auto belGetter = [](Context *ctx, BelId id) { return ctx->getBelName(id); };
bel_root_ = std::unique_ptr<BelXYRoot>(
new BelXYRoot(ctx, "Bels", root_.get(), belMap, belGetter, ElementType::BEL));
std::map<std::pair<int, int>, std::vector<WireId>> wireMap;
for (int i = 0; i < ctx->chip_info->num_wires; i++) {
const auto wire = &ctx->chip_info->wire_data[i];
WireId wireid;
wireid.index = i;
wireMap[std::pair<int, int>(wire->x, wire->y)].push_back(wireid);
}
auto wireGetter = [](Context *ctx, WireId id) { return ctx->getWireName(id); };
wire_root_ = std::unique_ptr<WireXYRoot>(
new WireXYRoot(ctx, "Wires", root_.get(), wireMap, wireGetter, ElementType::WIRE));
std::map<std::pair<int, int>, std::vector<PipId>> pipMap;
for (int i = 0; i < ctx->chip_info->num_pips; i++) {
const auto pip = &ctx->chip_info->pip_data[i];
PipId pipid;
pipid.index = i;
pipMap[std::pair<int, int>(pip->x, pip->y)].push_back(pipid);
}
auto pipGetter = [](Context *ctx, PipId id) { return ctx->getPipName(id); };
pip_root_ = std::unique_ptr<PipXYRoot>(
new PipXYRoot(ctx, "Pips", root_.get(), pipMap, pipGetter, ElementType::PIP));
}
#endif
cell_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Cells"), root_.get(), ElementType::CELL));
net_root_ = std::unique_ptr<IdStringList>(new IdStringList(QString("Nets"), root_.get(), ElementType::NET));
endResetModel(); endResetModel();
updateCellsNets(ctx);
} }
void Model::updateCellsNets(Context *ctx) void Model::updateElements(Context *ctx, std::vector<IdString> elements)
{ {
if (!ctx) if (!ctx)
return; return;
beginResetModel(); beginResetModel();
root_->updateElements(ctx, elements);
std::vector<IdString> cells;
for (auto &pair : ctx->cells) {
cells.push_back(pair.first);
}
cell_root_->updateElements(ctx, cells);
std::vector<IdString> nets;
for (auto &pair : ctx->nets) {
nets.push_back(pair.first);
}
net_root_->updateElements(ctx, nets);
endResetModel(); endResetModel();
} }
@ -302,11 +242,7 @@ QList<QModelIndex> Model::search(QString text)
{ {
const int limit = 500; const int limit = 500;
QList<Item *> list; QList<Item *> list;
cell_root_->search(list, text, limit); root_->search(list, text, limit);
net_root_->search(list, text, limit);
bel_root_->search(list, text, limit);
wire_root_->search(list, text, limit);
pip_root_->search(list, text, limit);
QList<QModelIndex> res; QList<QModelIndex> res;
for (auto i : list) { for (auto i : list) {

View File

@ -102,6 +102,10 @@ class Item
virtual bool canFetchMore() const { return false; } virtual bool canFetchMore() const { return false; }
virtual void fetchMore() {} virtual void fetchMore() {}
virtual boost::optional<Item *> getById(IdString id) { return boost::none; }
virtual void search(QList<Item *> &results, QString text, int limit) {}
virtual void updateElements(Context *ctx, std::vector<IdString> elements) {}
virtual ~Item() virtual ~Item()
{ {
if (parent_ != nullptr) { if (parent_ != nullptr) {
@ -143,20 +147,20 @@ class IdStringList : public Item
public: public:
// Create an IdStringList at given partent that will contain elements of // Create an IdStringList at given partent that will contain elements of
// the given type. // the given type.
IdStringList(QString name, Item *parent, ElementType type) : Item(name, parent), child_type_(type) {} IdStringList(ElementType type) : Item("root", nullptr), child_type_(type) {}
// Split a name into alpha/non-alpha parts, which is then used for sorting // Split a name into alpha/non-alpha parts, which is then used for sorting
// of children. // of children.
static std::vector<QString> alphaNumSplit(const QString &str); static std::vector<QString> alphaNumSplit(const QString &str);
// getById finds a child for the given IdString. // getById finds a child for the given IdString.
IdStringItem *getById(IdString id) const { return managed_.at(id).get(); } virtual boost::optional<Item *> getById(IdString id) override { return managed_.at(id).get(); }
// (Re-)create children from a list of IdStrings. // (Re-)create children from a list of IdStrings.
void updateElements(Context *ctx, std::vector<IdString> elements); virtual void updateElements(Context *ctx, std::vector<IdString> elements) override;
// Find children that contain the given text. // Find children that contain the given text.
void search(QList<Item *> &results, QString text, int limit); virtual void search(QList<Item *> &results, QString text, int limit) override;
}; };
// ElementList is a dynamic list of ElementT (BelId,WireId,...) that are // ElementList is a dynamic list of ElementT (BelId,WireId,...) that are
@ -220,7 +224,7 @@ template <typename ElementT> class ElementList : public Item
virtual void fetchMore() override { fetchMore(100); } virtual void fetchMore() override { fetchMore(100); }
// getById finds a child for the given IdString. // getById finds a child for the given IdString.
boost::optional<Item *> getById(IdString id) virtual boost::optional<Item *> getById(IdString id) override
{ {
// Search requires us to load all our elements... // Search requires us to load all our elements...
while (canFetchMore()) while (canFetchMore())
@ -234,7 +238,7 @@ template <typename ElementT> class ElementList : public Item
} }
// Find children that contain the given text. // Find children that contain the given text.
void search(QList<Item *> &results, QString text, int limit) virtual void search(QList<Item *> &results, QString text, int limit) override
{ {
// Last chance to bail out from loading entire tree into memory. // Last chance to bail out from loading entire tree into memory.
if (limit != -1 && results.size() > limit) if (limit != -1 && results.size() > limit)
@ -278,8 +282,8 @@ template <typename ElementT> class ElementXYRoot : public Item
ElementType child_type_; ElementType child_type_;
public: public:
ElementXYRoot(Context *ctx, QString name, Item *parent, ElementMap map, ElementGetter getter, ElementType type) ElementXYRoot(Context *ctx, ElementMap map, ElementGetter getter, ElementType type)
: Item(name, parent), ctx_(ctx), map_(map), getter_(getter), child_type_(type) : Item("root", nullptr), ctx_(ctx), map_(map), getter_(getter), child_type_(type)
{ {
// Create all X and Y label Items/ElementLists. // Create all X and Y label Items/ElementLists.
@ -315,7 +319,7 @@ template <typename ElementT> class ElementXYRoot : public Item
} }
// getById finds a child for the given IdString. // getById finds a child for the given IdString.
boost::optional<Item *> getById(IdString id) virtual boost::optional<Item *> getById(IdString id) override
{ {
// For now, scan linearly all ElementLists. // For now, scan linearly all ElementLists.
// TODO(q3k) fix this once we have tree API from arch // TODO(q3k) fix this once we have tree API from arch
@ -329,7 +333,7 @@ template <typename ElementT> class ElementXYRoot : public Item
} }
// Find children that contain the given text. // Find children that contain the given text.
void search(QList<Item *> &results, QString text, int limit) virtual void search(QList<Item *> &results, QString text, int limit) override
{ {
for (auto &l : managed_lists_) { for (auto &l : managed_lists_) {
if (limit != -1 && results.size() > limit) if (limit != -1 && results.size() > limit)
@ -345,15 +349,11 @@ class Model : public QAbstractItemModel
Context *ctx_ = nullptr; Context *ctx_ = nullptr;
public: public:
using BelXYRoot = ElementXYRoot<BelId>;
using WireXYRoot = ElementXYRoot<WireId>;
using PipXYRoot = ElementXYRoot<PipId>;
Model(QObject *parent = nullptr); Model(QObject *parent = nullptr);
~Model(); ~Model();
void loadContext(Context *ctx); void loadData(std::unique_ptr<Item> data);
void updateCellsNets(Context *ctx); void updateElements(Context *ctx, std::vector<IdString> elements);
Item *nodeFromIndex(const QModelIndex &idx) const; Item *nodeFromIndex(const QModelIndex &idx) const;
QModelIndex indexFromNode(Item *node) QModelIndex indexFromNode(Item *node)
{ {
@ -366,29 +366,7 @@ class Model : public QAbstractItemModel
QList<QModelIndex> search(QString text); QList<QModelIndex> search(QString text);
boost::optional<Item *> nodeForIdType(ElementType type, IdString id) const boost::optional<Item *> nodeForId(IdString id) const { return root_->getById(id); }
{
switch (type) {
case ElementType::BEL:
if (bel_root_ == nullptr)
return boost::none;
return bel_root_->getById(id);
case ElementType::WIRE:
if (wire_root_ == nullptr)
return boost::none;
return wire_root_->getById(id);
case ElementType::PIP:
if (pip_root_ == nullptr)
return boost::none;
return pip_root_->getById(id);
case ElementType::CELL:
return cell_root_->getById(id);
case ElementType::NET:
return net_root_->getById(id);
default:
return boost::none;
}
}
// Override QAbstractItemModel methods // Override QAbstractItemModel methods
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
@ -404,11 +382,6 @@ class Model : public QAbstractItemModel
private: private:
// Tree elements that we manage the memory for. // Tree elements that we manage the memory for.
std::unique_ptr<Item> root_; std::unique_ptr<Item> root_;
std::unique_ptr<BelXYRoot> bel_root_;
std::unique_ptr<WireXYRoot> wire_root_;
std::unique_ptr<PipXYRoot> pip_root_;
std::unique_ptr<IdStringList> cell_root_;
std::unique_ptr<IdStringList> net_root_;
}; };
}; // namespace TreeModel }; // namespace TreeModel

View File

@ -417,8 +417,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
int getGridDimX() const { return 34; } int getGridDimX() const { return chip_info->width; }
int getGridDimY() const { return 34; } int getGridDimY() const { return chip_info->height; }
int getTileBelDimZ(int, int) const { return 8; } int getTileBelDimZ(int, int) const { return 8; }
int getTilePipDimZ(int, int) const { return 1; } int getTilePipDimZ(int, int) const { return 1; }