forked from qt-creator/qt-creator
Make categorized product/example view reusable
Extract a SectionedGridView from the SectionedProducts that are used in the MarketPlace plugin, and make item delegate and pixmap fetching function to be used with the model(s) pluggable. Change-Id: I02aba87b27afd8ad18ff23346d1ac98da906db4b Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -13,12 +13,14 @@
|
||||
|
||||
#include <QEasingCurve>
|
||||
#include <QFontDatabase>
|
||||
#include <QHeaderView>
|
||||
#include <QHBoxLayout>
|
||||
#include <QHeaderView>
|
||||
#include <QHoverEvent>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include <QScrollArea>
|
||||
#include <QTimer>
|
||||
|
||||
#include <qdrawutil.h>
|
||||
@@ -117,6 +119,22 @@ void GridView::leaveEvent(QEvent *)
|
||||
viewportEvent(&hev); // Seemingly needed to kill the hover paint.
|
||||
}
|
||||
|
||||
SectionGridView::SectionGridView(QWidget *parent)
|
||||
: GridView(parent)
|
||||
{}
|
||||
|
||||
bool SectionGridView::hasHeightForWidth() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int SectionGridView::heightForWidth(int width) const
|
||||
{
|
||||
const int columnCount = width / Core::ListItemDelegate::GridItemWidth;
|
||||
const int rowCount = (model()->rowCount() + columnCount - 1) / columnCount;
|
||||
return rowCount * Core::ListItemDelegate::GridItemHeight;
|
||||
}
|
||||
|
||||
const QSize ListModel::defaultImageSize(214, 160);
|
||||
|
||||
ListModel::ListModel(QObject *parent)
|
||||
@@ -126,10 +144,23 @@ ListModel::ListModel(QObject *parent)
|
||||
|
||||
ListModel::~ListModel()
|
||||
{
|
||||
if (m_ownsItems)
|
||||
qDeleteAll(m_items);
|
||||
m_items.clear();
|
||||
}
|
||||
|
||||
void ListModel::appendItems(const QList<ListItem *> &items)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_items.size(), m_items.size() + items.size());
|
||||
m_items.append(items);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
const QList<ListItem *> ListModel::items() const
|
||||
{
|
||||
return m_items;
|
||||
}
|
||||
|
||||
int ListModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_items.size();
|
||||
@@ -166,6 +197,11 @@ void ListModel::setPixmapFunction(const PixmapFunction &fetchPixmapAndUpdatePixm
|
||||
m_fetchPixmapAndUpdatePixmapCache = fetchPixmapAndUpdatePixmapCache;
|
||||
}
|
||||
|
||||
void ListModel::setOwnsItems(bool owns)
|
||||
{
|
||||
m_ownsItems = owns;
|
||||
}
|
||||
|
||||
ListModelFilter::ListModelFilter(ListModel *sourceModel, QObject *parent) :
|
||||
QSortFilterProxyModel(parent)
|
||||
{
|
||||
@@ -346,6 +382,11 @@ void ListModelFilter::setSearchString(const QString &arg)
|
||||
delayedUpdateFilter();
|
||||
}
|
||||
|
||||
ListModel *ListModelFilter::sourceListModel() const
|
||||
{
|
||||
return static_cast<ListModel *>(sourceModel());
|
||||
}
|
||||
|
||||
bool ListModelFilter::leaveFilterAcceptsRowBeforeFiltering(const ListItem *, bool *) const
|
||||
{
|
||||
return false;
|
||||
@@ -583,4 +624,93 @@ void ListItemDelegate::goon()
|
||||
m_currentWidget->update(m_previousIndex);
|
||||
}
|
||||
|
||||
SectionedGridView::SectionedGridView(QWidget *parent)
|
||||
: QStackedWidget(parent)
|
||||
, m_allItemsView(new Core::GridView(this))
|
||||
{
|
||||
auto allItemsModel = new ListModel(this);
|
||||
allItemsModel->setPixmapFunction(m_pixmapFunction);
|
||||
// it just "borrows" the items from the section models:
|
||||
allItemsModel->setOwnsItems(false);
|
||||
m_filteredAllItemsModel = new Core::ListModelFilter(allItemsModel, this);
|
||||
|
||||
auto area = new QScrollArea(this);
|
||||
area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
area->setFrameShape(QFrame::NoFrame);
|
||||
area->setWidgetResizable(true);
|
||||
|
||||
auto sectionedView = new QWidget;
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addStretch();
|
||||
sectionedView->setLayout(layout);
|
||||
area->setWidget(sectionedView);
|
||||
|
||||
addWidget(area);
|
||||
|
||||
m_allItemsView->setModel(m_filteredAllItemsModel);
|
||||
addWidget(m_allItemsView);
|
||||
}
|
||||
|
||||
SectionedGridView::~SectionedGridView() = default;
|
||||
|
||||
void SectionedGridView::setItemDelegate(QAbstractItemDelegate *delegate)
|
||||
{
|
||||
m_allItemsView->setItemDelegate(delegate);
|
||||
for (GridView *view : std::as_const(m_gridViews))
|
||||
view->setItemDelegate(delegate);
|
||||
}
|
||||
|
||||
void SectionedGridView::setPixmapFunction(const Core::ListModel::PixmapFunction &pixmapFunction)
|
||||
{
|
||||
m_pixmapFunction = pixmapFunction;
|
||||
auto allProducts = static_cast<ListModel *>(m_filteredAllItemsModel->sourceModel());
|
||||
allProducts->setPixmapFunction(pixmapFunction);
|
||||
for (ListModel *model : std::as_const(m_sectionModels))
|
||||
model->setPixmapFunction(pixmapFunction);
|
||||
}
|
||||
|
||||
void SectionedGridView::setSearchString(const QString &searchString)
|
||||
{
|
||||
int view = searchString.isEmpty() ? 0 // sectioned view
|
||||
: 1; // search view
|
||||
setCurrentIndex(view);
|
||||
m_filteredAllItemsModel->setSearchString(searchString);
|
||||
}
|
||||
|
||||
ListModel *SectionedGridView::addSection(const Section §ion, const QList<ListItem *> &items)
|
||||
{
|
||||
auto model = new ListModel(this);
|
||||
model->setPixmapFunction(m_pixmapFunction);
|
||||
model->appendItems(items);
|
||||
|
||||
auto gridView = new SectionGridView(this);
|
||||
gridView->setItemDelegate(m_allItemsView->itemDelegate());
|
||||
gridView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
gridView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
gridView->setModel(model);
|
||||
|
||||
m_sectionModels.insert(section, model);
|
||||
const auto it = m_gridViews.insert(section, gridView);
|
||||
|
||||
auto sectionLabel = new QLabel(section.name);
|
||||
sectionLabel->setContentsMargins(0, Core::WelcomePageHelpers::ItemGap, 0, 0);
|
||||
sectionLabel->setFont(Core::WelcomePageHelpers::brandFont());
|
||||
auto scrollArea = qobject_cast<QScrollArea *>(widget(0));
|
||||
auto vbox = qobject_cast<QVBoxLayout *>(scrollArea->widget()->layout());
|
||||
|
||||
// insert new section depending on its priority, but before the last (stretch) item
|
||||
int position = std::distance(m_gridViews.begin(), it) * 2; // a section has a label and a grid
|
||||
QTC_ASSERT(position <= vbox->count() - 1, position = vbox->count() - 1);
|
||||
vbox->insertWidget(position, sectionLabel);
|
||||
vbox->insertWidget(position + 1, gridView);
|
||||
|
||||
// add the items also to the all products model to be able to search correctly
|
||||
auto allProducts = static_cast<ListModel *>(m_filteredAllItemsModel->sourceModel());
|
||||
allProducts->appendItems(items);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
@@ -7,10 +7,11 @@
|
||||
#include "iwelcomepage.h"
|
||||
|
||||
#include <QElapsedTimer>
|
||||
#include <QListView>
|
||||
#include <QPointer>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStackedWidget>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QListView>
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
@@ -40,10 +41,20 @@ class CORE_EXPORT GridView : public QListView
|
||||
{
|
||||
public:
|
||||
explicit GridView(QWidget *parent);
|
||||
|
||||
protected:
|
||||
void leaveEvent(QEvent *) final;
|
||||
};
|
||||
|
||||
class CORE_EXPORT SectionGridView : public GridView
|
||||
{
|
||||
public:
|
||||
explicit SectionGridView(QWidget *parent);
|
||||
|
||||
bool hasHeightForWidth() const;
|
||||
int heightForWidth(int width) const;
|
||||
};
|
||||
|
||||
using OptModelIndex = std::optional<QModelIndex>;
|
||||
|
||||
class CORE_EXPORT ListItem
|
||||
@@ -66,15 +77,21 @@ public:
|
||||
explicit ListModel(QObject *parent);
|
||||
~ListModel() override;
|
||||
|
||||
void appendItems(const QList<ListItem *> &items);
|
||||
const QList<ListItem *> items() const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const final;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
void setPixmapFunction(const PixmapFunction &fetchPixmapAndUpdatePixmapCache);
|
||||
|
||||
static const QSize defaultImageSize;
|
||||
|
||||
void setOwnsItems(bool owns);
|
||||
|
||||
protected:
|
||||
QList<ListItem *> m_items;
|
||||
PixmapFunction m_fetchPixmapAndUpdatePixmapCache;
|
||||
bool m_ownsItems = true;
|
||||
};
|
||||
|
||||
class CORE_EXPORT ListModelFilter : public QSortFilterProxyModel
|
||||
@@ -84,6 +101,8 @@ public:
|
||||
|
||||
void setSearchString(const QString &arg);
|
||||
|
||||
ListModel *sourceListModel() const;
|
||||
|
||||
protected:
|
||||
virtual bool leaveFilterAcceptsRowBeforeFiltering(const ListItem *item,
|
||||
bool *earlyExitResult) const;
|
||||
@@ -142,6 +161,45 @@ private:
|
||||
mutable QPixmap m_blurredThumbnail;
|
||||
};
|
||||
|
||||
class CORE_EXPORT Section
|
||||
{
|
||||
public:
|
||||
friend bool operator<(const Section &lhs, const Section &rhs)
|
||||
{
|
||||
if (lhs.priority < rhs.priority)
|
||||
return true;
|
||||
return lhs.priority > rhs.priority ? false : lhs.name < rhs.name;
|
||||
}
|
||||
|
||||
friend bool operator==(const Section &lhs, const Section &rhs)
|
||||
{
|
||||
return lhs.priority == rhs.priority && lhs.name == rhs.name;
|
||||
}
|
||||
|
||||
QString name;
|
||||
int priority;
|
||||
};
|
||||
|
||||
class CORE_EXPORT SectionedGridView : public QStackedWidget
|
||||
{
|
||||
public:
|
||||
explicit SectionedGridView(QWidget *parent = nullptr);
|
||||
~SectionedGridView();
|
||||
|
||||
void setItemDelegate(QAbstractItemDelegate *delegate);
|
||||
void setPixmapFunction(const Core::ListModel::PixmapFunction &pixmapFunction);
|
||||
void setSearchString(const QString &searchString);
|
||||
|
||||
Core::ListModel *addSection(const Section §ion, const QList<Core::ListItem *> &items);
|
||||
|
||||
private:
|
||||
QMap<Section, Core::ListModel *> m_sectionModels;
|
||||
QMap<Section, Core::GridView *> m_gridViews;
|
||||
Core::GridView *m_allItemsView = nullptr;
|
||||
Core::ListModelFilter *m_filteredAllItemsModel = nullptr;
|
||||
Core::ListModel::PixmapFunction m_pixmapFunction;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
Q_DECLARE_METATYPE(Core::ListItem *)
|
||||
|
@@ -14,49 +14,20 @@
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QLabel>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QPixmapCache>
|
||||
#include <QRegularExpression>
|
||||
#include <QScrollArea>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace Core;
|
||||
|
||||
namespace Marketplace {
|
||||
namespace Internal {
|
||||
|
||||
/**
|
||||
* @brief AllProductsModel does not own its items. Using this model only to display
|
||||
* the same items stored inside other models without the need to duplicate the items.
|
||||
*/
|
||||
class AllProductsModel : public ProductListModel
|
||||
{
|
||||
public:
|
||||
explicit AllProductsModel(QObject *parent) : ProductListModel(parent) {}
|
||||
~AllProductsModel() override { m_items.clear(); }
|
||||
};
|
||||
|
||||
class ProductGridView : public Core::GridView
|
||||
{
|
||||
public:
|
||||
ProductGridView(QWidget *parent) : Core::GridView(parent) {}
|
||||
|
||||
bool hasHeightForWidth() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int heightForWidth(int width) const override
|
||||
{
|
||||
const int columnCount = width / Core::ListItemDelegate::GridItemWidth;
|
||||
const int rowCount = (model()->rowCount() + columnCount - 1) / columnCount;
|
||||
return rowCount * Core::ListItemDelegate::GridItemHeight;
|
||||
}
|
||||
};
|
||||
|
||||
class ProductItemDelegate : public Core::ListItemDelegate
|
||||
{
|
||||
public:
|
||||
@@ -69,28 +40,6 @@ 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)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_items.size(), m_items.size() + items.size());
|
||||
m_items.append(items);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
const QList<Core::ListItem *> ProductListModel::items() const
|
||||
{
|
||||
return m_items;
|
||||
}
|
||||
|
||||
static const QNetworkRequest constructRequest(const QString &collection)
|
||||
{
|
||||
QString url("https://marketplace.qt.io");
|
||||
@@ -128,37 +77,22 @@ static int priority(const QString &collection)
|
||||
}
|
||||
|
||||
SectionedProducts::SectionedProducts(QWidget *parent)
|
||||
: QStackedWidget(parent)
|
||||
, m_allProductsView(new Core::GridView(this))
|
||||
, m_filteredAllProductsModel(new Core::ListModelFilter(new AllProductsModel(this), this))
|
||||
: SectionedGridView(parent)
|
||||
, m_productDelegate(new ProductItemDelegate)
|
||||
{
|
||||
auto area = new QScrollArea(this);
|
||||
area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
area->setFrameShape(QFrame::NoFrame);
|
||||
area->setWidgetResizable(true);
|
||||
|
||||
auto sectionedView = new QWidget;
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addStretch();
|
||||
sectionedView->setLayout(layout);
|
||||
area->setWidget(sectionedView);
|
||||
|
||||
addWidget(area);
|
||||
|
||||
m_allProductsView->setItemDelegate(m_productDelegate);
|
||||
m_allProductsView->setModel(m_filteredAllProductsModel);
|
||||
addWidget(m_allProductsView);
|
||||
|
||||
connect(m_productDelegate, &ProductItemDelegate::tagClicked,
|
||||
this, &SectionedProducts::onTagClicked);
|
||||
setItemDelegate(m_productDelegate);
|
||||
setPixmapFunction([this](const QString &url) -> QPixmap {
|
||||
queueImageForDownload(url);
|
||||
return {};
|
||||
});
|
||||
connect(m_productDelegate,
|
||||
&ProductItemDelegate::tagClicked,
|
||||
this,
|
||||
&SectionedProducts::onTagClicked);
|
||||
}
|
||||
|
||||
SectionedProducts::~SectionedProducts()
|
||||
{
|
||||
qDeleteAll(m_gridViews);
|
||||
delete m_productDelegate;
|
||||
}
|
||||
|
||||
@@ -286,12 +220,15 @@ void SectionedProducts::queueImageForDownload(const QString &url)
|
||||
fetchNextImage();
|
||||
}
|
||||
|
||||
void SectionedProducts::setSearchString(const QString &searchString)
|
||||
static void updateModelIndexesForUrl(ListModel *model, const QString &url)
|
||||
{
|
||||
int view = searchString.isEmpty() ? 0 // sectioned view
|
||||
: 1; // search view
|
||||
setCurrentIndex(view);
|
||||
m_filteredAllProductsModel->setSearchString(searchString);
|
||||
const QList<ListItem *> items = model->items();
|
||||
for (int row = 0, end = items.size(); row < end; ++row) {
|
||||
if (items.at(row)->imageUrl == url) {
|
||||
const QModelIndex index = model->index(row);
|
||||
emit model->dataChanged(index, index, {ListModel::ItemImageRole, Qt::DisplayRole});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SectionedProducts::fetchNextImage()
|
||||
@@ -307,8 +244,8 @@ void SectionedProducts::fetchNextImage()
|
||||
|
||||
if (QPixmapCache::find(nextUrl, nullptr)) {
|
||||
// this image is already cached it might have been added while downloading
|
||||
for (ProductListModel *model : std::as_const(m_productModels))
|
||||
model->updateModelIndexesForUrl(nextUrl);
|
||||
for (ListModel *model : std::as_const(m_productModels))
|
||||
updateModelIndexesForUrl(model, nextUrl);
|
||||
fetchNextImage();
|
||||
return;
|
||||
}
|
||||
@@ -332,12 +269,13 @@ void SectionedProducts::onImageDownloadFinished(QNetworkReply *reply)
|
||||
if (pixmap.loadFromData(data, imageFormat.toLatin1())) {
|
||||
const QString url = imageUrl.toString();
|
||||
const int dpr = qApp->devicePixelRatio();
|
||||
pixmap = pixmap.scaled(ProductListModel::defaultImageSize * dpr,
|
||||
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap = pixmap.scaled(ListModel::defaultImageSize * dpr,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
pixmap.setDevicePixelRatio(dpr);
|
||||
QPixmapCache::insert(url, pixmap);
|
||||
for (ProductListModel *model : std::as_const(m_productModels))
|
||||
model->updateModelIndexesForUrl(url);
|
||||
for (ListModel *model : std::as_const(m_productModels))
|
||||
updateModelIndexesForUrl(model, url);
|
||||
}
|
||||
} // handle error not needed - it's okay'ish to have no images as long as the rest works
|
||||
|
||||
@@ -347,33 +285,7 @@ void SectionedProducts::onImageDownloadFinished(QNetworkReply *reply)
|
||||
void SectionedProducts::addNewSection(const Section §ion, const QList<Core::ListItem *> &items)
|
||||
{
|
||||
QTC_ASSERT(!items.isEmpty(), return);
|
||||
ProductListModel *productModel = new ProductListModel(this);
|
||||
productModel->appendItems(items);
|
||||
auto filteredModel = new Core::ListModelFilter(productModel, this);
|
||||
auto gridView = new ProductGridView(this);
|
||||
gridView->setItemDelegate(m_productDelegate);
|
||||
gridView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
gridView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
gridView->setModel(filteredModel);
|
||||
|
||||
m_productModels.insert(section, productModel);
|
||||
const auto it = m_gridViews.insert(section, gridView);
|
||||
|
||||
auto sectionLabel = new QLabel(section.name);
|
||||
sectionLabel->setContentsMargins(0, Core::WelcomePageHelpers::ItemGap, 0, 0);
|
||||
sectionLabel->setFont(Core::WelcomePageHelpers::brandFont());
|
||||
auto scrollArea = qobject_cast<QScrollArea *>(widget(0));
|
||||
auto vbox = qobject_cast<QVBoxLayout *>(scrollArea->widget()->layout());
|
||||
|
||||
// insert new section depending on its priority, but before the last (stretch) item
|
||||
int position = std::distance(m_gridViews.begin(), it) * 2; // a section has a label and a grid
|
||||
QTC_ASSERT(position <= vbox->count() - 1, position = vbox->count() - 1);
|
||||
vbox->insertWidget(position, sectionLabel);
|
||||
vbox->insertWidget(position + 1, gridView);
|
||||
|
||||
// add the items also to the all products model to be able to search correctly
|
||||
auto allProducts = static_cast<ProductListModel *>(m_filteredAllProductsModel->sourceModel());
|
||||
allProducts->appendItems(items);
|
||||
m_productModels.append(addSection(section, items));
|
||||
}
|
||||
|
||||
void SectionedProducts::onTagClicked(const QString &tag)
|
||||
@@ -385,18 +297,10 @@ void SectionedProducts::onTagClicked(const QString &tag)
|
||||
QList<Core::ListItem *> SectionedProducts::items()
|
||||
{
|
||||
QList<Core::ListItem *> result;
|
||||
for (const ProductListModel *model : std::as_const(m_productModels))
|
||||
for (const ListModel *model : std::as_const(m_productModels))
|
||||
result.append(model->items());
|
||||
return result;
|
||||
}
|
||||
|
||||
void ProductListModel::updateModelIndexesForUrl(const QString &url)
|
||||
{
|
||||
for (int row = 0, end = m_items.size(); row < end; ++row) {
|
||||
if (m_items.at(row)->imageUrl == url)
|
||||
emit dataChanged(index(row), index(row), {ItemImageRole, Qt::DisplayRole});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Marketplace
|
||||
|
@@ -24,34 +24,7 @@ public:
|
||||
QString handle;
|
||||
};
|
||||
|
||||
class ProductListModel : public Core::ListModel
|
||||
{
|
||||
public:
|
||||
explicit ProductListModel(QObject *parent);
|
||||
void appendItems(const QList<Core::ListItem *> &items);
|
||||
const QList<Core::ListItem *> items() const;
|
||||
void updateModelIndexesForUrl(const QString &url);
|
||||
};
|
||||
|
||||
struct Section
|
||||
{
|
||||
friend bool operator<(const Section &lhs, const Section &rhs)
|
||||
{
|
||||
if (lhs.priority < rhs.priority)
|
||||
return true;
|
||||
return lhs.priority > rhs.priority ? false : lhs.name < rhs.name;
|
||||
}
|
||||
|
||||
friend bool operator==(const Section &lhs, const Section &rhs)
|
||||
{
|
||||
return lhs.priority == rhs.priority && lhs.name == rhs.name;
|
||||
}
|
||||
|
||||
QString name;
|
||||
int priority;
|
||||
};
|
||||
|
||||
class SectionedProducts : public QStackedWidget
|
||||
class SectionedProducts : public Core::SectionedGridView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -59,8 +32,6 @@ public:
|
||||
~SectionedProducts() override;
|
||||
void updateCollections();
|
||||
void queueImageForDownload(const QString &url);
|
||||
void setColumnCount(int columns);
|
||||
void setSearchString(const QString &searchString);
|
||||
|
||||
signals:
|
||||
void errorOccurred(int errorCode, const QString &errorString);
|
||||
@@ -74,7 +45,7 @@ private:
|
||||
|
||||
void fetchNextImage();
|
||||
void onImageDownloadFinished(QNetworkReply *reply);
|
||||
void addNewSection(const Section §ion, const QList<Core::ListItem *> &items);
|
||||
void addNewSection(const Core::Section §ion, const QList<Core::ListItem *> &items);
|
||||
void onTagClicked(const QString &tag);
|
||||
|
||||
QList<Core::ListItem *> items();
|
||||
@@ -82,10 +53,7 @@ private:
|
||||
QQueue<QString> m_pendingCollections;
|
||||
QSet<QString> m_pendingImages;
|
||||
QMap<QString, QString> m_collectionTitles;
|
||||
QMap<Section, ProductListModel *> m_productModels;
|
||||
QMap<Section, Core::GridView *> m_gridViews;
|
||||
Core::GridView *m_allProductsView = nullptr;
|
||||
Core::ListModelFilter *m_filteredAllProductsModel = nullptr;
|
||||
QList<Core::ListModel *> m_productModels;
|
||||
ProductItemDelegate *m_productDelegate = nullptr;
|
||||
bool m_isDownloadingImage = false;
|
||||
int m_columnCount = 1;
|
||||
|
Reference in New Issue
Block a user