Simplify Launcher thumbnail display code
Remove old code paths in the AircraftModel/LocalCache, especially
This commit is contained in:
parent
a27dfe1feb
commit
0483f2996a
5 changed files with 41 additions and 142 deletions
|
@ -38,8 +38,6 @@
|
||||||
|
|
||||||
#include "QmlAircraftInfo.hxx"
|
#include "QmlAircraftInfo.hxx"
|
||||||
|
|
||||||
const int STANDARD_THUMBNAIL_HEIGHT = 128;
|
|
||||||
|
|
||||||
using namespace simgear::pkg;
|
using namespace simgear::pkg;
|
||||||
|
|
||||||
bool isPackageFailure(Delegate::StatusCode status)
|
bool isPackageFailure(Delegate::StatusCode status)
|
||||||
|
@ -70,18 +68,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void catalogRefreshed(CatalogRef aCatalog, StatusCode aReason) override
|
void catalogRefreshed(CatalogRef aCatalog, StatusCode aReason) override;
|
||||||
{
|
|
||||||
if (aReason == STATUS_IN_PROGRESS) {
|
|
||||||
// nothing to do
|
|
||||||
} else if ((aReason == STATUS_REFRESHED) || (aReason == STATUS_SUCCESS)) {
|
|
||||||
m_model->refreshPackages();
|
|
||||||
} else {
|
|
||||||
qWarning() << "failed refresh of"
|
|
||||||
<< QString::fromStdString(aCatalog->url()) << ":" << aReason << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void startInstall(InstallRef aInstall) override
|
void startInstall(InstallRef aInstall) override
|
||||||
{
|
{
|
||||||
QModelIndex mi(indexForPackage(aInstall->package()));
|
QModelIndex mi(indexForPackage(aInstall->package()));
|
||||||
|
@ -128,44 +115,6 @@ protected:
|
||||||
m_model->dataChanged(mi, mi);
|
m_model->dataChanged(mi, mi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void dataForThumbnail(const std::string& aThumbnailUrl,
|
|
||||||
size_t length, const uint8_t* bytes) override
|
|
||||||
{
|
|
||||||
QImage img = QImage::fromData(QByteArray::fromRawData(reinterpret_cast<const char*>(bytes), length));
|
|
||||||
if (img.isNull()) {
|
|
||||||
qWarning() << "failed to load image data for URL:" <<
|
|
||||||
QString::fromStdString(aThumbnailUrl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap pix = QPixmap::fromImage(img);
|
|
||||||
if (pix.height() > STANDARD_THUMBNAIL_HEIGHT) {
|
|
||||||
pix = pix.scaledToHeight(STANDARD_THUMBNAIL_HEIGHT, Qt::SmoothTransformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString url = QString::fromStdString(aThumbnailUrl);
|
|
||||||
m_model->m_downloadedPixmapCache.insert(url, pix);
|
|
||||||
|
|
||||||
// notify any affected items. Linear scan here avoids another map/dict structure.
|
|
||||||
for (auto pkg : m_model->m_packages) {
|
|
||||||
const size_t variantCount = pkg->variants().size();
|
|
||||||
bool notifyChanged = false;
|
|
||||||
|
|
||||||
for (size_t v=0; v < variantCount; ++v) {
|
|
||||||
const Package::Thumbnail& thumb(pkg->thumbnailForVariant(v));
|
|
||||||
if (thumb.url == aThumbnailUrl) {
|
|
||||||
notifyChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notifyChanged) {
|
|
||||||
QModelIndex mi = indexForPackage(pkg);
|
|
||||||
m_model->dataChanged(mi, mi);
|
|
||||||
}
|
|
||||||
} // of packages iteration
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex indexForPackage(const PackageRef& ref) const
|
QModelIndex indexForPackage(const PackageRef& ref) const
|
||||||
{
|
{
|
||||||
|
@ -182,6 +131,22 @@ private:
|
||||||
AircraftItemModel* m_model;
|
AircraftItemModel* m_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void PackageDelegate::catalogRefreshed(CatalogRef aCatalog, StatusCode aReason)
|
||||||
|
{
|
||||||
|
if (aReason == STATUS_IN_PROGRESS) {
|
||||||
|
// nothing to do
|
||||||
|
} else if ((aReason == STATUS_REFRESHED) || (aReason == STATUS_SUCCESS)) {
|
||||||
|
m_model->refreshPackages();
|
||||||
|
} else {
|
||||||
|
qWarning() << "failed refresh of"
|
||||||
|
<< QString::fromStdString(aCatalog->url()) << ":" << aReason << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
/// \brief AircraftItemModel::AircraftItemModel
|
||||||
|
/// \param pr
|
||||||
|
///
|
||||||
AircraftItemModel::AircraftItemModel(QObject* pr) :
|
AircraftItemModel::AircraftItemModel(QObject* pr) :
|
||||||
QAbstractListModel(pr)
|
QAbstractListModel(pr)
|
||||||
{
|
{
|
||||||
|
@ -322,16 +287,12 @@ QVariant AircraftItemModel::dataFromItem(AircraftItemPtr item, const DelegateSta
|
||||||
}
|
}
|
||||||
|
|
||||||
return item->description;
|
return item->description;
|
||||||
} else if (role == Qt::DecorationRole) {
|
|
||||||
return item->thumbnail();
|
|
||||||
} else if (role == AircraftPathRole) {
|
} else if (role == AircraftPathRole) {
|
||||||
return item->path;
|
return item->path;
|
||||||
} else if (role == AircraftAuthorsRole) {
|
} else if (role == AircraftAuthorsRole) {
|
||||||
return item->authors;
|
return item->authors;
|
||||||
} else if ((role >= AircraftRatingRole) && (role < AircraftVariantDescriptionRole)) {
|
} else if ((role >= AircraftRatingRole) && (role < AircraftVariantDescriptionRole)) {
|
||||||
return item->ratings[role - AircraftRatingRole];
|
return item->ratings[role - AircraftRatingRole];
|
||||||
} else if (role == AircraftThumbnailRole) {
|
|
||||||
return item->thumbnail();
|
|
||||||
} else if (role == AircraftPackageIdRole) {
|
} else if (role == AircraftPackageIdRole) {
|
||||||
// can we fake an ID? otherwise fall through to a null variant
|
// can we fake an ID? otherwise fall through to a null variant
|
||||||
} else if (role == AircraftPackageStatusRole) {
|
} else if (role == AircraftPackageStatusRole) {
|
||||||
|
@ -367,10 +328,6 @@ QVariant AircraftItemModel::dataFromItem(AircraftItemPtr item, const DelegateSta
|
||||||
|
|
||||||
QVariant AircraftItemModel::dataFromPackage(const PackageRef& item, const DelegateState& state, int role) const
|
QVariant AircraftItemModel::dataFromPackage(const PackageRef& item, const DelegateState& state, int role) const
|
||||||
{
|
{
|
||||||
if (role == Qt::DecorationRole) {
|
|
||||||
role = AircraftThumbnailRole;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (role >= AircraftVariantDescriptionRole) {
|
if (role >= AircraftVariantDescriptionRole) {
|
||||||
int variantIndex = role - AircraftVariantDescriptionRole;
|
int variantIndex = role - AircraftVariantDescriptionRole;
|
||||||
QString desc = QString::fromStdString(item->nameForVariant(variantIndex));
|
QString desc = QString::fromStdString(item->nameForVariant(variantIndex));
|
||||||
|
@ -418,8 +375,6 @@ QVariant AircraftItemModel::dataFromPackage(const PackageRef& item, const Delega
|
||||||
// this value wants the number of aditional variants, i.e not
|
// this value wants the number of aditional variants, i.e not
|
||||||
// including the primary. Hence the -1 term.
|
// including the primary. Hence the -1 term.
|
||||||
return static_cast<quint32>(item->variants().size() - 1);
|
return static_cast<quint32>(item->variants().size() - 1);
|
||||||
} else if (role == AircraftThumbnailRole) {
|
|
||||||
return packageThumbnail(item, state);
|
|
||||||
} else if (role == AircraftAuthorsRole) {
|
} else if (role == AircraftAuthorsRole) {
|
||||||
std::string authors = item->getLocalisedProp("author", state.variant);
|
std::string authors = item->getLocalisedProp("author", state.variant);
|
||||||
if (!authors.empty()) {
|
if (!authors.empty()) {
|
||||||
|
@ -453,42 +408,6 @@ QVariant AircraftItemModel::packageRating(const PackageRef& p, int ratingIndex)
|
||||||
return LocalAircraftCache::ratingFromProperties(p->properties()->getChild("rating"), ratingIndex);
|
return LocalAircraftCache::ratingFromProperties(p->properties()->getChild("rating"), ratingIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant AircraftItemModel::packageThumbnail(PackageRef p, const DelegateState& ds, bool download) const
|
|
||||||
{
|
|
||||||
const Package::Thumbnail& thumb(p->thumbnailForVariant(ds.variant));
|
|
||||||
if (thumb.url.empty()) {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString urlQString(QString::fromStdString(thumb.url));
|
|
||||||
if (m_downloadedPixmapCache.contains(urlQString)) {
|
|
||||||
// cache hit, easy
|
|
||||||
return m_downloadedPixmapCache.value(urlQString);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the on-disk store.
|
|
||||||
InstallRef ex = p->existingInstall();
|
|
||||||
if (ex.valid()) {
|
|
||||||
SGPath thumbPath = ex->path() / thumb.path;
|
|
||||||
if (thumbPath.exists()) {
|
|
||||||
QPixmap pix;
|
|
||||||
pix.load(QString::fromStdString(thumbPath.utf8Str()));
|
|
||||||
// resize to the standard size
|
|
||||||
if (pix.height() > STANDARD_THUMBNAIL_HEIGHT) {
|
|
||||||
pix = pix.scaledToHeight(STANDARD_THUMBNAIL_HEIGHT);
|
|
||||||
}
|
|
||||||
m_downloadedPixmapCache[urlQString] = pix;
|
|
||||||
return pix;
|
|
||||||
}
|
|
||||||
} // of have existing install
|
|
||||||
|
|
||||||
if (download) {
|
|
||||||
m_packageRoot->requestThumbnailData(thumb.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AircraftItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
bool AircraftItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
{
|
{
|
||||||
int row = index.row();
|
int row = index.row();
|
||||||
|
@ -517,7 +436,6 @@ QHash<int, QByteArray> AircraftItemModel::roleNames() const
|
||||||
result[AircraftAuthorsRole] = "authors";
|
result[AircraftAuthorsRole] = "authors";
|
||||||
result[AircraftVariantCountRole] = "variantCount";
|
result[AircraftVariantCountRole] = "variantCount";
|
||||||
result[AircraftLongDescriptionRole] = "description";
|
result[AircraftLongDescriptionRole] = "description";
|
||||||
result[AircraftThumbnailRole] = "thumbnail";
|
|
||||||
result[AircraftPackageSizeRole] = "packageSizeBytes";
|
result[AircraftPackageSizeRole] = "packageSizeBytes";
|
||||||
result[AircraftPackageStatusRole] = "packageStatus";
|
result[AircraftPackageStatusRole] = "packageStatus";
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,6 @@ const int AircraftURIRole = Qt::UserRole + 14;
|
||||||
const int AircraftIsHelicopterRole = Qt::UserRole + 16;
|
const int AircraftIsHelicopterRole = Qt::UserRole + 16;
|
||||||
const int AircraftIsSeaplaneRole = Qt::UserRole + 17;
|
const int AircraftIsSeaplaneRole = Qt::UserRole + 17;
|
||||||
const int AircraftPackageRefRole = Qt::UserRole + 19;
|
const int AircraftPackageRefRole = Qt::UserRole + 19;
|
||||||
const int AircraftThumbnailRole = Qt::UserRole + 20;
|
|
||||||
|
|
||||||
const int AircraftStatusRole = Qt::UserRole + 22;
|
const int AircraftStatusRole = Qt::UserRole + 22;
|
||||||
const int AircraftMinVersionRole = Qt::UserRole + 23;
|
const int AircraftMinVersionRole = Qt::UserRole + 23;
|
||||||
|
@ -153,7 +152,6 @@ private:
|
||||||
simgear::pkg::RootRef m_packageRoot;
|
simgear::pkg::RootRef m_packageRoot;
|
||||||
simgear::pkg::PackageList m_packages;
|
simgear::pkg::PackageList m_packages;
|
||||||
|
|
||||||
mutable QHash<QString, QPixmap> m_downloadedPixmapCache;
|
|
||||||
int m_cachedLocalAircraftCount = 0;
|
int m_cachedLocalAircraftCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -177,23 +177,6 @@ void AircraftItem::toDataStream(QDataStream& ds) const
|
||||||
ds << tags;
|
ds << tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap AircraftItem::thumbnail(bool loadIfRequired) const
|
|
||||||
{
|
|
||||||
if (m_thumbnail.isNull() && loadIfRequired) {
|
|
||||||
QFileInfo info(path);
|
|
||||||
QDir dir = info.dir();
|
|
||||||
if (dir.exists(thumbnailPath)) {
|
|
||||||
m_thumbnail.load(dir.filePath(thumbnailPath));
|
|
||||||
// resize to the standard size
|
|
||||||
if (m_thumbnail.height() > STANDARD_THUMBNAIL_HEIGHT) {
|
|
||||||
m_thumbnail = m_thumbnail.scaledToHeight(STANDARD_THUMBNAIL_HEIGHT, Qt::SmoothTransformation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_thumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AircraftItem::indexOfVariant(QUrl uri) const
|
int AircraftItem::indexOfVariant(QUrl uri) const
|
||||||
{
|
{
|
||||||
const QString path = uri.toLocalFile();
|
const QString path = uri.toLocalFile();
|
||||||
|
|
|
@ -49,8 +49,6 @@ struct AircraftItem
|
||||||
|
|
||||||
void toDataStream(QDataStream& ds) const;
|
void toDataStream(QDataStream& ds) const;
|
||||||
|
|
||||||
QPixmap thumbnail(bool loadIfRequired = true) const;
|
|
||||||
|
|
||||||
int indexOfVariant(QUrl uri) const;
|
int indexOfVariant(QUrl uri) const;
|
||||||
|
|
||||||
bool excluded = false;
|
bool excluded = false;
|
||||||
|
@ -75,7 +73,6 @@ struct AircraftItem
|
||||||
QUrl supportUrl;
|
QUrl supportUrl;
|
||||||
QVariant status(int variant);
|
QVariant status(int variant);
|
||||||
private:
|
private:
|
||||||
mutable QPixmap m_thumbnail;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocalAircraftCache : public QObject
|
class LocalAircraftCache : public QObject
|
||||||
|
|
|
@ -27,30 +27,33 @@ public:
|
||||||
void startInstall(pkg::InstallRef) override {}
|
void startInstall(pkg::InstallRef) override {}
|
||||||
void installProgress(pkg::InstallRef, unsigned int, unsigned int) override {}
|
void installProgress(pkg::InstallRef, unsigned int, unsigned int) override {}
|
||||||
void finishInstall(pkg::InstallRef, StatusCode ) override {}
|
void finishInstall(pkg::InstallRef, StatusCode ) override {}
|
||||||
|
|
||||||
void dataForThumbnail(const std::string& aThumbnailUrl,
|
void dataForThumbnail(const std::string& aThumbnailUrl,
|
||||||
size_t length, const uint8_t* bytes) override
|
size_t length, const uint8_t* bytes) override;
|
||||||
{
|
|
||||||
if (aThumbnailUrl != owner->url().toString().toStdString()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QImage img = QImage::fromData(QByteArray::fromRawData(reinterpret_cast<const char*>(bytes), length));
|
|
||||||
if (img.isNull()) {
|
|
||||||
if (length > 0) {
|
|
||||||
// warn if we had valid bytes but couldn't load it, i.e corrupted data or similar
|
|
||||||
qWarning() << "failed to load image data for URL:" << QString::fromStdString(aThumbnailUrl);
|
|
||||||
owner->clearImage();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
owner->setImage(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThumbnailImageItem* owner;
|
ThumbnailImageItem* owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ThumbnailImageItem::ThumbnailPackageDelegate::dataForThumbnail(const std::string& aThumbnailUrl,
|
||||||
|
size_t length, const uint8_t* bytes)
|
||||||
|
{
|
||||||
|
if (aThumbnailUrl != owner->url().toString().toStdString()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iLength = static_cast<int>(length);
|
||||||
|
QImage img = QImage::fromData(QByteArray::fromRawData(reinterpret_cast<const char*>(bytes), iLength));
|
||||||
|
if (img.isNull()) {
|
||||||
|
if (length > 0) {
|
||||||
|
// warn if we had valid bytes but couldn't load it, i.e corrupted data or similar
|
||||||
|
qWarning() << "failed to load image data for URL:" << QString::fromStdString(aThumbnailUrl);
|
||||||
|
owner->clearImage();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
owner->setImage(img);
|
||||||
|
}
|
||||||
|
|
||||||
ThumbnailImageItem::ThumbnailImageItem(QQuickItem* parent) :
|
ThumbnailImageItem::ThumbnailImageItem(QQuickItem* parent) :
|
||||||
QQuickItem(parent),
|
QQuickItem(parent),
|
||||||
m_delegate(new ThumbnailPackageDelegate(this)),
|
m_delegate(new ThumbnailPackageDelegate(this)),
|
||||||
|
@ -81,7 +84,7 @@ QSGNode *ThumbnailImageItem::updatePaintNode(QSGNode* oldNode, QQuickItem::Updat
|
||||||
textureNode->setOwnsTexture(true);
|
textureNode->setOwnsTexture(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSGTexture* tex = window()->createTextureFromImage(m_image);
|
QSGTexture* tex = window()->createTextureFromImage(m_image, QQuickWindow::TextureIsOpaque);
|
||||||
textureNode->setTexture(tex);
|
textureNode->setTexture(tex);
|
||||||
textureNode->markDirty(QSGBasicGeometryNode::DirtyMaterial);
|
textureNode->markDirty(QSGBasicGeometryNode::DirtyMaterial);
|
||||||
m_imageDirty = false;
|
m_imageDirty = false;
|
||||||
|
@ -123,7 +126,7 @@ void ThumbnailImageItem::setAircraftUri(QString uri)
|
||||||
pkg::Root* root = globals->packageRoot();
|
pkg::Root* root = globals->packageRoot();
|
||||||
pkg::PackageRef package = root->getPackageById(packageId);
|
pkg::PackageRef package = root->getPackageById(packageId);
|
||||||
if (package) {
|
if (package) {
|
||||||
int variant = package->indexOfVariant(packageId);
|
auto variant = package->indexOfVariant(packageId);
|
||||||
const auto thumbnail = package->thumbnailForVariant(variant);
|
const auto thumbnail = package->thumbnailForVariant(variant);
|
||||||
m_imageUrl = QUrl(QString::fromStdString(thumbnail.url));
|
m_imageUrl = QUrl(QString::fromStdString(thumbnail.url));
|
||||||
if (m_imageUrl.isValid()) {
|
if (m_imageUrl.isValid()) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue