aboutsummaryrefslogtreecommitdiffstats
path: root/gui/treemodel.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gui/treemodel.cc')
-rw-r--r--gui/treemodel.cc103
1 files changed, 102 insertions, 1 deletions
diff --git a/gui/treemodel.cc b/gui/treemodel.cc
index d46d7b6b..eaf62928 100644
--- a/gui/treemodel.cc
+++ b/gui/treemodel.cc
@@ -2,6 +2,7 @@
* nextpnr -- Next Generation Place and Route
*
* Copyright (C) 2018 Miodrag Milanovic <miodrag@symbioticeda.com>
+ * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,9 +25,109 @@ NEXTPNR_NAMESPACE_BEGIN
namespace TreeModel {
+
+// converts 'aa123bb432' -> ['aa', '123', 'bb', '432']
+std::vector<QString> IdStringList::alphaNumSplit(const QString &str)
+{
+ std::vector<QString> res;
+ QString current_part;
+
+ bool number = true;
+ for (const auto c : str) {
+ if (current_part.size() == 0 && res.size() == 0) {
+ current_part.push_back(c);
+ number = c.isNumber();
+ continue;
+ }
+
+ if (number != c.isNumber()) {
+ number = c.isNumber();
+ res.push_back(current_part);
+ current_part.clear();
+ }
+
+ current_part.push_back(c);
+ }
+
+ res.push_back(current_part);
+
+ return res;
+}
+
+void IdStringList::updateElements(Context *ctx, std::vector<IdString> elements)
+{
+ // For any elements that are not yet in managed_, created them.
+ std::unordered_set<IdString> element_set;
+ for (auto elem : elements) {
+ element_set.insert(elem);
+ auto existing = managed_.find(elem);
+ if (existing == managed_.end()) {
+ auto item = new IdStringItem(ctx, elem, this, child_type_);
+ managed_.emplace(elem, std::unique_ptr<IdStringItem>(item));
+ }
+ }
+
+ children_.clear();
+ // For any elements that are in managed_ but not in new, delete them.
+ for (auto &pair : managed_) {
+ if (element_set.count(pair.first) != 0) {
+ children_.push_back(pair.second.get());
+ continue;
+ }
+ managed_.erase(pair.first);
+ }
+
+ // Sort new children
+ qSort(children_.begin(), children_.end(), [&](const Item *a, const Item *b){
+ auto parts_a = alphaNumSplit(a->name());
+ auto parts_b = alphaNumSplit(b->name());
+
+ // Short-circuit for different part count.
+ if (parts_a.size() != parts_b.size()) {
+ return parts_a.size() < parts_b.size();
+ }
+
+ for (size_t i = 0; i < parts_a.size(); i++) {
+ auto &part_a = parts_a.at(i);
+ auto &part_b = parts_b.at(i);
+
+ bool a_is_number, b_is_number;
+ int a_number = part_a.toInt(&a_is_number);
+ int b_number = part_b.toInt(&b_is_number);
+
+ // If both parts are numbers, compare numerically.
+ // If they're equal, continue to next part.
+ if (a_is_number && b_is_number) {
+ if (a_number != b_number) {
+ return a_number < b_number;
+ } else {
+ continue;
+ }
+ }
+
+ // For different alpha/nonalpha types, make numeric parts appear
+ // first.
+ if (a_is_number != b_is_number) {
+ return a_is_number;
+ }
+
+ // If both parts are numbers, compare lexically.
+ // If they're equal, continue to next part.
+ if (part_a == part_b) {
+ continue;
+ }
+ return part_a < part_b;
+ }
+
+ // Same string.
+ return true;
+ });
+}
+
+
Model::Model(QObject *parent) :
QAbstractItemModel(parent),
- root_(new Item("Elements", nullptr, ElementType::NONE)) {}
+ root_(new Item("Elements", nullptr)) {}
Model::~Model() {}