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"