1 /*
2 SPDX-FileCopyrightText: 2013-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6
7 #include "learner.h"
8 #include "learner_p.h"
9 #include "liblearner_debug.h"
10 #include <QDir>
11 #include <QFileInfo>
12 #include <QHash>
13 #include <QPixmap>
14
15 using namespace LearnerProfile;
16
Learner(QObject * parent)17 Learner::Learner(QObject *parent)
18 : QObject(parent)
19 , d(new LearnerPrivate)
20 {
21 connect(this, &Learner::goalAdded, this, &Learner::goalCountChanged);
22 connect(this, &Learner::goalRemoved, this, &Learner::goalCountChanged);
23 }
24
~Learner()25 Learner::~Learner()
26 {
27 }
28
name() const29 QString Learner::name() const
30 {
31 return d->m_name;
32 }
33
setName(const QString & name)34 void Learner::setName(const QString &name)
35 {
36 if (name == d->m_name) {
37 return;
38 }
39 d->m_name = name;
40 emit nameChanged();
41 }
42
identifier() const43 int Learner::identifier() const
44 {
45 return d->m_identifier;
46 }
47
setIdentifier(int identifier)48 void Learner::setIdentifier(int identifier)
49 {
50 if (identifier == d->m_identifier) {
51 return;
52 }
53 d->m_identifier = identifier;
54 emit identifierChanged();
55 }
56
imageUrl() const57 QString Learner::imageUrl() const
58 {
59 QString path = d->imagePath();
60 if (!QFileInfo::exists(path)) {
61 return QString();
62 }
63 return "file://" + path;
64 }
65
clearImage()66 void Learner::clearImage()
67 {
68 const QString path {d->imagePath()};
69 if (!QFileInfo::exists(path)) {
70 return;
71 }
72 QFile file;
73 if (!file.remove(path)) {
74 qCCritical(LIBLEARNER_LOG) << "could not remove image:" << path;
75 }
76 emit imageChanged();
77 }
78
importImage(const QString & path)79 void Learner::importImage(const QString &path)
80 {
81 if (!QFileInfo::exists(path)) {
82 qCWarning(LIBLEARNER_LOG) << "image path points to a non-existing file, aborting: " << path;
83 return;
84 }
85
86 // create image directory if it does not exist
87 QDir dir;
88 if (!dir.exists(d->imageDirectory())) {
89 dir.mkdir(d->imageDirectory());
90 }
91
92 QPixmap image = QPixmap(path);
93 image = image.scaled(120, 120);
94 if (!image.save(d->imagePath(), "PNG")) {
95 qCCritical(LIBLEARNER_LOG()) << "could not save scaled image to" << d->imagePath();
96 }
97 emit imageChanged();
98 qCDebug(LIBLEARNER_LOG) << "saved scaled image from " << path << " at " << d->imagePath();
99 }
100
goals() const101 QList<LearningGoal *> Learner::goals() const
102 {
103 return d->m_goals;
104 }
105
addGoal(LearnerProfile::LearningGoal * goal)106 void Learner::addGoal(LearnerProfile::LearningGoal *goal)
107 {
108 if (d->m_goals.contains(goal)) {
109 return;
110 }
111 emit goalAboutToBeAdded(goal, d->m_goals.count());
112 d->m_goals.append(goal);
113 emit goalAdded();
114 }
115
removeGoal(LearnerProfile::LearningGoal * goal)116 void Learner::removeGoal(LearnerProfile::LearningGoal *goal)
117 {
118 int index = d->m_goals.indexOf(goal);
119 if (index < 0) {
120 qCritical() << "Cannot remove goal, not found: aborting";
121 return;
122 }
123 emit goalAboutToBeRemoved(index);
124 d->m_goals.removeAt(index);
125 emit goalRemoved(this, goal);
126 }
127
hasGoal(LearningGoal * goal) const128 bool Learner::hasGoal(LearningGoal *goal) const
129 {
130 foreach (LearningGoal *cmpGoal, d->m_goals) {
131 if (goal->identifier() == cmpGoal->identifier()) {
132 return true;
133 }
134 }
135 return false;
136 }
137
setActiveGoal(LearningGoal * goal)138 void Learner::setActiveGoal(LearningGoal *goal)
139 {
140 if (d->m_activeGoal.contains(goal->category()) && d->m_activeGoal[goal->category()] == goal) {
141 return;
142 }
143
144 d->m_activeGoal.insert(goal->category(), goal);
145 emit activeGoalChanged();
146 }
147
setActiveGoal(Learner::Category categoryLearner,const QString & identifier)148 void Learner::setActiveGoal(Learner::Category categoryLearner, const QString &identifier)
149 {
150 // TODO:Qt5 change method parameter to LearningGoal::Category
151 // workaround for Q_INVOKABLE access of enum
152 LearningGoal::Category category = static_cast<LearningGoal::Category>(categoryLearner);
153
154 if (d->m_activeGoal.contains(category) && d->m_activeGoal[category]->identifier() == identifier) {
155 return;
156 }
157
158 foreach (LearningGoal *goal, d->m_goals) {
159 if (goal->category() == category && goal->identifier() == identifier) {
160 setActiveGoal(goal);
161 return;
162 }
163 }
164 qCritical() << "Could not select learning goal with ID " << identifier << ": not registered for this learner";
165 }
166
activeGoal(Learner::Category categoryLearner) const167 LearningGoal *Learner::activeGoal(Learner::Category categoryLearner) const
168 {
169 // TODO:Qt5 change method parameter to LearningGoal::Category
170 // workaround for Q_INVOKABLE access of enum
171 LearningGoal::Category category = static_cast<LearningGoal::Category>(categoryLearner);
172 if (!d->m_activeGoal.contains(category)) {
173 qCWarning(LIBLEARNER_LOG) << "(Learner " << identifier() << ") No current learning goal set for category " << category << " : fall back to first in list";
174 foreach (LearningGoal *goal, d->m_goals) {
175 if (goal->category() == category) {
176 return goal;
177 }
178 }
179 qCWarning(LIBLEARNER_LOG) << "No learning goals of category " << category << " registered";
180 return nullptr;
181 }
182 return d->m_activeGoal[category];
183 }
184