1
0
Fork 0

Simplify Launcher thumbnail display code

Remove old code paths in the AircraftModel/LocalCache, especially
This commit is contained in:
James Turner 2020-03-26 16:56:01 +00:00
parent a27dfe1feb
commit 0483f2996a
5 changed files with 41 additions and 142 deletions

View file

@ -38,8 +38,6 @@
#include "QmlAircraftInfo.hxx"
const int STANDARD_THUMBNAIL_HEIGHT = 128;
using namespace simgear::pkg;
bool isPackageFailure(Delegate::StatusCode status)
@ -70,18 +68,7 @@ public:
}
protected:
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 catalogRefreshed(CatalogRef aCatalog, StatusCode aReason) override;
void startInstall(InstallRef aInstall) override
{
QModelIndex mi(indexForPackage(aInstall->package()));
@ -128,44 +115,6 @@ protected:
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:
QModelIndex indexForPackage(const PackageRef& ref) const
{
@ -182,6 +131,22 @@ private:
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) :
QAbstractListModel(pr)
{
@ -322,16 +287,12 @@ QVariant AircraftItemModel::dataFromItem(AircraftItemPtr item, const DelegateSta
}
return item->description;
} else if (role == Qt::DecorationRole) {
return item->thumbnail();
} else if (role == AircraftPathRole) {
return item->path;
} else if (role == AircraftAuthorsRole) {
return item->authors;
} else if ((role >= AircraftRatingRole) && (role < AircraftVariantDescriptionRole)) {
return item->ratings[role - AircraftRatingRole];
} else if (role == AircraftThumbnailRole) {
return item->thumbnail();
} else if (role == AircraftPackageIdRole) {
// can we fake an ID? otherwise fall through to a null variant
} 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
{
if (role == Qt::DecorationRole) {
role = AircraftThumbnailRole;
}
if (role >= AircraftVariantDescriptionRole) {
int variantIndex = role - AircraftVariantDescriptionRole;
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
// including the primary. Hence the -1 term.
return static_cast<quint32>(item->variants().size() - 1);
} else if (role == AircraftThumbnailRole) {
return packageThumbnail(item, state);
} else if (role == AircraftAuthorsRole) {
std::string authors = item->getLocalisedProp("author", state.variant);
if (!authors.empty()) {
@ -453,42 +408,6 @@ QVariant AircraftItemModel::packageRating(const PackageRef& p, int 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)
{
int row = index.row();
@ -517,7 +436,6 @@ QHash<int, QByteArray> AircraftItemModel::roleNames() const
result[AircraftAuthorsRole] = "authors";
result[AircraftVariantCountRole] = "variantCount";
result[AircraftLongDescriptionRole] = "description";
result[AircraftThumbnailRole] = "thumbnail";
result[AircraftPackageSizeRole] = "packageSizeBytes";
result[AircraftPackageStatusRole] = "packageStatus";

View file

@ -50,7 +50,6 @@ const int AircraftURIRole = Qt::UserRole + 14;
const int AircraftIsHelicopterRole = Qt::UserRole + 16;
const int AircraftIsSeaplaneRole = Qt::UserRole + 17;
const int AircraftPackageRefRole = Qt::UserRole + 19;
const int AircraftThumbnailRole = Qt::UserRole + 20;
const int AircraftStatusRole = Qt::UserRole + 22;
const int AircraftMinVersionRole = Qt::UserRole + 23;
@ -153,7 +152,6 @@ private:
simgear::pkg::RootRef m_packageRoot;
simgear::pkg::PackageList m_packages;
mutable QHash<QString, QPixmap> m_downloadedPixmapCache;
int m_cachedLocalAircraftCount = 0;
};

View file

@ -177,23 +177,6 @@ void AircraftItem::toDataStream(QDataStream& ds) const
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
{
const QString path = uri.toLocalFile();

View file

@ -49,8 +49,6 @@ struct AircraftItem
void toDataStream(QDataStream& ds) const;
QPixmap thumbnail(bool loadIfRequired = true) const;
int indexOfVariant(QUrl uri) const;
bool excluded = false;
@ -75,7 +73,6 @@ struct AircraftItem
QUrl supportUrl;
QVariant status(int variant);
private:
mutable QPixmap m_thumbnail;
};
class LocalAircraftCache : public QObject

View file

@ -27,30 +27,33 @@ public:
void startInstall(pkg::InstallRef) override {}
void installProgress(pkg::InstallRef, unsigned int, unsigned int) override {}
void finishInstall(pkg::InstallRef, StatusCode ) override {}
void dataForThumbnail(const std::string& aThumbnailUrl,
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);
}
size_t length, const uint8_t* bytes) override;
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) :
QQuickItem(parent),
m_delegate(new ThumbnailPackageDelegate(this)),
@ -81,7 +84,7 @@ QSGNode *ThumbnailImageItem::updatePaintNode(QSGNode* oldNode, QQuickItem::Updat
textureNode->setOwnsTexture(true);
}
QSGTexture* tex = window()->createTextureFromImage(m_image);
QSGTexture* tex = window()->createTextureFromImage(m_image, QQuickWindow::TextureIsOpaque);
textureNode->setTexture(tex);
textureNode->markDirty(QSGBasicGeometryNode::DirtyMaterial);
m_imageDirty = false;
@ -123,7 +126,7 @@ void ThumbnailImageItem::setAircraftUri(QString uri)
pkg::Root* root = globals->packageRoot();
pkg::PackageRef package = root->getPackageById(packageId);
if (package) {
int variant = package->indexOfVariant(packageId);
auto variant = package->indexOfVariant(packageId);
const auto thumbnail = package->thumbnailForVariant(variant);
m_imageUrl = QUrl(QString::fromStdString(thumbnail.url));
if (m_imageUrl.isValid()) {