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 "exampleslistmodel.h"
|
||||||
|
|
||||||
|
#include "screenshotcropper.h"
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QFutureWatcher>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QPixmapCache>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
@@ -39,6 +45,7 @@
|
|||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -46,6 +53,8 @@
|
|||||||
namespace QtSupport {
|
namespace QtSupport {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
const QSize ExamplesListModel::exampleImageSize(188, 145);
|
||||||
|
|
||||||
static bool debugExamples()
|
static bool debugExamples()
|
||||||
{
|
{
|
||||||
static bool isDebugging = qEnvironmentVariableIsSet("QTC_DEBUG_EXAMPLESMODEL");
|
static bool isDebugging = qEnvironmentVariableIsSet("QTC_DEBUG_EXAMPLESMODEL");
|
||||||
@@ -303,6 +312,7 @@ void ExamplesListModel::parseExamples(QXmlStreamReader *reader,
|
|||||||
item.hasSourceCode = !item.projectPath.isEmpty();
|
item.hasSourceCode = !item.projectPath.isEmpty();
|
||||||
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, examplesInstallPath);
|
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, examplesInstallPath);
|
||||||
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||||
|
QPixmapCache::remove(item.imageUrl);
|
||||||
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||||
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
||||||
|
|
||||||
@@ -356,6 +366,7 @@ void ExamplesListModel::parseDemos(QXmlStreamReader *reader,
|
|||||||
item.hasSourceCode = !item.projectPath.isEmpty();
|
item.hasSourceCode = !item.projectPath.isEmpty();
|
||||||
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, demosInstallPath);
|
item.projectPath = relativeOrInstallPath(item.projectPath, projectsOffset, demosInstallPath);
|
||||||
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||||
|
QPixmapCache::remove(item.imageUrl);
|
||||||
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||||
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
item.isHighlighted = attributes.value(QLatin1String("isHighlighted")).toString() == QLatin1String("true");
|
||||||
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
} else if (reader->name() == QLatin1String("fileToOpen")) {
|
||||||
@@ -400,6 +411,7 @@ void ExamplesListModel::parseTutorials(QXmlStreamReader *reader, const QString &
|
|||||||
item.projectPath.prepend(slash);
|
item.projectPath.prepend(slash);
|
||||||
item.projectPath.prepend(projectsOffset);
|
item.projectPath.prepend(projectsOffset);
|
||||||
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
item.imageUrl = attributes.value(QLatin1String("imageUrl")).toString();
|
||||||
|
QPixmapCache::remove(item.imageUrl);
|
||||||
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
item.docUrl = attributes.value(QLatin1String("docUrl")).toString();
|
||||||
item.isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
|
item.isVideo = attributes.value(QLatin1String("isVideo")).toString() == QLatin1String("true");
|
||||||
item.videoUrl = attributes.value(QLatin1String("videoUrl")).toString();
|
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()
|
void ExamplesListModel::updateExamples()
|
||||||
{
|
{
|
||||||
QString examplesInstallPath;
|
QString examplesInstallPath;
|
||||||
@@ -605,8 +623,30 @@ QVariant ExamplesListModel::data(const QModelIndex &index, int role) const
|
|||||||
{
|
{
|
||||||
case Qt::DisplayRole: // for search only
|
case Qt::DisplayRole: // for search only
|
||||||
return QString(prefixForItem(item) + item.name + ' ' + item.tags.join(' '));
|
return QString(prefixForItem(item) + item.name + ' ' + item.tags.join(' '));
|
||||||
case Qt::UserRole:
|
case ExampleItemRole:
|
||||||
return QVariant::fromValue<ExampleItem>(item);
|
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:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@@ -666,7 +706,8 @@ ExamplesListModelFilter::ExamplesListModelFilter(ExamplesListModel *sourceModel,
|
|||||||
|
|
||||||
bool ExamplesListModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
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)
|
if (m_showTutorialsOnly && item.type != Tutorial)
|
||||||
return false;
|
return false;
|
||||||
|
@@ -125,6 +125,11 @@ class ExamplesListModel : public QAbstractListModel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum ExampleListDataRole {
|
||||||
|
ExampleItemRole = Qt::UserRole,
|
||||||
|
ExampleImageRole = Qt::UserRole + 1
|
||||||
|
};
|
||||||
|
|
||||||
explicit ExamplesListModel(QObject *parent);
|
explicit ExamplesListModel(QObject *parent);
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const final;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const final;
|
||||||
@@ -135,6 +140,8 @@ public:
|
|||||||
QStringList exampleSets() const;
|
QStringList exampleSets() const;
|
||||||
ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; }
|
ExampleSetModel *exampleSetModel() { return &m_exampleSetModel; }
|
||||||
|
|
||||||
|
static const QSize exampleImageSize;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectedExampleSetChanged(int);
|
void selectedExampleSetChanged(int);
|
||||||
|
|
||||||
|
@@ -55,7 +55,6 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPixmapCache>
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
@@ -369,7 +368,7 @@ class ExampleDelegate : public QStyledItemDelegate
|
|||||||
public:
|
public:
|
||||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const final
|
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;
|
const QRect rc = option.rect;
|
||||||
|
|
||||||
// Quick hack for empty items in the last row.
|
// Quick hack for empty items in the last row.
|
||||||
@@ -414,29 +413,9 @@ public:
|
|||||||
|
|
||||||
// The pixmap.
|
// The pixmap.
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
const QSize requestSize(188, 145);
|
QPixmap pm = index.data(ExamplesListModel::ExampleImageRole).value<QPixmap>();
|
||||||
|
QRect inner(x + 11, y - offset, ExamplesListModel::exampleImageSize.width(),
|
||||||
QPixmap pm;
|
ExamplesListModel::exampleImageSize.height());
|
||||||
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());
|
|
||||||
QRect pixmapRect = inner;
|
QRect pixmapRect = inner;
|
||||||
if (!pm.isNull()) {
|
if (!pm.isNull()) {
|
||||||
painter->setPen(foregroundColor2);
|
painter->setPen(foregroundColor2);
|
||||||
@@ -576,7 +555,6 @@ private:
|
|||||||
mutable QRect m_currentArea;
|
mutable QRect m_currentArea;
|
||||||
mutable QPointer<QAbstractItemView> m_currentWidget;
|
mutable QPointer<QAbstractItemView> m_currentWidget;
|
||||||
mutable QVector<QPair<QString, QRect>> m_currentTagRects;
|
mutable QVector<QPair<QString, QRect>> m_currentTagRects;
|
||||||
mutable QPixmapCache m_pixmapCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExamplesPageWidget : public QWidget
|
class ExamplesPageWidget : public QWidget
|
||||||
|
Reference in New Issue
Block a user