forked from qt-creator/qt-creator
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:
@@ -150,8 +150,8 @@ QVariant ListModel::data(const QModelIndex &index, int role) const
|
||||
QPixmap pixmap;
|
||||
if (QPixmapCache::find(item->imageUrl, &pixmap))
|
||||
return pixmap;
|
||||
if (pixmap.isNull())
|
||||
pixmap = fetchPixmapAndUpdatePixmapCache(item->imageUrl);
|
||||
if (pixmap.isNull() && m_fetchPixmapAndUpdatePixmapCache)
|
||||
pixmap = m_fetchPixmapAndUpdatePixmapCache(item->imageUrl);
|
||||
return pixmap;
|
||||
}
|
||||
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) :
|
||||
QSortFilterProxyModel(parent)
|
||||
{
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QListView>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
namespace Utils { class FancyLineEdit; }
|
||||
@@ -58,23 +59,22 @@ public:
|
||||
class CORE_EXPORT ListModel : public QAbstractListModel
|
||||
{
|
||||
public:
|
||||
enum ListDataRole {
|
||||
ItemRole = Qt::UserRole,
|
||||
ItemImageRole,
|
||||
ItemTagsRole
|
||||
};
|
||||
enum ListDataRole { ItemRole = Qt::UserRole, ItemImageRole, ItemTagsRole };
|
||||
|
||||
using PixmapFunction = std::function<QPixmap(QString)>;
|
||||
|
||||
explicit ListModel(QObject *parent);
|
||||
~ListModel() override;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const final;
|
||||
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;
|
||||
|
||||
protected:
|
||||
QList<ListItem *> m_items;
|
||||
PixmapFunction m_fetchPixmapAndUpdatePixmapCache;
|
||||
};
|
||||
|
||||
class CORE_EXPORT ListModelFilter : public QSortFilterProxyModel
|
||||
|
@@ -72,6 +72,11 @@ public:
|
||||
ProductListModel::ProductListModel(QObject *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)
|
||||
@@ -165,13 +170,6 @@ void SectionedProducts::updateCollections()
|
||||
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)
|
||||
{
|
||||
QTC_ASSERT(reply, return);
|
||||
|
@@ -31,9 +31,6 @@ public:
|
||||
void appendItems(const QList<Core::ListItem *> &items);
|
||||
const QList<Core::ListItem *> items() const;
|
||||
void updateModelIndexesForUrl(const QString &url);
|
||||
|
||||
protected:
|
||||
QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url) const override;
|
||||
};
|
||||
|
||||
struct Section
|
||||
|
@@ -223,6 +223,45 @@ int ExampleSetModel::getExtraExampleSetIndex(int i) const
|
||||
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)
|
||||
: Core::ListModel(parent)
|
||||
{
|
||||
@@ -232,6 +271,7 @@ ExamplesListModel::ExamplesListModel(QObject *parent)
|
||||
&Core::HelpManager::Signals::documentationChanged,
|
||||
this,
|
||||
&ExamplesListModel::updateExamples);
|
||||
setPixmapFunction(fetchPixmapAndUpdatePixmapCache);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
QString examplesInstallPath;
|
||||
@@ -491,39 +525,6 @@ void ExamplesListModel::updateExamples()
|
||||
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()
|
||||
{
|
||||
QtVersions versions = QtVersionManager::sortVersions(QtVersionManager::versions(
|
||||
|
@@ -111,8 +111,6 @@ public:
|
||||
QStringList exampleSets() const;
|
||||
ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; }
|
||||
|
||||
QPixmap fetchPixmapAndUpdatePixmapCache(const QString &url) const override;
|
||||
|
||||
signals:
|
||||
void selectedExampleSetChanged(int);
|
||||
|
||||
|
Reference in New Issue
Block a user