diff --git a/src/GUI/AircraftModel.cxx b/src/GUI/AircraftModel.cxx index 5a1d799ea..ab7b23316 100644 --- a/src/GUI/AircraftModel.cxx +++ b/src/GUI/AircraftModel.cxx @@ -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(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(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 AircraftItemModel::roleNames() const result[AircraftAuthorsRole] = "authors"; result[AircraftVariantCountRole] = "variantCount"; result[AircraftLongDescriptionRole] = "description"; - result[AircraftThumbnailRole] = "thumbnail"; result[AircraftPackageSizeRole] = "packageSizeBytes"; result[AircraftPackageStatusRole] = "packageStatus"; diff --git a/src/GUI/AircraftModel.hxx b/src/GUI/AircraftModel.hxx index a0f12cf17..f1b8f3bac 100644 --- a/src/GUI/AircraftModel.hxx +++ b/src/GUI/AircraftModel.hxx @@ -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 m_downloadedPixmapCache; int m_cachedLocalAircraftCount = 0; }; diff --git a/src/GUI/LocalAircraftCache.cxx b/src/GUI/LocalAircraftCache.cxx index d65464b1d..a3d88ae20 100644 --- a/src/GUI/LocalAircraftCache.cxx +++ b/src/GUI/LocalAircraftCache.cxx @@ -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(); diff --git a/src/GUI/LocalAircraftCache.hxx b/src/GUI/LocalAircraftCache.hxx index e789a3844..3efb1f978 100644 --- a/src/GUI/LocalAircraftCache.hxx +++ b/src/GUI/LocalAircraftCache.hxx @@ -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 diff --git a/src/GUI/ThumbnailImageItem.cxx b/src/GUI/ThumbnailImageItem.cxx index b4a24be6a..a2444470e 100644 --- a/src/GUI/ThumbnailImageItem.cxx +++ b/src/GUI/ThumbnailImageItem.cxx @@ -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(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(length); + QImage img = QImage::fromData(QByteArray::fromRawData(reinterpret_cast(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()) {