diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp index 03f2c5dcf51..d875511b2a9 100644 --- a/src/plugins/qtsupport/exampleslistmodel.cpp +++ b/src/plugins/qtsupport/exampleslistmodel.cpp @@ -25,9 +25,15 @@ #include "exampleslistmodel.h" +#include "screenshotcropper.h" + +#include #include #include #include +#include +#include +#include #include #include @@ -39,6 +45,7 @@ #include #include +#include #include #include @@ -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(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(); + const ExampleItem item = sourceModel()->index(sourceRow, 0, sourceParent).data( + ExamplesListModel::ExampleItemRole).value(); if (m_showTutorialsOnly && item.type != Tutorial) return false; diff --git a/src/plugins/qtsupport/exampleslistmodel.h b/src/plugins/qtsupport/exampleslistmodel.h index e6d1a252c99..44d898f17dd 100644 --- a/src/plugins/qtsupport/exampleslistmodel.h +++ b/src/plugins/qtsupport/exampleslistmodel.h @@ -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); diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index 045222fe77f..814681980e2 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -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(); + const ExampleItem item = index.data(ExamplesListModel::ExampleItemRole).value(); 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(); + 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 m_currentWidget; mutable QVector> m_currentTagRects; - mutable QPixmapCache m_pixmapCache; }; class ExamplesPageWidget : public QWidget