#include #include #include #include #include #include #include #include #include #include #include #include #include = // ------------------- ItemData Struct ------------------- // struct ItemData { QString filename; int rating; ItemData(const QString &filename, int rating) : filename(filename), rating(rating) { } }; // ------------------- Custom List Model ------------------- // class ItemModel : public QAbstractListModel { Q_OBJECT public: explicit ItemModel(QObject *parent = nullptr) : QAbstractListModel(parent) { } int rowCount(const QModelIndex &parent = QModelIndex()) const override { if (parent.isValid()) return 0; return items.count(); } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if (!index.isValid()) return QVariant(); const ItemData &item = items.at(index.row()); if (role == Qt::DisplayRole) { return item.filename; // Display the filename in the list view } else if (role == Qt::UserRole) { return item.rating; // Return the rating as user data } return QVariant(); } void addItem(const QString &filename, int rating) { beginInsertRows(QModelIndex(), items.count(), items.count()); items.append(ItemData(filename, rating)); endInsertRows(); } void setItemRating(int row, int rating) { if (row < 0 || row >= items.count()) return; items[row].rating = rating; emit dataChanged(index(row), index(row), {Qt::UserRole}); } private: QList items; }; // ------------------- Custom Widget ------------------- // class ItemWidget : public QWidget { Q_OBJECT public: explicit ItemWidget(QWidget *parent = nullptr) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); label = new QLabel("Default Text", this); button = new QPushButton("Click Me", this); layout->addWidget(label); layout->addWidget(button); layout->setSpacing(5); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); connect(button, &QPushButton::clicked, this, &ItemWidget::onButtonClicked); } void setText(const QString &text) { label->setText(text); } void setItemIndex(const QModelIndex &index) { itemIndex = index; } QSize sizeHint() const override { return QSize(200, 70); } signals: void buttonClicked(const QModelIndex &index); private slots: void onButtonClicked() { if (itemIndex.isValid()) { qDebug() << "Widget::Button clicked on item:" << itemIndex.row(); emit buttonClicked(itemIndex); } } private: QLabel *label; QPushButton *button; QModelIndex itemIndex; }; // ------------------- Custom Delegate ------------------- // class ItemDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit ItemDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) { } QWidget *createEditor(QWidget *, const QStyleOptionViewItem &, const QModelIndex &) const override { return nullptr; // Disable editing mode } void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override { // Do nothing. Items will be handled by widgets inside the view. } QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override { ItemWidget tempWidget; tempWidget.ensurePolished(); return tempWidget.sizeHint(); } }; // ------------------- List View with Widgets ------------------- // class WidgetListView : public QListView { Q_OBJECT public: explicit WidgetListView(QWidget *parent = nullptr) : QListView(parent) { setItemDelegate(new ItemDelegate(this)); setEditTriggers(QAbstractItemView::NoEditTriggers); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); } void setModel(QAbstractItemModel *model) override { QListView::setModel(model); // Remove previous widgets qDeleteAll(itemWidgets); itemWidgets.clear(); // Create widgets for each item for (int row = 0; row < model->rowCount(); ++row) { QModelIndex index = model->index(row, 0); ItemWidget *widget = new ItemWidget(this); widget->setText(index.data(Qt::DisplayRole).toString()); widget->setItemIndex(index); connect(widget, &ItemWidget::buttonClicked, this, &WidgetListView::onItemButtonClicked); setIndexWidget(index, widget); itemWidgets.append(widget); } } private slots: void onItemButtonClicked(const QModelIndex &index) { qDebug() << "Button clicked on item:" << index.row(); } private: QList itemWidgets; }; class RatingFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit RatingFilterProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) { } void setAllowedRatings(const QSet &ratings) { qDebug() << "\nRATINGS"; allowedRatings = ratings; invalidateFilter(); } protected: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override { if (allowedRatings.isEmpty()) { qDebug() << "VISIBLE:" << sourceRow; return true; } QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); int rating = index.data(Qt::UserRole).toInt(); // return allowedRatings.contains(rating); bool visible = allowedRatings.contains(rating); if (visible) { qDebug() << "VISIBLE:" << sourceRow; } else { qDebug() << "NOT VISIBLE:" << sourceRow; } return visible; } private: QSet allowedRatings; }; // ------------------- Main Application ------------------- // int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; QVBoxLayout *layout = new QVBoxLayout(&window); ItemModel model; model.addItem("File0.txt", 0); model.addItem("File1.txt", 1); model.addItem("File2.txt", 2); model.addItem("File3.txt", 3); model.addItem("File4.txt", 4); model.addItem("File5.txt", 5); // Create and set up QSortFilterProxyModel RatingFilterProxyModel *proxyModel = new RatingFilterProxyModel; proxyModel->setSourceModel(&model); proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); // Set case insensitive filtering WidgetListView *listView = new WidgetListView; listView->setModel(proxyModel); QHBoxLayout *filterLayout = new QHBoxLayout; QSet selectedRatings; QList ratingCheckBoxes; for (int i = 1; i <= 5; ++i) { QCheckBox *cb = new QCheckBox(QString::number(i), &window); ratingCheckBoxes.append(cb); filterLayout->addWidget(cb); QObject::connect(cb, &QCheckBox::checkStateChanged, [&]() { selectedRatings.clear(); for (QCheckBox *checkBox : ratingCheckBoxes) { if (checkBox->isChecked()) { selectedRatings.insert(checkBox->text().toInt()); } } proxyModel->setAllowedRatings(selectedRatings); }); } layout->addLayout(filterLayout); layout->addWidget(listView); window.setLayout(layout); window.show(); return app.exec(); } #include "main.moc"