Welcome: Remove requirement for subclassing ListModel

By using aggregation for the pixmap fetching.

Change-Id: I6647cc6fa7995581c692050af32e41ba9aa86491
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Eike Ziller
2023-01-12 16:10:09 +01:00
parent ab9935af73
commit aff6c4b2d2
6 changed files with 58 additions and 59 deletions

View File

@@ -150,8 +150,8 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
QPixmap pixmap; QPixmap pixmap;
if (QPixmapCache::find(item->imageUrl, &pixmap)) if (QPixmapCache::find(item->imageUrl, &pixmap))
return pixmap; return pixmap;
if (pixmap.isNull()) if (pixmap.isNull() && m_fetchPixmapAndUpdatePixmapCache)
pixmap = fetchPixmapAndUpdatePixmapCache(item->imageUrl); pixmap = m_fetchPixmapAndUpdatePixmapCache(item->imageUrl);
return pixmap; return pixmap;
} }
case ItemTagsRole: case ItemTagsRole:
@@ -161,6 +161,11 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
} }
} }
void ListModel::setPixmapFunction(const PixmapFunction &fetchPixmapAndUpdatePixmapCache)
{
m_fetchPixmapAndUpdatePixmapCache = fetchPixmapAndUpdatePixmapCache;
}
ListModelFilter::ListModelFilter(ListModel *sourceModel, QObject *parent) : ListModelFilter::ListModelFilter(ListModel *sourceModel, QObject *parent) :
QSortFilterProxyModel(parent) QSortFilterProxyModel(parent)
{ {

View File

@@ -12,6 +12,7 @@
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include <QListView> #include <QListView>
#include <functional>
#include <optional> #include <optional>
namespace Utils { class FancyLineEdit; } namespace Utils { class FancyLineEdit; }
@@ -58,23 +59,22 @@ public:
class CORE_EXPORT ListModel : public QAbstractListModel class CORE_EXPORT ListModel : public QAbstractListModel
{ {
public: public:
enum ListDataRole { enum ListDataRole { ItemRole = Qt::UserRole, ItemImageRole, ItemTagsRole };
ItemRole = Qt::UserRole,
ItemImageRole, using PixmapFunction = std::function<QPixmap(QString)>;
ItemTagsRole
};
explicit ListModel(QObject *parent); explicit ListModel(QObject *parent);
~ListModel() override; ~ListModel() override;
int rowCount(const QModelIndex &parent = QModelIndex()) const final; int rowCount(const QModelIndex &parent = QModelIndex()) const final;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url) const = 0; void setPixmapFunction(const PixmapFunction &fetchPixmapAndUpdatePixmapCache);
static const QSize defaultImageSize; static const QSize defaultImageSize;
protected: protected:
QList<ListItem *> m_items; QList<ListItem *> m_items;
PixmapFunction m_fetchPixmapAndUpdatePixmapCache;
}; };
class CORE_EXPORT ListModelFilter : public QSortFilterProxyModel class CORE_EXPORT ListModelFilter : public QSortFilterProxyModel

View File

@@ -72,6 +72,11 @@ public:
ProductListModel::ProductListModel(QObject *parent) ProductListModel::ProductListModel(QObject *parent)
: Core::ListModel(parent) : Core::ListModel(parent)
{ {
setPixmapFunction([this](const QString &url) -> QPixmap {
if (auto sectionedProducts = qobject_cast<SectionedProducts *>(this->parent()))
sectionedProducts->queueImageForDownload(url);
return {};
});
} }
void ProductListModel::appendItems(const QList<Core::ListItem *> &items) void ProductListModel::appendItems(const QList<Core::ListItem *> &items)
@@ -165,13 +170,6 @@ void SectionedProducts::updateCollections()
this, [this, reply]() { onFetchCollectionsFinished(reply); }); this, [this, reply]() { onFetchCollectionsFinished(reply); });
} }
QPixmap ProductListModel::fetchPixmapAndUpdatePixmapCache(const QString &url) const
{
if (auto sectionedProducts = qobject_cast<SectionedProducts *>(parent()))
sectionedProducts->queueImageForDownload(url);
return QPixmap();
}
void SectionedProducts::onFetchCollectionsFinished(QNetworkReply *reply) void SectionedProducts::onFetchCollectionsFinished(QNetworkReply *reply)
{ {
QTC_ASSERT(reply, return); QTC_ASSERT(reply, return);

View File

@@ -31,9 +31,6 @@ public:
void appendItems(const QList<Core::ListItem *> &items); void appendItems(const QList<Core::ListItem *> &items);
const QList<Core::ListItem *> items() const; const QList<Core::ListItem *> items() const;
void updateModelIndexesForUrl(const QString &url); void updateModelIndexesForUrl(const QString &url);
protected:
QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url) const override;
}; };
struct Section struct Section

