QtSupport: move example image loading from delegate to model

Change-Id: I287336b4d36d648666093a4894ab131b8999ca98
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
David Schulz
2018-01-31 12:14:35 +01:00
parent 109c3f06f8
commit 3c2ad7eed9
3 changed files with 54 additions and 28 deletions

View File

@@ -25,9 +25,15 @@
#include "exampleslistmodel.h"
#include "screenshotcropper.h"
#include <QBuffer>
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFutureWatcher>
#include <QImageReader>
#include <QPixmapCache>
#include <QUrl>
#include <QXmlStreamReader>
@@ -39,6 +45,7 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
#include <algorithm>
@@ -46,6 +53,8 @@
namespace QtSupport {
namespace Internal {
const QSize ExamplesListModel::exampleImageSize(188, 145);
static bool debugExamples()
{
static bool isDebugging = qEnvironmentVariableIsSet("QTC_DEBUG_EXAMPLESMODEL");
@@ -303,6 +312,7 @@ void ExamplesListModel::parseExamples(QXmlStreamReader *reader,
item.hasSourceCode = !item.projectPath.isEmpty();
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, examplesInstallPath);
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
QPixmapCache::remove(item.imageUrl);
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
@@ -356,6 +366,7 @@ void ExamplesListModel::parseDemos(QXmlStreamReader *reader,
item.hasSourceCode = !item.projectPath.isEmpty();
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, demosInstallPath);
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
QPixmapCache::remove(item.imageUrl);
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
} else if (reader->name() == QLatin1String("fileToOpen")) {
@@ -400,6 +411,7 @@ void ExamplesListModel::parseTutorials(QXmlStreamReader *reader, const QString &
item.projectPath.prepend(slash);
item.projectPath.prepend(projectsOffset);
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
QPixmapCache::remove(item.imageUrl);
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
item.isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
item.videoUrl = attributes.value(QLatin1String("videoUrl")).toString();
@@ -426,6 +438,12 @@ 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 Utils::FileUtils::normalizePathName(Core::ICore::resourcePath());
}
void ExamplesListModel::updateExamples()
{
QString examplesInstallPath;
@@ -605,8 +623,30 @@ QVariant ExamplesListModel::data(const QModelIndex &index, int role) const
{
case Qt::DisplayRole: // for search only
return QString(prefixForItem(item) + item.name + ' ' + item.tags.join(' '));
case Qt::UserRole:
case ExampleItemRole:
return QVariant::fromValue<ExampleItem>(item);
case ExampleImageRole: {
QPixmap pixmap;
if (QPixmapCache::find(item.imageUrl, &pixmap))
return pixmap;
pixmap.load(item.imageUrl);
if (pixmap.isNull())
pixmap.load(resourcePath() + "/welcomescreen/widgets/" + item.imageUrl);
if (pixmap.isNull()) {
QByteArray fetchedData = Core::HelpManager::fileData(item.imageUrl);
if (!fetchedData.isEmpty()) {
QBuffer imgBuffer(&fetchedData);
imgBuffer.open(QIODevice::ReadOnly);
QImageReader reader(&imgBuffer);
QImage img = reader.read();
img = ScreenshotCropper::croppedImage(img, item.imageUrl,
ExamplesListModel::exampleImageSize);
pixmap = QPixmap::fromImage(img);
}
}
QPixmapCache::insert(item.imageUrl, pixmap);
return pixmap;
}
default:
return QVariant();
}
@@ -666,7 +706,8 @@ ExamplesListModelFilter::ExamplesListModelFilter(ExamplesListModel *sourceModel,
bool ExamplesListModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
const ExampleItem item = sourceModel()->index(sourceRow, 0, sourceParent).data(Qt::UserRole).value<ExampleItem>();
const ExampleItem item = sourceModel()->index(sourceRow, 0, sourceParent).data(
ExamplesListModel::ExampleItemRole).value<ExampleItem>();
if (m_showTutorialsOnly && item.type != Tutorial)
return false;

View File

@@ -125,6 +125,11 @@ class ExamplesListModel : public QAbstractListModel
Q_OBJECT
public:
enum ExampleListDataRole {
ExampleItemRole = Qt::UserRole,
ExampleImageRole = Qt::UserRole + 1
};
explicit ExamplesListModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const final;
@@ -135,6 +140,8 @@ public:
QStringList exampleSets() const;
ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; }
static const QSize exampleImageSize;
signals:
void selectedExampleSetChanged(int);

View File

@@ -55,7 +55,6 @@
#include <QLabel>
#include <QMessageBox>
#include <QPainter>
#include <QPixmapCache>
#include <QPointer>
#include <QPushButton>
#include <QStyledItemDelegate>
@@ -369,7 +368,7 @@ class ExampleDelegate : public QStyledItemDelegate
public:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const final
{
const ExampleItem item = index.data(Qt::UserRole).value<ExampleItem>();
const ExampleItem item = index.data(ExamplesListModel::ExampleItemRole).value<ExampleItem>();
const QRect rc = option.rect;
// Quick hack for empty items in the last row.
@@ -414,29 +413,9 @@ public:
// The pixmap.
if (offset == 0) {
const QSize requestSize(188, 145);
QPixmap pm;
if (QPixmap *foundPixmap = m_pixmapCache.find(item.imageUrl)) {
pm = *foundPixmap;
} else {
pm.load(item.imageUrl);
if (pm.isNull())
pm.load(resourcePath() + "/welcomescreen/widgets/" + item.imageUrl);
if (pm.isNull()) {
// FIXME: Make async
QByteArray fetchedData = HelpManager::fileData(item.imageUrl);
QBuffer imgBuffer(&fetchedData);
imgBuffer.open(QIODevice::ReadOnly);
QImageReader reader(&imgBuffer);
QImage img = reader.read();
img = ScreenshotCropper::croppedImage(img, item.imageUrl, requestSize);
pm = QPixmap::fromImage(img);
}
m_pixmapCache.insert(item.imageUrl, pm);
}
QRect inner(x + 11, y - offset, requestSize.width(), requestSize.height());
QPixmap pm = index.data(ExamplesListModel::ExampleImageRole).value<QPixmap>();
QRect inner(x + 11, y - offset, ExamplesListModel::exampleImageSize.width(),
ExamplesListModel::exampleImageSize.height());
QRect pixmapRect = inner;
if (!pm.isNull()) {
painter->setPen(foregroundColor2);
@@ -576,7 +555,6 @@ private:
mutable QRect m_currentArea;
mutable QPointer<QAbstractItemView> m_currentWidget;
mutable QVector<QPair<QString, QRect>> m_currentTagRects;
mutable QPixmapCache m_pixmapCache;
};
class ExamplesPageWidget : public QWidget