1 /*
2     SPDX-FileCopyrightText: 2008-2010 Frederik Gladhorn <gladhorn@kde.org>
3     SPDX-FileCopyrightText: 2008 Daniel Laidig <d.laidig@gmx.de>
4     SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "statisticsmainwindow.h"
8 
9 #include <QHeaderView>
10 
11 #include <KActionCollection>
12 #include <KConfig>
13 #include <KLocalizedString>
14 
15 #include <KEduVocDocument>
16 
17 #include "lessonstatisticsview.h"
18 #include "parleyactions.h"
19 #include "parleymainwindow.h"
20 #include "practice/configure/configurepracticedialog.h"
21 #include "statisticsmodel.h"
22 
23 #include "prefs.h"
24 
25 #include "conjugationoptions.h"
26 #include "ui_statisticsmainwindow.h"
27 
StatisticsMainWindow(const std::shared_ptr<KEduVocDocument> & doc,ParleyMainWindow * parent)28 StatisticsMainWindow::StatisticsMainWindow(const std::shared_ptr<KEduVocDocument> &doc, ParleyMainWindow *parent)
29     : KXmlGuiWindow(parent)
30     , m_mainWindow(parent)
31     , m_doc(doc)
32     , m_ui(new Ui::StatisticsMainWindow)
33 {
34     // KXmlGui
35     setXMLFile(QStringLiteral("statisticsui.rc"));
36     setObjectName(QStringLiteral("Statistics"));
37 
38     QWidget *mainWidget = new QWidget(this);
39     setCentralWidget(mainWidget);
40     m_ui->setupUi(mainWidget);
41     // m_ui->caption->setText(i18nc("caption for an overview of the confidence levels for a document"
42     //                             "Statistics for \"%1\"", m_doc->title()));
43     m_statisticsModel = new StatisticsModel(this);
44 
45     setDocument(doc);
46     initActions();
47     initPracticeModeSelection();
48     initLanguages();
49     initPracticeMode();
50 
51     KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName());
52     applyMainWindowSettings(cfg);
53 }
54 
~StatisticsMainWindow()55 StatisticsMainWindow::~StatisticsMainWindow()
56 {
57     if (m_conjugationOptions) {
58         m_conjugationOptions->updateSettings();
59     }
60     KConfigGroup cfg(KSharedConfig::openConfig(QStringLiteral("parleyrc")), objectName());
61     saveMainWindowSettings(cfg);
62     delete m_ui;
63 }
64 
syncConfig()65 void StatisticsMainWindow::syncConfig()
66 {
67     // qDebug() << "save tenses";
68     if (m_conjugationOptions) {
69         m_conjugationOptions->updateSettings();
70     }
71 }
72 
setDocument(const std::shared_ptr<KEduVocDocument> & doc)73 void StatisticsMainWindow::setDocument(const std::shared_ptr<KEduVocDocument> &doc)
74 {
75     m_doc = doc;
76     m_statisticsModel->setDocument(doc);
77     m_ui->lessonStatistics->setModel(m_statisticsModel);
78     m_ui->lessonStatistics->restoreExpandedStatus();
79     m_ui->lessonStatistics->resizeColumnToContents(0);
80 }
81 
initActions()82 void StatisticsMainWindow::initActions()
83 {
84     ParleyActions::create(ParleyActions::EnterEditMode, m_mainWindow, SLOT(showEditor()), actionCollection());
85     ParleyActions::create(ParleyActions::StartPractice, m_mainWindow, SLOT(startPractice()), actionCollection());
86     ParleyActions::create(ParleyActions::ConfigurePractice, m_mainWindow, SLOT(configurePractice()), actionCollection());
87 }
88 
initPracticeModeSelection()89 void StatisticsMainWindow::initPracticeModeSelection()
90 {
91     switch (Prefs::practiceMode()) {
92     case Prefs::EnumPracticeMode::FlashCardsPractice:
93         m_ui->flashCard->setChecked(true);
94         break;
95     case Prefs::EnumPracticeMode::MixedLettersPractice:
96         m_ui->mixedLetters->setChecked(true);
97         break;
98     case Prefs::EnumPracticeMode::MultipleChoicePractice:
99         m_ui->multipleChoice->setChecked(true);
100         break;
101     case Prefs::EnumPracticeMode::WrittenPractice:
102         m_ui->written->setChecked(true);
103         break;
104     case Prefs::EnumPracticeMode::ExampleSentencesPractice:
105         m_ui->exampleSentence->setChecked(true);
106         break;
107     case Prefs::EnumPracticeMode::GenderPractice:
108         m_ui->gender->setChecked(true);
109         break;
110     case Prefs::EnumPracticeMode::ComparisonPractice:
111         m_ui->comparisonForms->setChecked(true);
112         break;
113     case Prefs::EnumPracticeMode::ConjugationPractice:
114         m_ui->conjugations->setChecked(true);
115         showConjugationOptions();
116         break;
117     default:
118         break;
119     }
120     connect(m_ui->flashCard, &QRadioButton::clicked, this, [=] {
121         practiceModeSelected(Prefs::EnumPracticeMode::FlashCardsPractice);
122     });
123     connect(m_ui->mixedLetters, &QRadioButton::clicked, this, [=] {
124         practiceModeSelected(Prefs::EnumPracticeMode::MixedLettersPractice);
125     });
126     connect(m_ui->multipleChoice, &QRadioButton::clicked, this, [=] {
127         practiceModeSelected(Prefs::EnumPracticeMode::MultipleChoicePractice);
128     });
129     connect(m_ui->written, &QRadioButton::clicked, this, [=] {
130         practiceModeSelected(Prefs::EnumPracticeMode::WrittenPractice);
131     });
132     connect(m_ui->exampleSentence, &QRadioButton::clicked, this, [=] {
133         practiceModeSelected(Prefs::EnumPracticeMode::ExampleSentencesPractice);
134     });
135     connect(m_ui->gender, &QRadioButton::clicked, this, [=] {
136         practiceModeSelected(Prefs::EnumPracticeMode::GenderPractice);
137     });
138     connect(m_ui->comparisonForms, &QRadioButton::clicked, this, [=] {
139         practiceModeSelected(Prefs::EnumPracticeMode::ComparisonPractice);
140     });
141     connect(m_ui->conjugations, &QRadioButton::clicked, this, [=] {
142         practiceModeSelected(Prefs::EnumPracticeMode::ConjugationPractice);
143     });
144 }
145 
initLanguages()146 void StatisticsMainWindow::initLanguages()
147 {
148     // qDebug() << "init languages: " << Prefs::learningLanguage() << Prefs::knownLanguage();
149     const int totalNumLanguages = m_doc->identifierCount();
150 
151     if (Prefs::knownLanguage() < 0 || totalNumLanguages <= Prefs::knownLanguage()) {
152         Prefs::setKnownLanguage(0);
153     }
154     if (Prefs::learningLanguage() < 0 || totalNumLanguages <= Prefs::learningLanguage()) {
155         Prefs::setLearningLanguage(0);
156     }
157 
158     if (Prefs::knownLanguage() >= totalNumLanguages || Prefs::learningLanguage() >= totalNumLanguages || Prefs::learningLanguage() == Prefs::knownLanguage()) {
159         Prefs::setKnownLanguage(0);
160         Prefs::setLearningLanguage(1);
161         // qDebug() << "Invalid language selection.";
162     }
163 
164     // Insert data into the comboboxes.
165     for (int i = 0; i < totalNumLanguages; ++i) {
166         m_ui->learnedLanguage->insertItem(i, m_doc->identifier(i).name());
167         m_ui->knownLanguage->insertItem(i, m_doc->identifier(i).name());
168     }
169     m_ui->learnedLanguage->setCurrentIndex(Prefs::learningLanguage());
170     m_ui->knownLanguage->setCurrentIndex(Prefs::knownLanguage());
171 
172     connect(m_ui->learnedLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged()));
173     connect(m_ui->knownLanguage, SIGNAL(currentIndexChanged(int)), SLOT(languagesChanged()));
174 
175     languagesChanged();
176 }
177 
languagesChanged()178 void StatisticsMainWindow::languagesChanged()
179 {
180     int knownLanguage = m_ui->knownLanguage->currentIndex();
181     int learningLanguage = m_ui->learnedLanguage->currentIndex();
182     Prefs::setLearningLanguage(learningLanguage);
183     Prefs::setKnownLanguage(knownLanguage);
184 
185     emit languagesChanged(knownLanguage, learningLanguage);
186 
187     updateVisibleColumns();
188     updateModelSettings();
189 }
190 
initPracticeMode()191 void StatisticsMainWindow::initPracticeMode()
192 {
193     m_ui->practiceDirection->insertItem(0, i18n("Known to Learning"));
194     m_ui->practiceDirection->insertItem(1, i18n("Learning to Known"));
195     m_ui->practiceDirection->insertItem(2, i18n("Mixed Directions"));
196     // m_ui->practiceDirection->insertItem(3, i18n("Mixed Directions with Sound"));
197 
198     int practiceDirection(Prefs::rememberPracticeDirection() ? practiceDirectionForPracticeMode(Prefs::practiceMode()) : Prefs::practiceDirection());
199 
200     if (practiceDirection < 0 || 3 < practiceDirection)
201         Prefs::setPracticeDirection(Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly);
202 
203     m_ui->practiceDirection->setCurrentIndex(practiceDirection);
204     connect(m_ui->practiceDirection,
205             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
206             this,
207             &StatisticsMainWindow::practiceDirectionChanged);
208 
209     m_ui->rememberPracticeDirection->setChecked(Prefs::rememberPracticeDirection());
210     connect(m_ui->rememberPracticeDirection, &QCheckBox::toggled, this, &StatisticsMainWindow::rememberPracticeDirectionChanged);
211 }
212 
practiceModeSelected(int mode)213 void StatisticsMainWindow::practiceModeSelected(int mode)
214 {
215     int previousPracticeMode = Prefs::practiceMode();
216     Prefs::setPracticeMode(static_cast<Prefs::EnumPracticeMode::type>(mode));
217     // qDebug() << "mode: " << mode << Prefs::practiceMode();
218 
219     showConjugationOptions(mode == Prefs::EnumPracticeMode::ConjugationPractice);
220 
221     if (Prefs::rememberPracticeDirection()) {
222         setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), previousPracticeMode);
223         m_ui->practiceDirection->setCurrentIndex(practiceDirectionForPracticeMode(mode));
224     }
225 
226     updateModelSettings();
227 }
228 
practiceDirectionChanged(int mode)229 void StatisticsMainWindow::practiceDirectionChanged(int mode)
230 {
231     // qDebug() << "new practice direction:" << mode;
232     Prefs::setPracticeDirection(static_cast<Prefs::EnumPracticeDirection::type>(mode));
233     if (Prefs::rememberPracticeDirection()) {
234         setPracticeDirectionForPracticeMode(mode, Prefs::practiceMode());
235     }
236     updateVisibleColumns();
237     updateModelSettings();
238 }
239 
rememberPracticeDirectionChanged(bool checked)240 void StatisticsMainWindow::rememberPracticeDirectionChanged(bool checked)
241 {
242     //     qDebug() << "remember practice direction changed to: " << checked;
243     Prefs::setRememberPracticeDirection(checked);
244     if (checked) {
245         setPracticeDirectionForPracticeMode(Prefs::practiceDirection(), Prefs::practiceMode());
246     }
247 }
248 
updateVisibleColumns()249 void StatisticsMainWindow::updateVisibleColumns()
250 {
251     bool isHidden;
252     for (int i = ContainerModel::FirstDataColumn; i < m_ui->lessonStatistics->header()->count(); i++) {
253         int iLang = i - ContainerModel::FirstDataColumn;
254 
255         switch (Prefs::practiceDirection()) {
256         case Prefs::EnumPracticeDirection::LearningToKnown:
257             isHidden = iLang != Prefs::knownLanguage();
258             break;
259         case Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly:
260         case Prefs::EnumPracticeDirection::MixedDirectionsWithSound:
261             isHidden = iLang != Prefs::knownLanguage() && iLang != Prefs::learningLanguage();
262             break;
263         case Prefs::EnumPracticeDirection::KnownToLearning:
264         // Use KnownToLearning as default.
265         default:
266             isHidden = iLang != Prefs::learningLanguage();
267             break;
268         }
269 
270         m_ui->lessonStatistics->setColumnHidden(i, isHidden);
271         m_ui->lessonStatistics->adjustColumnWidths();
272     }
273 }
274 
showConjugationOptions(bool visible)275 void StatisticsMainWindow::showConjugationOptions(bool visible)
276 {
277     if (!m_conjugationOptions && !visible) {
278         return;
279     }
280 
281     if (!m_conjugationOptions) {
282         m_conjugationOptions = new ConjugationOptions(m_doc.get(), m_ui->modeSpecificOptions);
283         QHBoxLayout *layout = new QHBoxLayout(m_ui->modeSpecificOptions);
284         layout->setContentsMargins(0, 0, 0, 0);
285         layout->addWidget(m_conjugationOptions);
286         connect(this, QOverload<int, int>::of(&StatisticsMainWindow::languagesChanged), m_conjugationOptions, &ConjugationOptions::setLanguages);
287         m_conjugationOptions->setLanguages(Prefs::knownLanguage(), Prefs::learningLanguage());
288         connect(m_conjugationOptions, &ConjugationOptions::checkBoxChanged, this, &StatisticsMainWindow::updateModelSettings);
289     }
290     m_conjugationOptions->setVisible(visible);
291 }
292 
configurePractice()293 void StatisticsMainWindow::configurePractice()
294 {
295     ConfigurePracticeDialog dialog(m_doc.get(), this, QStringLiteral("practice settings"), Prefs::self());
296     dialog.exec();
297 }
298 
practiceDirectionForPracticeMode(int mode) const299 int StatisticsMainWindow::practiceDirectionForPracticeMode(int mode) const
300 {
301     int direction = Prefs::practiceDirectionsByPracticeMode().value(mode, Prefs::practiceDirection());
302     if ((direction < 0) || (direction > Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly)) {
303         direction = Prefs::EnumPracticeDirection::MixedDirectionsWordsOnly;
304     }
305     return direction;
306 }
307 
setPracticeDirectionForPracticeMode(int direction,int mode)308 void StatisticsMainWindow::setPracticeDirectionForPracticeMode(int direction, int mode)
309 {
310     QList<int> directions = Prefs::practiceDirectionsByPracticeMode();
311     // Expand list if fields not used before
312     for (int i = directions.size() - 1; i < mode; ++i) {
313         directions.append(Prefs::practiceDirection());
314     }
315     directions[mode] = direction;
316     Prefs::setPracticeDirectionsByPracticeMode(directions);
317 }
318 
updateModelSettings()319 void StatisticsMainWindow::updateModelSettings()
320 {
321     m_ui->lessonStatistics->saveExpandedStatus();
322     m_statisticsModel->updateDocumentSettings();
323     m_ui->lessonStatistics->restoreExpandedStatus();
324 }
325