diff options
Diffstat (limited to 'gui/treemodel.h')
-rw-r--r-- | gui/treemodel.h | 216 |
1 files changed, 209 insertions, 7 deletions
diff --git a/gui/treemodel.h b/gui/treemodel.h index a85c290a..7de54db4 100644 --- a/gui/treemodel.h +++ b/gui/treemodel.h @@ -61,17 +61,212 @@ class ContextTreeItem QString itemName; }; +class LazyTreeItem +{ + protected: + QString name_; + LazyTreeItem *parent_; + QList<LazyTreeItem *> children_; + + void addChild(LazyTreeItem *child) + { + children_.append(child); + } + + public: + LazyTreeItem(QString name, LazyTreeItem *parent) : + name_(name), parent_(parent) + { + // Register in parent if exists. + if (parent_ != nullptr) { + parent_->addChild(this); + } + }; + + int count() const + { + return children_.count(); + } + + QString name() const + { + return name_; + } + + LazyTreeItem *child(int index) + { + return children_.at(index); + } + + int indexOf(LazyTreeItem *child) const + { + return children_.indexOf(child, 0); + } + + LazyTreeItem *parent() + { + return parent_; + } + + virtual bool canFetchMore() const = 0; + virtual void fetchMore() = 0; + virtual ElementType type() const = 0; + virtual IdString id() const = 0; + + virtual ~LazyTreeItem() {} +}; + +class StaticTreeItem : public LazyTreeItem +{ + public: + using LazyTreeItem::LazyTreeItem; + + virtual bool canFetchMore() const override + { + return false; + } + + virtual void fetchMore() override + { + } + + virtual ~StaticTreeItem() {} + + virtual ElementType type() const override + { + return ElementType::NONE; + } + + virtual IdString id() const override + { + return IdString(); + } +}; + +template <typename ElementT> +class ElementList : public LazyTreeItem +{ + public: + using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; + using ElementGetter = std::function<IdString(Context *, ElementT)>; + + private: + Context *ctx_; + const ElementMap *map_; + int x_, y_; + ElementGetter getter_; + std::vector<std::unique_ptr<StaticTreeItem>> managed_; + + // scope valid until map gets mutated... + const std::vector<ElementT> *elements() const + { + return &map_->at(std::pair<int, int>(x_, y_)); + } + + public: + ElementList(Context *ctx, QString name, LazyTreeItem *parent, ElementMap *map, int x, int y, ElementGetter getter) : + LazyTreeItem(name, parent), ctx_(ctx), map_(map), x_(x), y_(y), getter_(getter) + { + } + + virtual bool canFetchMore() const override + { + return children_.size() < elements()->size(); + } + + void fetchMore(int count) + { + int start = children_.size(); + size_t end = std::min(start + count, (int)elements()->size()); + for (int i = start; i < end; i++) { + QString name(getter_(ctx_, elements()->at(i)).c_str(ctx_)); + + // Remove X.../Y.../ prefix + QString prefix = QString("X%1/Y%2/").arg(x_).arg(y_); + if (name.startsWith(prefix)) + name.remove(0, prefix.size()); + + auto item = new StaticTreeItem(name, this); + managed_.push_back(std::move(std::unique_ptr<StaticTreeItem>(item))); + } + } + + virtual void fetchMore() override + { + fetchMore(100); + } + + virtual ElementType type() const override + { + return ElementType::NONE; + } + + virtual IdString id() const override + { + return IdString(); + } +}; + +template <typename ElementT> +class ElementXYRoot : public StaticTreeItem +{ + public: + using ElementMap = std::map<std::pair<int, int>, std::vector<ElementT>>; + using ElementGetter = std::function<IdString(Context *, ElementT)>; + + + private: + Context *ctx_; + std::vector<std::unique_ptr<LazyTreeItem>> bels_; + ElementMap map_; + ElementGetter getter_; + + public: + ElementXYRoot(Context *ctx, QString name, LazyTreeItem *parent, ElementMap map, ElementGetter getter) : + StaticTreeItem(name, parent), ctx_(ctx), map_(map), getter_(getter) + { + std::vector<int> y_present; + + for (int i = 0; i < ctx->getGridDimX(); i++) { + y_present.clear(); + // first find all the elements in all Y coordinates in this X + for (int j = 0; j < ctx->getGridDimY(); j++) { + if (map_.count(std::pair<int, int>(i, j)) == 0) + continue; + y_present.push_back(j); + } + // no bels in any X coordinate? do not add X tree item. + if (y_present.size() == 0) + continue; + + // create X item for tree + auto item = new StaticTreeItem(QString("X%1").arg(i), this); + bels_.push_back(std::move(std::unique_ptr<LazyTreeItem>(item))); + for (auto j : y_present) { + auto item2 = new ElementList<ElementT>(ctx_, QString("Y%1").arg(j), item, &map_, i, j, getter_); + item2->fetchMore(1); + bels_.push_back(std::move(std::unique_ptr<LazyTreeItem>(item2))); + } + } + } +}; + class ContextTreeModel : public QAbstractItemModel { public: + using BelXYRoot = ElementXYRoot<BelId>; + using WireXYRoot = ElementXYRoot<WireId>; + using PipXYRoot = ElementXYRoot<PipId>; + ContextTreeModel(QObject *parent = nullptr); ~ContextTreeModel(); void loadData(Context *ctx); void updateData(Context *ctx); - ContextTreeItem *nodeFromIndex(const QModelIndex &idx) const; - QModelIndex indexFromNode(ContextTreeItem *node); - ContextTreeItem *nodeForIdType(const ElementType type, const QString name) const; + LazyTreeItem *nodeFromIndex(const QModelIndex &idx) const; + //QModelIndex indexFromNode(ContextTreeItem *node); + //ContextTreeItem *nodeForIdType(const ElementType type, const QString name) const; + // Override QAbstractItemModel methods int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; @@ -80,12 +275,19 @@ class ContextTreeModel : public QAbstractItemModel QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; + void fetchMore(const QModelIndex &parent) Q_DECL_OVERRIDE; + bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE; private: - ContextTreeItem *root; - QMap<QString, ContextTreeItem *> nameToItem[6]; - ContextTreeItem *nets_root; - ContextTreeItem *cells_root; + std::unique_ptr<LazyTreeItem> root_; + std::unique_ptr<BelXYRoot> bel_root_; + std::unique_ptr<WireXYRoot> wire_root_; + std::unique_ptr<PipXYRoot> pip_root_; + //std::unique_ptr<ElementXYRoot> wires_root_; + //std::unique_ptr<ElementXYRoot> pips_root_; + //QMap<QString, ContextTreeItem *> nameToItem[6]; + //ContextTreeItem *nets_root; + //ContextTreeItem *cells_root; }; NEXTPNR_NAMESPACE_END |