View File

@@ -223,6 +223,45 @@ int ExampleSetModel::getExtraExampleSetIndex(int i) const
return variant.toInt(); return variant.toInt();
} }
static QString resourcePath()
{
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
return Core::ICore::resourcePath().normalizedPathName().toString();
}
static QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url)
{
QPixmap pixmap;
if (QPixmapCache::find(url, &pixmap))
return pixmap;
if (url.startsWith("qthelp://")) {
QByteArray fetchedData = Core::HelpManager::fileData(url);
if (!fetchedData.isEmpty()) {
QBuffer imgBuffer(&fetchedData);
imgBuffer.open(QIODevice::ReadOnly);
QImageReader reader(&imgBuffer, QFileInfo(url).suffix().toLatin1());
QImage img = reader.read();
img.convertTo(QImage::Format_RGB32);
const int dpr = qApp->devicePixelRatio();
// boundedTo -> don't scale thumbnails up
const QSize scaledSize = Core::ListModel::defaultImageSize.boundedTo(img.size()) * dpr;
pixmap = QPixmap::fromImage(
img.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
pixmap.setDevicePixelRatio(dpr);
}
} else {
pixmap.load(url);
if (pixmap.isNull())
pixmap.load(resourcePath() + "/welcomescreen/widgets/" + url);
}
QPixmapCache::insert(url, pixmap);
return pixmap;
}
ExamplesListModel::ExamplesListModel(QObject *parent) ExamplesListModel::ExamplesListModel(QObject *parent)
: Core::ListModel(parent) : Core::ListModel(parent)
{ {
@@ -232,6 +271,7 @@ ExamplesListModel::ExamplesListModel(QObject *parent)
&Core::HelpManager::Signals::documentationChanged, &Core::HelpManager::Signals::documentationChanged,
this, this,
&ExamplesListModel::updateExamples); &ExamplesListModel::updateExamples);
setPixmapFunction(fetchPixmapAndUpdatePixmapCache);
} }
static QString fixStringForTags(const QString &string) static QString fixStringForTags(const QString &string)
@@ -435,12 +475,6 @@ void ExamplesListModel::parseTutorials(QXmlStreamReader *reader, const QString &
} }
} }
static QString resourcePath()
{
// normalize paths so QML doesn't freak out if it's wrongly capitalized on Windows
return Core::ICore::resourcePath().normalizedPathName().toString();
}
void ExamplesListModel::updateExamples() void ExamplesListModel::updateExamples()
{ {
QString examplesInstallPath; QString examplesInstallPath;
@@ -491,39 +525,6 @@ void ExamplesListModel::updateExamples()
endResetModel(); endResetModel();
} }
QPixmap ExamplesListModel::fetchPixmapAndUpdatePixmapCache(const QString &url) const
{
QPixmap pixmap;
if (QPixmapCache::find(url, &pixmap))
return pixmap;
if (url.startsWith("qthelp://")) {
QByteArray fetchedData = Core::HelpManager::fileData(url);
if (!fetchedData.isEmpty()) {
QBuffer imgBuffer(&fetchedData);
imgBuffer.open(QIODevice::ReadOnly);
QImageReader reader(&imgBuffer, QFileInfo(url).suffix().toLatin1());
QImage img = reader.read();
img.convertTo(QImage::Format_RGB32);
const int dpr = qApp->devicePixelRatio();
// boundedTo -> don't scale thumbnails up
const QSize scaledSize = ListModel::defaultImageSize.boundedTo(img.size()) * dpr;
pixmap = QPixmap::fromImage(
img.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
pixmap.setDevicePixelRatio(dpr);
}
} else {
pixmap.load(url);
if (pixmap.isNull())
pixmap.load(resourcePath() + "/welcomescreen/widgets/" + url);
}
QPixmapCache::insert(url, pixmap);
return pixmap;
}
void ExampleSetModel::updateQtVersionList() void ExampleSetModel::updateQtVersionList()
{ {
QtVersions versions = QtVersionManager::sortVersions(QtVersionManager::versions( QtVersions versions = QtVersionManager::sortVersions(QtVersionManager::versions(

View File

@@ -111,8 +111,6 @@ public:
QStringList exampleSets() const; QStringList exampleSets() const;
ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; } ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; }
QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url) const override;
signals: signals:
void selectedExampleSetChanged(int); void selectedExampleSetChanged(int);