File indexing completed on 2024-04-14 03:49:06

0001 /*
0002     SPDX-FileCopyrightText: 2008 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "lessonview.h"
0007 
0008 #include "vocabularymodel.h"
0009 #include "vocabularyview.h"
0010 
0011 #include <KActionCollection>
0012 #include <KLocalizedString>
0013 #include <KMessageBox>
0014 #include <QAction>
0015 #include <QInputDialog>
0016 
0017 #include <KEduVocExpression>
0018 #include <KEduVocLesson>
0019 #include <kmessagebox.h>
0020 
0021 #include "editor/editor.h"
0022 #include "prefs.h"
0023 
0024 using namespace Editor;
0025 
0026 LessonView::LessonView(EditorWindow *parent)
0027     : ContainerView(parent)
0028     , m_editorWindow(parent)
0029 {
0030     QAction *actionNewLesson = new QAction(this);
0031     parent->actionCollection()->addAction(QStringLiteral("new_lesson"), actionNewLesson);
0032     actionNewLesson->setText(i18n("New Unit"));
0033     actionNewLesson->setIcon(QIcon::fromTheme(QStringLiteral("lesson-add")));
0034     actionNewLesson->setWhatsThis(i18n("Add a new unit to your document"));
0035     actionNewLesson->setToolTip(actionNewLesson->whatsThis());
0036     actionNewLesson->setStatusTip(actionNewLesson->whatsThis());
0037 
0038     QAction *actionRenameLesson = new QAction(this);
0039     parent->actionCollection()->addAction(QStringLiteral("rename_lesson"), actionRenameLesson);
0040     actionRenameLesson->setText(i18n("Rename Unit"));
0041     actionRenameLesson->setIcon(QIcon::fromTheme(QStringLiteral("edit-rename")));
0042     //    actionRenameLesson->setWhatsThis(i18n("Rename the selected unit"));
0043     actionRenameLesson->setToolTip(actionRenameLesson->whatsThis());
0044     actionRenameLesson->setStatusTip(actionRenameLesson->whatsThis());
0045 
0046     QAction *actionDeleteLesson = new QAction(this);
0047     parent->actionCollection()->addAction(QStringLiteral("delete_lesson"), actionDeleteLesson);
0048     actionDeleteLesson->setText(i18n("Delete Unit"));
0049     actionDeleteLesson->setIcon(QIcon::fromTheme(QStringLiteral("lesson-remove")));
0050     actionDeleteLesson->setWhatsThis(i18n("Delete the selected unit."));
0051     actionDeleteLesson->setToolTip(actionDeleteLesson->whatsThis());
0052     actionDeleteLesson->setStatusTip(actionDeleteLesson->whatsThis());
0053 
0054     QAction *actionSplitLesson = new QAction(this);
0055     parent->actionCollection()->addAction(QStringLiteral("split_lesson"), actionSplitLesson);
0056     actionSplitLesson->setText(i18n("Split Unit into Smaller Units"));
0057     actionSplitLesson->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); /// @todo better icon
0058     actionSplitLesson->setWhatsThis(i18n("Make multiple smaller units out of one big unit."));
0059     actionSplitLesson->setToolTip(actionSplitLesson->whatsThis());
0060     actionSplitLesson->setStatusTip(actionSplitLesson->whatsThis());
0061 
0062     QAction *actionMoveToNewLesson = new QAction(this);
0063     parent->actionCollection()->addAction(QStringLiteral("move_to_new_lesson"), actionMoveToNewLesson);
0064     actionMoveToNewLesson->setText(i18n("Move to new lesson"));
0065     actionMoveToNewLesson->setIcon(QIcon::fromTheme(QStringLiteral("edit-move")));
0066     actionMoveToNewLesson->setWhatsThis(i18n("Moves the selected vocabulary to a new lesson"));
0067     actionMoveToNewLesson->setToolTip(actionMoveToNewLesson->whatsThis());
0068     actionMoveToNewLesson->setStatusTip(actionMoveToNewLesson->whatsThis());
0069 
0070     QAction *actionRemoveGradesLesson = new QAction(this);
0071     parent->actionCollection()->addAction(QStringLiteral("remove_grades_lesson"), actionRemoveGradesLesson);
0072     actionRemoveGradesLesson->setText(i18n("Remove Confidence Levels"));
0073     actionRemoveGradesLesson->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear"))); /// @todo better icon
0074     actionRemoveGradesLesson->setWhatsThis(i18n("Remove confidence levels from this unit."));
0075     actionRemoveGradesLesson->setToolTip(actionRemoveGradesLesson->whatsThis());
0076     actionRemoveGradesLesson->setStatusTip(actionRemoveGradesLesson->whatsThis());
0077 
0078     QAction *actionRemoveGradesLessonChildren = new QAction(this);
0079     parent->actionCollection()->addAction(QStringLiteral("remove_grades_lesson_children"), actionRemoveGradesLessonChildren);
0080     actionRemoveGradesLessonChildren->setText(i18n("Remove Confidence Levels From This Unit And All Subunits"));
0081     actionRemoveGradesLessonChildren->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
0082     actionRemoveGradesLessonChildren->setWhatsThis(i18n("Remove confidence levels from this unit and all subunits."));
0083     actionRemoveGradesLessonChildren->setToolTip(actionRemoveGradesLessonChildren->whatsThis());
0084     actionRemoveGradesLessonChildren->setStatusTip(actionRemoveGradesLessonChildren->whatsThis());
0085 
0086     QAction *actionExpandAll = new QAction(this);
0087     parent->actionCollection()->addAction(QStringLiteral("expand_all_lesson_children"), actionExpandAll);
0088     actionExpandAll->setText(i18n("Expand Units and Subunits"));
0089     actionExpandAll->setIcon(QIcon::fromTheme(QStringLiteral("go-down-search")));
0090     actionExpandAll->setWhatsThis(i18n("Expand all units and subunits."));
0091     actionExpandAll->setToolTip(actionExpandAll->whatsThis());
0092     actionExpandAll->setStatusTip(actionExpandAll->whatsThis());
0093 
0094     QAction *actionCollapseAll = new QAction(this);
0095     parent->actionCollection()->addAction(QStringLiteral("collapse_all_lesson_children"), actionCollapseAll);
0096     actionCollapseAll->setText(i18n("Collapse All Units And Subunits"));
0097     actionCollapseAll->setIcon(QIcon::fromTheme(QStringLiteral("go-up-search")));
0098     actionCollapseAll->setWhatsThis(i18n("Collapse all units and subunits."));
0099     actionCollapseAll->setToolTip(actionCollapseAll->whatsThis());
0100     actionCollapseAll->setStatusTip(actionCollapseAll->whatsThis());
0101 
0102     connect(actionNewLesson, &QAction::triggered, this, &LessonView::slotCreateNewLesson);
0103     connect(actionRenameLesson, &QAction::triggered, this, &LessonView::slotRename);
0104     connect(actionDeleteLesson, &QAction::triggered, this, &LessonView::slotDeleteLesson);
0105     connect(actionSplitLesson, &QAction::triggered, this, &LessonView::slotSplitLesson);
0106     connect(actionMoveToNewLesson, &QAction::triggered, this, &LessonView::moveToNewLesson);
0107     connect(actionRemoveGradesLesson, &QAction::triggered, this, &LessonView::slotRemoveGradesLesson);
0108     connect(actionRemoveGradesLessonChildren, &QAction::triggered, this, &LessonView::slotRemoveGradesLessonChildren);
0109     connect(actionExpandAll, &QAction::triggered, this, &LessonView::expandAllLesson);
0110     connect(actionCollapseAll, &QAction::triggered, this, &LessonView::collapseAllLesson);
0111 
0112     // right click menu for the lesson view:
0113     addAction(actionNewLesson);
0114     addAction(actionRenameLesson);
0115     addAction(actionDeleteLesson);
0116     QAction *separator = new QAction(this);
0117     separator->setSeparator(true);
0118     addAction(separator);
0119     addAction(actionRemoveGradesLesson);
0120     addAction(actionRemoveGradesLessonChildren);
0121     separator = new QAction(this);
0122     separator->setSeparator(true);
0123     addAction(separator);
0124     addAction(actionSplitLesson);
0125     addAction(actionExpandAll);
0126     addAction(actionCollapseAll);
0127 }
0128 
0129 void LessonView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
0130 {
0131     QTreeView::currentChanged(current, previous);
0132 
0133     if (current.isValid()) {
0134         KEduVocLesson *container = static_cast<KEduVocLesson *>(current.internalPointer());
0135         if (container) {
0136             Q_EMIT selectedLessonChanged(container);
0137             Q_EMIT signalShowContainer(container);
0138         }
0139     }
0140 }
0141 
0142 void LessonView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
0143 {
0144     QTreeView::selectionChanged(selected, deselected);
0145 
0146     if (selected.count() == 0) {
0147         return;
0148     }
0149 
0150     KEduVocLesson *container = static_cast<KEduVocLesson *>(selected.indexes().value(0).internalPointer());
0151     if (container) {
0152         Q_EMIT selectedLessonChanged(container);
0153     }
0154 }
0155 
0156 void LessonView::setTranslation(KEduVocExpression *entry, int translation)
0157 {
0158     Q_UNUSED(translation)
0159 
0160     if (entry == nullptr) {
0161         selectionModel()->clearSelection();
0162         return;
0163     }
0164 
0165     QModelIndex index(m_model->index(entry->lesson()));
0166     selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
0167     scrollTo(index);
0168 }
0169 
0170 void LessonView::slotCreateNewLesson()
0171 {
0172     QModelIndex selectedIndex = selectionModel()->currentIndex();
0173 
0174     if (!selectedIndex.isValid()) {
0175         selectedIndex = m_model->index(0, 0, QModelIndex());
0176     }
0177 
0178     QModelIndex modelIndex = m_model->appendContainer(selectedIndex);
0179 
0180     scrollTo(modelIndex);
0181     selectionModel()->setCurrentIndex(modelIndex, QItemSelectionModel::ClearAndSelect);
0182     edit(modelIndex); // let the user type a new name for the lesson
0183 }
0184 
0185 void LessonView::slotDeleteLesson()
0186 {
0187     QModelIndex selectedIndex = selectionModel()->currentIndex();
0188 
0189     if (selectedIndex.parent() == QModelIndex()) {
0190         KMessageBox::information(this, i18n("The root lesson cannot be deleted."));
0191         return;
0192     }
0193 
0194     KEduVocLesson *lesson = static_cast<KEduVocLesson *>(selectedIndex.internalPointer());
0195 
0196     int count = lesson->entryCount(KEduVocLesson::Recursive);
0197 
0198     if (count == 0
0199         || KMessageBox::warningTwoActions(this,
0200                                           i18np("There is %1 word left in this unit. Do you want to delete it?",
0201                                                 "There are %1 words left in this unit. Do you want to delete them?",
0202                                                 count),
0203                                           QString(),
0204                                           KStandardGuiItem::del(),
0205                                           KStandardGuiItem::cancel())
0206             == KMessageBox::PrimaryAction) {
0207         m_model->deleteContainer(selectedIndex);
0208     }
0209 }
0210 
0211 void LessonView::slotSplitLesson()
0212 {
0213     if (!selectionModel()->currentIndex().isValid()) {
0214         return;
0215     }
0216 
0217     /** @todo A nicer dialog would be great.
0218      * Maybe with radio buttons to ask, if the entries should be in random order or as they come. */
0219     bool ok = false;
0220     int numEntries = QInputDialog::getInt(this,
0221                                           i18n("Entries per Unit"),
0222                                           i18n("The unit will be split into smaller unit. How many entries in each unit do you want?"),
0223                                           Prefs::entriesPerLesson(),
0224                                           1,
0225                                           1000,
0226                                           1,
0227                                           &ok);
0228 
0229     if (!ok) {
0230         return;
0231     }
0232     Prefs::setEntriesPerLesson(numEntries);
0233     m_model->splitLesson(selectionModel()->currentIndex(), numEntries, LessonModel::Random);
0234     setExpanded(selectionModel()->currentIndex(), true);
0235 }
0236 
0237 void LessonView::moveToNewLesson()
0238 {
0239     const QModelIndexList indexes = m_editorWindow->vocabularyView()->getSelectedIndexes();
0240     if (indexes.isEmpty()) {
0241         return;
0242     }
0243 
0244     KEduVocDocument *doc = m_model->document();
0245     KEduVocLesson *lesson = new KEduVocLesson(i18n("New Lesson"), doc->lesson());
0246     doc->lesson()->appendChildContainer(lesson);
0247 
0248     for (const QModelIndex &index : indexes) {
0249         lesson->appendEntry(qvariant_cast<KEduVocExpression *>(index.data(VocabularyModel::EntryRole)));
0250     }
0251 }
0252 
0253 void LessonView::slotRemoveGradesLesson()
0254 {
0255     QModelIndex selectedIndex = selectionModel()->currentIndex();
0256     KEduVocLesson *lesson = static_cast<KEduVocLesson *>(selectedIndex.internalPointer());
0257     lesson->resetGrades(-1, KEduVocContainer::NotRecursive);
0258     Q_EMIT signalShowContainer(lesson);
0259 }
0260 
0261 void LessonView::slotRemoveGradesLessonChildren()
0262 {
0263     QModelIndex selectedIndex = selectionModel()->currentIndex();
0264     KEduVocLesson *lesson = static_cast<KEduVocLesson *>(selectedIndex.internalPointer());
0265     lesson->resetGrades(-1, KEduVocContainer::Recursive);
0266     Q_EMIT signalShowContainer(lesson);
0267 }
0268 
0269 void LessonView::setModel(LessonModel *model)
0270 {
0271     m_model = model;
0272     ContainerView::setModel(model);
0273     connect(model, &QAbstractItemModel::columnsInserted, this, &LessonView::columnsInserted);
0274     for (int i = 2; i < model->columnCount(QModelIndex()); i++) {
0275         setColumnHidden(i, true);
0276     }
0277 }
0278 
0279 void LessonView::columnsInserted()
0280 {
0281     for (int i = 2; i < m_model->columnCount(QModelIndex()); i++) {
0282         setColumnHidden(i, true);
0283     }
0284 }
0285 
0286 void LessonView::expandAllLesson()
0287 {
0288     expandAll();
0289 }
0290 
0291 void LessonView::collapseAllLesson()
0292 {
0293     collapseAll();
0294 }
0295 
0296 #include "moc_lessonview.cpp"