File indexing completed on 2024-11-24 04:39:29
0001 /* 0002 This file is part of Contact Editor. 0003 0004 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org> 0005 SPDX-FileCopyrightText: 2016-2024 Laurent Montel <montel@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "customfieldslistdelegate.h" 0011 0012 #include "customfieldsmodel.h" 0013 0014 #include <KLocalizedString> 0015 #include <KMessageBox> 0016 0017 #include <QAbstractItemView> 0018 #include <QCheckBox> 0019 #include <QDateEdit> 0020 #include <QDateTimeEdit> 0021 #include <QMouseEvent> 0022 #include <QSpinBox> 0023 #include <QTimeEdit> 0024 #include <QTimer> 0025 0026 using namespace Akonadi; 0027 CustomFieldsListDelegate::CustomFieldsListDelegate(QAbstractItemView *view, QObject *parent) 0028 : QStyledItemDelegate(parent) 0029 , mIcon(QIcon::fromTheme(QStringLiteral("list-remove"))) 0030 , mButtonSize(16, 16) 0031 , mItemView(view) 0032 { 0033 } 0034 0035 CustomFieldsListDelegate::~CustomFieldsListDelegate() = default; 0036 0037 QWidget *CustomFieldsListDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &item, const QModelIndex &index) const 0038 { 0039 if (index.column() == 1) { 0040 const CustomField::Type type = static_cast<CustomField::Type>(index.data(CustomFieldsModel::TypeRole).toInt()); 0041 0042 switch (type) { 0043 case CustomField::TextType: 0044 case CustomField::UrlType: 0045 default: 0046 return QStyledItemDelegate::createEditor(parent, item, index); 0047 case CustomField::NumericType: { 0048 auto editor = new QSpinBox(parent); 0049 editor->setFrame(false); 0050 editor->setAutoFillBackground(true); 0051 return editor; 0052 } 0053 case CustomField::BooleanType: { 0054 auto editor = new QCheckBox(parent); 0055 return editor; 0056 } 0057 case CustomField::DateType: { 0058 auto editor = new QDateEdit(parent); 0059 editor->setFrame(false); 0060 editor->setAutoFillBackground(true); 0061 return editor; 0062 } 0063 case CustomField::TimeType: { 0064 auto editor = new QTimeEdit(parent); 0065 editor->setFrame(false); 0066 editor->setAutoFillBackground(true); 0067 return editor; 0068 } 0069 case CustomField::DateTimeType: { 0070 auto editor = new QDateTimeEdit(parent); 0071 editor->setFrame(false); 0072 editor->setAutoFillBackground(true); 0073 return editor; 0074 } 0075 } 0076 } else { 0077 return QStyledItemDelegate::createEditor(parent, item, index); 0078 } 0079 } 0080 0081 void CustomFieldsListDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const 0082 { 0083 if (index.column() == 1) { 0084 const CustomField::Type type = static_cast<CustomField::Type>(index.data(CustomFieldsModel::TypeRole).toInt()); 0085 0086 switch (type) { 0087 case CustomField::TextType: 0088 case CustomField::UrlType: 0089 QStyledItemDelegate::setEditorData(editor, index); 0090 break; 0091 case CustomField::NumericType: { 0092 auto widget = qobject_cast<QSpinBox *>(editor); 0093 widget->setValue(index.data(Qt::EditRole).toInt()); 0094 break; 0095 } 0096 case CustomField::BooleanType: { 0097 auto widget = qobject_cast<QCheckBox *>(editor); 0098 widget->setChecked(index.data(Qt::EditRole).toString() == QLatin1StringView("true")); 0099 break; 0100 } 0101 case CustomField::DateType: { 0102 auto widget = qobject_cast<QDateEdit *>(editor); 0103 widget->setDisplayFormat(QStringLiteral("dd.MM.yyyy")); 0104 widget->setDate(QDate::fromString(index.data(Qt::EditRole).toString(), Qt::ISODate)); 0105 break; 0106 } 0107 case CustomField::TimeType: { 0108 auto widget = qobject_cast<QTimeEdit *>(editor); 0109 widget->setDisplayFormat(QStringLiteral("hh:mm")); 0110 widget->setTime(QTime::fromString(index.data(Qt::EditRole).toString(), Qt::ISODate)); 0111 break; 0112 } 0113 case CustomField::DateTimeType: { 0114 auto widget = qobject_cast<QDateTimeEdit *>(editor); 0115 widget->setDisplayFormat(QStringLiteral("dd.MM.yyyy hh:mm")); 0116 widget->setDateTime(QDateTime::fromString(index.data(Qt::EditRole).toString(), Qt::ISODate)); 0117 break; 0118 } 0119 } 0120 } else { 0121 QStyledItemDelegate::setEditorData(editor, index); 0122 } 0123 } 0124 0125 void CustomFieldsListDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const 0126 { 0127 if (index.column() == 1) { 0128 const CustomField::Type type = static_cast<CustomField::Type>(index.data(CustomFieldsModel::TypeRole).toInt()); 0129 0130 switch (type) { 0131 case CustomField::TextType: 0132 case CustomField::UrlType: 0133 QStyledItemDelegate::setModelData(editor, model, index); 0134 break; 0135 case CustomField::NumericType: { 0136 auto widget = qobject_cast<QSpinBox *>(editor); 0137 model->setData(index, QString::number(widget->value())); 0138 break; 0139 } 0140 case CustomField::BooleanType: { 0141 auto widget = qobject_cast<QCheckBox *>(editor); 0142 model->setData(index, widget->isChecked() ? QStringLiteral("true") : QStringLiteral("false")); 0143 break; 0144 } 0145 case CustomField::DateType: { 0146 auto widget = qobject_cast<QDateEdit *>(editor); 0147 model->setData(index, widget->date().toString(Qt::ISODate)); 0148 break; 0149 } 0150 case CustomField::TimeType: { 0151 auto widget = qobject_cast<QTimeEdit *>(editor); 0152 model->setData(index, widget->time().toString(Qt::ISODate)); 0153 break; 0154 } 0155 case CustomField::DateTimeType: { 0156 auto widget = qobject_cast<QDateTimeEdit *>(editor); 0157 model->setData(index, widget->dateTime().toString(Qt::ISODate)); 0158 break; 0159 } 0160 } 0161 } else { 0162 QStyledItemDelegate::setModelData(editor, model, index); 0163 } 0164 } 0165 0166 void CustomFieldsListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const 0167 { 0168 // TODO: somehow mark local/global/external fields 0169 QStyledItemDelegate::paint(painter, option, index); 0170 if (index.column() == 1) { 0171 mIcon.paint(painter, option.rect, Qt::AlignRight); 0172 } 0173 } 0174 0175 QSize CustomFieldsListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0176 { 0177 Q_UNUSED(option) 0178 0179 QSize hint = QStyledItemDelegate::sizeHint(option, index); 0180 hint.setHeight(qMax(hint.height(), mButtonSize.height())); 0181 0182 if (index.column() == 1) { 0183 hint.setWidth(hint.width() + mButtonSize.width()); 0184 } 0185 0186 return hint; 0187 } 0188 0189 bool CustomFieldsListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) 0190 { 0191 if (index.column() == 1) { 0192 if (event->type() == QEvent::MouseButtonRelease) { 0193 const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); 0194 QRect buttonRect = mItemView->visualRect(index); 0195 buttonRect.setLeft(buttonRect.right() - mButtonSize.width()); 0196 0197 if (buttonRect.contains(mouseEvent->pos())) { 0198 removeField(index.row(), model); 0199 return true; 0200 } 0201 } 0202 } 0203 return QStyledItemDelegate::editorEvent(event, model, option, index); 0204 } 0205 0206 void CustomFieldsListDelegate::setFirstColumnAsCurrent() 0207 { 0208 mItemView->setCurrentIndex(mItemView->model()->index(mItemView->currentIndex().row(), 0)); 0209 } 0210 0211 void CustomFieldsListDelegate::removeField(int row, QAbstractItemModel *model) 0212 { 0213 if (KMessageBox::warningContinueCancel(mItemView, 0214 i18nc("Custom Fields", "Do you really want to delete the selected custom field?"), 0215 i18nc("@title:window", "Confirm Delete"), 0216 KStandardGuiItem::del()) 0217 != KMessageBox::Continue) { 0218 return; 0219 } 0220 0221 model->removeRow(row); 0222 QTimer::singleShot(0, this, &CustomFieldsListDelegate::setFirstColumnAsCurrent); 0223 } 0224 0225 #include "moc_customfieldslistdelegate.cpp"