Refactor GUI to use IdStringLists

The GUI internally had an 'IdStringList' type that I hadn't spotted, to
avoid a conflict this is renamed to IdList which also reflects its new
purpose better.

Signed-off-by: D. Shah <dave@ds0.me>
This commit is contained in:
D. Shah 2021-02-01 10:49:59 +00:00
parent d792bce0fb
commit 3ae96bff88
4 changed files with 50 additions and 51 deletions

View File

@ -340,11 +340,9 @@ void DesignWidget::newContext(Context *ctx)
} }
getTreeByElementType(ElementType::CELL) getTreeByElementType(ElementType::CELL)
->loadData(ctx, ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::CELL)));
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::CELL)));
getTreeByElementType(ElementType::NET) getTreeByElementType(ElementType::NET)
->loadData(ctx, ->loadData(ctx, std::unique_ptr<TreeModel::IdList>(new TreeModel::IdList(ElementType::NET)));
std::unique_ptr<TreeModel::IdStringList>(new TreeModel::IdStringList(ElementType::NET)));
} }
updateTree(); updateTree();
} }
@ -357,10 +355,10 @@ void DesignWidget::updateTree()
while (i != highlightSelected.end()) { while (i != highlightSelected.end()) {
QMap<TreeModel::Item *, int>::iterator prev = i; QMap<TreeModel::Item *, int>::iterator prev = i;
++i; ++i;
if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()) == ctx->nets.end()) { if (prev.key()->type() == ElementType::NET && ctx->nets.find(prev.key()->id()[0]) == ctx->nets.end()) {
highlightSelected.erase(prev); highlightSelected.erase(prev);
} }
if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()) == ctx->cells.end()) { if (prev.key()->type() == ElementType::CELL && ctx->cells.find(prev.key()->id()[0]) == ctx->cells.end()) {
highlightSelected.erase(prev); highlightSelected.erase(prev);
} }
} }
@ -369,13 +367,13 @@ 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);
std::vector<IdString> cells; std::vector<IdStringList> cells;
for (auto &pair : ctx->cells) { for (auto &pair : ctx->cells) {
cells.push_back(pair.first); cells.push_back(IdStringList(pair.first));
} }
std::vector<IdString> nets; std::vector<IdStringList> nets;
for (auto &pair : ctx->nets) { for (auto &pair : ctx->nets) {
nets.push_back(pair.first); nets.push_back(IdStringList(pair.first));
} }
getTreeByElementType(ElementType::CELL)->updateElements(cells); getTreeByElementType(ElementType::CELL)->updateElements(cells);
@ -603,7 +601,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
clearProperties(); clearProperties();
IdString c = clickItem->id(); IdStringList c = clickItem->id();
Q_EMIT selected(getDecals(type, c), false); Q_EMIT selected(getDecals(type, c), false);
if (type == ElementType::BEL) { if (type == ElementType::BEL) {
@ -613,7 +611,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
BelId bel = ctx->getBelByName(c); BelId bel = ctx->getBelByName(c);
QtProperty *topItem = addTopLevelProperty("Bel"); QtProperty *topItem = addTopLevelProperty("Bel");
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", ctx->nameOfBel(bel));
addProperty(topItem, QVariant::String, "Type", ctx->getBelType(bel).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getBelType(bel).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkBelAvail(bel));
addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL); addProperty(topItem, QVariant::String, "Bound Cell", ctx->nameOf(ctx->getBoundBelCell(bel)), ElementType::CELL);
@ -640,7 +638,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
WireId wire = ctx->getWireByName(c); WireId wire = ctx->getWireByName(c);
QtProperty *topItem = addTopLevelProperty("Wire"); QtProperty *topItem = addTopLevelProperty("Wire");
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", ctx->nameOfWire(wire));
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire)); addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET); addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
@ -677,7 +675,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
int counter = 0; int counter = 0;
QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill"); QtProperty *pipsDownItem = addSubGroup(topItem, "Pips Downhill");
for (const auto &item : ctx->getPipsDownhill(wire)) { for (const auto &item : ctx->getPipsDownhill(wire)) {
addProperty(pipsDownItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP); addProperty(pipsDownItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP);
counter++; counter++;
if (counter == 50) { if (counter == 50) {
addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); addProperty(pipsDownItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
@ -688,7 +686,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
counter = 0; counter = 0;
QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill"); QtProperty *pipsUpItem = addSubGroup(topItem, "Pips Uphill");
for (const auto &item : ctx->getPipsUphill(wire)) { for (const auto &item : ctx->getPipsUphill(wire)) {
addProperty(pipsUpItem, QVariant::String, "", ctx->getPipName(item).c_str(ctx), ElementType::PIP); addProperty(pipsUpItem, QVariant::String, "", ctx->nameOfPip(item), ElementType::PIP);
counter++; counter++;
if (counter == 50) { if (counter == 50) {
addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE); addProperty(pipsUpItem, QVariant::String, "Warning", "Too many items...", ElementType::NONE);
@ -702,7 +700,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
PipId pip = ctx->getPipByName(c); PipId pip = ctx->getPipByName(c);
QtProperty *topItem = addTopLevelProperty("Pip"); QtProperty *topItem = addTopLevelProperty("Pip");
addProperty(topItem, QVariant::String, "Name", c.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", ctx->nameOfPip(pip));
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx)); addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip)); 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, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
@ -734,7 +732,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
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);
NetInfo *net = ctx->nets.at(c).get(); NetInfo *net = ctx->nets.at(c[0]).get();
QtProperty *topItem = addTopLevelProperty("Net"); QtProperty *topItem = addTopLevelProperty("Net");
@ -785,14 +783,14 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
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);
CellInfo *cell = ctx->cells.at(c).get(); CellInfo *cell = ctx->cells.at(c[0]).get();
QtProperty *topItem = addTopLevelProperty("Cell"); QtProperty *topItem = addTopLevelProperty("Cell");
addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx)); addProperty(topItem, QVariant::String, "Name", cell->name.c_str(ctx));
addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx)); addProperty(topItem, QVariant::String, "Type", cell->type.c_str(ctx));
if (cell->bel != BelId()) if (cell->bel != BelId())
addProperty(topItem, QVariant::String, "Bel", ctx->getBelName(cell->bel).c_str(ctx), ElementType::BEL); addProperty(topItem, QVariant::String, "Bel", ctx->nameOfBel(cell->bel), ElementType::BEL);
else else
addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL); addProperty(topItem, QVariant::String, "Bel", "", ElementType::BEL);
addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength)); addProperty(topItem, QVariant::Int, "Bel strength", int(cell->belStrength));
@ -836,7 +834,7 @@ void DesignWidget::onSelectionChanged(int num, const QItemSelection &, const QIt
} }
} }
std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value) std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdStringList value)
{ {
std::vector<DecalXY> decals; std::vector<DecalXY> decals;
switch (type) { switch (type) {
@ -859,7 +857,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
} }
} break; } break;
case ElementType::NET: { case ElementType::NET: {
NetInfo *net = ctx->nets.at(value).get(); NetInfo *net = ctx->nets.at(value[0]).get();
for (auto &item : net->wires) { for (auto &item : net->wires) {
decals.push_back(ctx->getWireDecal(item.first)); decals.push_back(ctx->getWireDecal(item.first));
if (item.second.pip != PipId()) { if (item.second.pip != PipId()) {
@ -868,7 +866,7 @@ std::vector<DecalXY> DesignWidget::getDecals(ElementType type, IdString value)
} }
} break; } break;
case ElementType::CELL: { case ElementType::CELL: {
CellInfo *cell = ctx->cells.at(value).get(); CellInfo *cell = ctx->cells.at(value[0]).get();
if (cell->bel != BelId()) { if (cell->bel != BelId()) {
decals.push_back(ctx->getBelDecal(cell->bel)); decals.push_back(ctx->getBelDecal(cell->bel));
} }

View File

@ -71,7 +71,7 @@ class DesignWidget : public QWidget
int getElementIndex(ElementType type); int getElementIndex(ElementType type);
void updateButtons(); void updateButtons();
void addToHistory(int tab, QModelIndex item); void addToHistory(int tab, QModelIndex item);
std::vector<DecalXY> getDecals(ElementType type, IdString value); std::vector<DecalXY> getDecals(ElementType type, IdStringList value);
void updateHighlightGroup(QList<TreeModel::Item *> item, int group); void updateHighlightGroup(QList<TreeModel::Item *> item, int group);
void clearAllSelectionModels(); void clearAllSelectionModels();
Q_SIGNALS: Q_SIGNALS:

View File

@ -26,7 +26,7 @@ NEXTPNR_NAMESPACE_BEGIN
namespace TreeModel { namespace TreeModel {
// converts 'aa123bb432' -> ['aa', '123', 'bb', '432'] // converts 'aa123bb432' -> ['aa', '123', 'bb', '432']
std::vector<QString> IdStringList::alphaNumSplit(const QString &str) std::vector<QString> IdList::alphaNumSplit(const QString &str)
{ {
std::vector<QString> res; std::vector<QString> res;
QString current_part; QString current_part;
@ -53,12 +53,12 @@ std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
return res; return res;
} }
void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements) void IdList::updateElements(Context *ctx, std::vector<IdStringList> elements)
{ {
bool changed = false; bool changed = false;
// For any elements that are not yet in managed_, created them. // For any elements that are not yet in managed_, created them.
std::unordered_set<IdString> element_set; std::unordered_set<IdStringList> element_set;
for (auto elem : elements) { for (auto elem : elements) {
element_set.insert(elem); element_set.insert(elem);
auto existing = managed_.find(elem); auto existing = managed_.find(elem);
@ -134,7 +134,7 @@ void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
}); });
} }
void IdStringList::search(QList<Item *> &results, QString text, int limit) void IdList::search(QList<Item *> &results, QString text, int limit)
{ {
for (const auto &child : children_) { for (const auto &child : children_) {
if (limit != -1 && results.size() > limit) if (limit != -1 && results.size() > limit)
@ -157,7 +157,7 @@ void Model::loadData(Context *ctx, std::unique_ptr<Item> data)
endResetModel(); endResetModel();
} }
void Model::updateElements(std::vector<IdString> elements) void Model::updateElements(std::vector<IdStringList> elements)
{ {
if (!ctx_) if (!ctx_)
return; return;

View File

@ -95,16 +95,16 @@ class Item
int indexOf(Item *child) { return children_.indexOf(child, 0); } int indexOf(Item *child) { return children_.indexOf(child, 0); }
// Arch id and type that correspond to this element. // Arch id and type that correspond to this element.
virtual IdString id() const { return IdString(); } virtual IdStringList id() const { return IdStringList(); }
virtual ElementType type() const { return ElementType::NONE; } virtual ElementType type() const { return ElementType::NONE; }
// Lazy loading methods. // Lazy loading methods.
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 boost::optional<Item *> getById(IdStringList id) { return boost::none; }
virtual void search(QList<Item *> &results, QString text, int limit) {} virtual void search(QList<Item *> &results, QString text, int limit) {}
virtual void updateElements(Context *ctx, std::vector<IdString> elements) {} virtual void updateElements(Context *ctx, std::vector<IdStringList> elements) {}
virtual ~Item() virtual ~Item()
{ {
@ -118,46 +118,46 @@ class Item
class IdStringItem : public Item class IdStringItem : public Item
{ {
private: private:
IdString id_; IdStringList id_;
ElementType type_; ElementType type_;
public: public:
IdStringItem(Context *ctx, IdString str, Item *parent, ElementType type) IdStringItem(Context *ctx, IdStringList str, Item *parent, ElementType type)
: Item(QString(str.c_str(ctx)), parent), id_(str), type_(type) : Item(QString(str.str(ctx).c_str()), parent), id_(str), type_(type)
{ {
} }
virtual IdString id() const override { return id_; } virtual IdStringList id() const override { return id_; }
virtual ElementType type() const override { return type_; } virtual ElementType type() const override { return type_; }
}; };
// IdString list is a static list of IdStrings which can be set/updates from // IdList is a static list of IdStringLists which can be set/updates from
// a vector of IdStrings. It will render each IdStrings as a child, with the // a vector of IdStrings. It will render each IdStrings as a child, with the
// list sorted in a smart way. // list sorted in a smart way.
class IdStringList : public Item class IdList : public Item
{ {
private: private:
// Children that we manage the memory for, stored for quick lookup from // Children that we manage the memory for, stored for quick lookup from
// IdString to child. // IdString to child.
std::unordered_map<IdString, std::unique_ptr<IdStringItem>> managed_; std::unordered_map<IdStringList, std::unique_ptr<IdStringItem>> managed_;
// Type of children that the list creates. // Type of children that the list creates.
ElementType child_type_; ElementType child_type_;
public: public:
// Create an IdStringList at given parent that will contain elements of // Create an IdList at given parent that will contain elements of
// the given type. // the given type.
IdStringList(ElementType type) : Item("root", nullptr), child_type_(type) {} IdList(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.
virtual boost::optional<Item *> getById(IdString id) override { return managed_.at(id).get(); } virtual boost::optional<Item *> getById(IdStringList id) override { return managed_.at(id).get(); }
// (Re-)create children from a list of IdStrings. // (Re-)create children from a list of IdStrings.
virtual void updateElements(Context *ctx, std::vector<IdString> elements) override; virtual void updateElements(Context *ctx, std::vector<IdStringList> elements) override;
// Find children that contain the given text. // Find children that contain the given text.
virtual void search(QList<Item *> &results, QString text, int limit) override; virtual void search(QList<Item *> &results, QString text, int limit) override;
@ -173,7 +173,7 @@ template <typename ElementT> class ElementList : public Item
// A map from tile (X,Y) to list of ElementTs in that tile. // A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString. // A method that converts an ElementT to an IdString.
using ElementGetter = std::function<IdString(Context *, ElementT)>; using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private: private:
Context *ctx_; Context *ctx_;
@ -184,7 +184,7 @@ template <typename ElementT> class ElementList : public Item
ElementGetter getter_; ElementGetter getter_;
// Children that we manage the memory for, stored for quick lookup from // Children that we manage the memory for, stored for quick lookup from
// IdString to child. // IdString to child.
std::unordered_map<IdString, std::unique_ptr<Item>> managed_; std::unordered_map<IdStringList, std::unique_ptr<Item>> managed_;
// Type of children that he list creates. // Type of children that he list creates.
ElementType child_type_; ElementType child_type_;
@ -209,9 +209,10 @@ template <typename ElementT> class ElementList : public Item
size_t end = std::min(start + count, elements()->size()); size_t end = std::min(start + count, elements()->size());
for (size_t i = start; i < end; i++) { for (size_t i = start; i < end; i++) {
auto idstring = getter_(ctx_, elements()->at(i)); auto idstring = getter_(ctx_, elements()->at(i));
QString name(idstring.c_str(ctx_)); std::string name_str = idstring.str(ctx_);
QString name(name_str.c_str());
// Remove X.../Y.../ prefix // Remove X.../Y.../ prefix - TODO: find a way to use IdStringList splitting here
QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_); QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_);
if (name.startsWith(prefix)) if (name.startsWith(prefix))
name.remove(0, prefix.size()); name.remove(0, prefix.size());
@ -224,7 +225,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.
virtual boost::optional<Item *> getById(IdString id) override virtual boost::optional<Item *> getById(IdStringList id) override
{ {
// Search requires us to load all our elements... // Search requires us to load all our elements...
while (canFetchMore()) while (canFetchMore())
@ -267,7 +268,7 @@ template <typename ElementT> class ElementXYRoot : public Item
// A map from tile (X,Y) to list of ElementTs in that tile. // A map from tile (X,Y) to list of ElementTs in that tile.
using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>;
// A method that converts an ElementT to an IdString. // A method that converts an ElementT to an IdString.
using ElementGetter = std::function<IdString(Context *, ElementT)>; using ElementGetter = std::function<IdStringList(Context *, ElementT)>;
private: private:
Context *ctx_; Context *ctx_;
@ -319,7 +320,7 @@ template <typename ElementT> class ElementXYRoot : public Item
} }
// getById finds a child for the given IdString. // getById finds a child for the given IdString.
virtual boost::optional<Item *> getById(IdString id) override virtual boost::optional<Item *> getById(IdStringList 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
@ -353,7 +354,7 @@ class Model : public QAbstractItemModel
~Model(); ~Model();
void loadData(Context *ctx, std::unique_ptr<Item> data); void loadData(Context *ctx, std::unique_ptr<Item> data);
void updateElements(std::vector<IdString> elements); void updateElements(std::vector<IdStringList> elements);
Item *nodeFromIndex(const QModelIndex &idx) const; Item *nodeFromIndex(const QModelIndex &idx) const;
QModelIndex indexFromNode(Item *node) QModelIndex indexFromNode(Item *node)
{ {
@ -366,7 +367,7 @@ class Model : public QAbstractItemModel
QList<QModelIndex> search(QString text); QList<QModelIndex> search(QString text);
boost::optional<Item *> nodeForId(IdString id) const { return root_->getById(id); } boost::optional<Item *> nodeForId(IdStringList id) const { return root_->getById(id); }
// 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;