Skip to content

Instantly share code, notes, and snippets.

@khurd21
Created June 12, 2024 04:56
Show Gist options
  • Save khurd21/f783bf70926846a3c79005bc4ff52f9a to your computer and use it in GitHub Desktop.
Save khurd21/f783bf70926846a3c79005bc4ff52f9a to your computer and use it in GitHub Desktop.
#include <QApplication>
#include <QMainWindow>
#include <QLabel>
#include <QHBoxLayout>
#include <QPushButton>
#include <QScrollArea>
#include <QAbstractListModel>
#include <QAbstractItemDelegate>
#include <QListView>
#include <QPainter>
struct Item {
QString title;
QString description;
};
Q_DECLARE_METATYPE(Item)
class WidgetModel : public QObject {
Q_OBJECT
public:
explicit WidgetModel(QObject* parent = nullptr) : QObject(parent) {}
void addItems(const int count) {
for (int i = 0; i < count; ++i) {
m_items.append({
QString("Title %1").arg(m_items.size() + 1),
QString("Description %1").arg(m_items.size() + 1)});
}
emit itemsChanged(m_items);
}
signals:
void itemsChanged(const QList<Item>& items);
private:
QList<Item> m_items;
};
class ItemWidget : public QWidget {
public:
explicit ItemWidget(const Item& item, QWidget* parent = nullptr) : QWidget(parent) {
const auto layout = new QHBoxLayout(this);
layout->addWidget(new QLabel(item.title, this));
layout->addWidget(new QLabel(item.description, this));
}
};
class PaintModel : public QAbstractListModel {
Q_OBJECT
public:
explicit PaintModel(QObject* parent = nullptr) : QAbstractListModel(parent) {
qRegisterMetaType<Item>("Item");
}
int rowCount(const QModelIndex& parent = QModelIndex()) const override {
Q_UNUSED(parent);
return m_items.size();
}
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override {
if (!index.isValid() || index.row() >= m_items.size())
return {};
const auto& item = m_items.at(index.row());
if (role == Qt::DisplayRole) {
return QVariant::fromValue(item);
}
return {};
}
void addItems(int count) {
beginInsertRows(QModelIndex(), m_items.size(), m_items.size() + count - 1);
for (int i = 0; i < count; ++i) {
m_items.append({
QString("Title %1").arg(m_items.size() + 1),
QString("Description %1").arg(m_items.size() + 1)});
}
endInsertRows();
}
private:
QList<Item> m_items;
};
class PaintDelegate : public QAbstractItemDelegate {
Q_OBJECT
public:
explicit PaintDelegate(QObject* parent = nullptr) : QAbstractItemDelegate(parent) {}
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override {
if (!index.isValid())
return;
// Cast the QVariant back to an Item struct
Item item = index.data(Qt::DisplayRole).value<Item>();
painter->save();
// Draw background
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
} else {
painter->fillRect(option.rect, option.palette.base());
}
// Draw text
painter->setPen(option.palette.color(QPalette::Text));
painter->drawText(option.rect.adjusted(10, 5, -10, -25), Qt::AlignLeft | Qt::AlignVCenter, item.title);
painter->drawText(option.rect.adjusted(10, 30, -10, -10), Qt::AlignLeft | Qt::AlignVCenter, item.description);
painter->restore();
}
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override {
Q_UNUSED(option);
Q_UNUSED(index);
return QSize(300, 70); // Adjust the size of each item as needed
}
};
class MyWindow : public QMainWindow {
Q_OBJECT
public:
MyWindow(QWidget *parent = nullptr)
: QMainWindow(parent) {
setWindowTitle("My Qt Application");
resize(800, 600);
}
~MyWindow() = default;
};
class WidgetView : public QWidget {
Q_OBJECT
public:
explicit WidgetView(WidgetModel* model, QWidget* parent = nullptr)
: QWidget(parent), m_model(model) {
m_layout = new QVBoxLayout(this);
setLayout(m_layout);
// Connect the model's signal to the view's update method
connect(model, &WidgetModel::itemsChanged, this, &WidgetView::updateView);
}
public slots:
void updateView(const QList<Item>& items) {
// Clear the current widgets
clearLayout(m_layout);
// Add new widgets based on the model's items
for (const auto& item : items) {
m_layout->addWidget(new ItemWidget(item));
}
}
private:
void clearLayout(QLayout* layout) {
while (QLayoutItem* item = layout->takeAt(0)) {
delete item->widget();
delete item;
}
}
QVBoxLayout* m_layout{};
WidgetModel* m_model{};
};
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
// Models
WidgetModel widgetModel;
PaintModel paintModel;
// Main widget and layout
QWidget mainWidget;
mainWidget.setWindowTitle("Qt Example: Widget vs Paint Delegate");
mainWidget.resize(1000, 600); // Increased window size
QHBoxLayout* mainLayout = new QHBoxLayout(&mainWidget);
// Left: Widget-based view
QVBoxLayout* widgetLayout = new QVBoxLayout;
QPushButton* addWidgetButton = new QPushButton("Add Widget Items");
QObject::connect(addWidgetButton, &QPushButton::clicked, [&widgetModel]() {
widgetModel.addItems(5000);
});
QScrollArea* widgetScrollArea = new QScrollArea;
WidgetView* widgetView = new WidgetView(&widgetModel);
widgetScrollArea->setWidget(widgetView);
widgetScrollArea->setWidgetResizable(true);
widgetLayout->addWidget(addWidgetButton);
widgetLayout->addWidget(widgetScrollArea);
QWidget* widgetContainer = new QWidget;
widgetContainer->setLayout(widgetLayout);
// Right: Paint-based view
QVBoxLayout* paintLayout = new QVBoxLayout;
QPushButton* addPaintButton = new QPushButton("Add Paint Items");
QObject::connect(addPaintButton, &QPushButton::clicked, [&paintModel]() {
paintModel.addItems(100'000);
});
QListView* paintListView = new QListView;
paintListView->setModel(&paintModel);
paintListView->setItemDelegate(new PaintDelegate(paintListView));
paintLayout->addWidget(addPaintButton);
paintLayout->addWidget(paintListView);
QWidget* paintContainer = new QWidget;
paintContainer->setLayout(paintLayout);
mainLayout->addWidget(widgetContainer);
mainLayout->addWidget(paintContainer);
mainWidget.show();
return app.exec();
}
#include "main.moc"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment