File indexing completed on 2024-06-16 04:50:35
0001 /* 0002 SPDX-FileCopyrightText: 2006-2008 Tobias Koenig <tokoe@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "agenttypewidget.h" 0008 0009 #include <QApplication> 0010 #include <QHBoxLayout> 0011 #include <QListView> 0012 #include <QPainter> 0013 0014 #include "agentfilterproxymodel.h" 0015 #include "agenttype.h" 0016 #include "agenttypemodel.h" 0017 0018 namespace Akonadi 0019 { 0020 namespace Internal 0021 { 0022 /** 0023 * @internal 0024 */ 0025 class AgentTypeWidgetDelegate : public QAbstractItemDelegate 0026 { 0027 Q_OBJECT 0028 public: 0029 explicit AgentTypeWidgetDelegate(QObject *parent = nullptr); 0030 0031 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0032 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; 0033 0034 private: 0035 void drawFocus(QPainter * /*painter*/, const QStyleOptionViewItem & /*option*/, QRect /*rect*/) const; 0036 }; 0037 0038 } // namespace Internal 0039 0040 using Akonadi::Internal::AgentTypeWidgetDelegate; 0041 0042 /** 0043 * @internal 0044 */ 0045 class AgentTypeWidgetPrivate 0046 { 0047 public: 0048 explicit AgentTypeWidgetPrivate(AgentTypeWidget *parent) 0049 : mParent(parent) 0050 { 0051 } 0052 0053 void currentAgentTypeChanged(const QModelIndex & /*currentIndex*/, const QModelIndex & /*previousIndex*/); 0054 0055 void typeActivated(const QModelIndex &index) 0056 { 0057 if (index.flags() & (Qt::ItemIsSelectable | Qt::ItemIsEnabled)) { 0058 Q_EMIT mParent->activated(); 0059 } 0060 } 0061 0062 AgentTypeWidget *const mParent; 0063 QListView *mView = nullptr; 0064 AgentTypeModel *mModel = nullptr; 0065 AgentFilterProxyModel *proxyModel = nullptr; 0066 }; 0067 0068 void AgentTypeWidgetPrivate::currentAgentTypeChanged(const QModelIndex ¤tIndex, const QModelIndex &previousIndex) 0069 { 0070 AgentType currentType; 0071 if (currentIndex.isValid()) { 0072 currentType = currentIndex.data(AgentTypeModel::TypeRole).value<AgentType>(); 0073 } 0074 0075 AgentType previousType; 0076 if (previousIndex.isValid()) { 0077 previousType = previousIndex.data(AgentTypeModel::TypeRole).value<AgentType>(); 0078 } 0079 0080 Q_EMIT mParent->currentChanged(currentType, previousType); 0081 } 0082 0083 AgentTypeWidget::AgentTypeWidget(QWidget *parent) 0084 : QWidget(parent) 0085 , d(new AgentTypeWidgetPrivate(this)) 0086 { 0087 auto layout = new QHBoxLayout(this); 0088 layout->setContentsMargins({}); 0089 0090 d->mView = new QListView(this); 0091 d->mView->setItemDelegate(new AgentTypeWidgetDelegate(d->mView)); 0092 d->mView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); 0093 d->mView->setAlternatingRowColors(true); 0094 layout->addWidget(d->mView); 0095 0096 d->mModel = new AgentTypeModel(d->mView); 0097 d->proxyModel = new AgentFilterProxyModel(this); 0098 d->proxyModel->setSourceModel(d->mModel); 0099 d->proxyModel->sort(0); 0100 d->mView->setModel(d->proxyModel); 0101 0102 d->mView->selectionModel()->setCurrentIndex(d->mView->model()->index(0, 0), QItemSelectionModel::Select); 0103 d->mView->scrollTo(d->mView->model()->index(0, 0)); 0104 connect(d->mView->selectionModel(), &QItemSelectionModel::currentChanged, this, [this](const QModelIndex &start, const QModelIndex &end) { 0105 d->currentAgentTypeChanged(start, end); 0106 }); 0107 connect(d->mView, qOverload<const QModelIndex &>(&QListView::activated), this, [this](const QModelIndex &index) { 0108 d->typeActivated(index); 0109 }); 0110 } 0111 0112 AgentTypeWidget::~AgentTypeWidget() = default; 0113 0114 AgentType AgentTypeWidget::currentAgentType() const 0115 { 0116 QItemSelectionModel *selectionModel = d->mView->selectionModel(); 0117 if (!selectionModel) { 0118 return AgentType(); 0119 } 0120 0121 QModelIndex index = selectionModel->currentIndex(); 0122 if (!index.isValid()) { 0123 return AgentType(); 0124 } 0125 0126 return index.data(AgentTypeModel::TypeRole).value<AgentType>(); 0127 } 0128 0129 AgentFilterProxyModel *AgentTypeWidget::agentFilterProxyModel() const 0130 { 0131 return d->proxyModel; 0132 } 0133 0134 /** 0135 * AgentTypeWidgetDelegate 0136 */ 0137 0138 AgentTypeWidgetDelegate::AgentTypeWidgetDelegate(QObject *parent) 0139 : QAbstractItemDelegate(parent) 0140 { 0141 } 0142 0143 void AgentTypeWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0144 { 0145 if (!index.isValid()) { 0146 return; 0147 } 0148 0149 painter->setRenderHint(QPainter::Antialiasing); 0150 0151 const QString name = index.model()->data(index, Qt::DisplayRole).toString(); 0152 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString(); 0153 0154 const QVariant data = index.model()->data(index, Qt::DecorationRole); 0155 0156 QPixmap pixmap; 0157 if (data.isValid() && data.typeId() == QMetaType::QIcon) { 0158 pixmap = qvariant_cast<QIcon>(data).pixmap(64, 64); 0159 } 0160 0161 const QFont oldFont = painter->font(); 0162 QFont boldFont(oldFont); 0163 boldFont.setBold(true); 0164 painter->setFont(boldFont); 0165 QFontMetrics fm = painter->fontMetrics(); 0166 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height(); 0167 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width(); 0168 painter->setFont(oldFont); 0169 0170 fm = painter->fontMetrics(); 0171 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height(); 0172 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width(); 0173 int wp = pixmap.width(); 0174 0175 QStyleOptionViewItem opt(option); 0176 opt.showDecorationSelected = true; 0177 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter); 0178 0179 QPen pen = painter->pen(); 0180 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; 0181 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { 0182 cg = QPalette::Inactive; 0183 } 0184 if (option.state & QStyle::State_Selected) { 0185 painter->setPen(option.palette.color(cg, QPalette::HighlightedText)); 0186 } else { 0187 painter->setPen(option.palette.color(cg, QPalette::Text)); 0188 } 0189 0190 painter->setFont(option.font); 0191 0192 painter->drawPixmap(option.rect.x() + 5, option.rect.y() + 5, pixmap); 0193 0194 painter->setFont(boldFont); 0195 if (!name.isEmpty()) { 0196 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7, wn, hn, Qt::AlignLeft, name); 0197 } 0198 painter->setFont(oldFont); 0199 0200 if (!comment.isEmpty()) { 0201 painter->drawText(option.rect.x() + 5 + wp + 5, option.rect.y() + 7 + hn, wc, hc, Qt::AlignLeft, comment); 0202 } 0203 0204 painter->setPen(pen); 0205 0206 drawFocus(painter, option, option.rect); 0207 } 0208 0209 QSize AgentTypeWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0210 { 0211 if (!index.isValid()) { 0212 return QSize(0, 0); 0213 } 0214 0215 const QString name = index.model()->data(index, Qt::DisplayRole).toString(); 0216 const QString comment = index.model()->data(index, AgentTypeModel::DescriptionRole).toString(); 0217 0218 QFontMetrics fm = option.fontMetrics; 0219 int hn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).height(); 0220 int wn = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, name).width(); 0221 int hc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).height(); 0222 int wc = fm.boundingRect(0, 0, 0, 0, Qt::AlignLeft, comment).width(); 0223 0224 int width = 0; 0225 int height = 0; 0226 0227 if (!name.isEmpty()) { 0228 height += hn; 0229 width = qMax(width, wn); 0230 } 0231 0232 if (!comment.isEmpty()) { 0233 height += hc; 0234 width = qMax(width, wc); 0235 } 0236 0237 height = qMax(height, 64) + 10; 0238 width += 64 + 15; 0239 0240 return QSize(width, height); 0241 } 0242 0243 void AgentTypeWidgetDelegate::drawFocus(QPainter *painter, const QStyleOptionViewItem &option, QRect rect) const 0244 { 0245 if (option.state & QStyle::State_HasFocus) { 0246 QStyleOptionFocusRect o; 0247 o.QStyleOption::operator=(option); 0248 o.rect = rect; 0249 o.state |= QStyle::State_KeyboardFocusChange; 0250 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled) ? QPalette::Normal : QPalette::Disabled; 0251 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Window); 0252 QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter); 0253 } 0254 } 0255 0256 } // namespace Akonadi 0257 0258 #include "agenttypewidget.moc" 0259 0260 #include "moc_agenttypewidget.cpp"