forked from qt-creator/qt-creator
QtSupport: move example image loading from delegate to model
Change-Id: I287336b4d36d648666093a4894ab131b8999ca98 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user