diff --git a/simgear/package/CMakeLists.txt b/simgear/package/CMakeLists.txt index ae048978..6ed7ac9c 100644 --- a/simgear/package/CMakeLists.txt +++ b/simgear/package/CMakeLists.txt @@ -7,6 +7,7 @@ set(HEADERS Install.hxx Root.hxx Delegate.hxx + PackageCommon.hxx ) set(SOURCES diff --git a/simgear/package/Catalog.cxx b/simgear/package/Catalog.cxx index 849b7f18..fb09685f 100644 --- a/simgear/package/Catalog.cxx +++ b/simgear/package/Catalog.cxx @@ -295,21 +295,27 @@ bool Catalog::removeDirectory() return d.remove(true /* recursive */); } -PackageList const& -Catalog::packages() const +PackageList +Catalog::packages(Type ty) const { - return m_packages; + PackageList r; + std::copy_if(m_packages.begin(), m_packages.end(), + std::back_inserter(r), + [ty](const PackageRef& p) { + return p->type() == ty; + }); + return r; } PackageList Catalog::packagesMatching(const SGPropertyNode* aFilter) const { PackageList r; - for (auto p : m_packages) { - if (p->matches(aFilter)) { - r.push_back(p); - } - } + std::copy_if(m_packages.begin(), m_packages.end(), + std::back_inserter(r), + [aFilter](const PackageRef& p) { + return p->matches(aFilter); + }); return r; } @@ -317,27 +323,23 @@ PackageList Catalog::packagesNeedingUpdate() const { PackageList r; - for (auto p : m_packages) { - if (!p->isInstalled()) { - continue; - } - - if (p->install()->hasUpdate()) { - r.push_back(p); - } - } + std::copy_if(m_packages.begin(), m_packages.end(), + std::back_inserter(r), + [](const PackageRef& p) { + return p->isInstalled() && p->install()->hasUpdate(); + }); return r; } PackageList -Catalog::installedPackages() const +Catalog::installedPackages(Type ty) const { PackageList r; - for (auto p : m_packages) { - if (p->isInstalled()) { - r.push_back(p); - } - } + std::copy_if(m_packages.begin(), m_packages.end(), + std::back_inserter(r), + [ty](const PackageRef& p) { + return p->isInstalled() && p->type() == ty; + }); return r; } diff --git a/simgear/package/Catalog.hxx b/simgear/package/Catalog.hxx index c83d5c45..5ca664e4 100644 --- a/simgear/package/Catalog.hxx +++ b/simgear/package/Catalog.hxx @@ -32,6 +32,7 @@ #include #include +#include namespace simgear { @@ -40,20 +41,6 @@ namespace HTTP { class Client; } namespace pkg { - -// forward decls -class Package; -class Catalog; -class Root; -class Install; - -typedef SGSharedPtr PackageRef; -typedef SGSharedPtr CatalogRef; -typedef SGSharedPtr InstallRef; - -typedef std::vector PackageList; -typedef std::vector CatalogList; - class Catalog : public SGReferenced { public: @@ -79,7 +66,7 @@ public: /** * Get all packages in this catalog. */ - PackageList const& packages() const; + PackageList packages(Type ty = AircraftPackage) const; /** * retrieve packages in this catalog matching a filter. @@ -90,7 +77,7 @@ public: /** * packages which are locally installed */ - PackageList installedPackages() const; + PackageList installedPackages(Type ty = AircraftPackage) const; /** * retrieve all the packages in the catalog which are installed diff --git a/simgear/package/Install.hxx b/simgear/package/Install.hxx index 086c5284..c46de446 100644 --- a/simgear/package/Install.hxx +++ b/simgear/package/Install.hxx @@ -20,9 +20,10 @@ #include -#include #include +#include #include +#include #include #include @@ -35,15 +36,6 @@ namespace simgear namespace pkg { -// forward decls -class Package; -class Catalog; -class Install; - -typedef SGSharedPtr PackageRef; -typedef SGSharedPtr CatalogRef; -typedef SGSharedPtr InstallRef; - /** * */ diff --git a/simgear/package/Package.cxx b/simgear/package/Package.cxx index 7feafe53..cb9e34fe 100644 --- a/simgear/package/Package.cxx +++ b/simgear/package/Package.cxx @@ -29,10 +29,30 @@ #include #include +namespace { + +const string_list static_typeNames = { + "aircraft", + "ai-model", + "add-on"}; + +} + namespace simgear { namespace pkg { +Type typeFromString(const std::string& s) +{ + const auto l = strutils::lowercase(s); + const auto it = std::find(static_typeNames.begin(), static_typeNames.end(), l); + if (it != static_typeNames.end()) { + return static_cast(std::distance(static_typeNames.begin(), it)); + } + + return AircraftPackage; // for backwards-compat +} + Package::Package(const SGPropertyNode* aProps, CatalogRef aCatalog) : m_catalog(aCatalog.get()) { @@ -53,6 +73,12 @@ void Package::initWithProps(const SGPropertyNode* aProps) for (auto var : m_props->getChildren("variant")) { m_variants.push_back(var->getStringValue("id")); } + + if (aProps->hasChild("type")) { + m_type = typeFromString(m_props->getStringValue("type")); + } else { + m_type = AircraftPackage; + } } void Package::updateFromProps(const SGPropertyNode* aProps) @@ -133,6 +159,12 @@ bool Package::matches(const SGPropertyNode* aFilter) const } } + if (filter_name == "type") { + handled = true; + const auto n = strutils::lowercase(aFilter->getStringValue()); + return (n == static_typeNames.at(static_cast(m_type))); + } + if (!handled) { SG_LOG(SG_GENERAL, SG_WARN, "unknown filter term:" << filter_name); } @@ -186,10 +218,23 @@ bool Package::isInstalled() const return pathOnDisk().exists(); } +std::string Package::directoryForType(Type type) +{ + switch (type) { + case AircraftPackage: + default: + return "Aircraft"; + case AIModelPackage: + return "AI/Aircraft"; + case AddOnPackage: + return "Add-On"; + } +} + SGPath Package::pathOnDisk() const { SGPath p(m_catalog->installRoot()); - p.append("Aircraft"); + p.append(directoryForType(m_type)); p.append(dirName()); return p; } @@ -585,6 +630,10 @@ bool Package::validate() const return true; } +Type Package::type() const +{ + return m_type; +} } // of namespace pkg diff --git a/simgear/package/Package.hxx b/simgear/package/Package.hxx index 88408c54..abb850bd 100644 --- a/simgear/package/Package.hxx +++ b/simgear/package/Package.hxx @@ -28,6 +28,8 @@ #include #include +#include + typedef std::set string_set; namespace simgear @@ -35,19 +37,7 @@ namespace simgear namespace pkg { - -// forward decls -class Install; -class Catalog; -class Package; - -typedef SGSharedPtr PackageRef; -typedef SGSharedPtr CatalogRef; -typedef SGSharedPtr InstallRef; - -typedef std::vector PackageList; - - class Package : public SGReferenced +class Package : public SGReferenced { public: @@ -214,6 +204,11 @@ public: * (parents and children) */ std::string parentIdForVariant(unsigned int variantIndex) const; + + Type type() const; + + static std::string directoryForType(Type type); + private: SGPath pathOnDisk() const; @@ -240,6 +235,7 @@ private: bool matchesDescription(const std::string &search) const; SGPropertyNode_ptr m_props; + Type m_type; std::string m_id; string_set m_tags; Catalog* m_catalog = nullptr; // non-owning ref, explicitly diff --git a/simgear/package/PackageCommon.hxx b/simgear/package/PackageCommon.hxx new file mode 100644 index 00000000..1902e6ab --- /dev/null +++ b/simgear/package/PackageCommon.hxx @@ -0,0 +1,52 @@ +// Copyright (C) 2021 James Turner - james@flightgear.org +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#pragma once + +#include + +#include + +namespace simgear { + +namespace pkg { + +enum Type { + AircraftPackage = 0, + AIModelPackage, + AddOnPackage + + // if you extend this enum, extend the static_typeNames string array + // in Package.cxx file as well. +}; + +// forward decls +class Install; +class Catalog; +class Package; +class Root; + +typedef SGSharedPtr PackageRef; +typedef SGSharedPtr CatalogRef; +typedef SGSharedPtr InstallRef; + +typedef std::vector PackageList; +typedef std::vector CatalogList; + +} // namespace pkg + +} // namespace simgear diff --git a/simgear/package/Root.cxx b/simgear/package/Root.cxx index 983729fb..affac887 100755 --- a/simgear/package/Root.cxx +++ b/simgear/package/Root.cxx @@ -534,13 +534,13 @@ CatalogList Root::allCatalogs() const } PackageList -Root::allPackages() const +Root::allPackages(Type ty) const { PackageList r; CatalogDict::const_iterator it = d->catalogs.begin(); for (; it != d->catalogs.end(); ++it) { - const PackageList& r2(it->second->packages()); + const PackageList& r2(it->second->packages(ty)); r.insert(r.end(), r2.begin(), r2.end()); } diff --git a/simgear/package/Root.hxx b/simgear/package/Root.hxx index a1114461..05adbddf 100644 --- a/simgear/package/Root.hxx +++ b/simgear/package/Root.hxx @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -40,18 +41,6 @@ namespace HTTP { namespace pkg { -// forward decls -class Package; -class Catalog; -class Install; - -typedef SGSharedPtr PackageRef; -typedef SGSharedPtr CatalogRef; -typedef SGSharedPtr InstallRef; - -typedef std::vector PackageList; -typedef std::vector CatalogList; - class Root : public SGReferenced { public: @@ -114,8 +103,8 @@ public: /** * */ - PackageList allPackages() const; - + PackageList allPackages(Type ty = AircraftPackage) const; + /** * retrieve packages matching a filter. * filter consists of required / minimum values, AND-ed together.