diff --git a/src/plugins/coreplugin/welcomepagehelper.cpp b/src/plugins/coreplugin/welcomepagehelper.cpp index fbb4214b565..e3360b35f08 100644 --- a/src/plugins/coreplugin/welcomepagehelper.cpp +++ b/src/plugins/coreplugin/welcomepagehelper.cpp @@ -78,18 +78,15 @@ SearchBox::SearchBox(QWidget *parent) } GridView::GridView(QWidget *parent) - : QTableView(parent) + : QListView(parent) { - setVerticalScrollMode(ScrollPerPixel); - horizontalHeader()->hide(); - horizontalHeader()->setDefaultSectionSize(GridProxyModel::GridItemWidth); - verticalHeader()->hide(); - verticalHeader()->setDefaultSectionSize(GridProxyModel::GridItemHeight); + setResizeMode(QListView::Adjust); setMouseTracking(true); // To enable hover. setSelectionMode(QAbstractItemView::NoSelection); setFrameShape(QFrame::NoFrame); - setGridStyle(Qt::NoPen); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setViewMode(IconMode); + setUniformItemSizes(true); QPalette pal; pal.setColor(QPalette::Base, themeColor(Theme::Welcome_BackgroundColor)); @@ -102,129 +99,6 @@ void GridView::leaveEvent(QEvent *) viewportEvent(&hev); // Seemingly needed to kill the hover paint. } -void GridProxyModel::setSourceModel(QAbstractItemModel *newModel) -{ - if (m_sourceModel == newModel) - return; - if (m_sourceModel) - disconnect(m_sourceModel, nullptr, this, nullptr); - m_sourceModel = newModel; - if (newModel) { - connect(newModel, &QAbstractItemModel::layoutAboutToBeChanged, this, [this] { - emit layoutAboutToBeChanged(); - }); - connect(newModel, &QAbstractItemModel::layoutChanged, this, [this] { - emit layoutChanged(); - }); - connect(newModel, &QAbstractItemModel::modelAboutToBeReset, this, [this] { - beginResetModel(); - }); - connect(newModel, &QAbstractItemModel::modelReset, this, [this] { endResetModel(); }); - connect(newModel, &QAbstractItemModel::rowsAboutToBeInserted, this, [this] { - beginResetModel(); - }); - connect(newModel, &QAbstractItemModel::rowsInserted, this, [this] { endResetModel(); }); - connect(newModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, [this] { - beginResetModel(); - }); - connect(newModel, &QAbstractItemModel::rowsRemoved, this, [this] { endResetModel(); }); - connect(newModel, - &QAbstractItemModel::dataChanged, - this, - [this] (const QModelIndex &topLeft, - const QModelIndex &bottomRight, - const QVector &roles) { - emit QAbstractItemModel::dataChanged(mapFromSource(topLeft), - mapFromSource(bottomRight), roles); - }); - } -} - -QAbstractItemModel *GridProxyModel::sourceModel() const -{ - return m_sourceModel; -} - -QVariant GridProxyModel::data(const QModelIndex &index, int role) const -{ - const OptModelIndex sourceIndex = mapToSource(index); - if (sourceIndex) - return sourceModel()->data(*sourceIndex, role); - return QVariant(); -} - -Qt::ItemFlags GridProxyModel::flags(const QModelIndex &index) const -{ - const OptModelIndex sourceIndex = mapToSource(index); - if (sourceIndex) - return sourceModel()->flags(*sourceIndex); - return Qt::ItemFlags(); -} - -bool GridProxyModel::hasChildren(const QModelIndex &parent) const -{ - const OptModelIndex sourceParent = mapToSource(parent); - if (sourceParent) - return sourceModel()->hasChildren(*sourceParent); - return false; -} - -void GridProxyModel::setColumnCount(int columnCount) -{ - if (columnCount == m_columnCount) - return; - QTC_ASSERT(columnCount >= 1, columnCount = 1); - m_columnCount = columnCount; - emit layoutChanged(); -} - -int GridProxyModel::rowCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - int rows = sourceModel()->rowCount(QModelIndex()); - return (rows + m_columnCount - 1) / m_columnCount; -} - -int GridProxyModel::columnCount(const QModelIndex &parent) const -{ - if (parent.isValid()) - return 0; - return m_columnCount; -} - -QModelIndex GridProxyModel::index(int row, int column, const QModelIndex &) const -{ - return createIndex(row, column, nullptr); -} - -QModelIndex GridProxyModel::parent(const QModelIndex &) const -{ - return QModelIndex(); -} - -// The items at the lower right of the grid might not correspond to source items, if -// source's row count is not N*columnCount -OptModelIndex GridProxyModel::mapToSource(const QModelIndex &proxyIndex) const -{ - if (!proxyIndex.isValid()) - return QModelIndex(); - int sourceRow = proxyIndex.row() * m_columnCount + proxyIndex.column(); - if (sourceRow < sourceModel()->rowCount()) - return sourceModel()->index(sourceRow, 0); - return OptModelIndex(); -} - -QModelIndex GridProxyModel::mapFromSource(const QModelIndex &sourceIndex) const -{ - if (!sourceIndex.isValid()) - return QModelIndex(); - QTC_CHECK(sourceIndex.column() == 0); - int proxyRow = sourceIndex.row() / m_columnCount; - int proxyColumn = sourceIndex.row() % m_columnCount; - return index(proxyRow, proxyColumn, QModelIndex()); -} - const QSize ListModel::defaultImageSize(188, 145); ListModel::ListModel(QObject *parent) @@ -474,13 +348,13 @@ void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti const int d = 10; const int x = rc.x() + d; const int y = rc.y() + d; - const int w = rc.width() - 2 * d - GridProxyModel::GridItemGap; + const int w = rc.width() - 2 * d; const int h = rc.height() - 2 * d; const bool hovered = option.state & QStyle::State_MouseOver; - const int tagsBase = GridProxyModel::TagsSeparatorY + 10; - const int shiftY = GridProxyModel::TagsSeparatorY - 20; - const int nameY = GridProxyModel::TagsSeparatorY - 20; + const int tagsBase = TagsSeparatorY + 10; + const int shiftY = TagsSeparatorY - 20; + const int nameY = TagsSeparatorY - 20; const QRect textRect = QRect(x, y + nameY, w, h); @@ -576,8 +450,7 @@ void ListItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti // Separator line between text and 'Tags:' section painter->setPen(lightColor); - painter->drawLine(x, y + GridProxyModel::TagsSeparatorY, - x + w, y + GridProxyModel::TagsSeparatorY); + painter->drawLine(x, y + TagsSeparatorY, x + w, y + TagsSeparatorY); // The 'Tags:' section const int tagsHeight = h - tagsBase; @@ -623,7 +496,7 @@ bool ListItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, if (index.isValid()) { const QPoint pos = mev->pos(); - if (pos.y() > option.rect.y() + GridProxyModel::TagsSeparatorY) { + if (pos.y() > option.rect.y() + TagsSeparatorY) { //const QStringList tags = idx.data(Tags).toStringList(); for (const auto &it : qAsConst(m_currentTagRects)) { if (it.second.contains(pos)) @@ -637,6 +510,11 @@ bool ListItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, return QStyledItemDelegate::editorEvent(event, model, option, index); } +QSize ListItemDelegate::sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const +{ + return {GridItemWidth, GridItemHeight}; +} + void ListItemDelegate::drawPixmapOverlay(const ListItem *, QPainter *, const QStyleOptionViewItem &, const QRect &) const { diff --git a/src/plugins/coreplugin/welcomepagehelper.h b/src/plugins/coreplugin/welcomepagehelper.h index 884d64de8df..90645f4dee5 100644 --- a/src/plugins/coreplugin/welcomepagehelper.h +++ b/src/plugins/coreplugin/welcomepagehelper.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include namespace Utils { class FancyLineEdit; } @@ -48,7 +48,7 @@ public: Utils::FancyLineEdit *m_lineEdit = nullptr; }; -class CORE_EXPORT GridView : public QTableView +class CORE_EXPORT GridView : public QListView { public: explicit GridView(QWidget *parent); @@ -58,33 +58,6 @@ protected: using OptModelIndex = Utils::optional; -class CORE_EXPORT GridProxyModel : public QAbstractItemModel -{ -public: - void setSourceModel(QAbstractItemModel *newModel); - QAbstractItemModel *sourceModel() const; - QVariant data(const QModelIndex &index, int role) const final; - Qt::ItemFlags flags(const QModelIndex &index) const final; - bool hasChildren(const QModelIndex &parent) const final; - void setColumnCount(int columnCount); - int rowCount(const QModelIndex &parent) const final; - int columnCount(const QModelIndex &parent) const final; - QModelIndex index(int row, int column, const QModelIndex &) const final; - QModelIndex parent(const QModelIndex &) const final; - - OptModelIndex mapToSource(const QModelIndex &proxyIndex) const; - QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; - - static constexpr int GridItemWidth = 230; - static constexpr int GridItemHeight = 230; - static constexpr int GridItemGap = 10; - static constexpr int TagsSeparatorY = GridItemHeight - 60; - -private: - QAbstractItemModel *m_sourceModel = nullptr; - int m_columnCount = 1; -}; - class CORE_EXPORT ListItem { public: @@ -148,12 +121,18 @@ public: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + static constexpr int GridItemWidth = 230; + static constexpr int GridItemHeight = 230; + static constexpr int GridItemGap = 10; + static constexpr int TagsSeparatorY = GridItemHeight - 60; + signals: void tagClicked(const QString &tag); protected: bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; virtual void drawPixmapOverlay(const ListItem *item, QPainter *painter, const QStyleOptionViewItem &option, diff --git a/src/plugins/marketplace/productlistmodel.cpp b/src/plugins/marketplace/productlistmodel.cpp index ca1818ee99d..92e397a8710 100644 --- a/src/plugins/marketplace/productlistmodel.cpp +++ b/src/plugins/marketplace/productlistmodel.cpp @@ -66,41 +66,23 @@ class ProductGridView : public Core::GridView { public: ProductGridView(QWidget *parent) : Core::GridView(parent) {} - QSize viewportSizeHint() const override - { - if (!model()) - return Core::GridView::viewportSizeHint(); - static int gridW = Core::GridProxyModel::GridItemWidth + Core::GridProxyModel::GridItemGap; - static int gridH = Core::GridProxyModel::GridItemHeight + Core::GridProxyModel::GridItemGap; - return QSize(model()->columnCount() * gridW, model()->rowCount() * gridH); + bool hasHeightForWidth() const override + { + return true; } - void setColumnCount(int columnCount) + int heightForWidth(int width) const override { - if (columnCount < 1) - columnCount = 1; - - auto gridProxyModel = static_cast(model()); - gridProxyModel->setColumnCount(columnCount); + 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: - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override - { - const Core::ListItem *item = index.data(Core::ListModel::ItemRole).value(); - - // "empty" items (last row of a section) - if (!item) - return Core::ListItemDelegate::sizeHint(option, index); - - return QSize(Core::GridProxyModel::GridItemWidth + Core::GridProxyModel::GridItemGap, - Core::GridProxyModel::GridItemHeight + Core::GridProxyModel::GridItemGap); - } - void clickAction(const Core::ListItem *item) const override { QTC_ASSERT(item, return); @@ -163,9 +145,8 @@ static int priority(const QString &collection) SectionedProducts::SectionedProducts(QWidget *parent) : QStackedWidget(parent) - , m_allProductsView(new ProductGridView(this)) + , m_allProductsView(new Core::GridView(this)) , m_filteredAllProductsModel(new Core::ListModelFilter(new AllProductsModel(this), this)) - , m_gridModel(new Core::GridProxyModel) , m_productDelegate(new ProductItemDelegate) { auto area = new QScrollArea(this); @@ -182,9 +163,8 @@ SectionedProducts::SectionedProducts(QWidget *parent) addWidget(area); - m_gridModel->setSourceModel(m_filteredAllProductsModel); m_allProductsView->setItemDelegate(m_productDelegate); - m_allProductsView->setModel(m_gridModel); + m_allProductsView->setModel(m_filteredAllProductsModel); addWidget(m_allProductsView); connect(m_productDelegate, &ProductItemDelegate::tagClicked, @@ -195,7 +175,6 @@ SectionedProducts::~SectionedProducts() { qDeleteAll(m_gridViews); delete m_productDelegate; - delete m_gridModel; } void SectionedProducts::updateCollections() @@ -328,18 +307,6 @@ void SectionedProducts::queueImageForDownload(const QString &url) fetchNextImage(); } -void SectionedProducts::setColumnCount(int columns) -{ - if (columns < 1) - columns = 1; - m_columnCount = columns; - for (ProductGridView *view : qAsConst(m_gridViews)) { - view->setColumnCount(columns); - view->setFixedSize(view->viewportSizeHint()); - } - m_allProductsView->setColumnCount(columns); -} - void SectionedProducts::setSearchString(const QString &searchString) { int view = searchString.isEmpty() ? 0 // sectioned view @@ -401,14 +368,11 @@ void SectionedProducts::addNewSection(const Section §ion, const QListappendItems(items); auto filteredModel = new Core::ListModelFilter(productModel, this); - Core::GridProxyModel *gridModel = new Core::GridProxyModel; - gridModel->setSourceModel(filteredModel); auto gridView = new ProductGridView(this); gridView->setItemDelegate(m_productDelegate); gridView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); gridView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - gridView->setModel(gridModel); - gridModel->setColumnCount(m_columnCount); + gridView->setModel(filteredModel); m_productModels.insert(section, productModel); const auto it = m_gridViews.insert(section, gridView); @@ -425,12 +389,10 @@ void SectionedProducts::addNewSection(const Section §ion, const QListcount() - 1, position = vbox->count() - 1); vbox->insertWidget(position, sectionLabel); vbox->insertWidget(position + 1, gridView); - gridView->setFixedSize(gridView->viewportSizeHint()); // add the items also to the all products model to be able to search correctly auto allProducts = static_cast(m_filteredAllProductsModel->sourceModel()); allProducts->appendItems(items); - m_allProductsView->setColumnCount(m_columnCount); } void SectionedProducts::onTagClicked(const QString &tag) diff --git a/src/plugins/marketplace/productlistmodel.h b/src/plugins/marketplace/productlistmodel.h index 42d13dc417f..df2070f213b 100644 --- a/src/plugins/marketplace/productlistmodel.h +++ b/src/plugins/marketplace/productlistmodel.h @@ -108,10 +108,9 @@ private: QSet m_pendingImages; QMap m_collectionTitles; QMap m_productModels; - QMap m_gridViews; - ProductGridView *m_allProductsView = nullptr; + QMap m_gridViews; + Core::GridView *m_allProductsView = nullptr; Core::ListModelFilter *m_filteredAllProductsModel = nullptr; - Core::GridProxyModel * const m_gridModel; ProductItemDelegate *m_productDelegate = nullptr; bool m_isDownloadingImage = false; int m_columnCount = 1; diff --git a/src/plugins/marketplace/qtmarketplacewelcomepage.cpp b/src/plugins/marketplace/qtmarketplacewelcomepage.cpp index e8bbc25d6ef..738ee04269b 100644 --- a/src/plugins/marketplace/qtmarketplacewelcomepage.cpp +++ b/src/plugins/marketplace/qtmarketplacewelcomepage.cpp @@ -124,18 +124,6 @@ public: QWidget::showEvent(event); } - void resizeEvent(QResizeEvent *ev) final - { - QWidget::resizeEvent(ev); - m_sectionedProducts->setColumnCount(bestColumnCount()); - } - - int bestColumnCount() const - { - return qMax(1, width() / (Core::GridProxyModel::GridItemWidth - + Core::GridProxyModel::GridItemGap)); - } - void onTagClicked(const QString &tag) { QString text = m_searcher->text(); diff --git a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp index d02dddcbce6..a036c095198 100644 --- a/src/plugins/qtsupport/gettingstartedwelcomepage.cpp +++ b/src/plugins/qtsupport/gettingstartedwelcomepage.cpp @@ -293,8 +293,8 @@ public: // for macOS dark mode pal.setColor(QPalette::Text, Utils::creatorTheme()->color(Theme::Welcome_TextColor)); exampleSetSelector->setPalette(pal); - exampleSetSelector->setMinimumWidth(GridProxyModel::GridItemWidth); - exampleSetSelector->setMaximumWidth(GridProxyModel::GridItemWidth); + exampleSetSelector->setMinimumWidth(Core::ListItemDelegate::GridItemWidth); + exampleSetSelector->setMaximumWidth(Core::ListItemDelegate::GridItemWidth); ExampleSetModel *exampleSetModel = m_examplesModel->exampleSetModel(); exampleSetSelector->setModel(exampleSetModel); exampleSetSelector->setCurrentIndex(exampleSetModel->selectedExampleSet()); @@ -312,10 +312,8 @@ public: hbox->addSpacing(sideMargin); vbox->addItem(hbox); - m_gridModel.setSourceModel(filteredModel); - auto gridView = new GridView(this); - gridView->setModel(&m_gridModel); + gridView->setModel(filteredModel); gridView->setItemDelegate(&m_exampleDelegate); if (auto sb = gridView->verticalScrollBar()) sb->setSingleStep(25); @@ -327,17 +325,6 @@ public: filteredModel, &ExamplesListModelFilter::setSearchString); } - int bestColumnCount() const - { - return qMax(1, width() / (GridProxyModel::GridItemWidth + GridProxyModel::GridItemGap)); - } - - void resizeEvent(QResizeEvent *ev) final - { - QWidget::resizeEvent(ev); - m_gridModel.setColumnCount(bestColumnCount()); - } - void onTagClicked(const QString &tag) { QString text = m_searcher->text(); @@ -348,7 +335,6 @@ public: ExampleDelegate m_exampleDelegate; QPointer m_examplesModel; QLineEdit *m_searcher; - GridProxyModel m_gridModel; }; QWidget *ExamplesWelcomePage::createWidget() const