aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergiusz Bazanski <q3k@q3k.org>2018-08-01 01:27:20 +0100
committerSergiusz Bazanski <q3k@q3k.org>2018-08-01 01:27:20 +0100
commite9e7004bf9b6abf27bf61063b4abbe5895a11073 (patch)
tree848bef473a016bb3e3ae56ee58445a856c60d0b3
parentc8cf0bbc0542635101d3b5d4e5553e0ddd4ee7c6 (diff)
downloadnextpnr-e9e7004bf9b6abf27bf61063b4abbe5895a11073.tar.gz
nextpnr-e9e7004bf9b6abf27bf61063b4abbe5895a11073.tar.bz2
nextpnr-e9e7004bf9b6abf27bf61063b4abbe5895a11073.zip
gui: clickable tree, better sorting
-rw-r--r--gui/treemodel.h118
1 files changed, 84 insertions, 34 deletions
diff --git a/gui/treemodel.h b/gui/treemodel.h
index a6df8858..69116112 100644
--- a/gui/treemodel.h
+++ b/gui/treemodel.h
@@ -119,6 +119,21 @@ class StaticTreeItem : public LazyTreeItem
}
};
+class IdStringItem : public StaticTreeItem
+{
+ private:
+ IdString id_;
+
+ public:
+ IdStringItem(Context *ctx, IdString str, LazyTreeItem *parent, ElementType type) :
+ StaticTreeItem(QString(str.c_str(ctx)), parent, type), id_(str) {}
+
+ virtual IdString id() const override
+ {
+ return id_;
+ }
+};
+
template <typename ElementT>
class ElementList : public LazyTreeItem
{
@@ -156,14 +171,15 @@ class ElementList : public LazyTreeItem
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_));
+ auto idstring = getter_(ctx_, elements()->at(i));
+ QString name(idstring.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, child_type_);
+ auto item = new IdStringItem(ctx_, idstring, this, child_type_);
managed_.push_back(std::move(std::unique_ptr<StaticTreeItem>(item)));
}
}
@@ -182,13 +198,40 @@ class ElementList : public LazyTreeItem
class IdStringList : public StaticTreeItem
{
private:
- std::unordered_map<IdString, std::unique_ptr<StaticTreeItem>> managed_;
+ std::unordered_map<IdString, std::unique_ptr<IdStringItem>> managed_;
ElementType child_type_;
public:
IdStringList(QString name, LazyTreeItem *parent, ElementType type) :
StaticTreeItem(name, parent, ElementType::NONE), child_type_(type) {}
using StaticTreeItem::StaticTreeItem;
+ static std::vector<QString> 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 updateElements(Context *ctx, std::vector<IdString> elements)
{
// for any elements that are not yet in managed_, created them.
@@ -197,8 +240,8 @@ class IdStringList : public StaticTreeItem
element_set.insert(elem);
auto existing = managed_.find(elem);
if (existing == managed_.end()) {
- auto item = new StaticTreeItem(elem.c_str(ctx), this, child_type_);
- managed_.emplace(elem, std::unique_ptr<StaticTreeItem>(item));
+ auto item = new IdStringItem(ctx, elem, this, child_type_);
+ managed_.emplace(elem, std::unique_ptr<IdStringItem>(item));
}
}
@@ -214,38 +257,45 @@ class IdStringList : public StaticTreeItem
// sort new children
qSort(children_.begin(), children_.end(), [&](const LazyTreeItem *a, const LazyTreeItem *b){
- QString name_a = a->name();
- QString name_b = b->name();
- // Try to extract a common prefix from both strings.
- QString common;
- for (int i = 0; i < std::min(name_a.size(), name_b.size()); i++) {
- const QChar c_a = name_a[i];
- const QChar c_b = name_b[i];
- if (c_a == c_b) {
- common.push_back(c_a);
- } else {
- break;
- }
- }
- // No common part? lexical sort.
- if (common.size() == 0) {
- return a->name() < b->name();
- }
+ auto parts_a = alphaNumSplit(a->name());
+ auto parts_b = alphaNumSplit(b->name());
- // Get the non-common parts.
- name_a.remove(0, common.size());
- name_b.remove(0, common.size());
- // And see if they're strings.
- bool ok = true;
- int num_a = name_a.toInt(&ok);
- if (!ok) {
- return a->name() < b->name();
+ if (parts_a.size() != parts_b.size()) {
+ return parts_a.size() < parts_b.size();
}
- int num_b = name_b.toInt(&ok);
- if (!ok) {
- return a->name() < b->name();
+
+ for (int 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 (a_is_number && b_is_number) {
+ if (a_number != b_number) {
+ return a_number < b_number;
+ } else {
+ continue;
+ }
+ }
+
+ if (a_is_number != b_is_number) {
+ return a_is_number;
+ }
+
+ // both strings
+
+ if (part_a == part_b) {
+ continue;
+ }
+
+ return part_a < part_b;
}
- return num_a < num_b;
+
+ // both equal
+ return true;
});
}
};