File indexing completed on 2024-04-14 04:51:49

0001 /**
0002  * SPDX-FileCopyrightText: 2015 Holger Kaelberer <holger.k@elberer.de>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "notifyingapplicationmodel.h"
0008 
0009 #include <algorithm>
0010 
0011 #include <QDebug>
0012 #include <QIcon>
0013 #include <QString>
0014 
0015 #include <KLocalizedString>
0016 
0017 // #include "modeltest.h"
0018 
0019 NotifyingApplicationModel::NotifyingApplicationModel(QObject *parent)
0020     : QAbstractTableModel(parent)
0021 {
0022 }
0023 
0024 QVector<NotifyingApplication> NotifyingApplicationModel::apps()
0025 {
0026     return m_apps;
0027 }
0028 
0029 void NotifyingApplicationModel::appendApp(const NotifyingApplication &app)
0030 {
0031     if (app.name.isEmpty() || apps().contains(app))
0032         return;
0033     beginInsertRows(QModelIndex(), m_apps.size(), m_apps.size());
0034     m_apps.append(app);
0035     endInsertRows();
0036 }
0037 
0038 bool NotifyingApplicationModel::containsApp(const QString &name) const
0039 {
0040     for (const auto &a : m_apps)
0041         if (a.name == name)
0042             return true;
0043     return false;
0044 }
0045 
0046 Qt::ItemFlags NotifyingApplicationModel::flags(const QModelIndex &index) const
0047 {
0048     Qt::ItemFlags flags = Qt::ItemIsEnabled;
0049     if (index.isValid() && index.row() >= 0 && index.row() < m_apps.size() && index.column() < 3) {
0050         if (index.column() == 0)
0051             flags |= Qt::ItemIsEditable | Qt::ItemIsUserCheckable;
0052         else if (index.column() == 2) {
0053             if (m_apps[index.row()].active)
0054                 flags |= Qt::ItemIsEditable;
0055             else
0056                 flags ^= Qt::ItemIsEnabled;
0057         } else if (index.column() == 1) {
0058             if (!m_apps[index.row()].active)
0059                 flags ^= Qt::ItemIsEnabled;
0060         }
0061     }
0062     return flags;
0063 }
0064 
0065 void NotifyingApplicationModel::clearApplications()
0066 {
0067     if (!m_apps.isEmpty()) {
0068         beginRemoveRows(QModelIndex(), 0, m_apps.size() - 1);
0069         m_apps.clear();
0070         endRemoveRows();
0071     }
0072 }
0073 
0074 QVariant NotifyingApplicationModel::data(const QModelIndex &index, int role) const
0075 {
0076     if (!index.isValid() || index.row() < 0 || index.row() >= m_apps.size() || index.column() > 3) {
0077         return QVariant();
0078     }
0079 
0080     switch (role) {
0081     case Qt::TextAlignmentRole: {
0082         if (index.column() == 0)
0083             return int(Qt::AlignCenter | Qt::AlignVCenter);
0084         else
0085             return int(Qt::AlignLeft | Qt::AlignVCenter);
0086         break;
0087     }
0088     case Qt::DisplayRole: {
0089         if (index.column() == 1)
0090             return m_apps[index.row()].name;
0091         else if (index.column() == 0)
0092             return QVariant(); // m_apps[index.row()].active;
0093         else if (index.column() == 2)
0094             return m_apps[index.row()].blacklistExpression.pattern();
0095         else
0096             return QVariant();
0097         break;
0098     }
0099     case Qt::DecorationRole: {
0100         if (index.column() == 1)
0101             return QIcon::fromTheme(m_apps[index.row()].icon, QIcon::fromTheme(QStringLiteral("application-x-executable")));
0102         else
0103             return QVariant();
0104         break;
0105     }
0106     case Qt::EditRole: {
0107         if (index.column() == 0)
0108             return m_apps[index.row()].active ? Qt::Checked : Qt::Unchecked;
0109         else if (index.column() == 2)
0110             return m_apps[index.row()].blacklistExpression.pattern();
0111         else
0112             return QVariant();
0113         break;
0114     }
0115     case Qt::CheckStateRole: {
0116         if (index.column() == 0)
0117             return m_apps[index.row()].active ? Qt::Checked : Qt::Unchecked;
0118         else
0119             return QVariant();
0120         break;
0121     }
0122     }
0123     return QVariant();
0124 }
0125 
0126 bool NotifyingApplicationModel::setData(const QModelIndex &index, const QVariant &value, int role)
0127 {
0128     if (!index.isValid() || (index.column() != 0 && index.column() != 2) || index.row() < 0 || index.row() >= m_apps.size())
0129         return false;
0130 
0131     bool res = false;
0132     QModelIndex bottomRight = createIndex(index.row(), index.column());
0133     switch (role) {
0134     case Qt::CheckStateRole: {
0135         if (index.column() == 0) {
0136             m_apps[index.row()].active = ((Qt::CheckState)value.toInt() == Qt::Checked);
0137             bottomRight = createIndex(index.row(), index.column() + 1);
0138             res = true;
0139         }
0140         break;
0141     }
0142     case Qt::EditRole: {
0143         if (index.column() == 2) {
0144             m_apps[index.row()].blacklistExpression.setPattern(value.toString());
0145             res = true;
0146         }
0147     }
0148     }
0149     if (res) {
0150         Q_EMIT dataChanged(index, bottomRight);
0151         Q_EMIT applicationsChanged(); // -> notify config that we need to save
0152     }
0153     return res;
0154 }
0155 
0156 void NotifyingApplicationModel::sort(int column, Qt::SortOrder order)
0157 {
0158     if (column != 1)
0159         return;
0160 
0161     if (order == Qt::AscendingOrder)
0162         std::sort(m_apps.begin(), m_apps.end(), [](const NotifyingApplication &a, const NotifyingApplication &b) {
0163             return (a.name.compare(b.name, Qt::CaseInsensitive) < 1);
0164         });
0165     else
0166         std::sort(m_apps.begin(), m_apps.end(), [](const NotifyingApplication &a, const NotifyingApplication &b) {
0167             return (b.name.compare(a.name, Qt::CaseInsensitive) < 1);
0168         });
0169     Q_EMIT dataChanged(createIndex(0, 0), createIndex(m_apps.size(), 2));
0170 }
0171 
0172 QVariant NotifyingApplicationModel::headerData(int section, Qt::Orientation /*orientation*/, int role) const
0173 {
0174     switch (role) {
0175     case Qt::DisplayRole: {
0176         if (section == 1)
0177             return i18n("Name");
0178         else if (section == 0)
0179             return QVariant(); // i18n("Sync");
0180         else
0181             return i18n("Blacklisted");
0182     }
0183     case Qt::ToolTipRole: {
0184         if (section == 1)
0185             return i18n("Name of a notifying application.");
0186         else if (section == 0)
0187             return i18n("Synchronize notifications of an application?");
0188         else
0189             return i18n(
0190                 "Regular expression defining which notifications should not be sent.\nThis pattern is applied to the summary and, if selected above, the body "
0191                 "of notifications.");
0192     }
0193     }
0194     return QVariant();
0195 }
0196 
0197 int NotifyingApplicationModel::columnCount(const QModelIndex &) const
0198 {
0199     return 3;
0200 }
0201 
0202 int NotifyingApplicationModel::rowCount(const QModelIndex &parent) const
0203 {
0204     if (parent.isValid()) {
0205         // Return size 0 if we are a child because this is not a tree
0206         return 0;
0207     }
0208     return m_apps.size();
0209 }
0210 
0211 #include "moc_notifyingapplicationmodel.cpp"