diff --git a/src/blackmisc/db/artifact.cpp b/src/blackmisc/db/artifact.cpp new file mode 100644 index 000000000..b3825f023 --- /dev/null +++ b/src/blackmisc/db/artifact.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2017 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "artifact.h" +#include "blackmisc/stringutils.h" +#include "blackconfig/buildconfig.h" +#include +#include + +using namespace BlackConfig; +using namespace BlackMisc::Network; + +namespace BlackMisc +{ + namespace Db + { + CArtifact::CArtifact() + { } + + CArtifact::CArtifact( + const QString &name, const QString &version, const QString &md5, + CArtifact::ArtifactType type, int size, bool existing, const CPlatform &platform): + m_name(name.trimmed()), m_version(trimVersionString(version)), + m_md5(md5), m_type(static_cast(type)), m_size(size), m_existing(existing), + m_platform(platform) + { + if (!name.isEmpty() && version.isEmpty()) + { + m_version = versionNumberFromFilename(name); + } + } + + bool CArtifact::matchesName(const QString &name, Qt::CaseSensitivity cs) const + { + const bool m = (cs == Qt::CaseInsensitive) ? + caseInsensitiveStringCompare(this->getName(), name) : + name == this->getName(); + if (m) { return true; } + return name.startsWith(this->getName(), cs); + } + + QString CArtifact::getFileSizeHumanReadable() const + { + if (m_size < 0) { return QStringLiteral(""); } + return CFileUtils::humanReadableFileSize(m_size); + } + + bool CArtifact::matchesAnyPlatform(const CPlatform &platform) const + { + return m_platform.matchesAny(platform); + } + + bool CArtifact::isWithDistribution(const CDistribution &distribution, bool acceptMoreStableDistributions) const + { + if (distribution.isEmpty() || !this->hasDistributions()) { return false; } + for (const CDistribution &dist : this->getDistributions()) + { + if (dist == distribution) { return true; } + if (acceptMoreStableDistributions && dist.isStabilityBetter(distribution)) { return true; } + } + return false; + } + + CRemoteFile CArtifact::asRemoteFile() const + { + if (!this->hasDistributions()) { return CRemoteFile(); } + CRemoteFile rf(this->getName(), this->getFileSize()); + const CDistribution d = this->getMostStableDistribution(); + const CUrl url = d.getDownloadUrls().getRandomUrl(); + rf.setUtcTimestamp(this->getUtcTimestamp()); + rf.setUrl(url); + rf.setDescription(this->getPlatform().toQString() + " " + d.getChannel()); + return rf; + } + + QVersionNumber CArtifact::getQVersion() const + { + return QVersionNumber::fromString(getVersionString()); + } + + bool CArtifact::isNewerThanCurrentBuild() const + { + if (this->isUnknown()) { return false; } + if (this->getVersionString().isEmpty()) { return false; } + return this->getQVersion() > CBuildConfig::getVersion(); + } + + QString CArtifact::convertToQString(bool i18n) const + { + return this->convertToQString(", ", i18n); + } + + QString CArtifact::convertToQString(const QString &separator, bool i18n) const + { + Q_UNUSED(i18n); + return QLatin1String("name: ") % + this->getName() % + separator % + QLatin1String("size: ") % + this->getFileSizeHumanReadable() % + separator % + QLatin1String("OS: ") % + this->getPlatform().toQString(i18n) % + separator % + QLatin1String("timestamp: ") % + this->getFormattedUtcTimestampYmdhms(); + } + + CVariant CArtifact::propertyByIndex(const CPropertyIndex &index) const + { + if (index.isMyself()) { return CVariant::from(*this); } + if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) { return IDatastoreObjectWithIntegerKey::propertyByIndex(index); } + + const ColumnIndex i = index.frontCasted(); + switch (i) + { + case IndexName: return CVariant::fromValue(m_name); + case IndexMd5: return CVariant::fromValue(m_md5); + case IndexPlatform: return m_platform.propertyByIndex(index.copyFrontRemoved()); + case IndexType: return CVariant::fromValue(m_type); + case IndexSize: return CVariant::fromValue(m_size); + case IndexSizeHumanReadable: return CVariant::fromValue(this->getFileSizeHumanReadable()); + case IndexVersionString: return CVariant::fromValue(m_version); + case IndexQVersion: return CVariant::fromValue(this->getQVersion()); + case IndexDistributions: return CVariant::fromValue(m_distributions); + default: return CValueObject::propertyByIndex(index); + } + } + + void CArtifact::setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant) + { + if (index.isMyself()) { (*this) = variant.to(); return; } + if (IDatastoreObjectWithIntegerKey::canHandleIndex(index)) + { + IDatastoreObjectWithIntegerKey::setPropertyByIndex(index, variant); + return; + } + + const ColumnIndex i = index.frontCasted(); + switch (i) + { + case IndexName: this->setName(variant.toQString()); break; + case IndexMd5: m_md5 = variant.toQString(); break; + case IndexPlatform: m_platform.setPropertyByIndex(index.copyFrontRemoved(), variant); break; + case IndexType: m_type = variant.toInt(); break; + case IndexSize: m_size = variant.toInt(); break; + case IndexVersionString: m_version = variant.toQString(); break; + case IndexDistributions: m_distributions = variant.value(); break; + default: CValueObject::setPropertyByIndex(index, variant); break; + } + } + + CArtifact CArtifact::fromDatabaseJson(const QJsonObject &json, const QString &prefix) + { + Q_UNUSED(prefix); // not nested + + const QString name = json.value("name").toString(); + const QString md5 = json.value("md5").toString(); + const QString version = json.value("version").toString(); + const CPlatform platform = CPlatform(json.value("os").toString()); + const CArtifact::ArtifactType type = stringToType(json.value("type").toString()); + const int size = json.value("size").toInt(-1); + const bool existing = json.value("existing").toBool(); + + CArtifact artifact(name, version, md5, type, size, existing, platform); + artifact.setKeyAndTimestampFromDatabaseJson(json); + if (json.contains("distributions")) + { + const QJsonObject distJson = json.value("distributions").toObject(); + if (!distJson.isEmpty() && distJson.contains("distributionArray")) + { + const CDistributionList distributions = CDistributionList::fromDatabaseJson(distJson.value("distributionArray").toArray()); + artifact.setDistributions(distributions); + } + } + return artifact; + } + + const QString &CArtifact::typeToString(CArtifact::ArtifactType type) + { + static const QString xswb("xSwiftBus"); + static const QString installer("pilot client installer"); + static const QString symbols("symbols"); + static const QString unknown("unknown"); + + switch (type) + { + case XSwiftBus: return xswb; + case PilotClientInstaller: return installer; + case Symbols: return symbols; + case UnknownArtifact: + default: break; + } + return unknown; + } + + QString CArtifact::versionNumberFromFilename(const QString &filename) + { + if (filename.isEmpty()) { return QStringLiteral(""); } + + // swift-installer-linux-64-0.7.3_2017-03-25_11-24-50.run + thread_local const QRegularExpression firstSegments("\\d+\\.\\d+\\.\\d+"); + const QRegularExpressionMatch firstSegmentsMatch = firstSegments.match(filename); + if (!firstSegmentsMatch.hasMatch()) + { + return QStringLiteral(""); // no version, invalid + } + QString v = firstSegmentsMatch.captured(0); // first 3 segments, like 0.9.3 + if (!v.endsWith('.')) { v += '.'; } + + thread_local const QRegularExpression ts1("\\d{4}.?\\d{2}.?\\d{2}.?\\d{2}.?\\d{2}.?\\d{2}"); + const QRegularExpressionMatch ts1Match = ts1.match(filename); + if (!ts1Match.hasMatch()) + { + // version without timestamp + v += "0"; + return v; + } + + const QString versionTimestampString = BlackMisc::digitOnlyString(ts1Match.captured(0)); + const QDateTime versionTimestamp = QDateTime::fromString(versionTimestampString, "yyyyMMddHHmmss"); + const QString lastSegment = QString::number(CBuildConfig::buildTimestampAsVersionSegment(versionTimestamp)); + + v += lastSegment; + return v; + } + + CArtifact::ArtifactType CArtifact::stringToType(const QString &str) + { + const QString s(str.trimmed().toLower()); + if (s.contains("installer")) return CArtifact::PilotClientInstaller; + if (s.contains("client")) return CArtifact::PilotClientInstaller; + if (s.contains("symb")) return CArtifact::Symbols; + if (s.contains("bus")) return CArtifact::XSwiftBus; + return CArtifact::UnknownArtifact; + } + + QString CArtifact::trimVersionString(const QString &version) + { + if (version.count('.') != 3) return version; // no 4th segment + QStringList parts = version.split('.'); + const QString p4 = trim4thSegment(parts[3]); + if (p4 == parts[3]) { return version; } // nothing changed + parts[3] = p4; + const QString v = parts.join('.'); + return v; + } + + QString CArtifact::trim4thSegment(const QString &seg) + { + // yyyyMMddHHmmss (14): offset is 2010xxxxx + if (seg.length() <= 13) { return seg; } + const int fs = CBuildConfig::buildTimestampAsVersionSegment(QDateTime::fromString(seg, "yyyyMMddHHmmss")); + return QString::number(fs); + } + } // ns +} // ns diff --git a/src/blackmisc/db/artifact.h b/src/blackmisc/db/artifact.h new file mode 100644 index 000000000..eb6a25d56 --- /dev/null +++ b/src/blackmisc/db/artifact.h @@ -0,0 +1,198 @@ +/* Copyright (C) 2017 + * swift project community / contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_DB_ARTIFACT_H +#define BLACKMISC_DB_ARTIFACT_H + +#include "distributionlist.h" +#include "datastore.h" +#include "blackmisc/platform.h" +#include "blackmisc/blackmiscexport.h" +#include "blackmisc/network/remotefile.h" +#include +#include + +namespace BlackMisc +{ + namespace Db + { + //! Artifacts ("our software" products) + class BLACKMISC_EXPORT CArtifact : + public CValueObject, + public IDatastoreObjectWithIntegerKey + { + public: + //! Properties by index + enum ColumnIndex + { + IndexName = CPropertyIndex::GlobalIndexCArtifact, + IndexMd5, + IndexType, + IndexPlatform, + IndexVersionString, + IndexQVersion, + IndexSize, + IndexSizeHumanReadable, + IndexDistributions + }; + + //! Type + enum ArtifactType + { + UnknownArtifact, + PilotClientInstaller, + Symbols, + XSwiftBus + }; + + //! Default constructor + CArtifact(); + + //! Constructor + CArtifact(const QString &name, const QString &version, const QString &md5, + ArtifactType type, int size, bool existing, const CPlatform &platform); + + //! Destructor. + ~CArtifact() {} + + //! Having name? + bool hasName() const { return !m_name.isEmpty(); } + + //! Name (i.e. installer name, symbol name) + const QString &getName() const { return m_name; } + + //! Set the name + void setName(const QString &name) { m_name = name.trimmed(); } + + //! Matching name? + bool matchesName(const QString &name, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + //! Having a version string? + bool hasVersionString() const { return !m_version.isEmpty(); } + + //! Version for platform + const QString &getVersionString() const { return m_version; } + + //! Get type + ArtifactType getType() const { return static_cast(m_type); } + + //! Unknown + bool isUnknown() const { return this->getType() == UnknownArtifact; } + + //! Set type + void setType(ArtifactType type) { m_type = static_cast(type); } + + //! File size + int getFileSize() const { return m_size; } + + //! \copydoc CFileUtils::humanReadableFileSize + QString getFileSizeHumanReadable() const; + + //! Set file size + void setFileSize(int size) { m_size = size; } + + //! MD5 + const QString &getMd5() const { return m_md5; } + + //! OS + const CPlatform &getPlatform() const { return m_platform; } + + //! Matches any platform + bool matchesAnyPlatform(const CPlatform &platform) const; + + //! Set the OS + void setPlatform(const CPlatform &platform) { m_platform = platform; } + + //! Related distributions + const CDistributionList &getDistributions() const { return m_distributions; } + + //! Most stable distribution if any + CDistribution getMostStableDistribution() const { return this->getDistributions().getMostStableOrDefault(); } + + //! Related distributions + void setDistributions(const CDistributionList &distributions) { m_distributions = distributions; } + + //! Has distributions? + bool hasDistributions() const { return !m_distributions.isEmpty(); } + + //! Is distributed with given distribution? + bool isWithDistribution(const CDistribution &distribution, bool acceptMoreStableDistributions) const; + + //! Turn into remote file + //! \note requires distributions + Network::CRemoteFile asRemoteFile() const; + + //! Version as QVersion + QVersionNumber getQVersion() const; + + //! Newer tahn the current build + bool isNewerThanCurrentBuild() const; + + //! \copydoc BlackMisc::Mixin::String::toQString + QString convertToQString(bool i18n = false) const; + + //! To string + QString convertToQString(const QString &separator, bool i18n = false) const; + + //! \copydoc BlackMisc::Mixin::Index::propertyByIndex + CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; + + //! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex + void setPropertyByIndex(const BlackMisc::CPropertyIndex &index, const BlackMisc::CVariant &variant); + + //! Object from database JSON format + static CArtifact fromDatabaseJson(const QJsonObject &json, const QString &prefix = {}); + + //! Type as string + static const QString &typeToString(ArtifactType type); + + private: + QString m_name; //!< channel the files belong to + QString m_version; //!< version string + QString m_md5; //!< MD5 checksum + int m_type = static_cast(UnknownArtifact); //!< artifact type + int m_size = -1; //!< size + bool m_existing = false; //!< existing artifact for download + CPlatform m_platform; //!< platform (i.e. OS) + CDistributionList m_distributions; //!< related distributions + + //! Extract version number from a file name + static QString versionNumberFromFilename(const QString &filename); + + //! Type from string + static ArtifactType stringToType(const QString &str); + + //! Trim the 4th segment of a version string + static QString trimVersionString(const QString &version); + + //! Trim a strin representing 4th segment + static QString trim4thSegment(const QString &seg); + + BLACK_METACLASS( + CArtifact, + BLACK_METAMEMBER(name), + BLACK_METAMEMBER(version), + BLACK_METAMEMBER(md5), + BLACK_METAMEMBER(type), + BLACK_METAMEMBER(size), + BLACK_METAMEMBER(existing), + BLACK_METAMEMBER(platform), + BLACK_METAMEMBER(distributions), + BLACK_METAMEMBER(timestampMSecsSinceEpoch) + ); + }; + } // ns +} // ns + +Q_DECLARE_METATYPE(BlackMisc::Db::CArtifact) +Q_DECLARE_METATYPE(BlackMisc::Db::CArtifact::ArtifactType) + +#endif // guard diff --git a/src/blackmisc/db/artifactlist.cpp b/src/blackmisc/db/artifactlist.cpp new file mode 100644 index 000000000..511e73104 --- /dev/null +++ b/src/blackmisc/db/artifactlist.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 2017 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +#include "artifactlist.h" +#include "blackmisc/stringutils.h" + +using namespace BlackMisc::Network; + +namespace BlackMisc +{ + namespace Db + { + CArtifactList::CArtifactList() { } + + CArtifactList::CArtifactList(const CSequence &other) : + CSequence(other) + { } + + CPlatformSet CArtifactList::getPlatforms() const + { + CPlatformSet platforms; + for (const CArtifact &artifact : *this) + { + platforms.insert(artifact.getPlatform()); + } + return platforms; + } + + CArtifact CArtifactList::findFirstByMatchingPlatformOrDefault(const CPlatform &platform) const + { + return this->findFirstByOrDefault(&CArtifact::getPlatform, platform.getPlatform()); + } + + CArtifact CArtifactList::findFirstByMatchingNameOrDefault(const QString &name, Qt::CaseSensitivity cs) const + { + for (const CArtifact &artifact : *this) + { + if (artifact.matchesName(name, cs)) { return artifact; } + } + return CArtifact(); + } + + CArtifactList CArtifactList::findByMatchingPlatform(const CPlatform &platform) const + { + CArtifactList artifacts; + for (const CArtifact &artifact : *this) + { + if (artifact.matchesAnyPlatform(platform)) { artifacts.push_back(artifact); } + } + return artifacts; + } + + CArtifactList CArtifactList::findByType(const CArtifact::ArtifactType type) const + { + return this->findBy(&CArtifact::getType, type); + } + + CArtifactList CArtifactList::findMatchingForCurrentPlatform() const + { + return this->findByMatchingPlatform(CPlatform::currentPlatform()); + } + + CArtifactList CArtifactList::findByDistribution(const CDistribution &distribution, bool findMoreStableDistribution) const + { + CArtifactList al; + for (const CArtifact &artifact : *this) + { + if (!artifact.isWithDistribution(distribution, findMoreStableDistribution)) { continue; } + al.push_back(artifact); + } + return al; + } + + CArtifactList CArtifactList::findByDistributionAndPlatform(const CDistribution &distribution, const CPlatform &platform, bool findMoreStableDistributions) const + { + return this->findByMatchingPlatform(platform).findByDistribution(distribution, findMoreStableDistributions); + } + + CArtifact CArtifactList::findFirstByVersionOrDefault(const QVersionNumber &version) const + { + return this->findFirstByOrDefault(&CArtifact::getQVersion, version); + } + + CArtifact CArtifactList::findFirstByVersionOrDefault(const QString &version) const + { + const QVersionNumber v = QVersionNumber::fromString(version); + return this->findFirstByVersionOrDefault(v); + } + + CDistributionList CArtifactList::getDistributions() const + { + CDistributionList dl; + for (const CArtifact &artifact : *this) + { + for (const CDistribution &d : artifact.getDistributions()) + { + // add only once + if (dl.contains(d)) { continue; } + dl.push_back(d); + } + } + return dl; + } + + void CArtifactList::sortByVersion(Qt::SortOrder order) + { + this->sort([order](const CArtifact & a, const CArtifact & b) + { + const QVersionNumber av = a.getQVersion(); + const QVersionNumber bv = b.getQVersion(); + return order == Qt::AscendingOrder ? av < bv : bv < av; + }); + } + + CArtifact CArtifactList::getLatestArtifactOrDefault() const + { + if (this->size() < 2) { return this->frontOrDefault(); } + CArtifactList copy(*this); + copy.sortByVersion(); + return copy.back(); + } + + CRemoteFileList CArtifactList::asRemoteFiles() const + { + CRemoteFileList rfs; + for (const CArtifact &artifact : *this) + { + const CRemoteFile rf = artifact.asRemoteFile(); + if (rf.hasName()) + { + rfs.push_back(rf); + } + } + return rfs; + } + + QString CArtifactList::getLatestVersionString() const + { + return this->getLatestArtifactOrDefault().getVersionString(); + } + + QVersionNumber CArtifactList::getLatestQVersion() const + { + return this->getLatestArtifactOrDefault().getQVersion(); + } + + QStringList CArtifactList::getSortedNames() const + { + CArtifactList copy(*this); + copy.sortByVersion(Qt::DescendingOrder); + QStringList names; + for (const CArtifact &artifact : as_const(copy)) + { + if (artifact.hasName()) + { + names.push_back(artifact.getName()); + } + } + return names; + } + + QStringList CArtifactList::getSortedVersions() const + { + CArtifactList copy(*this); + copy.sortByVersion(Qt::DescendingOrder); + QStringList versions; + for (const CArtifact &artifact : as_const(copy)) + { + if (artifact.hasVersionString()) + { + versions.push_back(artifact.getVersionString()); + } + } + return versions; + } + + qint64 CArtifactList::getTotalFileSize() const + { + qint64 s = 0; + for (const CArtifact a : *this) + { + s += a.getFileSize(); + } + return s; + } + + QString CArtifactList::getTotalFileSizeHumanReadable() const + { + return CFileUtils::humanReadableFileSize(this->getTotalFileSize()); + } + + CArtifactList CArtifactList::fromDatabaseJson(const QJsonArray &array) + { + CArtifactList artifacts; + for (const QJsonValue &value : array) + { + const CArtifact artifact(CArtifact::fromDatabaseJson(value.toObject())); + artifacts.push_back(artifact); + } + return artifacts; + } + + CArtifactList CArtifactList::fromDatabaseJson(const QString &json) + { + if (json.isEmpty()) { return CArtifactList(); } + return CArtifactList::fromDatabaseJson(Json::jsonArrayFromString(json)); + } + } // namespace +} // namespace diff --git a/src/blackmisc/db/artifactlist.h b/src/blackmisc/db/artifactlist.h new file mode 100644 index 000000000..0bdaf10dc --- /dev/null +++ b/src/blackmisc/db/artifactlist.h @@ -0,0 +1,121 @@ +/* Copyright (C) 2017 + * swift project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project, + * including this file, may be copied, modified, propagated, or distributed except according to the terms + * contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_DB_ARTIFACTLIST_H +#define BLACKMISC_DB_ARTIFACTLIST_H + +#include "artifact.h" +#include "distributionlist.h" +#include "datastoreobjectlist.h" +#include "blackmisc/network/remotefilelist.h" +#include "blackmisc/platformset.h" +#include "blackmisc/blackmiscexport.h" +#include "blackmisc/collection.h" +#include "blackmisc/sequence.h" +#include "blackmisc/variant.h" +#include +#include + +namespace BlackMisc +{ + namespace Db + { + //! Multiple artifacts + class BLACKMISC_EXPORT CArtifactList : + public CSequence, + public IDatastoreObjectList, + public Mixin::MetaType + { + public: + BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CArtifactList) + + //! Empty constructor. + CArtifactList(); + + //! Construct from a base class object. + CArtifactList(const CSequence &other); + + //! All platforms for all channels + CPlatformSet getPlatforms() const; + + //! Find first by platform + CArtifact findFirstByMatchingPlatformOrDefault(const CPlatform &platform) const; + + //! FInd first by name + CArtifact findFirstByMatchingNameOrDefault(const QString &name, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; + + //! Find by platform + CArtifactList findByMatchingPlatform(const CPlatform &platform) const; + + //! Find by type + CArtifactList findByType(const CArtifact::ArtifactType type) const; + + //! Find for my platform + CArtifactList findMatchingForCurrentPlatform() const; + + //! Find by distribution + CArtifactList findByDistribution(const CDistribution &distribution, bool findMoreStableDistribution = false) const; + + //! Find by distribution and platform + CArtifactList findByDistributionAndPlatform(const CDistribution &distribution, const CPlatform &platform, bool findMoreStableDistributions = false) const; + + //! Find by version + CArtifact findFirstByVersionOrDefault(const QVersionNumber &version) const; + + //! Find by version + CArtifact findFirstByVersionOrDefault(const QString &version) const; + + //! All distributions related to these artifacts + CDistributionList getDistributions() const; + + //! Sort by version + void sortByVersion(Qt::SortOrder order = Qt::AscendingOrder); + + //! Latest (newest) artifact + CArtifact getLatestArtifactOrDefault() const; + + //! As remote files + Network::CRemoteFileList asRemoteFiles() const; + + //! Latest version + QString getLatestVersionString() const; + + //! Latest version + QVersionNumber getLatestQVersion() const; + + //! All unique names + //! \note sorted by version, latest version first + QStringList getSortedNames() const; + + //! All unique versions + //! \note sorted by version, latest version first + QStringList getSortedVersions() const; + + //! Size of all artifacts + qint64 getTotalFileSize() const; + + //! Size of all artifacts + QString getTotalFileSizeHumanReadable() const; + + //! From database JSON by array + static CArtifactList fromDatabaseJson(const QJsonArray &array); + + //! From database JSON by string + static CArtifactList fromDatabaseJson(const QString &json); + }; + } // ns +} // ns + +Q_DECLARE_METATYPE(BlackMisc::Db::CArtifactList) +Q_DECLARE_METATYPE(BlackMisc::CCollection) +Q_DECLARE_METATYPE(BlackMisc::CSequence) + +#endif //guard diff --git a/src/blackmisc/db/datastoreobjectlist.cpp b/src/blackmisc/db/datastoreobjectlist.cpp index fe59550e8..89551dddb 100644 --- a/src/blackmisc/db/datastoreobjectlist.cpp +++ b/src/blackmisc/db/datastoreobjectlist.cpp @@ -16,6 +16,7 @@ #include "blackmisc/aviation/aircrafticaocodelist.h" #include "blackmisc/aviation/airlineicaocodelist.h" #include "blackmisc/db/dbinfolist.h" +#include "blackmisc/db/artifactlist.h" #include "blackmisc/db/distributionlist.h" #include "blackmisc/simulation/aircraftmodellist.h" #include "blackmisc/simulation/distributorlist.h" @@ -232,6 +233,7 @@ namespace BlackMisc template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; + template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE IDatastoreObjectList; diff --git a/src/blackmisc/db/datastoreobjectlist.h b/src/blackmisc/db/datastoreobjectlist.h index ccaa2fde7..19a1d7c64 100644 --- a/src/blackmisc/db/datastoreobjectlist.h +++ b/src/blackmisc/db/datastoreobjectlist.h @@ -87,6 +87,7 @@ namespace BlackMisc extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; + extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE IDatastoreObjectList; diff --git a/src/blackmisc/db/db.h b/src/blackmisc/db/db.h index 4c48f86e5..0ef835eec 100644 --- a/src/blackmisc/db/db.h +++ b/src/blackmisc/db/db.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 +/* Copyright (C) 2017 * swift Project Community / Contributors * * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level @@ -23,5 +23,7 @@ #include "blackmisc/db/dbflags.h" #include "blackmisc/db/distribution.h" #include "blackmisc/db/distributionlist.h" +#include "blackmisc/db/artifact.h" +#include "blackmisc/db/artifactlist.h" #endif // guard diff --git a/src/blackmisc/db/registermetadatadb.cpp b/src/blackmisc/db/registermetadatadb.cpp index 6e854856e..1eacc7f90 100644 --- a/src/blackmisc/db/registermetadatadb.cpp +++ b/src/blackmisc/db/registermetadatadb.cpp @@ -16,9 +16,11 @@ namespace BlackMisc { void registerMetadata() { + CDbFlags::registerMetadata(); CDbInfo::registerMetadata(); CDbInfoList::registerMetadata(); - CDbFlags::registerMetadata(); + CArtifact::registerMetadata(); + CArtifactList::registerMetadata(); CDistribution::registerMetadata(); CDistributionList::registerMetadata(); } diff --git a/src/blackmisc/timestampobjectlist.cpp b/src/blackmisc/timestampobjectlist.cpp index 43497bff0..85d2541fd 100644 --- a/src/blackmisc/timestampobjectlist.cpp +++ b/src/blackmisc/timestampobjectlist.cpp @@ -15,6 +15,7 @@ #include "blackmisc/aviation/airport.h" #include "blackmisc/aviation/airportlist.h" #include "blackmisc/db/dbinfolist.h" +#include "blackmisc/db/artifactlist.h" #include "blackmisc/db/distributionlist.h" #include "blackmisc/network/textmessage.h" #include "blackmisc/network/textmessagelist.h" @@ -248,6 +249,7 @@ namespace BlackMisc template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; + template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; template class BLACKMISC_EXPORT_DEFINE_TEMPLATE ITimestampObjectList; diff --git a/src/blackmisc/timestampobjectlist.h b/src/blackmisc/timestampobjectlist.h index d59c1d0dc..cf1dbf2ae 100644 --- a/src/blackmisc/timestampobjectlist.h +++ b/src/blackmisc/timestampobjectlist.h @@ -135,6 +135,8 @@ namespace BlackMisc { class CDbInfo; class CDbInfoList; + class CArtifact; + class CArtifactList; class CDistribution; class CDistributionList; } @@ -161,6 +163,7 @@ namespace BlackMisc extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; + extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList; extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE ITimestampObjectList;