File indexing completed on 2024-04-28 05:11:31

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Sandro Knauß <knauss@kolabsys.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #include "attendeetablemodel.h"
0008 
0009 #include <KEmailAddress>
0010 
0011 #include <KLocalizedString>
0012 
0013 using namespace IncidenceEditorNG;
0014 
0015 AttendeeTableModel::AttendeeTableModel(QObject *parent)
0016     : QAbstractTableModel(parent)
0017 {
0018 }
0019 
0020 int AttendeeTableModel::rowCount(const QModelIndex & /*parent*/) const
0021 {
0022     return mAttendeeList.count();
0023 }
0024 
0025 int AttendeeTableModel::columnCount(const QModelIndex & /*parent*/) const
0026 {
0027     return 8;
0028 }
0029 
0030 Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
0031 {
0032     if (!index.isValid()) {
0033         return Qt::ItemIsEnabled;
0034     }
0035     if (index.column() == Available || index.column() == Name || index.column() == Email) { // Available is read only
0036         return QAbstractTableModel::flags(index);
0037     } else {
0038         return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
0039     }
0040 }
0041 
0042 QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
0043 {
0044     if (!index.isValid()) {
0045         return {};
0046     }
0047 
0048     if (index.row() >= mAttendeeList.size()) {
0049         return {};
0050     }
0051 
0052     const KCalendarCore::Attendee attendee = mAttendeeList[index.row()];
0053     if (role == Qt::DisplayRole || role == Qt::EditRole) {
0054         switch (index.column()) {
0055         case Role:
0056             return attendee.role();
0057         case FullName:
0058             return attendee.fullName();
0059         case Available: {
0060             AvailableStatus available = mAttendeeAvailable[index.row()];
0061             if (role == Qt::DisplayRole) {
0062                 switch (available) {
0063                 case Free:
0064                     return i18n("Free");
0065                 case Busy:
0066                     return i18n("Busy");
0067                 case Accepted:
0068                     return i18n("Accepted");
0069                 case Unknown:
0070                     return i18n("Unknown");
0071                 default:
0072                     return i18n("Unknown");
0073                 }
0074             } else {
0075                 return available;
0076             }
0077         }
0078         case Status:
0079             return attendee.status();
0080         case CuType:
0081             return attendee.cuType();
0082         case Response:
0083             return attendee.RSVP();
0084         case Name:
0085             return attendee.name();
0086         case Email:
0087             return attendee.email();
0088         }
0089     }
0090     if (role == AttendeeRole) {
0091         return QVariant::fromValue(attendee);
0092     }
0093     return {};
0094 }
0095 
0096 bool AttendeeTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
0097 {
0098     QString email;
0099     QString name;
0100     if (index.isValid() && role == Qt::EditRole) {
0101         KCalendarCore::Attendee &attendee = mAttendeeList[index.row()]; // clazy:exclude=detaching-member
0102         switch (index.column()) {
0103         case Role:
0104             attendee.setRole(static_cast<KCalendarCore::Attendee::Role>(value.toInt()));
0105             break;
0106         case FullName:
0107             if (mRemoveEmptyLines && value.toString().trimmed().isEmpty()) {
0108                 // Do not remove last empty line if mKeepEmpty==true
0109                 // (only works if initially there is only one empty line)
0110                 if (!mKeepEmpty || !(attendee.name().isEmpty() && attendee.email().isEmpty())) {
0111                     removeRows(index.row(), 1);
0112                     return true;
0113                 }
0114             }
0115             KEmailAddress::extractEmailAddressAndName(value.toString(), email, name);
0116             attendee.setName(name);
0117             attendee.setEmail(email);
0118 
0119             addEmptyAttendee();
0120             break;
0121         case Available:
0122             mAttendeeAvailable[index.row()] = static_cast<AvailableStatus>(value.toInt());
0123             break;
0124         case Status:
0125             attendee.setStatus(static_cast<KCalendarCore::Attendee::PartStat>(value.toInt()));
0126             break;
0127         case CuType:
0128             attendee.setCuType(static_cast<KCalendarCore::Attendee::CuType>(value.toInt()));
0129             break;
0130         case Response:
0131             attendee.setRSVP(value.toBool());
0132             break;
0133         default:
0134             return false;
0135         }
0136         Q_EMIT dataChanged(index, index);
0137         return true;
0138     }
0139     return false;
0140 }
0141 
0142 QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation, int role) const
0143 {
0144     if (role != Qt::DisplayRole) {
0145         return {};
0146     }
0147 
0148     if (orientation == Qt::Horizontal) {
0149         switch (section) {
0150         case Role:
0151             return i18nc("vCard attendee role", "Role");
0152         case FullName:
0153             return i18nc("Attendees  (name+emailaddress)", "Name");
0154         case Available:
0155             return i18nc("Is attendee available for incidence", "Available");
0156         case Status:
0157             return i18nc("Status of attendee in an incidence (accepted, declined, delegated, ...)", "Status");
0158         case CuType:
0159             return i18nc("Type of calendar user (vCard attribute)", "User Type");
0160         case Response:
0161             return i18nc("Has attendee to respond to the invitation", "Response");
0162         case Name:
0163             return i18nc("Attendee name", "Name");
0164         case Email:
0165             return i18nc("Attendee email", "Email");
0166         }
0167     }
0168 
0169     return {};
0170 }
0171 
0172 bool AttendeeTableModel::insertRows(int position, int rows, const QModelIndex &parent)
0173 {
0174     beginInsertRows(parent, position, position + rows - 1);
0175 
0176     for (int row = 0; row < rows; ++row) {
0177         KCalendarCore::Attendee attendee(QLatin1StringView(""), QLatin1StringView(""));
0178         mAttendeeList.insert(position, attendee);
0179         mAttendeeAvailable.insert(mAttendeeAvailable.begin() + position, AvailableStatus{});
0180     }
0181 
0182     endInsertRows();
0183     return true;
0184 }
0185 
0186 bool AttendeeTableModel::removeRows(int position, int rows, const QModelIndex &parent)
0187 {
0188     beginRemoveRows(parent, position, position + rows - 1);
0189 
0190     for (int row = 0; row < rows; ++row) {
0191         mAttendeeAvailable.erase(mAttendeeAvailable.begin() + position);
0192         mAttendeeList.remove(position);
0193     }
0194 
0195     endRemoveRows();
0196     return true;
0197 }
0198 
0199 bool AttendeeTableModel::insertAttendee(int position, const KCalendarCore::Attendee &attendee)
0200 {
0201     beginInsertRows(QModelIndex(), position, position);
0202     mAttendeeList.insert(position, attendee);
0203     mAttendeeAvailable.insert(mAttendeeAvailable.begin() + position, AvailableStatus{});
0204     endInsertRows();
0205 
0206     addEmptyAttendee();
0207 
0208     return true;
0209 }
0210 
0211 void AttendeeTableModel::setAttendees(const KCalendarCore::Attendee::List &attendees)
0212 {
0213     beginResetModel();
0214 
0215     mAttendeeList = attendees;
0216     mAttendeeAvailable.clear();
0217     mAttendeeAvailable.resize(attendees.size());
0218 
0219     addEmptyAttendee();
0220 
0221     endResetModel();
0222 }
0223 
0224 KCalendarCore::Attendee::List AttendeeTableModel::attendees() const
0225 {
0226     return mAttendeeList;
0227 }
0228 
0229 void AttendeeTableModel::addEmptyAttendee()
0230 {
0231     if (mKeepEmpty) {
0232         bool create = true;
0233         for (const KCalendarCore::Attendee &attendee : std::as_const(mAttendeeList)) {
0234             if (attendee.fullName().isEmpty()) {
0235                 create = false;
0236                 break;
0237             }
0238         }
0239 
0240         if (create) {
0241             insertRows(rowCount(), 1);
0242         }
0243     }
0244 }
0245 
0246 bool AttendeeTableModel::keepEmpty() const
0247 {
0248     return mKeepEmpty;
0249 }
0250 
0251 void AttendeeTableModel::setKeepEmpty(bool keepEmpty)
0252 {
0253     if (keepEmpty != mKeepEmpty) {
0254         mKeepEmpty = keepEmpty;
0255         addEmptyAttendee();
0256     }
0257 }
0258 
0259 bool AttendeeTableModel::removeEmptyLines() const
0260 {
0261     return mRemoveEmptyLines;
0262 }
0263 
0264 void AttendeeTableModel::setRemoveEmptyLines(bool removeEmptyLines)
0265 {
0266     mRemoveEmptyLines = removeEmptyLines;
0267 }
0268 
0269 ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
0270     : QSortFilterProxyModel(parent)
0271 {
0272 }
0273 
0274 bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0275 {
0276     const QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent);
0277     KCalendarCore::Attendee::CuType cuType = static_cast<KCalendarCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
0278 
0279     return cuType == KCalendarCore::Attendee::Resource || cuType == KCalendarCore::Attendee::Room;
0280 }
0281 
0282 AttendeeFilterProxyModel::AttendeeFilterProxyModel(QObject *parent)
0283     : QSortFilterProxyModel(parent)
0284 {
0285 }
0286 
0287 bool AttendeeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
0288 {
0289     const QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent);
0290     KCalendarCore::Attendee::CuType cuType = static_cast<KCalendarCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
0291 
0292     return !(cuType == KCalendarCore::Attendee::Resource || cuType == KCalendarCore::Attendee::Room);
0293 }
0294 
0295 #include "moc_attendeetablemodel.cpp"