diff --git a/.arcconfig b/.arcconfig new file mode 100644 index 00000000..377c7ecb --- /dev/null +++ b/.arcconfig @@ -0,0 +1,3 @@ +{ + "phabricator.uri" : "https://phabricator.kde.org/" +} diff --git a/src/collection/readonlycontainermodel.h b/src/collection/readonlycontainermodel.h index 1bf76dde..b8366645 100644 --- a/src/collection/readonlycontainermodel.h +++ b/src/collection/readonlycontainermodel.h @@ -1,66 +1,66 @@ /*************************************************************************** Copyright 2007-2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef READONLYCONTAINERMODEL_H #define READONLYCONTAINERMODEL_H #include #include #include #include #include /** * Model for the tree of containers (lessons, word types). * ReadonlyContainerModel is a read only tree model. * @see ContainerModel for its subclass that includes more options. */ class ReadonlyContainerModel : public QAbstractItemModel { Q_OBJECT public: explicit ReadonlyContainerModel(KEduVocContainer::EnumContainerType type, QObject *parent = 0); QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QModelIndex index(KEduVocContainer* container) const; QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; KEduVocContainer::EnumContainerType containerType(); public slots: /** Set the new source kvtml file * @param doc the new file */ - void setDocument(KEduVocDocument *doc); + virtual void setDocument(KEduVocDocument *doc); protected: virtual KEduVocContainer *rootContainer() const = 0; KEduVocContainer::EnumContainerType m_type; KEduVocDocument *m_doc; }; #endif diff --git a/src/statistics/conjugationoptions.cpp b/src/statistics/conjugationoptions.cpp index 97ebc150..34774bf8 100644 --- a/src/statistics/conjugationoptions.cpp +++ b/src/statistics/conjugationoptions.cpp @@ -1,89 +1,113 @@ /************************************************************************** Copyright 2007-2010 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "conjugationoptions.h" #include "languagesettings.h" #include "documentsettings.h" #include "prefs.h" #include #include #include #include #include #include -ConjugationOptions::ConjugationOptions(KEduVocDocument* doc, QWidget * parent) +ConjugationOptions::ConjugationOptions(KEduVocDocument *doc, QWidget *parent) : QWidget(parent) , m_doc(doc) , m_language(0) { m_treeWidget = new QTreeWidget(this); m_treeWidget->setHeaderLabel(i18n("Tenses")); m_treeWidget->setRootIsDecorated(false); QHBoxLayout* layout = new QHBoxLayout(this); layout->addWidget(m_treeWidget); layout->setMargin(0); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); + connect(m_treeWidget, &QTreeWidget::itemChanged, + this, &ConjugationOptions::processCheckBoxChanged); } void ConjugationOptions::setLanguages(int from, int to) { Q_UNUSED(from) if (to >= m_doc->identifierCount()) { to = 0; } m_language = to; setupTenses(); } void ConjugationOptions::setupTenses() { + m_treeWidget->blockSignals(true); m_treeWidget->clear(); + m_checkStates.clear(); DocumentSettings documentSettings(m_doc->url().url() + QString::number(m_language)); documentSettings.load(); QStringList activeTenses = documentSettings.conjugationTenses(); qDebug() << "activeTenses:" << activeTenses << " id tenses: " << m_doc->identifier(m_language).tenseList(); QTreeWidgetItem* tenseItem; foreach(const QString & tenseName, m_doc->identifier(m_language).tenseList()) { tenseItem = new QTreeWidgetItem(m_treeWidget); tenseItem->setText(0, tenseName); if (activeTenses.contains(tenseName)) { tenseItem->setCheckState(0, Qt::Checked); + m_checkStates[tenseItem] = Qt::Checked; } else { tenseItem->setCheckState(0, Qt::Unchecked); + m_checkStates[tenseItem] = Qt::Unchecked; } tenseItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); m_treeWidget->addTopLevelItem(tenseItem); } + m_treeWidget->blockSignals(false); } void ConjugationOptions::updateSettings() { qDebug() << "Save language selection"; - QTreeWidgetItem* parentItem = m_treeWidget->invisibleRootItem(); + QTreeWidgetItem *parentItem = m_treeWidget->invisibleRootItem(); + if (parentItem == nullptr) { + return; + } QStringList activeTenses; for (int i = 0; i < parentItem->childCount(); i++) { - QTreeWidgetItem* tenseItem = parentItem->child(i); + QTreeWidgetItem *tenseItem = parentItem->child(i); if (tenseItem->checkState(0) == Qt::Checked) { activeTenses.append(tenseItem->text(0)); } } DocumentSettings documentSettings(m_doc->url().url() + QString::number(m_language)); documentSettings.setConjugationTenses(activeTenses); documentSettings.save(); } + +void ConjugationOptions::processCheckBoxChanged(QTreeWidgetItem *item, int column) +{ + if (column != 0) { + return; + } + Qt::CheckState newCheckState = item->checkState(column); + if (m_checkStates.contains(item) && (m_checkStates[item] != newCheckState)) { + m_checkStates[item] = newCheckState; + updateSettings(); + emit checkBoxChanged(); + } +} + diff --git a/src/statistics/conjugationoptions.h b/src/statistics/conjugationoptions.h index ce3a1998..8901613b 100644 --- a/src/statistics/conjugationoptions.h +++ b/src/statistics/conjugationoptions.h @@ -1,40 +1,50 @@ /*************************************************************************** Copyright 2007-2010 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CONJUGATIONOPTIONS_H #define CONJUGATIONOPTIONS_H #include +#include class KEduVocDocument; class QTreeWidget; +class QTreeWidgetItem; class ConjugationOptions : public QWidget { Q_OBJECT public: - ConjugationOptions(KEduVocDocument* doc, QWidget *parent); + ConjugationOptions(KEduVocDocument *doc, QWidget *parent); public Q_SLOTS: void setLanguages(int from, int to); void updateSettings(); +signals: + void checkBoxChanged(); + private: void setupTenses(); - KEduVocDocument* m_doc; +private slots: + void processCheckBoxChanged(QTreeWidgetItem *item, int column); + +private: + KEduVocDocument *m_doc; int m_language; - QTreeWidget* m_treeWidget; + QTreeWidget *m_treeWidget; + QMap m_checkStates; }; #endif diff --git a/src/statistics/lessonstatisticsview.cpp b/src/statistics/lessonstatisticsview.cpp index 72eab92f..e7dfbe40 100644 --- a/src/statistics/lessonstatisticsview.cpp +++ b/src/statistics/lessonstatisticsview.cpp @@ -1,169 +1,175 @@ /*************************************************************************** Copyright 2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // Own #include "lessonstatisticsview.h" // Qt #include #include #include #include // KDE #include #include #include #include #include // Parley #include "statisticslegendwidget.h" #include "statisticsmodel.h" #include "keduvoclesson.h" #include "utils.h" // GradeDelegate shows the graphic colored bar in the statistics, // showing how far the student has come on the way to enlightenment. class GradeDelegate: public QItemDelegate { public: GradeDelegate(QObject *parent = 0) : QItemDelegate(parent) { } void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const Q_DECL_OVERRIDE + const QModelIndex &index) const Q_DECL_OVERRIDE { QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0); // empty lesson? If so, paint nothing. if (!index.data(StatisticsModel::TotalCount).toInt()) { return; } // Draw the colored bar. - KEduVocContainer *container = index.data(StatisticsModel::Container).value(); + KEduVocContainer *container = index.data(StatisticsModel::Container) + .value(); + QStringList activeConjugationTenses = index.data(StatisticsModel::ActiveConjugationTenses) + .toStringList(); WordCount wordCount; - wordCount.fillFromContainer(*container, index.column() - ContainerModel::FirstDataColumn); + wordCount.fillFromContainerForPracticeMode( + *container, + index.column() - ContainerModel::FirstDataColumn, + activeConjugationTenses + ); ConfidenceColors colors(ConfidenceColors::ProgressiveColorScheme); paintColorBar(*painter, option.rect, wordCount, colors); // in utils // Draw the text telling the percentage on top of the bar. painter->drawText(option.rect, Qt::AlignCenter, - QStringLiteral("%1%").arg(index.data(StatisticsModel::TotalPercent).toInt())); + QStringLiteral("%1%").arg(index.data(StatisticsModel::TotalPercent).toInt())); } }; // ---------------------------------------------------------------- LessonStatisticsView::LessonStatisticsView(QWidget *parent) : ContainerView(parent) { header()->setVisible(true); header()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignBottom); header()->setSectionsMovable( true ); // inherits context menu policy - so action will show up in right click menu QAction *removeGradesAction = new QAction(this); removeGradesAction->setText(i18n("Remove confidence levels from this unit")); removeGradesAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear"))); removeGradesAction->setWhatsThis(i18n("Remove confidence levels from this unit")); removeGradesAction->setToolTip(removeGradesAction->whatsThis()); removeGradesAction->setStatusTip(removeGradesAction->whatsThis()); connect(removeGradesAction, &QAction::triggered, this, &LessonStatisticsView::removeGrades); addAction(removeGradesAction); QAction *removeGradesChildrenAction = new QAction(this); removeGradesChildrenAction->setText(i18n("Remove confidence levels from this unit and all sub-units")); removeGradesChildrenAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear"))); removeGradesChildrenAction->setWhatsThis(i18n("Remove confidence level from this unit and all sub-units")); removeGradesChildrenAction->setToolTip(removeGradesChildrenAction->whatsThis()); removeGradesChildrenAction->setStatusTip(removeGradesChildrenAction->whatsThis()); connect(removeGradesChildrenAction, &QAction::triggered, this, &LessonStatisticsView::removeGradesChildren); addAction(removeGradesChildrenAction); connect(header(), &QHeaderView::geometriesChanged, this, &LessonStatisticsView::adjustColumnWidths); connect(header(), &QHeaderView::sectionResized, this, &LessonStatisticsView::sectionResized); } void LessonStatisticsView::setModel(ContainerModel *model) { ContainerView::setModel(model); GradeDelegate *delegate = new GradeDelegate(this); for (int i = ContainerModel::FirstDataColumn; i < model->columnCount(QModelIndex()); i++) { setItemDelegateForColumn(i, delegate); } adjustColumnWidths(); } void LessonStatisticsView::resizeEvent(QResizeEvent *event) { adjustColumnWidths(); ContainerView::resizeEvent(event); } void LessonStatisticsView::sectionResized(int index, int /*oldSize*/, int /*newSize*/) { if (index < ContainerModel::FirstDataColumn) { adjustColumnWidths(); } } void LessonStatisticsView::adjustColumnWidths() { int firstWidth = columnWidth(0) + columnWidth(1); - // Subtract 5 here otherwise we get a horizontal scrollbar. - int totalWidth = width() - firstWidth - 5; + int totalWidth = viewport()->width() - firstWidth; int columnCount = model()->columnCount(QModelIndex()); int visibleColumns = 0; for (int i = ContainerModel::FirstDataColumn; i < columnCount; ++i) { if (!isColumnHidden(i)) visibleColumns++; } int columnWidth = visibleColumns > 0 ? totalWidth / visibleColumns : 150; for (int i = ContainerModel::FirstDataColumn; i < model()->columnCount(QModelIndex()); i++) { setColumnWidth(i, columnWidth); } // header()->resizeSections(QHeaderView::ResizeToContents); header()->setSectionResizeMode(QHeaderView::Interactive); header()->setStretchLastSection(true); } void LessonStatisticsView::removeGrades() { QModelIndex selectedIndex = selectionModel()->currentIndex(); KEduVocLesson *lesson = static_cast(selectedIndex.internalPointer()); lesson->resetGrades(-1, KEduVocContainer::NotRecursive); } void LessonStatisticsView::removeGradesChildren() { QModelIndex selectedIndex = selectionModel()->currentIndex(); KEduVocLesson *lesson = static_cast(selectedIndex.internalPointer()); lesson->resetGrades(-1, KEduVocContainer::Recursive); } diff --git a/src/statistics/lessonstatisticsview.h b/src/statistics/lessonstatisticsview.h index 6657fe5f..91deb8be 100644 --- a/src/statistics/lessonstatisticsview.h +++ b/src/statistics/lessonstatisticsview.h @@ -1,50 +1,50 @@ /*************************************************************************** Copyright 2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef LESSONSTATISTICSVIEW_H #define LESSONSTATISTICSVIEW_H #include "containerview.h" /** * View for the lesson list. * @author Frederik Gladhorn */ class LessonStatisticsView : public ContainerView { Q_OBJECT public: LessonStatisticsView(QWidget *parent); void setModel(ContainerModel *model) Q_DECL_OVERRIDE; -private Q_SLOTS: - void removeGrades(); - void removeGradesChildren(); +public Q_SLOTS: + void adjustColumnWidths(); protected: void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; private Q_SLOTS: + void removeGrades(); + void removeGradesChildren(); void sectionResized(int index, int /*oldSize*/, int /*newSize*/); - void adjustColumnWidths(); private: void setModel(QAbstractItemModel *model) Q_DECL_OVERRIDE { Q_UNUSED(model) } }; #endif diff --git a/src/statistics/statisticsmainwindow.cpp b/src/statistics/statisticsmainwindow.cpp index c251f870..8e6975e2 100644 --- a/src/statistics/statisticsmainwindow.cpp +++ b/src/statistics/statisticsmainwindow.cpp @@ -1,320 +1,336 @@ /*************************************************************************** Copyright 2008-2010 Frederik Gladhorn Copyright 2008 Daniel Laidig *************************************************************************** *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "statisticsmainwindow.h" #include #include #include #include #include #include "practice/configure/configurepracticedialog.h" #include "lessonstatisticsview.h" #include "statisticsmodel.h" #include "parleymainwindow.h" #include "parleyactions.h" #include "prefs.h" #include "ui_statisticsmainwindow.h" #include "conjugationoptions.h" StatisticsMainWindow::StatisticsMainWindow(KEduVocDocument *doc, ParleyMainWindow *parent) : KXmlGuiWindow(parent) , m_mainWindow(parent) , m_doc(doc) , m_ui(new Ui::StatisticsMainWindow) , m_conjugationOptions(0) { // KXmlGui setXMLFile(QStringLiteral("statisticsui.rc")); setObjectName(QStringLiteral("Statistics")); QWidget *mainWidget = new QWidget(this); setCentralWidget(mainWidget); m_ui->setupUi(mainWidget); //m_ui->caption->setText(i18nc("caption for an overview of the confidence levels for a document" // "Statistics for \"%1\"", m_doc->title())); m_statisticsModel = new StatisticsModel(this); setDocument(doc); initActions(); initPracticeModeSelection(); initLanguages(); initPracticeMode(); KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); applyMainWindowSettings(cfg); } StatisticsMainWindow::~StatisticsMainWindow() { if (m_conjugationOptions) { m_conjugationOptions->updateSettings(); } KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName()); saveMainWindowSettings(cfg); delete m_ui; } void StatisticsMainWindow::syncConfig() { //qDebug() << "save tenses"; if (m_conjugationOptions) { m_conjugationOptions->updateSettings(); } } void StatisticsMainWindow::setDocument(KEduVocDocument* doc) { m_doc = doc; m_statisticsModel->setDocument(doc); m_ui->lessonStatistics->setModel(m_statisticsModel); m_ui->lessonStatistics->expandAll(); m_ui->lessonStatistics->resizeColumnToContents(0); } void StatisticsMainWindow::initActions() { ParleyActions::create(ParleyActions::EnterEditMode, m_mainWindow, SLOT(showEditor()), actionCollection()); ParleyActions::create(ParleyActions::StartPractice, m_mainWindow, SLOT(startPractice()), actionCollection()); ParleyActions::create(ParleyActions::ConfigurePractice, m_mainWindow, SLOT(configurePractice()), actionCollection()); } void StatisticsMainWindow::initPracticeModeSelection() { switch (Prefs::practiceMode()) { case Prefs::EnumPracticeMode::FlashCardsPractice: m_ui->flashCard->setChecked(true); break; case Prefs::EnumPracticeMode::MixedLettersPractice: m_ui->mixedLetters->setChecked(true); break; case Prefs::EnumPracticeMode::MultipleChoicePractice: m_ui->multipleChoice->setChecked(true); break; case Prefs::EnumPracticeMode::WrittenPractice: m_ui->written->setChecked(true); break; case Prefs::EnumPracticeMode::ExampleSentencesPractice: m_ui->exampleSentence->setChecked(true); break; case Prefs::EnumPracticeMode::GenderPractice: m_ui->gender->setChecked(true); break; case Prefs::EnumPracticeMode::ComparisonPractice: m_ui->comparisonForms->setChecked(true); break; case Prefs::EnumPracticeMode::ConjugationPractice: m_ui->conjugations->setChecked(true); showConjugationOptions(); break; default: break; } QSignalMapper* mapper = new QSignalMapper(this); mapper->setMapping(m_ui->flashCard, Prefs::EnumPracticeMode::FlashCardsPractice); mapper->setMapping(m_ui->mixedLetters, Prefs::EnumPracticeMode::MixedLettersPractice); mapper->setMapping(m_ui->multipleChoice, Prefs::EnumPracticeMode::MultipleChoicePractice); mapper->setMapping(m_ui->written, Prefs::EnumPracticeMode::WrittenPractice); mapper->setMapping(m_ui->exampleSentence, Prefs::EnumPracticeMode::ExampleSentencesPractice); mapper->setMapping(m_ui->gender, Prefs::EnumPracticeMode::GenderPractice); mapper->setMapping(m_ui->comparisonForms, Prefs::EnumPracticeMode::ComparisonPractice); mapper->setMapping(m_ui->conjugations, Prefs::EnumPracticeMode::ConjugationPractice); connect(m_ui->flashCard, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->mixedLetters, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->multipleChoice, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->written, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->exampleSentence, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->gender, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->comparisonForms, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(m_ui->conjugations, SIGNAL(clicked(bool)), mapper, SLOT(map())); connect(mapper, SIGNAL(mapped(int)), this, SLOT(practiceModeSelected(int))); } void StatisticsMainWindow::initLanguages() { //qDebug() << "init languages: " << Prefs::learningLanguage() << Prefs::knownLanguage(); const int totalNumLanguages = m_doc->identifierCount(); if ( Prefs::knownLanguage() < 0 || totalNumLanguages <= Prefs::knownLanguage() ) { Prefs::setKnownLanguage(0); } if ( Prefs::learningLanguage() < 0 || totalNumLanguages <= Prefs::learningLanguage() ) { Prefs::setLearningLanguage(0); } if (Prefs::knownLanguage() >= totalNumLanguages || Prefs::learningLanguage() >= totalNumLanguages || Prefs::learningLanguage() == Prefs::knownLanguage()) { Prefs::setKnownLanguage(0); Prefs::setLearningLanguage(1); //qDebug() << "Invalid language selection."; } // Insert data into the comboboxes. for (int i = 0; i < totalNumLanguages; ++i) { m_ui->learnedLanguage->insertItem(i, m_doc->identifier(i).name()); m_ui->knownLanguage->insertItem(i, m_doc->identifier(i).name()); } m_ui->learnedLanguage->setCurrentIndex(Prefs::learningLanguage()); m_ui->knownLanguage->setCurrentIndex(Prefs::knownLanguage()); connect(m_ui->learnedLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged())); connect(m_ui->knownLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged())); languagesChanged(); } void StatisticsMainWindow::languagesChanged() { int knownLanguage = m_ui->knownLanguage->currentIndex(); int learningLanguage = m_ui->learnedLanguage->currentIndex(); Prefs::setLearningLanguage(learningLanguage); Prefs::setKnownLanguage(knownLanguage); emit languagesChanged(knownLanguage, learningLanguage); updateVisibleColumns(); + updateModelSettings(); } void StatisticsMainWindow::initPracticeMode() { m_ui->practiceDirection->insertItem(0, i18n("Known to Learning")); m_ui->practiceDirection->insertItem(1, i18n("Learning to Known")); m_ui->practiceDirection->insertItem(2, i18n("Mixed Directions")); //m_ui->practiceDirection->insertItem(3, i18n("Mixed Directions with Sound")); int practiceDirection(Prefs::rememberPracticeDirection() ? practiceDirectionForPracticeMode(Prefs::practiceMode()) : Prefs::practiceDirection()); if (practiceDirection < 0 || 3 < practiceDirection) Prefs::setPracticeDirection(Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly); m_ui->practiceDirection->setCurrentIndex(practiceDirection); connect(m_ui->practiceDirection, static_cast(&QComboBox::currentIndexChanged), this, &StatisticsMainWindow::practiceDirectionChanged); m_ui->rememberPracticeDirection->setChecked(Prefs::rememberPracticeDirection()); connect(m_ui->rememberPracticeDirection, &QCheckBox::toggled, this, &StatisticsMainWindow::rememberPracticeDirectionChanged); } void StatisticsMainWindow::practiceModeSelected(int mode) { int previousPracticeMode = Prefs::practiceMode(); Prefs::setPracticeMode(static_cast(mode)); //qDebug() << "mode: " << mode << Prefs::practiceMode(); showConjugationOptions(mode == Prefs::EnumPracticeMode::ConjugationPractice); if (Prefs::rememberPracticeDirection()) { setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), previousPracticeMode); m_ui->practiceDirection->setCurrentIndex(practiceDirectionForPracticeMode(mode)); } + + updateModelSettings(); } void StatisticsMainWindow::practiceDirectionChanged(int mode) { //qDebug() << "new practice direction:" << mode; Prefs::setPracticeDirection(static_cast(mode)); if (Prefs::rememberPracticeDirection()) { setPracticeDirectionForPracticeMode(mode, Prefs::practiceMode()); } + updateVisibleColumns(); + updateModelSettings(); } void StatisticsMainWindow::rememberPracticeDirectionChanged(bool checked) { // qDebug() << "remember practice direction changed to: " << checked; Prefs::setRememberPracticeDirection(checked); if (checked) { setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), Prefs::practiceMode()); } } void StatisticsMainWindow::updateVisibleColumns() { bool isHidden; for (int i = ContainerModel::FirstDataColumn; i < m_ui->lessonStatistics->header()->count(); i++) { int iLang = i - ContainerModel::FirstDataColumn; switch (Prefs::practiceDirection()) { case Prefs::EnumPracticeDirection::LearningToKnown: isHidden = iLang != Prefs::knownLanguage(); break; case Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly: case Prefs::EnumPracticeDirection::MixedDirectionsWithSound: isHidden = iLang != Prefs::knownLanguage() && iLang != Prefs::learningLanguage(); break; case Prefs::EnumPracticeDirection::KnownToLearning: // Use KnownToLearning as default. default: isHidden = iLang != Prefs::learningLanguage(); break; } m_ui->lessonStatistics->setColumnHidden(i, isHidden); + m_ui->lessonStatistics->adjustColumnWidths(); } } void StatisticsMainWindow::showConjugationOptions(bool visible) { if (!m_conjugationOptions && !visible) { return; } if (!m_conjugationOptions) { m_conjugationOptions = new ConjugationOptions(m_doc, m_ui->modeSpecificOptions); QHBoxLayout* layout = new QHBoxLayout(m_ui->modeSpecificOptions); layout->setMargin(0); layout->addWidget(m_conjugationOptions); - connect(this, SIGNAL(languagesChanged(int, int)), m_conjugationOptions, SLOT(setLanguages(int, int))); + connect(this, QOverload::of(&StatisticsMainWindow::languagesChanged), + m_conjugationOptions, &ConjugationOptions::setLanguages); m_conjugationOptions->setLanguages(Prefs::knownLanguage(), Prefs::learningLanguage()); + connect(m_conjugationOptions, &ConjugationOptions::checkBoxChanged, + this, &StatisticsMainWindow::updateModelSettings); } m_conjugationOptions->setVisible(visible); } void StatisticsMainWindow::configurePractice() { ConfigurePracticeDialog dialog(m_doc, this, QStringLiteral("practice settings"), Prefs::self()); dialog.exec(); } int StatisticsMainWindow::practiceDirectionForPracticeMode(int mode) const { int direction = Prefs::practiceDirectionsByPracticeMode().value(mode, Prefs::practiceDirection()); if ((direction < 0) || (direction > Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly)) { direction = Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly; } return direction; } void StatisticsMainWindow::setPracticeDirectionForPracticeMode(int direction, int mode) { QList directions = Prefs::practiceDirectionsByPracticeMode(); // Expand list if fields not used before for (int i = directions.size() - 1; i < mode; ++i) { directions.append(Prefs::practiceDirection()); } directions[mode] = direction; Prefs::setPracticeDirectionsByPracticeMode(directions); } + +void StatisticsMainWindow::updateModelSettings() +{ + m_statisticsModel->updateDocumentSettings(); + m_ui->lessonStatistics->expandAll(); +} + diff --git a/src/statistics/statisticsmainwindow.h b/src/statistics/statisticsmainwindow.h index 838bccfc..c950bb40 100644 --- a/src/statistics/statisticsmainwindow.h +++ b/src/statistics/statisticsmainwindow.h @@ -1,70 +1,71 @@ /*************************************************************************** copyright : (C) 1999-2001 Ewald Arnold (C) 2005-2007 Peter Hedlund Copyright 2008-2010 Frederik Gladhorn *************************************************************************** *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef STATISTICSMAINWINDOW_H #define STATISTICSMAINWINDOW_H #include class ConjugationOptions; class LessonStatisticsView; class StatisticsModel; class KEduVocDocument; class ParleyMainWindow; namespace Ui { class StatisticsMainWindow; } class StatisticsMainWindow : public KXmlGuiWindow { Q_OBJECT public: StatisticsMainWindow(KEduVocDocument *doc, ParleyMainWindow *parent); ~StatisticsMainWindow(); void setDocument(KEduVocDocument* doc); void syncConfig(); Q_SIGNALS: void languagesChanged(int, int); private slots: void configurePractice(); void languagesChanged(); void practiceModeSelected(int mode); void practiceDirectionChanged(int mode); void rememberPracticeDirectionChanged(bool checked); void updateVisibleColumns(); + void updateModelSettings(); private: void initActions(); void initPracticeModeSelection(); void initLanguages(); void initPracticeMode(); void showConjugationOptions(bool visible = true); int practiceDirectionForPracticeMode(int mode) const; void setPracticeDirectionForPracticeMode(int direction, int mode); ParleyMainWindow* m_mainWindow; KEduVocDocument* m_doc; StatisticsModel* m_statisticsModel; Ui::StatisticsMainWindow* m_ui; ConjugationOptions* m_conjugationOptions; }; #endif diff --git a/src/statistics/statisticsmodel.cpp b/src/statistics/statisticsmodel.cpp index 0482ff05..abc50868 100644 --- a/src/statistics/statisticsmodel.cpp +++ b/src/statistics/statisticsmodel.cpp @@ -1,105 +1,201 @@ /*************************************************************************** Copyright 2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "statisticsmodel.h" #include "statisticslegendwidget.h" +#include "utils.h" +#include +#include +#include #include #include #include -StatisticsModel::StatisticsModel(QObject * parent) +StatisticsModel::StatisticsModel(QObject *parent) : ContainerModel(KEduVocContainer::Lesson, parent) { } QVariant StatisticsModel::headerData(int section, Qt::Orientation orientation, int role) const { if (section >= FirstDataColumn) { if (role == Qt::DisplayRole && m_doc->identifierCount() > (section - FirstDataColumn) ) { return i18nc("Confidence level in language, table header", "Confidence (%1)" , m_doc->identifier(section - FirstDataColumn).name()); } } return ContainerModel::headerData(section, orientation, role); } -QVariant StatisticsModel::data(const QModelIndex & index, int role) const +QVariant StatisticsModel::data(const QModelIndex &index, int role) const { + Q_ASSERT(!m_documentSettings.isEmpty()); + + KEduVocContainer *container = static_cast(index.internalPointer()); + + // Entrie count + if (index.column() == TotalCountColumn) { + if (role == Qt::DisplayRole) { + switch (Prefs::practiceDirection()) { + case Prefs::EnumPracticeDirection::KnownToLearning: + return entryCountForPracticeMode(container, Prefs::learningLanguage()); + case Prefs::EnumPracticeDirection::LearningToKnown: + return entryCountForPracticeMode(container, Prefs::knownLanguage()); + case Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly: + case Prefs::EnumPracticeDirection::MixedDirectionsWithSound: + return entryCountForPracticeMode(container, Prefs::knownLanguage()) + + entryCountForPracticeMode(container, Prefs::learningLanguage()); + default: + return entryCountForPracticeMode(container, Prefs::learningLanguage()); + } + } + if (role == Qt::TextAlignmentRole) { + return Qt::AlignRight; + } + } + + // Colorbars if (index.column() >= FirstDataColumn) { - KEduVocContainer *container = static_cast(index.internalPointer()); - QVariant var; + int translation = index.column() - FirstDataColumn; switch (role) { case Container: - // Return a pointer to the container we are working on. - var.setValue(container); - return var; + { + // Return a pointer to the container we are working on. + QVariant var; + var.setValue(container); + return var; + } case TotalPercent: // Average grade - return container->averageGrade(index.column() - FirstDataColumn, KEduVocContainer::Recursive); + return averageGradeForPracticeMode(container, translation); case TotalCount: - return container->entryCount(KEduVocContainer::Recursive); + return entryCountForPracticeMode(container, translation); + case ActiveConjugationTenses: + return m_documentSettings.at(translation)->conjugationTenses(); default: - if (role >= Qt::UserRole) { - return container->expressionsOfGrade( - index.column() - FirstDataColumn, role - Grade0, KEduVocContainer::Recursive); + if ((role >= Grade0) && (role <= Grade7)) { + return expressionsOfGradeForPracticeMode(container, translation, role - Grade0); } } } - // checkboxes + // Checkboxes if (index.column() == 0 && role == Qt::CheckStateRole) { - KEduVocContainer *container = static_cast(index.internalPointer()); if (container->inPractice()) { return Qt::Checked; } else { return Qt::Unchecked; } } return ContainerModel::data(index, role); } +int StatisticsModel::averageGradeForPracticeMode(KEduVocContainer *container, int translation) const +{ + WordCount wordCount; + wordCount.fillFromContainerForPracticeMode( + *container, + translation, + m_documentSettings.at(translation)->conjugationTenses() + ); + return wordCount.percentageCompleted(); +} + +int StatisticsModel::entryCountForPracticeMode(KEduVocContainer *container, int translation) const +{ + WordCount wordCount; + wordCount.fillFromContainerForPracticeMode( + *container, + translation, + m_documentSettings.at(translation)->conjugationTenses() + ); + return wordCount.totalWords - wordCount.invalid; +} +int StatisticsModel::expressionsOfGradeForPracticeMode(KEduVocContainer *container, + int translation, grade_t grade) const +{ + WordCount wordCount; + wordCount.fillFromContainerForPracticeMode( + *container, + translation, + m_documentSettings.at(translation)->conjugationTenses() + ); + return wordCount.grades[grade]; +} -Qt::ItemFlags StatisticsModel::flags(const QModelIndex & index) const +Qt::ItemFlags StatisticsModel::flags(const QModelIndex &index) const { if (index.isValid()) { if (index.column() == 0) { return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable); } return (Qt::ItemIsEnabled | Qt::ItemIsSelectable); } return 0; } -int StatisticsModel::columnCount(const QModelIndex & parent) const +int StatisticsModel::columnCount(const QModelIndex &parent) const { Q_UNUSED(parent) return m_doc->identifierCount() + FirstDataColumn; } Qt::DropActions StatisticsModel::supportedDragActions() const { return 0; } -KEduVocContainer * StatisticsModel::rootContainer() const +KEduVocContainer *StatisticsModel::rootContainer() const { if (!m_doc) { return 0; } return m_doc->lesson(); } + +void StatisticsModel::loadDocumentsSettings() +{ + m_documentSettings.clear(); + if (m_doc == nullptr) { + return; + } + for (int i = 0 ; i < m_doc->identifierCount(); ++i) { + m_documentSettings << QSharedPointer( + new DocumentSettings(m_doc->url().url() + QString::number(i)) + ); + m_documentSettings.last()->load(); + + } +} + +void StatisticsModel::setDocument(KEduVocDocument *doc) +{ + beginResetModel(); + m_doc = doc; + loadDocumentsSettings(); + endResetModel(); +} + + +void StatisticsModel::updateDocumentSettings() +{ + beginResetModel(); + loadDocumentsSettings(); + endResetModel(); +} + diff --git a/src/statistics/statisticsmodel.h b/src/statistics/statisticsmodel.h index 282adf7b..05f98ade 100644 --- a/src/statistics/statisticsmodel.h +++ b/src/statistics/statisticsmodel.h @@ -1,60 +1,80 @@ /*************************************************************************** Copyright 2008 Frederik Gladhorn ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef STATISTICSMODEL_H #define STATISTICSMODEL_H #include "containermodel.h" +#include "prefs.h" +#include "documentsettings.h" + class StatisticsModel : public ContainerModel { Q_OBJECT public: enum GradeRoles { TotalPercent = Qt::UserRole, TotalCount, Grade0, Grade1, Grade2, Grade3, Grade4, Grade5, Grade6, Grade7, - Container + Container, + ActiveConjugationTenses }; explicit StatisticsModel(QObject *parent = 0); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE; Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; /** Indicate supported drag actions @return enum of actions supported **/ Qt::DropActions supportedDragActions() const Q_DECL_OVERRIDE; + + void updateDocumentSettings(); + +public slots: + virtual void setDocument(KEduVocDocument *doc) Q_DECL_OVERRIDE; + protected: - KEduVocContainer * rootContainer() const Q_DECL_OVERRIDE; + KEduVocContainer *rootContainer() const Q_DECL_OVERRIDE; + +private: + int averageGradeForPracticeMode(KEduVocContainer *container, int translation) const; + int entryCountForPracticeMode(KEduVocContainer *container, int translation) const; + int expressionsOfGradeForPracticeMode(KEduVocContainer *container, int translation, + grade_t grade) const; + void loadDocumentsSettings(); + +private: + QList> m_documentSettings; }; // For index.data() Q_DECLARE_METATYPE(KEduVocContainer*) #endif diff --git a/src/utils.cpp b/src/utils.cpp index 4398e72e..97126e03 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,222 +1,294 @@ /*************************************************************************** Copyright 2015 Inge Wallin ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ // Own #include "utils.h" // Qt #include #include // KEduVocDocument library #include #include // Parley #include "prefs.h" // ---------------------------------------------------------------- // class WordCount WordCount::WordCount() { clear(); } void WordCount::clear() { for (int i = 0; i <= KV_MAX_GRADE; ++i) { grades[i] = 0; pregrades[i] = 0; } invalid = 0; initialWords = 0; totalWords = 0; } int WordCount::percentageCompleted() const { // To calculate the percentage done we add: // * 1..KV_MAX_GRADE points for words in the initial phase (grade = 0, pregrade > 0) // * KV_MAX_GRADE * (1..KV_MAX_GRADE) points for words in the long-term phase (grade>0) // So the maximum number of points is KV_MAX_GRADE^2 per word. // // In the final calculation, we exclude all invalid words from the percentage. int points = 0; for (int i = 0; i < KV_MAX_GRADE + 1; ++i) { points += pregrades[i] * i; points += grades[i] * KV_MAX_GRADE * i; } if (totalWords - invalid == 0) { // Don't divide by 0. return 0; } else { return 100 * points / ((totalWords - invalid) * KV_MAX_GRADE * KV_MAX_GRADE); } } void WordCount::fillFromContainer(KEduVocContainer &container, int translationIndex, KEduVocContainer::EnumEntriesRecursive recursive) { clear(); foreach (KEduVocExpression *entry, container.entries(recursive)) { KEduVocTranslation &translation(*entry->translation(translationIndex)); + evaluateWord(translation, translation.text()); + } +} - ++totalWords; - if (translation.isEmpty()) { - ++invalid; - } else if (translation.preGrade() > 0) { - // Initial phase (we assume correctness, i.e. if pregrade>0 then grade = 0) - ++initialWords; - ++pregrades[translation.preGrade()]; - } else { - // Long term or unpracticed - ++grades[translation.grade()]; + +void WordCount::fillFromContainerForPracticeMode(KEduVocContainer &container, int translationIndex, + const QStringList &activeConjugationTenses, + KEduVocContainer::EnumEntriesRecursive recursive) +{ + KEduVocWordFlags wordTypeToProcess(KEduVocWordFlag::NoInformation); + switch (Prefs::practiceMode()) { + case Prefs::EnumPracticeMode::GenderPractice: + wordTypeToProcess = KEduVocWordFlag::Noun; + break; + case Prefs::EnumPracticeMode::ConjugationPractice: + wordTypeToProcess = KEduVocWordFlag::Verb; + break; + case Prefs::EnumPracticeMode::ComparisonPractice: + wordTypeToProcess = KEduVocWordFlag::Adjective | KEduVocWordFlag::Adverb; + break; + default: + fillFromContainer(container, translationIndex, recursive); + return; + } + + clear(); + + foreach (KEduVocExpression *entry, container.entries(recursive)) { + KEduVocTranslation &translation(*entry->translation(translationIndex)); + if (isValidForProcessing(translation, wordTypeToProcess)) { + switch (wordTypeToProcess) { + case KEduVocWordFlag::Noun: + { + KEduVocText article = translation.article(); + evaluateWord(article, translation.text()); + } + break; + case KEduVocWordFlag::Verb: + { + QStringList conjugationTenses = translation.conjugationTenses(); + foreach(const QString &activeTense, activeConjugationTenses) + { + if (conjugationTenses.contains(activeTense)) { + KEduVocConjugation conj = translation.getConjugation(activeTense); + foreach (KEduVocWordFlags key, conj.keys()) { + KEduVocText person = conj.conjugation(key); + evaluateWord(person, person.text()); + } + } + } + } + break; + case KEduVocWordFlag::Adjective | KEduVocWordFlag::Adverb: + { + KEduVocText comparative = translation.comparativeForm(); + evaluateWord(comparative, comparative.text()); + KEduVocText superlative = translation.superlativeForm(); + evaluateWord(superlative, superlative.text()); + } + break; + } } } } +bool WordCount::isValidForProcessing(KEduVocTranslation &trans, KEduVocWordFlags wordType) const +{ + return !trans.isEmpty() + && (trans.wordType() != nullptr) + && ((trans.wordType()->wordType() & wordType) != 0); +} + +void WordCount::evaluateWord(const KEduVocText &item, const QString &text) +{ + ++totalWords; + if (text.isEmpty()) { + ++invalid; + } else if (item.preGrade() > 0) { + // Initial phase (we assume correctness, i.e. if pregrade>0 then grade = 0) + ++initialWords; + ++pregrades[item.preGrade()]; + } else { + // Long term or unpracticed + ++grades[item.grade()]; + } +} + // ---------------------------------------------------------------- // class confidenceColors ConfidenceColors::ConfidenceColors(ColorScheme colorScheme) { initColors(colorScheme); } void ConfidenceColors::initColors(ColorScheme colorScheme) { switch (colorScheme) { case MultiColorScheme: default: // Not default at the last line. Hope this works... longTermColors[0] = QColor(25,38,41); //longTermColors[1] = QColor(Qt::yellow); longTermColors[1] = QColor(25,38,41,64); longTermColors[2] = QColor(237,21,21); longTermColors[3] = QColor(246,116,0); longTermColors[4] = QColor(201,206,59); longTermColors[5] = QColor(28,220,154); longTermColors[6] = QColor(17,209,22); longTermColors[7] = QColor(61,174,253); initialTermColor = QColor(25,38,41,64); // Find something else invalidColor = QColor(Qt::red); break; case ProgressiveColorScheme: { static const int AlphaMax = 255; static const int AlphaStep = ((AlphaMax - 10) / KV_MAX_GRADE); QColor color; // Confidence 1..max for (int grade = 1; grade <= KV_MAX_GRADE; ++grade) { color = Prefs::gradeColor(); color.setAlpha(AlphaMax - (KV_MAX_GRADE - grade) * AlphaStep); longTermColors[grade] = color; } // Unpracticed (confidence 0) color = QColor("#FFFFFF"); color.setAlpha(AlphaMax); longTermColors[0] = color; // Use one color for all initial phase values color = Prefs::preGradeColor(); color.setAlpha(AlphaMax); initialTermColor = color; // Invalid invalidColor = Prefs::invalidUnitColor(); break; } } // These two are placeholders for the wordcloud background color. frontEndColors[0] = QColor(255,221,217); frontEndColors[1] = QColor(238,232,213); } // ---------------------------------------------------------------- // Various utility functions void paintColorBar(QPainter &painter, const QRect &rect, const WordCount &wordCount, const ConfidenceColors &colors) { // The outline of the total bar. QRect roundedRect(rect); roundedRect.adjust(1, 1, -1, -1); QPainterPath roundedPath; roundedPath.addRoundedRect(roundedRect, 2.0, 2.0); int xPosition = 0; // >0: grade, 0: initial, -1: untrained, -2: invalid for (int i = KV_MAX_GRADE; i >= -2; --i) { qreal fraction; QColor color; // Get the fraction and the color if (i > 0) { // long term fraction = qreal(wordCount.grades[i]) / qreal(wordCount.totalWords); color = colors.longTermColors[i]; } else if (i == 0) { // initial term fraction = qreal(wordCount.initialWords) / qreal(wordCount.totalWords); color = colors.initialTermColor; } else if (i == -1) { // untrained (stored in longterm[0]) fraction = qreal(wordCount.grades[0]) / qreal(wordCount.totalWords); color = colors.longTermColors[0]; } else { fraction = qreal(wordCount.invalid) / qreal(wordCount.totalWords); color = colors.invalidColor; } // Create a rect from the current fraction and // adjust the rect to the outer limits. int barElementWidth = fraction * rect.width(); //int barElementWidth = fraction * roundedRect.width(); <-- Use this instead? QRectF barElement(rect.x() + xPosition, rect.y(), barElementWidth, rect.height()); QPainterPath barElementPath; barElementPath.addRect(barElement); // Intersect the QPainterPath of inner rectangle with outer, // so that the inner rectangle takes the shape of the outer rounded rectangle. QPainterPath barElementIntersectedPath = roundedPath.intersected(barElementPath); xPosition += barElementWidth; // Paint! painter.setBrush(QBrush(color)); painter.drawPath(barElementIntersectedPath); } } diff --git a/src/utils.h b/src/utils.h index 49d8d232..4e839b3d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,71 +1,82 @@ /*************************************************************************** Copyright 2015 Inge Wallin ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef UTILS_H #define UTILS_H // Qt #include // KEduVocDocument library #include +#include class QPainter; class QRect; +class KEduVocTranslation; // The WordCount struct contains the number of words in each category. // This could be used for number of words due, total number of words, etc. struct WordCount { WordCount(); void clear(); int percentageCompleted() const; // Fill the WordCount data from the container. void fillFromContainer(KEduVocContainer &container, int translationIndex, KEduVocContainer::EnumEntriesRecursive recursive = KEduVocContainer::Recursive); + // Fill the WordCount data from the container for the selected practice mode. + void fillFromContainerForPracticeMode(KEduVocContainer &container, int translationIndex, + const QStringList &activeConjugationTenses, + KEduVocContainer::EnumEntriesRecursive recursive = KEduVocContainer::Recursive); + int grades[KV_MAX_GRADE + 1]; // Number of entries in each grade including grade=0, pregrade=0 int pregrades[KV_MAX_GRADE + 1]; // Number of entries in each grade including grade=0, pregrade=0 int invalid; // Number of invalid entries (not always applicable); int initialWords; // Number of entries in initial phase (grade=0, pregrade>0) // This is the sum of the numbers in pregrades[]. int totalWords; // Total number of words // This is the sum of grades[], pregrades[] and invalid + +private: + bool isValidForProcessing(KEduVocTranslation &trans, KEduVocWordFlags wordType) const; + void evaluateWord(const KEduVocText &item, const QString &text); }; struct ConfidenceColors { enum ColorScheme { MultiColorScheme, //< The color scheme from the dashboard ProgressiveColorScheme //< The color scheme from the practice component }; ConfidenceColors(ColorScheme colorScheme = MultiColorScheme); void initColors(ColorScheme colorScheme); QColor longTermColors[KV_MAX_GRADE + 1]; QColor initialTermColor; QColor invalidColor; QColor frontEndColors[2]; // Placeholders for the wordcloud background colors }; void paintColorBar(QPainter &painter, const QRect &rect, const WordCount &wordCount, const ConfidenceColors &colors); #endif // UTILS_H