diff --git a/src/blackmisc/aviation/aircraftcategory.cpp b/src/blackmisc/aviation/aircraftcategory.cpp index 376aeb1d8..d14edb504 100644 --- a/src/blackmisc/aviation/aircraftcategory.cpp +++ b/src/blackmisc/aviation/aircraftcategory.cpp @@ -83,6 +83,15 @@ namespace BlackMisc m_l3 = l3; } + QList CAircraftCategory::getLevel() const + { + QList l; + if (m_l1 > 0) l << m_l1; + if (m_l2 > 0) l << m_l2; + if (m_l3 > 0) l << m_l3; + return l; + } + bool CAircraftCategory::isFirstLevel() const { return (m_l3 == 0 && m_l2 == 0 && m_l1 > 0); @@ -110,6 +119,23 @@ namespace BlackMisc return stringCompare(path, this->getPath(), cs); } + bool CAircraftCategory::matchesLevel(int l1, int l2, int l3) const + { + if (l1 != m_l1) { return false; } + if (l2 > 0 && l2 != m_l2) { return false; } + if (l3 > 0 && l3 != m_l3) { return false; } + return true; + } + + bool CAircraftCategory::matchesLevel(const QList &level) const + { + if (level.isEmpty()) { return false; } + const int l1 = level.first(); + const int l2 = level.size() > 1 ? level.at(1) : 0; + const int l3 = level.size() > 2 ? level.at(2) : 0; + return this->matchesLevel(l1, l2, l3); + } + CVariant CAircraftCategory::propertyByIndex(const BlackMisc::CPropertyIndex &index) const { if (index.isMyself()) { return CVariant::from(*this); } @@ -184,5 +210,11 @@ namespace BlackMisc c = Compare::compare(m_l3, other.m_l3); return c; } + + bool CAircraftCategory::isHigherLevel(const CAircraftCategory &other) const + { + const int c = this->compareByLevel(other); + return c < 0; + } } // namespace } // namespace diff --git a/src/blackmisc/aviation/aircraftcategory.h b/src/blackmisc/aviation/aircraftcategory.h index ebde8966a..30e2238ec 100644 --- a/src/blackmisc/aviation/aircraftcategory.h +++ b/src/blackmisc/aviation/aircraftcategory.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -77,6 +78,9 @@ namespace BlackMisc //! Level void setLevel(int l1, int l2, int l3); + //! Levels depending on depth, 3.2 -> 3,2 / 1.0 -> 1 / 4.3.1 -> 4,3,1 + QList getLevel() const; + //! First level int getFirstLevel() const { return m_l1; } @@ -95,6 +99,12 @@ namespace BlackMisc //! Matching path? bool matchesPath(const QString &path, Qt::CaseSensitivity cs); + //! Is matching the level, 0 ignored + bool matchesLevel(int l1, int l2 = 0, int l3 = 0) const; + + //! Is matching the level, 0 ignored + bool matchesLevel(const QList &level) const; + //! Assignable? bool isAssignable() const { return m_assignable; } @@ -122,6 +132,9 @@ namespace BlackMisc //! Level compare int compareByLevel(const CAircraftCategory &other) const; + //! Higher level? + bool isHigherLevel(const CAircraftCategory &other) const; + //! NULL object static const CAircraftCategory &null(); diff --git a/src/blackmisc/aviation/aircraftcategorylist.cpp b/src/blackmisc/aviation/aircraftcategorylist.cpp index 66ef2f8d2..5e0470a83 100644 --- a/src/blackmisc/aviation/aircraftcategorylist.cpp +++ b/src/blackmisc/aviation/aircraftcategorylist.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace BlackMisc { @@ -68,12 +69,57 @@ namespace BlackMisc return ll; } + CAircraftCategoryList CAircraftCategoryList::findHighestLevels(const CAircraftCategoryList &categories) + { + if (categories.isEmpty()) { return CAircraftCategoryList(); } + QMap highestLevels; + for (const CAircraftCategory &category : *this) + { + const int fl = category.getFirstLevel(); + if (highestLevels.contains(fl)) + { + if (highestLevels[fl].isHigherLevel(category)) + { + highestLevels[fl] = category; + } + } + else + { + highestLevels[fl] = category; + } + } + + CAircraftCategoryList topLevels; + for (const CAircraftCategory &category : highestLevels.values()) + { + topLevels.push_back(category); + } + return topLevels; + } + CAircraftCategoryList CAircraftCategoryList::findByFirstLevel(int level) const { CAircraftCategoryList categories; for (const CAircraftCategory &category : *this) { - if (category.getFirstLevel() != level) { continue; } + if (category.getFirstLevel() == level) + { + categories.push_back(category); + } + } + return categories; + } + + CAircraftCategoryList CAircraftCategoryList::findByLevel(const QList &level) const + { + CAircraftCategoryList categories; + if (level.isEmpty()) { return categories; } + for (const CAircraftCategory &category : *this) + { + if (category.matchesLevel(level)) + { + categories.push_back(category); + } } return categories; } @@ -83,6 +129,45 @@ namespace BlackMisc return this->findBy(&CAircraftCategory::isFirstLevel, true); } + CAircraftCategoryList CAircraftCategoryList::findSiblings(const CAircraftCategory &category) const + { + QList levels = category.getLevel(); + CAircraftCategoryList categories; + if (levels.size() < 2) + { + categories = this->findFirstLevels(); + } + else + { + levels.removeLast(); + categories = this->findByLevel(levels); + } + categories.remove(category); + return categories; + } + + int CAircraftCategoryList::removeIfLevel(const QList &level) + { + if (level.isEmpty()) { return 0; } + const int c = this->size(); + const CAircraftCategoryList removed = this->removedLevel(level); + const int delta = c - removed.size(); + if (delta > 0) { *this = removed; } + return delta; + } + + CAircraftCategoryList CAircraftCategoryList::removedLevel(const QList &level) const + { + if (level.isEmpty()) { return *this; } // nothing removed + CAircraftCategoryList removed; + for (const CAircraftCategory &category : * this) + { + if (category.matchesLevel(level)) { continue; } + removed.push_back(category); + } + return removed; + } + CAircraftCategoryList CAircraftCategoryList::fromDatabaseJson(const QJsonArray &array) { CAircraftCategoryList categories; diff --git a/src/blackmisc/aviation/aircraftcategorylist.h b/src/blackmisc/aviation/aircraftcategorylist.h index d7ccada16..1a5c1e725 100644 --- a/src/blackmisc/aviation/aircraftcategorylist.h +++ b/src/blackmisc/aviation/aircraftcategorylist.h @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace BlackMisc @@ -57,12 +58,28 @@ namespace BlackMisc //! All levels sorted QList getFirstLevels() const; + //! Find highest (top) level of categories + CAircraftCategoryList findHighestLevels(const CAircraftCategoryList &categories); + //! Find by first level CAircraftCategoryList findByFirstLevel(int level) const; + //! Find by levels + CAircraftCategoryList findByLevel(const QList &level) const; + //! Find first levels CAircraftCategoryList findFirstLevels() const; + //! Find siblings + //! \remark if level is 3.2, siblings are 3.1 and 3.3 + CAircraftCategoryList findSiblings(const CAircraftCategory &category) const; + + //! Remove by level + int removeIfLevel(const QList &level); + + //! With removed categories + CAircraftCategoryList removedLevel(const QList &level) const; + //! From our database JSON format static CAircraftCategoryList fromDatabaseJson(const QJsonArray &array); };