├── README.md ├── cardview.pro ├── cardview_example ├── cardview_example.pro ├── resource │ └── pixmap │ │ ├── cardimage_300_150.jpg │ │ └── cardimage_free_size.jpg ├── resources.qrc └── source │ ├── main.cpp │ ├── simplecardentitymodel.cpp │ └── simplecardentitymodel.h ├── cardview_library ├── cardview_library.pro └── source │ ├── cardview.cpp │ ├── cardviewheaderitemdelegate.cpp │ ├── cardviewitemdelegate.cpp │ ├── cardviewsimpleitemdelegate.cpp │ ├── cardviewwrappermodel.cpp │ ├── include │ ├── cardview.h │ ├── cardview_common.h │ ├── cardviewheaderitemdelegate.h │ ├── cardviewitemdelegate.h │ ├── cardviewsimpleitemdelegate.h │ └── cardviewwrappermodel.h │ └── lib │ ├── cardview.dll │ └── libcardview.a ├── screenshot1.png └── screenshot2.png /README.md: -------------------------------------------------------------------------------- 1 | CardView Library 2 | ================ 3 | 4 | Qt implementation of card view. Consists of wrapper proxy for custom models and 5 | implementation of QAbstractItemView for displaying model data in cards. 6 | 7 | Original Repository: https://github.com/dmitrytoropchin/cardview 8 | 9 | ![CardView Example](https://github.com/Qt-Widgets/cardview-scrollable-widget-working/blob/master/screenshot1.png) 10 | 11 | ![CardView Example](https://github.com/Qt-Widgets/cardview-scrollable-widget-working/blob/master/screenshot2.png) 12 | -------------------------------------------------------------------------------- /cardview.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | 3 | SUBDIRS = library \ 4 | example 5 | 6 | library.subdir = cardview_library 7 | example.subdir = cardview_example 8 | 9 | example.depends = library 10 | -------------------------------------------------------------------------------- /cardview_example/cardview_example.pro: -------------------------------------------------------------------------------- 1 | QT = core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | TEMPLATE = app 6 | 7 | INCLUDEPATH += source/ 8 | 9 | HEADERS = \ 10 | source/simplecardentitymodel.h 11 | 12 | SOURCES = \ 13 | source/simplecardentitymodel.cpp \ 14 | source/main.cpp 15 | 16 | 17 | unix|win32: LIBS += -L$$PWD/../cardview_library/source/lib/ -lcardview 18 | 19 | INCLUDEPATH += $$PWD/../cardview_library/source/include 20 | DEPENDPATH += $$PWD/../cardview_library/source/include 21 | 22 | win32:!win32-g++: PRE_TARGETDEPS += $$PWD/../cardview_library/source/lib/cardview.lib 23 | else:unix|win32-g++: PRE_TARGETDEPS += $$PWD/../cardview_library/source/lib/libcardview.a 24 | 25 | RESOURCES += \ 26 | resources.qrc 27 | -------------------------------------------------------------------------------- /cardview_example/resource/pixmap/cardimage_300_150.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/cardview_example/resource/pixmap/cardimage_300_150.jpg -------------------------------------------------------------------------------- /cardview_example/resource/pixmap/cardimage_free_size.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/cardview_example/resource/pixmap/cardimage_free_size.jpg -------------------------------------------------------------------------------- /cardview_example/resources.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | resource/pixmap/cardimage_300_150.jpg 4 | resource/pixmap/cardimage_free_size.jpg 5 | 6 | 7 | -------------------------------------------------------------------------------- /cardview_example/source/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cardview.h" 4 | #include 5 | #include 6 | #include 7 | 8 | #include "simplecardentitymodel.h" 9 | 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | QApplication app(argc, argv); 14 | 15 | // initializing CardView widget 16 | CardView *card_view = new CardView(); 17 | card_view->setWindowTitle("Card View Example"); 18 | card_view->setAttribute(Qt::WA_DeleteOnClose); 19 | card_view->resize(1000, 800); 20 | 21 | // initializing test source model 22 | SimpleCardEntityModel entity_model; 23 | entity_model.initTestData(20); 24 | 25 | // creating card view wrapper proxy model 26 | CardViewWrapperModel *wrapper_model = new CardViewWrapperModel(card_view); 27 | 28 | // set source model 29 | wrapper_model->setSourceModel(&entity_model); 30 | 31 | // setup mapping between CardWrapperModel and source model roles 32 | wrapper_model->setRoleMapping(CardViewWrapperModel::TitleTextRole, 33 | SimpleCardEntityModel::TitleRole); 34 | wrapper_model->setRoleMapping(CardViewWrapperModel::InformativeTextRole, 35 | SimpleCardEntityModel::InformativeTextRole); 36 | wrapper_model->setRoleMapping(CardViewWrapperModel::PictureRole, 37 | SimpleCardEntityModel::PictureRole); 38 | 39 | // set default value for roles which aren't provided by source model 40 | wrapper_model->setDefaultRoleValue(CardViewWrapperModel::CardSizeRole, 41 | QSize(300, 300)); 42 | 43 | // set wrapper model to CardView 44 | card_view->setModel(wrapper_model); 45 | 46 | // choose item delegate 47 | // card_view->setItemDelegate(new CardViewSimpleItemDelegate(card_view)); 48 | card_view->setItemDelegate(new CardViewHeaderItemDelegate(card_view)); 49 | 50 | card_view->show(); 51 | 52 | return app.exec(); 53 | } 54 | -------------------------------------------------------------------------------- /cardview_example/source/simplecardentitymodel.cpp: -------------------------------------------------------------------------------- 1 | #include "simplecardentitymodel.h" 2 | 3 | 4 | SimpleCardEntityModel::SimpleCardEntityModel(QObject *parent) : 5 | QAbstractListModel(parent) 6 | { 7 | } 8 | 9 | SimpleCardEntityModel::~SimpleCardEntityModel() 10 | { 11 | } 12 | 13 | int SimpleCardEntityModel::rowCount(const QModelIndex &parent) const 14 | { 15 | Q_UNUSED(parent); 16 | return m_entities.size(); 17 | } 18 | 19 | QVariant SimpleCardEntityModel::data(const QModelIndex &index, int role) const 20 | { 21 | if (!index.isValid()) 22 | return QVariant(); 23 | 24 | switch (role) { 25 | case Qt::DisplayRole: 26 | case Qt::ToolTipRole: 27 | case TitleRole: 28 | return m_entities.at(index.row()).title; 29 | case InformativeTextRole: 30 | return m_entities.at(index.row()).informative_text; 31 | case PictureRole: 32 | return m_entities.at(index.row()).picture; 33 | default: 34 | break; 35 | } 36 | 37 | return QVariant(); 38 | } 39 | 40 | Qt::ItemFlags SimpleCardEntityModel::flags(const QModelIndex &index) const 41 | { 42 | if (index.row() % 4 == 1) 43 | return Qt::NoItemFlags; 44 | return (Qt::ItemIsEnabled | Qt::ItemIsSelectable); 45 | } 46 | 47 | void SimpleCardEntityModel::setEntities(const QList entities) 48 | { 49 | beginResetModel(); 50 | m_entities = entities; 51 | endResetModel(); 52 | } 53 | 54 | void SimpleCardEntityModel::initTestData(int size) 55 | { 56 | QString title_template = "Card View Entity %1"; 57 | QString informative_text_template = 58 | "The QIdentityProxyModel class proxies its source model unmodified. " 59 | "QIdentityProxyModel can be used to forward the structure of a source model exactly, " 60 | "with no sorting, filtering or other transformation. " 61 | "This is similar in concept to an identity matrix where A.I = A. " 62 | "Because it does no sorting or filtering, this class is most suitable to proxy models " 63 | "which transform the data() of the source model. For example, a proxy model could be " 64 | "created to define the font used, or the background colour, or the tooltip etc. " 65 | "This removes the need to implement all data handling in the same class that creates " 66 | "the structure of the model, and can also be used to create re-usable components. " 67 | "This also provides a way to change the data in the case where a source model is " 68 | "supplied by a third party which can not be modified."; 69 | QPixmap picture_template = QPixmap("://resource/pixmap/cardimage_free_size.jpg"); 70 | 71 | QString disabled_title_template = "Disabled card %1"; 72 | QString disabled_informative_text_template = 73 | "Informative text for disabled card."; 74 | QPixmap disabled_picture_template = QPixmap("://resource/pixmap/cardimage_300_150.jpg"); 75 | 76 | 77 | beginResetModel(); 78 | 79 | m_entities.clear(); 80 | 81 | for (int i = 0; i < size; ++ i) { 82 | SimpleCardEntity entity; 83 | if (i % 4 == 1) { 84 | entity.title = disabled_title_template.arg(i + 1); 85 | entity.informative_text = disabled_informative_text_template; 86 | entity.picture = disabled_picture_template; 87 | } 88 | else { 89 | entity.title = title_template.arg(i + 1); 90 | entity.informative_text = informative_text_template; 91 | entity.picture = picture_template; 92 | } 93 | 94 | m_entities.append(entity); 95 | } 96 | 97 | endResetModel(); 98 | } 99 | -------------------------------------------------------------------------------- /cardview_example/source/simplecardentitymodel.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLECARDENTITYMODEL_H 2 | #define SIMPLECARDENTITYMODEL_H 3 | 4 | #include 5 | #include 6 | 7 | class SimpleCardEntityModel : public QAbstractListModel { 8 | Q_OBJECT 9 | public: 10 | enum Role { 11 | TitleRole = Qt::UserRole, 12 | InformativeTextRole, 13 | PictureRole 14 | }; 15 | 16 | struct SimpleCardEntity { 17 | QString title; 18 | QString informative_text; 19 | QPixmap picture; 20 | }; 21 | private: 22 | QList m_entities; 23 | public: 24 | explicit SimpleCardEntityModel(QObject *parent = 0); 25 | ~SimpleCardEntityModel(); 26 | 27 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 28 | QVariant data(const QModelIndex &index, int role) const; 29 | Qt::ItemFlags flags(const QModelIndex &index) const; 30 | 31 | void setEntities(const QList entities); 32 | 33 | void initTestData(int size = 10); 34 | }; 35 | 36 | #endif // SIMPLECARDENTITYMODEL_H 37 | -------------------------------------------------------------------------------- /cardview_library/cardview_library.pro: -------------------------------------------------------------------------------- 1 | QT = core gui 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 | 5 | TEMPLATE = lib 6 | TARGET = cardview 7 | 8 | DEFINES += CARDVIEW_LIBRARY 9 | 10 | DESTDIR = $$PWD/source/lib 11 | DLLDESTDIR = $DESTDIR 12 | 13 | INCLUDEPATH += source/ 14 | 15 | HEADERS += \ 16 | source/include/cardview_common.h \ 17 | source/include/cardview.h \ 18 | source/include/cardviewwrappermodel.h \ 19 | source/include/cardviewitemdelegate.h \ 20 | source/include/cardviewsimpleitemdelegate.h \ 21 | source/include/cardviewheaderitemdelegate.h 22 | 23 | SOURCES += \ 24 | source/cardview.cpp \ 25 | source/cardviewwrappermodel.cpp \ 26 | source/cardviewitemdelegate.cpp \ 27 | source/cardviewsimpleitemdelegate.cpp \ 28 | source/cardviewheaderitemdelegate.cpp 29 | -------------------------------------------------------------------------------- /cardview_library/source/cardview.cpp: -------------------------------------------------------------------------------- 1 | #include "include/cardview.h" 2 | 3 | 4 | CardView::CardView(QWidget *parent) : 5 | QListView(parent) 6 | { 7 | setFlow(QListView::LeftToRight); 8 | setResizeMode(QListView::Adjust); 9 | setWrapping(true); 10 | viewport()->setBackgroundRole(QPalette::Window); 11 | setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel); 12 | setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); 13 | } 14 | 15 | CardView::~CardView() 16 | { 17 | } 18 | -------------------------------------------------------------------------------- /cardview_library/source/cardviewheaderitemdelegate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "include/cardviewwrappermodel.h" 6 | #include "include/cardviewheaderitemdelegate.h" 7 | 8 | 9 | class CardViewHeaderItemDelegatePrivate { 10 | Q_DECLARE_PUBLIC(CardViewHeaderItemDelegate) 11 | 12 | CardViewHeaderItemDelegate *q_ptr; 13 | 14 | QMargins card_margins; 15 | QMargins card_text_margins; 16 | QMargins card_picture_margins; 17 | 18 | CardViewHeaderItemDelegatePrivate(CardViewHeaderItemDelegate *q) : q_ptr(q) {} 19 | ~CardViewHeaderItemDelegatePrivate() {} 20 | }; 21 | 22 | 23 | CardViewHeaderItemDelegate::CardViewHeaderItemDelegate(QObject *parent) : 24 | CardViewItemDelegate(parent), 25 | d_ptr(new CardViewHeaderItemDelegatePrivate(this)) 26 | { 27 | Q_D(CardViewHeaderItemDelegate); 28 | d->card_margins = QMargins(10, 10, 10, 10); 29 | d->card_text_margins = QMargins(20, 10, 20, 10); 30 | d->card_picture_margins = QMargins(); 31 | } 32 | 33 | CardViewHeaderItemDelegate::~CardViewHeaderItemDelegate() 34 | { 35 | delete d_ptr; 36 | } 37 | 38 | void CardViewHeaderItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, 39 | const QModelIndex &index) const 40 | { 41 | drawCard(painter, option, index); 42 | } 43 | 44 | QSize CardViewHeaderItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 45 | { 46 | Q_UNUSED(option); 47 | 48 | Q_D(const CardViewHeaderItemDelegate); 49 | 50 | QSize card_size = index.data(CardViewWrapperModel::CardSizeRole).toSize(); 51 | card_size.rwidth() += d->card_margins.left() + d->card_margins.right(); 52 | card_size.rheight() += d->card_margins.top() + d->card_margins.bottom(); 53 | 54 | return card_size; 55 | } 56 | 57 | void CardViewHeaderItemDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem &option, 58 | const QModelIndex &card_index) const 59 | { 60 | Q_D(const CardViewHeaderItemDelegate); 61 | 62 | QStyleOptionViewItemV4 view_item_option = option; 63 | initStyleOption(&view_item_option, card_index); 64 | 65 | // setup fonts and colors 66 | QFont title_text_font = view_item_option.font; 67 | title_text_font.setBold(true); 68 | title_text_font.setPointSize(title_text_font.pointSize() + 6); 69 | 70 | QFont informative_text_font = view_item_option.font; 71 | informative_text_font.setPointSize(informative_text_font.pointSize() - 1); 72 | 73 | QColor title_font_color = QColor(255, 255, 255, 255); 74 | QColor informative_text_color = view_item_option.palette.text().color(); 75 | 76 | QBrush card_background_brush = view_item_option.palette.base(); 77 | QBrush card_shadow_brush = QBrush(QColor(0, 0, 0, 50)); 78 | QBrush selection_brush = view_item_option.palette.highlight(); 79 | QBrush disabled_brush = QBrush(QColor(255, 255, 255, 50)); 80 | QBrush title_background_brush = QBrush(QColor(0, 0, 0, 150)); 81 | 82 | // calculate sub rectangles 83 | QRect card_rect = option.rect; 84 | card_rect.adjust(d->card_margins.left(), d->card_margins.top(), 85 | -d->card_margins.right(), -d->card_margins.bottom()); 86 | 87 | QRect card_shadow_rect = card_rect.translated(3, 3); 88 | 89 | QRect selection_rect = card_rect.adjusted(-4, -4, 4, 4); 90 | 91 | QRect picture_rect = QRect(card_rect.left(), card_rect.top(), 92 | card_rect.width(), card_rect.height() * 0.50); 93 | 94 | int title_background_rect_height = QFontMetrics(title_text_font).lineSpacing() + 95 | d->card_text_margins.top() + d->card_margins.bottom(); 96 | 97 | QRect title_background_rect = QRect(card_rect.left(), picture_rect.bottom() - title_background_rect_height, 98 | card_rect.width(), title_background_rect_height); 99 | title_background_rect.setBottom(picture_rect.bottom()); 100 | 101 | QRect informative_text_rect = QRect(card_rect.left(), picture_rect.bottom(), 102 | card_rect.width(), card_rect.height() * 0.50); 103 | informative_text_rect.setBottom(card_rect.bottom()); 104 | 105 | 106 | // apply margins 107 | QRect title_text_rect = 108 | title_background_rect.adjusted(d->card_text_margins.left(), d->card_text_margins.top(), 109 | -d->card_text_margins.right(), -d->card_text_margins.bottom()); 110 | informative_text_rect.adjust(d->card_text_margins.left(), d->card_text_margins.top(), 111 | -d->card_text_margins.right(), -d->card_text_margins.bottom()); 112 | picture_rect.adjust(d->card_picture_margins.left(), d->card_picture_margins.top(), 113 | -d->card_picture_margins.right(), -d->card_picture_margins.bottom()); 114 | 115 | // draw delegate 116 | painter->save(); 117 | 118 | painter->setRenderHint(QPainter::Antialiasing, true); 119 | 120 | if (view_item_option.state & QStyle::State_Selected) { 121 | painter->fillRect(selection_rect, selection_brush); 122 | } 123 | else { 124 | QPainterPath card_shadow_rounded_rect; 125 | card_shadow_rounded_rect.addRoundedRect(card_shadow_rect, 5, 5); 126 | painter->fillPath(card_shadow_rounded_rect, card_shadow_brush); 127 | } 128 | 129 | painter->setRenderHint(QPainter::Antialiasing, false); 130 | 131 | painter->fillRect(card_rect, card_background_brush); 132 | 133 | QPixmap card_pixmap = scaledPixmap(card_index.data(CardViewWrapperModel::PictureRole).value(), 134 | picture_rect); 135 | painter->drawImage(picture_rect, card_pixmap.toImage()); 136 | 137 | painter->fillRect(title_background_rect, title_background_brush); 138 | 139 | painter->setFont(title_text_font); 140 | painter->setPen(title_font_color); 141 | 142 | drawElidedText(painter, card_index.data(CardViewWrapperModel::TitleTextRole).toString(), 143 | title_text_font, title_text_rect, view_item_option.textElideMode); 144 | 145 | painter->setFont(informative_text_font); 146 | painter->setPen(informative_text_color); 147 | 148 | drawElidedText(painter, card_index.data(CardViewWrapperModel::InformativeTextRole).toString(), 149 | informative_text_font, informative_text_rect, view_item_option.textElideMode); 150 | 151 | if ((view_item_option.state & QStyle::State_Enabled) == 0) 152 | painter->fillRect(card_rect, disabled_brush); 153 | 154 | painter->restore(); 155 | } 156 | -------------------------------------------------------------------------------- /cardview_library/source/cardviewitemdelegate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "include/cardviewitemdelegate.h" 5 | 6 | 7 | CardViewItemDelegate::CardViewItemDelegate(QObject *parent) : 8 | QStyledItemDelegate(parent) 9 | { 10 | } 11 | 12 | void CardViewItemDelegate::drawElidedText(QPainter *painter, const QString &text, 13 | const QFont &font, const QRect &rect, 14 | Qt::TextElideMode elide_mode) const 15 | { 16 | QTextLayout text_layout(text, font); 17 | QFontMetrics font_metrics(font); 18 | 19 | int line_top_offset = rect.top(); 20 | 21 | text_layout.beginLayout(); 22 | 23 | forever { 24 | QTextLine text_line = text_layout.createLine(); 25 | if (!text_line.isValid()) 26 | break; 27 | 28 | text_line.setLineWidth(rect.width()); 29 | 30 | if (rect.bottom() >= (line_top_offset + font_metrics.lineSpacing() * 2)) { 31 | text_line.draw(painter, QPoint(rect.left(), line_top_offset)); 32 | line_top_offset += font_metrics.lineSpacing(); 33 | } 34 | else { 35 | QString last_line = text_layout.text().mid(text_line.textStart()); 36 | QString elided_last_line = 37 | font_metrics.elidedText(last_line, elide_mode, rect.width()); 38 | painter->drawText(QPoint(rect.left(), line_top_offset + font_metrics.ascent()), 39 | elided_last_line); 40 | break; 41 | } 42 | } 43 | } 44 | 45 | QPixmap CardViewItemDelegate::scaledPixmap(const QPixmap &pixmap, const QRect &target_rect) const 46 | { 47 | return pixmap.scaled(target_rect.size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); 48 | } 49 | 50 | CardViewItemDelegate::~CardViewItemDelegate() 51 | { 52 | } 53 | -------------------------------------------------------------------------------- /cardview_library/source/cardviewsimpleitemdelegate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "include/cardviewwrappermodel.h" 6 | #include "include/cardviewsimpleitemdelegate.h" 7 | 8 | 9 | class CardViewSimpleItemDelegatePrivate { 10 | Q_DECLARE_PUBLIC(CardViewSimpleItemDelegate) 11 | 12 | CardViewSimpleItemDelegate *q_ptr; 13 | QMargins card_margins; 14 | QMargins card_text_margins; 15 | QMargins card_picture_margins; 16 | 17 | CardViewSimpleItemDelegatePrivate(CardViewSimpleItemDelegate *q) : q_ptr(q) {} 18 | ~CardViewSimpleItemDelegatePrivate() {} 19 | }; 20 | 21 | 22 | CardViewSimpleItemDelegate::CardViewSimpleItemDelegate(QObject *parent) : 23 | CardViewItemDelegate(parent), 24 | d_ptr(new CardViewSimpleItemDelegatePrivate(this)) 25 | { 26 | Q_D(CardViewSimpleItemDelegate); 27 | d->card_margins = QMargins(10, 10, 10, 10); 28 | d->card_text_margins = QMargins(20, 10, 20, 10); 29 | d->card_picture_margins = QMargins(); 30 | } 31 | 32 | CardViewSimpleItemDelegate::~CardViewSimpleItemDelegate() 33 | { 34 | delete d_ptr; 35 | } 36 | 37 | void CardViewSimpleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, 38 | const QModelIndex &index) const 39 | { 40 | drawCard(painter, option, index); 41 | } 42 | 43 | QSize CardViewSimpleItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 44 | { 45 | Q_UNUSED(option); 46 | 47 | Q_D(const CardViewSimpleItemDelegate); 48 | 49 | QSize card_size = index.data(CardViewWrapperModel::CardSizeRole).toSize(); 50 | card_size.rwidth() += d->card_margins.left() + d->card_margins.right(); 51 | card_size.rheight() += d->card_margins.top() + d->card_margins.bottom(); 52 | 53 | return card_size; 54 | } 55 | 56 | void CardViewSimpleItemDelegate::drawCard(QPainter *painter, const QStyleOptionViewItem &option, 57 | const QModelIndex &card_index) const 58 | { 59 | Q_D(const CardViewSimpleItemDelegate); 60 | 61 | QStyleOptionViewItemV4 view_item_option = option; 62 | initStyleOption(&view_item_option, card_index); 63 | 64 | // setup fonts and colors 65 | QFont title_text_font = view_item_option.font; 66 | title_text_font.setBold(true); 67 | title_text_font.setPointSize(title_text_font.pointSize() + 6); 68 | 69 | QFont informative_text_font = view_item_option.font; 70 | informative_text_font.setPointSize(informative_text_font.pointSize() - 1); 71 | 72 | QColor title_font_color = view_item_option.palette.text().color(); 73 | QColor informative_text_color = view_item_option.palette.text().color(); 74 | 75 | QBrush card_background_brush = view_item_option.palette.base(); 76 | QBrush card_shadow_brush = QBrush(QColor(0, 0, 0, 50)); 77 | QBrush selection_brush = view_item_option.palette.highlight(); 78 | QBrush disabled_brush = QBrush(QColor(255, 255, 255, 50)); 79 | 80 | // calculate sub rectangles 81 | QRect card_rect = option.rect; 82 | card_rect.adjust(d->card_margins.left(), d->card_margins.top(), 83 | -d->card_margins.right(), -d->card_margins.bottom()); 84 | 85 | QRect card_shadow_rect = card_rect.translated(3, 3); 86 | 87 | QRect selection_rect = card_rect.adjusted(-4, -4, 4, 4); 88 | 89 | QRect picture_rect = QRect(card_rect.left(), card_rect.top(), 90 | card_rect.width(), card_rect.height() * 0.50); 91 | 92 | QRect title_text_rect = QRect(card_rect.left(), picture_rect.bottom(), 93 | card_rect.width(), card_rect.height() * 0.10); 94 | 95 | QRect informative_text_rect = QRect(card_rect.left(), title_text_rect.bottom(), 96 | card_rect.width(), card_rect.height() * 0.40); 97 | informative_text_rect.setBottom(card_rect.bottom()); 98 | 99 | 100 | // apply margins 101 | title_text_rect.adjust(d->card_text_margins.left(), d->card_text_margins.top(), 102 | -d->card_text_margins.right(), -d->card_text_margins.bottom()); 103 | informative_text_rect.adjust(d->card_text_margins.left(), d->card_text_margins.top(), 104 | -d->card_text_margins.right(), -d->card_text_margins.bottom()); 105 | picture_rect.adjust(d->card_picture_margins.left(), d->card_picture_margins.top(), 106 | -d->card_picture_margins.right(), -d->card_picture_margins.bottom()); 107 | 108 | // draw delegate 109 | painter->save(); 110 | 111 | painter->setRenderHint(QPainter::Antialiasing, true); 112 | 113 | if (view_item_option.state & QStyle::State_Selected) { 114 | painter->fillRect(selection_rect, selection_brush); 115 | } 116 | else { 117 | QPainterPath card_shadow_rounded_rect; 118 | card_shadow_rounded_rect.addRoundedRect(card_shadow_rect, 5, 5); 119 | painter->fillPath(card_shadow_rounded_rect, card_shadow_brush); 120 | } 121 | 122 | painter->setRenderHint(QPainter::Antialiasing, false); 123 | 124 | painter->fillRect(card_rect, card_background_brush); 125 | 126 | QPixmap card_pixmap = scaledPixmap(card_index.data(CardViewWrapperModel::PictureRole).value(), 127 | picture_rect); 128 | painter->drawImage(picture_rect, card_pixmap.toImage()); 129 | 130 | painter->setFont(title_text_font); 131 | painter->setPen(title_font_color); 132 | 133 | drawElidedText(painter, card_index.data(CardViewWrapperModel::TitleTextRole).toString(), 134 | title_text_font, title_text_rect, view_item_option.textElideMode); 135 | 136 | painter->setFont(informative_text_font); 137 | painter->setPen(informative_text_color); 138 | 139 | drawElidedText(painter, card_index.data(CardViewWrapperModel::InformativeTextRole).toString(), 140 | informative_text_font, informative_text_rect, view_item_option.textElideMode); 141 | 142 | if ((view_item_option.state & QStyle::State_Enabled) == 0) 143 | painter->fillRect(card_rect, disabled_brush); 144 | 145 | painter->restore(); 146 | } 147 | -------------------------------------------------------------------------------- /cardview_library/source/cardviewwrappermodel.cpp: -------------------------------------------------------------------------------- 1 | #include "include/cardviewwrappermodel.h" 2 | #include 3 | 4 | 5 | class CardViewWrapperModelPrivate { 6 | Q_DECLARE_PUBLIC(CardViewWrapperModel) 7 | 8 | CardViewWrapperModel *q_ptr; 9 | QHash role_mapping; 10 | QHash default_role_value; 11 | 12 | CardViewWrapperModelPrivate(CardViewWrapperModel *q) : q_ptr(q) {} 13 | ~CardViewWrapperModelPrivate() {} 14 | }; 15 | 16 | 17 | CardViewWrapperModel::CardViewWrapperModel(QObject *parent) : 18 | QIdentityProxyModel(parent), 19 | d_ptr(new CardViewWrapperModelPrivate(this)) 20 | { 21 | } 22 | 23 | CardViewWrapperModel::~CardViewWrapperModel() 24 | { 25 | delete d_ptr; 26 | } 27 | 28 | void CardViewWrapperModel::setRoleMapping(int card_model_role, int source_model_role) 29 | { 30 | Q_D(CardViewWrapperModel); 31 | d->role_mapping.insert(card_model_role, source_model_role); 32 | } 33 | 34 | void CardViewWrapperModel::setRoleMappings(const QHash &role_mapping) 35 | { 36 | Q_D(CardViewWrapperModel); 37 | d->role_mapping = role_mapping; 38 | } 39 | 40 | void CardViewWrapperModel::setDefaultRoleValue(int card_model_role, const QVariant &default_value) 41 | { 42 | Q_D(CardViewWrapperModel); 43 | d->default_role_value.insert(card_model_role, default_value); 44 | } 45 | 46 | QVariant CardViewWrapperModel::data(const QModelIndex &proxy_index, int role) const 47 | { 48 | Q_D(const CardViewWrapperModel); 49 | if (!d->role_mapping.contains(role) && d->default_role_value.contains(role)) 50 | return d->default_role_value.value(role, QVariant()); 51 | return QIdentityProxyModel::data(proxy_index, d->role_mapping.value(role, role)); 52 | } 53 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardview.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_CARDVIEW_H 2 | #define CARDVIEW_CARDVIEW_H 3 | 4 | #include 5 | #include "cardview_common.h" 6 | 7 | class CARDVIEW_EXPORT CardView : public QListView { 8 | Q_OBJECT 9 | public: 10 | explicit CardView(QWidget *parent = 0); 11 | ~CardView(); 12 | }; 13 | 14 | #endif // CARDVIEW_H 15 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardview_common.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_COMMON_H 2 | #define CARDVIEW_COMMON_H 3 | 4 | #include 5 | 6 | #if defined(CARDVIEW_LIBRARY) 7 | # define CARDVIEW_EXPORT Q_DECL_EXPORT 8 | #else 9 | # define CARDVIEW_EXPORT Q_DECL_IMPORT 10 | #endif 11 | 12 | #endif // CARDVIEW_COMMON_H 13 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardviewheaderitemdelegate.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_CARDVIEWHEADERITEMDELEGATE_H 2 | #define CARDVIEW_CARDVIEWHEADERITEMDELEGATE_H 3 | 4 | #include "cardview_common.h" 5 | #include "cardviewitemdelegate.h" 6 | 7 | class CardViewHeaderItemDelegatePrivate; 8 | 9 | class CARDVIEW_EXPORT CardViewHeaderItemDelegate : public CardViewItemDelegate { 10 | Q_OBJECT 11 | Q_DECLARE_PRIVATE(CardViewHeaderItemDelegate) 12 | 13 | CardViewHeaderItemDelegatePrivate * const d_ptr; 14 | public: 15 | explicit CardViewHeaderItemDelegate(QObject *parent = 0); 16 | ~CardViewHeaderItemDelegate(); 17 | 18 | void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 19 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; 20 | private: 21 | void drawCard(QPainter *painter, 22 | const QStyleOptionViewItem &option, 23 | const QModelIndex &card_index) const; 24 | }; 25 | 26 | #endif // CARDVIEW_CARDVIEWHEADERITEMDELEGATE_H 27 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardviewitemdelegate.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_CARDVIEWITEMDELEGATE_H 2 | #define CARDVIEW_CARDVIEWITEMDELEGATE_H 3 | 4 | #include 5 | #include "cardview_common.h" 6 | 7 | class CARDVIEW_EXPORT CardViewItemDelegate : public QStyledItemDelegate { 8 | Q_OBJECT 9 | protected: 10 | explicit CardViewItemDelegate(QObject *parent = 0); 11 | 12 | void drawElidedText(QPainter *painter, const QString &text, const QFont &font, 13 | const QRect &rect, Qt::TextElideMode elide_mode) const; 14 | 15 | QPixmap scaledPixmap(const QPixmap &pixmap, const QRect &target_rect) const; 16 | 17 | virtual void drawCard(QPainter *painter, 18 | const QStyleOptionViewItem &option, 19 | const QModelIndex &card_index) const = 0; 20 | public: 21 | virtual ~CardViewItemDelegate(); 22 | }; 23 | 24 | #endif // CARDVIEW_CARDVIEWITEMDELEGATE_H 25 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardviewsimpleitemdelegate.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_CARDVIEWSIMPLEITEMDELEGATE_H 2 | #define CARDVIEW_CARDVIEWSIMPLEITEMDELEGATE_H 3 | 4 | #include "cardview_common.h" 5 | #include "cardviewitemdelegate.h" 6 | 7 | class CardViewSimpleItemDelegatePrivate; 8 | 9 | class CARDVIEW_EXPORT CardViewSimpleItemDelegate : public CardViewItemDelegate { 10 | Q_OBJECT 11 | Q_DECLARE_PRIVATE(CardViewSimpleItemDelegate) 12 | 13 | CardViewSimpleItemDelegatePrivate * const d_ptr; 14 | public: 15 | explicit CardViewSimpleItemDelegate(QObject *parent = 0); 16 | ~CardViewSimpleItemDelegate(); 17 | 18 | void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 19 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; 20 | private: 21 | void drawCard(QPainter *painter, 22 | const QStyleOptionViewItem &option, 23 | const QModelIndex &card_index) const; 24 | }; 25 | 26 | #endif // CARDVIEW_CARDVIEWSIMPLEITEMDELEGATE_H 27 | -------------------------------------------------------------------------------- /cardview_library/source/include/cardviewwrappermodel.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDVIEW_CARDVIEWWRAPPERMODEL_H 2 | #define CARDVIEW_CARDVIEWWRAPPERMODEL_H 3 | 4 | #include 5 | #include "cardview_common.h" 6 | 7 | class CardViewWrapperModelPrivate; 8 | 9 | class CARDVIEW_EXPORT CardViewWrapperModel : public QIdentityProxyModel { 10 | Q_OBJECT 11 | Q_DECLARE_PRIVATE(CardViewWrapperModel) 12 | public: 13 | enum Role { 14 | TitleTextRole = 0x1000, // QString 15 | InformativeTextRole, // QString 16 | PictureRole, // QPixmap 17 | CardSizeRole // QSize 18 | }; 19 | private: 20 | CardViewWrapperModelPrivate * const d_ptr; 21 | public: 22 | explicit CardViewWrapperModel(QObject *parent = 0); 23 | ~CardViewWrapperModel(); 24 | 25 | void setRoleMapping(int card_model_role, int source_model_role); 26 | void setRoleMappings(const QHash &role_mapping); 27 | 28 | void setDefaultRoleValue(int card_model_role, const QVariant &default_value); 29 | 30 | QVariant data(const QModelIndex &proxy_index, int role) const; 31 | }; 32 | 33 | #endif // CARDVIEW_CARDVIEWWRAPPERMODEL_H 34 | -------------------------------------------------------------------------------- /cardview_library/source/lib/cardview.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/cardview_library/source/lib/cardview.dll -------------------------------------------------------------------------------- /cardview_library/source/lib/libcardview.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/cardview_library/source/lib/libcardview.a -------------------------------------------------------------------------------- /screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/screenshot1.png -------------------------------------------------------------------------------- /screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Qt-Widgets/cardview-scrollable-widget/9e41344bebfab201a3e8ec699160e1413b30f9f6/screenshot2.png --------------------------------------------------------------------------------