File indexing completed on 2022-10-04 13:56:33

0001 /*
0002  * SPDX-FileCopyrightText: 2007 Jeremy Whiting <jpwhiting@kde.org>
0003  * SPDX-FileCopyrightText: 2007 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "keduvoccontainer.h"
0008 
0009 #include "keduvocdocument.h"
0010 #include "keduvocexpression.h"
0011 
0012 #include <QDebug>
0013 
0014 /** private class to store information about a lesson */
0015 class KEduVocContainer::Private
0016 {
0017 public:
0018     ~Private();
0019 
0020     // properties for this lesson
0021     QString m_name;
0022     bool m_inPractice;
0023 
0024     // The containing document.  This is only set for the top lesson, so to
0025     // get to the document, you need to follow the parent pointer to the top
0026     // container.
0027     KEduVocDocument *m_document;
0028 
0029     // other lessons in the tree
0030     KEduVocContainer *m_parentContainer;
0031     QList < KEduVocContainer * > m_childContainers;
0032 
0033     EnumContainerType m_type;
0034 
0035     QList < KEduVocExpression* > m_childLessonEntries;
0036     bool m_childLessonEntriesValid;
0037 
0038     /// Image url
0039     QUrl m_imageUrl;
0040 };
0041 
0042 KEduVocContainer::Private::~Private()
0043 {
0044     qDeleteAll(m_childContainers);
0045 }
0046 
0047 
0048 // This is a private constructor only used by KEduVocDocument when creating
0049 // the top level lesson.
0050 KEduVocContainer::KEduVocContainer(const QString& name, EnumContainerType type,
0051                    KEduVocDocument *document)
0052         : d( new Private )
0053 {
0054     d->m_parentContainer = nullptr;
0055     d->m_name = name;
0056     d->m_inPractice = true;
0057     d->m_type = type;
0058     d->m_childLessonEntriesValid = false;
0059 
0060     d->m_document = document;
0061 }
0062 
0063 
0064 KEduVocContainer::KEduVocContainer(const QString& name, EnumContainerType type, KEduVocContainer *parent)
0065         : d( new Private )
0066 {
0067     d->m_parentContainer = parent;
0068     d->m_name = name;
0069     d->m_inPractice = true;
0070     d->m_type = type;
0071     d->m_childLessonEntriesValid = false;
0072 
0073     d->m_document = nullptr;
0074 }
0075 
0076 KEduVocContainer::KEduVocContainer( const KEduVocContainer &other )
0077         : d( new Private )
0078 {
0079     d->m_name = other.d->m_name;
0080     d->m_inPractice = other.d->m_inPractice;
0081     d->m_type = other.d->m_type;
0082     d->m_parentContainer = other.d->m_parentContainer;
0083     d->m_childLessonEntriesValid = false;
0084 }
0085 
0086 KEduVocContainer::~KEduVocContainer()
0087 {
0088     delete d;
0089 }
0090 
0091 KEduVocDocument *KEduVocContainer::document() const
0092 {
0093     KEduVocContainer *cont = (KEduVocContainer *)this;
0094     while (cont->d->m_parentContainer) {
0095     cont = cont->d->m_parentContainer;
0096     }
0097 
0098     Q_ASSERT(cont->d->m_document);
0099     return cont->d->m_document;
0100 }
0101 
0102 void KEduVocContainer::appendChildContainer(KEduVocContainer * child)
0103 {
0104     d->m_childContainers.append(child);
0105     child->d->m_parentContainer = this;
0106 
0107     invalidateChildLessonEntries();
0108 }
0109 
0110 KEduVocContainer * KEduVocContainer::childContainer(int row)
0111 {
0112     return d->m_childContainers.value(row);
0113 }
0114 
0115 
0116 KEduVocContainer * KEduVocContainer::childContainer(const QString & name)
0117 {
0118     if (d->m_name == name) {
0119         return this;
0120     }
0121 
0122     foreach (KEduVocContainer *container, d->m_childContainers) {
0123         KEduVocContainer *found = container->childContainer(name);
0124         if (found) {
0125             return found;
0126         }
0127     }
0128     return 0;
0129 }
0130 
0131 
0132 void KEduVocContainer::deleteChildContainer(int row)
0133 {
0134     qDebug() << "Delete of container - check entry deletion!";
0135     delete d->m_childContainers.takeAt(row);
0136 
0137     invalidateChildLessonEntries();
0138 }
0139 
0140 void KEduVocContainer::removeChildContainer(int row)
0141 {
0142     d->m_childContainers.removeAt(row);
0143     invalidateChildLessonEntries();
0144 }
0145 
0146 
0147 int KEduVocContainer::childContainerCount() const
0148 {
0149     return d->m_childContainers.count();
0150 }
0151 
0152 int KEduVocContainer::row() const
0153 {
0154     if (d->m_parentContainer) {
0155         return d->m_parentContainer->d->m_childContainers.indexOf(const_cast<KEduVocContainer*>(this));
0156     }
0157     return 0;
0158 }
0159 
0160 
0161 KEduVocContainer& KEduVocContainer::operator= ( const KEduVocContainer &other )
0162 {
0163     d->m_name = other.d->m_name;
0164     d->m_inPractice = other.d->m_inPractice;
0165     return *this;
0166 }
0167 
0168 bool KEduVocContainer::operator==(const KEduVocContainer &other) const
0169 {
0170     return  d->m_name == other.d->m_name &&
0171             d->m_inPractice == other.d->m_inPractice
0172 /// @todo make this return something useful
0173             ;
0174 }
0175 
0176 void KEduVocContainer::setName( const QString &name )
0177 {
0178     d->m_name = name;
0179 }
0180 
0181 QString KEduVocContainer::name()
0182 {
0183     return d->m_name;
0184 }
0185 
0186 bool KEduVocContainer::inPractice()
0187 {
0188     return d->m_inPractice;
0189 }
0190 
0191 void KEduVocContainer::setInPractice(bool inPractice)
0192 {
0193     d->m_inPractice = inPractice;
0194 }
0195 
0196 void KEduVocContainer::removeTranslation(int translation)
0197 {
0198     foreach(KEduVocContainer *childContainer, d->m_childContainers) {
0199         childContainer->removeTranslation(translation);
0200     }
0201 
0202     foreach(KEduVocExpression *entry, entries() ) {
0203         entry->removeTranslation( translation );
0204     }
0205 }
0206 
0207 QList< KEduVocExpression * > KEduVocContainer::entriesRecursive()
0208 {
0209     if (!d->m_childLessonEntriesValid) {
0210         updateChildLessonEntries();
0211     }
0212     return d->m_childLessonEntries;
0213 }
0214 
0215 QList< KEduVocContainer * > KEduVocContainer::childContainers()
0216 {
0217     return d->m_childContainers;
0218 }
0219 
0220 KEduVocContainer * KEduVocContainer::parent()
0221 {
0222     return d->m_parentContainer;
0223 }
0224 
0225 void KEduVocContainer::setContainerType(KEduVocContainer::EnumContainerType type)
0226 {
0227     d->m_type = type;
0228 }
0229 
0230 KEduVocContainer::EnumContainerType KEduVocContainer::containerType()
0231 {
0232     return d->m_type;
0233 }
0234 
0235 
0236 QUrl KEduVocContainer::imageUrl()
0237 {
0238     return d->m_imageUrl;
0239 }
0240 
0241 void KEduVocContainer::setImageUrl(const QUrl &url)
0242 {
0243     d->m_imageUrl = url;
0244 }
0245 
0246 void KEduVocContainer::insertChildContainer(int row, KEduVocContainer * child)
0247 {
0248     d->m_childContainers.insert(row, child);
0249     child->d->m_parentContainer = this;
0250 
0251     invalidateChildLessonEntries();
0252 }
0253 
0254 void KEduVocContainer::updateChildLessonEntries()
0255 {
0256     QList < KEduVocExpression* > entriesRecursive = entries();
0257 
0258     foreach(KEduVocContainer *childContainer, d->m_childContainers)
0259         foreach(KEduVocExpression * expr, childContainer->entries(Recursive))
0260             entriesRecursive.append(expr);
0261 
0262     d->m_childLessonEntries = entriesRecursive;
0263     d->m_childLessonEntriesValid = true;
0264 }
0265 
0266 void KEduVocContainer::invalidateChildLessonEntries()
0267 {
0268     d->m_childLessonEntriesValid = false;
0269     // propagate to parent
0270     if (d->m_parentContainer) {
0271         d->m_parentContainer->invalidateChildLessonEntries();
0272     }
0273 }
0274 
0275 double KEduVocContainer::averageGrade(int translation, EnumEntriesRecursive recursive)
0276 {
0277     int sum = 0,  presum = 0,  count = 0;
0278     foreach (KEduVocExpression *entry, entries(recursive)) {
0279         KEduVocTranslation & trans( *entry->translation(translation) );
0280         if ( !trans.isEmpty() ) {
0281             ++count;
0282             sum += trans.grade();
0283             presum += trans.preGrade();
0284         }
0285     }
0286     // make that a percentage
0287     // There are KV_MAX_GRADE grades from 0 -> 100 %
0288     // There are KV_MAX_GRADE preGrades within the first grade.
0289     if (count == 0) {
0290         return 100.0;
0291     }
0292     return ((sum * 100.0 / KV_MAX_GRADE) + (presum * 100.0 / (KV_MAX_GRADE * KV_MAX_GRADE))) / count;
0293 }
0294 
0295 int KEduVocContainer::expressionsOfGrade(int translation, grade_t grade, EnumEntriesRecursive recursive)
0296 {
0297     int sum = 0;
0298     foreach (KEduVocExpression *entry, entries(recursive)) {
0299         if (entry->translation(translation)->grade() == grade) {
0300             sum++;
0301         }
0302     }
0303     return sum;
0304 }
0305 
0306 void KEduVocContainer::resetGrades(int translation, EnumEntriesRecursive recursive)
0307 {
0308     foreach (KEduVocExpression *entry, entries(recursive)) {
0309         entry->resetGrades(translation);
0310     }
0311 
0312     document()->setModified(true);
0313 }