1 /*
2 * SPDX-FileCopyrightText: 2007 Jeremy Whiting <jpwhiting@kde.org>
3 * SPDX-FileCopyrightText: 2007 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "keduvoccontainer.h"
8
9 #include "keduvocdocument.h"
10 #include "keduvocexpression.h"
11
12 #include <QDebug>
13
14 /** private class to store information about a lesson */
15 class KEduVocContainer::Private
16 {
17 public:
18 ~Private();
19
20 // properties for this lesson
21 QString m_name;
22 bool m_inPractice;
23
24 // The containing document. This is only set for the top lesson, so to
25 // get to the document, you need to follow the parent pointer to the top
26 // container.
27 KEduVocDocument *m_document;
28
29 // other lessons in the tree
30 KEduVocContainer *m_parentContainer;
31 QList < KEduVocContainer * > m_childContainers;
32
33 EnumContainerType m_type;
34
35 QList < KEduVocExpression* > m_childLessonEntries;
36 bool m_childLessonEntriesValid;
37
38 /// Image url
39 QUrl m_imageUrl;
40 };
41
~Private()42 KEduVocContainer::Private::~Private()
43 {
44 qDeleteAll(m_childContainers);
45 }
46
47
48 // This is a private constructor only used by KEduVocDocument when creating
49 // the top level lesson.
KEduVocContainer(const QString & name,EnumContainerType type,KEduVocDocument * document)50 KEduVocContainer::KEduVocContainer(const QString& name, EnumContainerType type,
51 KEduVocDocument *document)
52 : d( new Private )
53 {
54 d->m_parentContainer = 0;
55 d->m_name = name;
56 d->m_inPractice = true;
57 d->m_type = type;
58 d->m_childLessonEntriesValid = false;
59
60 d->m_document = document;
61 }
62
63
KEduVocContainer(const QString & name,EnumContainerType type,KEduVocContainer * parent)64 KEduVocContainer::KEduVocContainer(const QString& name, EnumContainerType type, KEduVocContainer *parent)
65 : d( new Private )
66 {
67 d->m_parentContainer = parent;
68 d->m_name = name;
69 d->m_inPractice = true;
70 d->m_type = type;
71 d->m_childLessonEntriesValid = false;
72
73 d->m_document = 0;
74 }
75
KEduVocContainer(const KEduVocContainer & other)76 KEduVocContainer::KEduVocContainer( const KEduVocContainer &other )
77 : d( new Private )
78 {
79 d->m_name = other.d->m_name;
80 d->m_inPractice = other.d->m_inPractice;
81 d->m_type = other.d->m_type;
82 d->m_parentContainer = other.d->m_parentContainer;
83 d->m_childLessonEntriesValid = false;
84 }
85
~KEduVocContainer()86 KEduVocContainer::~KEduVocContainer()
87 {
88 delete d;
89 }
90
document() const91 KEduVocDocument *KEduVocContainer::document() const
92 {
93 KEduVocContainer *cont = (KEduVocContainer *)this;
94 while (cont->d->m_parentContainer) {
95 cont = cont->d->m_parentContainer;
96 }
97
98 Q_ASSERT(cont->d->m_document);
99 return cont->d->m_document;
100 }
101
appendChildContainer(KEduVocContainer * child)102 void KEduVocContainer::appendChildContainer(KEduVocContainer * child)
103 {
104 d->m_childContainers.append(child);
105 child->d->m_parentContainer = this;
106
107 invalidateChildLessonEntries();
108 }
109
childContainer(int row)110 KEduVocContainer * KEduVocContainer::childContainer(int row)
111 {
112 return d->m_childContainers.value(row);
113 }
114
115
childContainer(const QString & name)116 KEduVocContainer * KEduVocContainer::childContainer(const QString & name)
117 {
118 if (d->m_name == name) {
119 return this;
120 }
121
122 foreach (KEduVocContainer *container, d->m_childContainers) {
123 KEduVocContainer *found = container->childContainer(name);
124 if (found) {
125 return found;
126 }
127 }
128 return 0;
129 }
130
131
deleteChildContainer(int row)132 void KEduVocContainer::deleteChildContainer(int row)
133 {
134 qDebug() << "Delete of container - check entry deletion!";
135 delete d->m_childContainers.takeAt(row);
136
137 invalidateChildLessonEntries();
138 }
139
removeChildContainer(int row)140 void KEduVocContainer::removeChildContainer(int row)
141 {
142 d->m_childContainers.removeAt(row);
143 invalidateChildLessonEntries();
144 }
145
146
childContainerCount() const147 int KEduVocContainer::childContainerCount() const
148 {
149 return d->m_childContainers.count();
150 }
151
row() const152 int KEduVocContainer::row() const
153 {
154 if (d->m_parentContainer) {
155 return d->m_parentContainer->d->m_childContainers.indexOf(const_cast<KEduVocContainer*>(this));
156 }
157 return 0;
158 }
159
160
operator =(const KEduVocContainer & other)161 KEduVocContainer& KEduVocContainer::operator= ( const KEduVocContainer &other )
162 {
163 d->m_name = other.d->m_name;
164 d->m_inPractice = other.d->m_inPractice;
165 return *this;
166 }
167
operator ==(const KEduVocContainer & other) const168 bool KEduVocContainer::operator==(const KEduVocContainer &other) const
169 {
170 return d->m_name == other.d->m_name &&
171 d->m_inPractice == other.d->m_inPractice
172 /// @todo make this return something useful
173 ;
174 }
175
setName(const QString & name)176 void KEduVocContainer::setName( const QString &name )
177 {
178 d->m_name = name;
179 }
180
name()181 QString KEduVocContainer::name()
182 {
183 return d->m_name;
184 }
185
inPractice()186 bool KEduVocContainer::inPractice()
187 {
188 return d->m_inPractice;
189 }
190
setInPractice(bool inPractice)191 void KEduVocContainer::setInPractice(bool inPractice)
192 {
193 d->m_inPractice = inPractice;
194 }
195
removeTranslation(int translation)196 void KEduVocContainer::removeTranslation(int translation)
197 {
198 foreach(KEduVocContainer *childContainer, d->m_childContainers) {
199 childContainer->removeTranslation(translation);
200 }
201
202 foreach(KEduVocExpression *entry, entries() ) {
203 entry->removeTranslation( translation );
204 }
205 }
206
entriesRecursive()207 QList< KEduVocExpression * > KEduVocContainer::entriesRecursive()
208 {
209 if (!d->m_childLessonEntriesValid) {
210 updateChildLessonEntries();
211 }
212 return d->m_childLessonEntries;
213 }
214
childContainers()215 QList< KEduVocContainer * > KEduVocContainer::childContainers()
216 {
217 return d->m_childContainers;
218 }
219
parent()220 KEduVocContainer * KEduVocContainer::parent()
221 {
222 return d->m_parentContainer;
223 }
224
setContainerType(KEduVocContainer::EnumContainerType type)225 void KEduVocContainer::setContainerType(KEduVocContainer::EnumContainerType type)
226 {
227 d->m_type = type;
228 }
229
containerType()230 KEduVocContainer::EnumContainerType KEduVocContainer::containerType()
231 {
232 return d->m_type;
233 }
234
235
imageUrl()236 QUrl KEduVocContainer::imageUrl()
237 {
238 return d->m_imageUrl;
239 }
240
setImageUrl(const QUrl & url)241 void KEduVocContainer::setImageUrl(const QUrl &url)
242 {
243 d->m_imageUrl = url;
244 }
245
insertChildContainer(int row,KEduVocContainer * child)246 void KEduVocContainer::insertChildContainer(int row, KEduVocContainer * child)
247 {
248 d->m_childContainers.insert(row, child);
249 child->d->m_parentContainer = this;
250
251 invalidateChildLessonEntries();
252 }
253
updateChildLessonEntries()254 void KEduVocContainer::updateChildLessonEntries()
255 {
256 QList < KEduVocExpression* > entriesRecursive = entries();
257
258 foreach(KEduVocContainer *childContainer, d->m_childContainers)
259 foreach(KEduVocExpression * expr, childContainer->entries(Recursive))
260 entriesRecursive.append(expr);
261
262 d->m_childLessonEntries = entriesRecursive;
263 d->m_childLessonEntriesValid = true;
264 }
265
invalidateChildLessonEntries()266 void KEduVocContainer::invalidateChildLessonEntries()
267 {
268 d->m_childLessonEntriesValid = false;
269 // propagate to parent
270 if (d->m_parentContainer) {
271 d->m_parentContainer->invalidateChildLessonEntries();
272 }
273 }
274
averageGrade(int translation,EnumEntriesRecursive recursive)275 double KEduVocContainer::averageGrade(int translation, EnumEntriesRecursive recursive)
276 {
277 int sum = 0, presum = 0, count = 0;
278 foreach (KEduVocExpression *entry, entries(recursive)) {
279 KEduVocTranslation & trans( *entry->translation(translation) );
280 if ( !trans.isEmpty() ) {
281 ++count;
282 sum += trans.grade();
283 presum += trans.preGrade();
284 }
285 }
286 // make that a percentage
287 // There are KV_MAX_GRADE grades from 0 -> 100 %
288 // There are KV_MAX_GRADE preGrades within the first grade.
289 if (count == 0) {
290 return 100.0;
291 }
292 return ((sum * 100.0 / KV_MAX_GRADE) + (presum * 100.0 / (KV_MAX_GRADE * KV_MAX_GRADE))) / count;
293 }
294
expressionsOfGrade(int translation,grade_t grade,EnumEntriesRecursive recursive)295 int KEduVocContainer::expressionsOfGrade(int translation, grade_t grade, EnumEntriesRecursive recursive)
296 {
297 int sum = 0;
298 foreach (KEduVocExpression *entry, entries(recursive)) {
299 if (entry->translation(translation)->grade() == grade) {
300 sum++;
301 }
302 }
303 return sum;
304 }
305
resetGrades(int translation,EnumEntriesRecursive recursive)306 void KEduVocContainer::resetGrades(int translation, EnumEntriesRecursive recursive)
307 {
308 foreach (KEduVocExpression *entry, entries(recursive)) {
309 entry->resetGrades(translation);
310 }
311
312 document()->setModified(true);
313 }
314