1 /*
2     SPDX-FileCopyrightText: 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
3 
4     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6 
7 #include "profilemodel.h"
8 #include "liblearnerprofile/src/learner.h"
9 #include "liblearnerprofile/src/profilemanager.h"
10 
11 #include "artikulate_debug.h"
12 #include <KLocalizedString>
13 #include <QSignalMapper>
14 
15 using namespace LearnerProfile;
16 
ProfileModel(QObject * parent)17 ProfileModel::ProfileModel(QObject *parent)
18     : QAbstractListModel(parent)
19     , m_profileManager(nullptr)
20     , m_signalMapper(new QSignalMapper(this))
21 {
22     connect(m_signalMapper, SIGNAL(mapped(int)), SLOT(emitProfileChanged(int)));
23 }
24 
roleNames() const25 QHash<int, QByteArray> ProfileModel::roleNames() const
26 {
27     QHash<int, QByteArray> roles;
28     roles[IdRole] = "id";
29     roles[NameRole] = "name";
30     roles[DataRole] = "dataRole";
31 
32     return roles;
33 }
34 
setProfileManager(ProfileManager * profileManager)35 void ProfileModel::setProfileManager(ProfileManager *profileManager)
36 {
37     if (m_profileManager == profileManager) {
38         return;
39     }
40 
41     beginResetModel();
42 
43     if (m_profileManager) {
44         m_profileManager->disconnect(this);
45         foreach (Learner *learner, m_profileManager->profiles()) {
46             learner->disconnect(this);
47         }
48     }
49 
50     m_profileManager = profileManager;
51     if (m_profileManager) {
52         // initial setting of signal mappings
53         connect(m_profileManager, &ProfileManager::profileAdded, this, &ProfileModel::onProfileAdded);
54         connect(m_profileManager, &ProfileManager::profileAboutToBeRemoved, this, &ProfileModel::onProfileAboutToBeRemoved);
55 
56         // insert and connect all already existing profiles
57         int profiles = m_profileManager->profiles().count();
58         for (int i = 0; i < profiles; ++i) {
59             onProfileAdded(m_profileManager->profiles().at(i), i);
60         }
61         updateMappings();
62     }
63     endResetModel();
64 }
65 
profileManager() const66 ProfileManager *ProfileModel::profileManager() const
67 {
68     return m_profileManager;
69 }
70 
data(const QModelIndex & index,int role) const71 QVariant ProfileModel::data(const QModelIndex &index, int role) const
72 {
73     Q_ASSERT(m_profileManager);
74 
75     if (!index.isValid()) {
76         return QVariant();
77     }
78 
79     if (index.row() >= m_profileManager->profiles().count()) {
80         return QVariant();
81     }
82 
83     Learner *const learner = m_profileManager->profiles().at(index.row());
84 
85     switch (role) {
86         case Qt::DisplayRole:
87             return !learner->name().isEmpty() ? QVariant(learner->name()) : QVariant(i18nc("@item:inlistbox:", "unknown"));
88         case Qt::ToolTipRole:
89             return QVariant(learner->name());
90         case IdRole:
91             return learner->identifier();
92         case NameRole:
93             return learner->name();
94         case DataRole:
95             return QVariant::fromValue<QObject *>(learner);
96         default:
97             return QVariant();
98     }
99 }
100 
rowCount(const QModelIndex & parent) const101 int ProfileModel::rowCount(const QModelIndex &parent) const
102 {
103     if (!m_profileManager) {
104         return 0;
105     }
106 
107     if (parent.isValid()) {
108         return 0;
109     }
110     return m_profileManager->profiles().count();
111 }
112 
onProfileAdded(Learner * learner,int index)113 void ProfileModel::onProfileAdded(Learner *learner, int index)
114 {
115     connect(learner, SIGNAL(nameChanged()), m_signalMapper, SLOT(map()));
116     connect(learner, SIGNAL(identifierChanged()), m_signalMapper, SLOT(map()));
117     beginInsertRows(QModelIndex(), index, index);
118     updateMappings();
119     endInsertRows();
120 }
121 
onProfileAboutToBeRemoved(int index)122 void ProfileModel::onProfileAboutToBeRemoved(int index)
123 {
124     beginRemoveRows(QModelIndex(), index, index);
125     endRemoveRows();
126 }
127 
emitProfileChanged(int row)128 void ProfileModel::emitProfileChanged(int row)
129 {
130     beginResetModel();
131     endResetModel();
132     // FIXME very inefficient, but workaround to force new filtering in phrasefiltermodel
133     //      to exclude possible new excluded phrases
134     emit profileChanged(row);
135     emit dataChanged(index(row, 0), index(row, 0));
136 }
137 
headerData(int section,Qt::Orientation orientation,int role) const138 QVariant ProfileModel::headerData(int section, Qt::Orientation orientation, int role) const
139 {
140     if (role != Qt::DisplayRole) {
141         return QVariant();
142     }
143     if (orientation == Qt::Vertical) {
144         return QVariant(section + 1);
145     }
146     return QVariant(i18nc("@title:column", "Profile"));
147 }
148 
updateMappings()149 void ProfileModel::updateMappings()
150 {
151     if (!m_profileManager) {
152         return;
153     }
154     int profiles = m_profileManager->profiles().count();
155     for (int i = 0; i < profiles; ++i) {
156         m_signalMapper->setMapping(m_profileManager->profiles().at(i), i);
157     }
158 }
159