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

0001 /*
0002     SPDX-FileCopyrightText: 2008 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 // Own
0007 #include "lessonstatisticsview.h"
0008 
0009 // Qt
0010 #include <QApplication>
0011 #include <QHeaderView>
0012 #include <QItemDelegate>
0013 #include <QPainter>
0014 
0015 // KDE
0016 #include <KActionCollection>
0017 #include <KLocalizedString>
0018 #include <KMessageBox>
0019 #include <QAction>
0020 #include <QInputDialog>
0021 
0022 // Parley
0023 #include "documentsettings.h"
0024 #include "statisticslegendwidget.h"
0025 #include "statisticsmodel.h"
0026 #include "utils.h"
0027 #include <KEduVocLesson>
0028 
0029 // GradeDelegate shows the graphic colored bar in the statistics,
0030 // showing how far the student has come on the way to enlightenment.
0031 
0032 class GradeDelegate : public QItemDelegate
0033 {
0034 public:
0035     GradeDelegate(QObject *parent = nullptr)
0036         : QItemDelegate(parent)
0037     {
0038     }
0039 
0040     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
0041     {
0042         QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr);
0043 
0044         // empty lesson? If so, paint nothing.
0045         if (!index.data(StatisticsModel::TotalCount).toInt()) {
0046             return;
0047         }
0048 
0049         // Draw the colored bar.
0050         KEduVocContainer *container = index.data(StatisticsModel::Container).value<KEduVocContainer *>();
0051         QStringList activeConjugationTenses = index.data(StatisticsModel::ActiveConjugationTenses).toStringList();
0052         WordCount wordCount;
0053         wordCount.fillFromContainerForPracticeMode(*container, index.column() - ContainerModel::FirstDataColumn, activeConjugationTenses);
0054         ConfidenceColors colors(ConfidenceColors::ProgressiveColorScheme);
0055 
0056         paintColorBar(*painter, option.rect, wordCount, colors); // in utils
0057 
0058         // Draw the text telling the percentage on top of the bar.
0059         painter->drawText(option.rect, Qt::AlignCenter, QStringLiteral("%1%").arg(index.data(StatisticsModel::TotalPercent).toInt()));
0060     }
0061 };
0062 
0063 // ----------------------------------------------------------------
0064 
0065 LessonStatisticsView::LessonStatisticsView(QWidget *parent)
0066     : ContainerView(parent)
0067 {
0068     header()->setVisible(true);
0069     header()->setDefaultAlignment(Qt::AlignLeft | Qt::AlignBottom);
0070     header()->setSectionsMovable(true);
0071 
0072     // inherits context menu policy - so action will show up in right click menu
0073     QAction *removeGradesAction = new QAction(this);
0074     removeGradesAction->setText(i18n("Remove confidence levels from this unit"));
0075     removeGradesAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
0076     removeGradesAction->setWhatsThis(i18n("Remove confidence levels from this unit"));
0077     removeGradesAction->setToolTip(removeGradesAction->whatsThis());
0078     removeGradesAction->setStatusTip(removeGradesAction->whatsThis());
0079 
0080     connect(removeGradesAction, &QAction::triggered, this, &LessonStatisticsView::removeGrades);
0081     addAction(removeGradesAction);
0082 
0083     QAction *removeGradesChildrenAction = new QAction(this);
0084     removeGradesChildrenAction->setText(i18n("Remove confidence levels from this unit and all sub-units"));
0085     removeGradesChildrenAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear")));
0086     removeGradesChildrenAction->setWhatsThis(i18n("Remove confidence level from this unit and all sub-units"));
0087     removeGradesChildrenAction->setToolTip(removeGradesChildrenAction->whatsThis());
0088     removeGradesChildrenAction->setStatusTip(removeGradesChildrenAction->whatsThis());
0089 
0090     connect(removeGradesChildrenAction, &QAction::triggered, this, &LessonStatisticsView::removeGradesChildren);
0091     addAction(removeGradesChildrenAction);
0092 
0093     connect(header(), &QHeaderView::geometriesChanged, this, &LessonStatisticsView::adjustColumnWidths);
0094     connect(header(), &QHeaderView::sectionResized, this, &LessonStatisticsView::sectionResized);
0095 }
0096 
0097 LessonStatisticsView::~LessonStatisticsView()
0098 {
0099     saveExpandedStatus();
0100 }
0101 
0102 void LessonStatisticsView::setModel(ContainerModel *model)
0103 {
0104     ContainerView::setModel(model);
0105 
0106     GradeDelegate *delegate = new GradeDelegate(this);
0107     for (int i = ContainerModel::FirstDataColumn; i < model->columnCount(QModelIndex()); i++) {
0108         setItemDelegateForColumn(i, delegate);
0109     }
0110 
0111     adjustColumnWidths();
0112 }
0113 
0114 void LessonStatisticsView::resizeEvent(QResizeEvent *event)
0115 {
0116     adjustColumnWidths();
0117     ContainerView::resizeEvent(event);
0118 }
0119 
0120 void LessonStatisticsView::sectionResized(int index, int /*oldSize*/, int /*newSize*/)
0121 {
0122     if (index < ContainerModel::FirstDataColumn) {
0123         adjustColumnWidths();
0124     }
0125 }
0126 
0127 void LessonStatisticsView::adjustColumnWidths()
0128 {
0129     int firstWidth = columnWidth(0) + columnWidth(1);
0130     int totalWidth = viewport()->width() - firstWidth;
0131     int columnCount = model()->columnCount(QModelIndex());
0132     int visibleColumns = 0;
0133     for (int i = ContainerModel::FirstDataColumn; i < columnCount; ++i) {
0134         if (!isColumnHidden(i))
0135             visibleColumns++;
0136     }
0137     int columnWidth = visibleColumns > 0 ? totalWidth / visibleColumns : 150;
0138     for (int i = ContainerModel::FirstDataColumn; i < model()->columnCount(QModelIndex()); i++) {
0139         setColumnWidth(i, columnWidth);
0140     }
0141     //    header()->resizeSections(QHeaderView::ResizeToContents);
0142     header()->setSectionResizeMode(QHeaderView::Interactive);
0143     header()->setStretchLastSection(true);
0144 }
0145 
0146 void LessonStatisticsView::removeGrades()
0147 {
0148     QModelIndex selectedIndex = selectionModel()->currentIndex();
0149     KEduVocLesson *lesson = static_cast<KEduVocLesson *>(selectedIndex.internalPointer());
0150     lesson->resetGrades(-1, KEduVocContainer::NotRecursive);
0151 }
0152 
0153 void LessonStatisticsView::removeGradesChildren()
0154 {
0155     QModelIndex selectedIndex = selectionModel()->currentIndex();
0156     KEduVocLesson *lesson = static_cast<KEduVocLesson *>(selectedIndex.internalPointer());
0157     lesson->resetGrades(-1, KEduVocContainer::Recursive);
0158 }
0159 
0160 void LessonStatisticsView::saveExpandedStatus() const
0161 {
0162     auto statisticsModel = qobject_cast<StatisticsModel *>(model());
0163     Q_ASSERT(statisticsModel != nullptr);
0164 
0165     QStringList collapsedItems;
0166     getCollapsedItems(collapsedItems, statisticsModel->index(0, 0, QModelIndex()), QString());
0167 
0168     const KEduVocDocument *doc = statisticsModel->document().get();
0169     if (doc != nullptr) {
0170         DocumentSettings documentSettings(doc->url().url());
0171         documentSettings.setCollapsedStatisticsViewItems(collapsedItems);
0172         documentSettings.save();
0173     }
0174 }
0175 
0176 void LessonStatisticsView::getCollapsedItems(QStringList &collapsedItems, const QModelIndex &item, QString name) const
0177 {
0178     if (!item.isValid()) {
0179         return;
0180     }
0181 
0182     int rowCount = model()->rowCount(item);
0183     if (rowCount > 0) {
0184         // Item has children and therefore expandable
0185         name += item.data().toString();
0186         if (!isExpanded(item)) {
0187             collapsedItems << name;
0188         }
0189         for (int row = 0; row < rowCount; ++row) {
0190             getCollapsedItems(collapsedItems, model()->index(row, 0, item), name + '/');
0191         }
0192     }
0193 }
0194 
0195 void LessonStatisticsView::restoreExpandedStatus()
0196 {
0197     auto statisticsModel = qobject_cast<StatisticsModel *>(model());
0198     Q_ASSERT(statisticsModel != nullptr);
0199 
0200     const KEduVocDocument *doc = statisticsModel->document().get();
0201     if (doc != nullptr) {
0202         DocumentSettings documentSettings(doc->url().url());
0203         documentSettings.load();
0204         QStringList collapsedItems = documentSettings.collapsedStatisticsViewItems();
0205         setCollapsedItems(collapsedItems, statisticsModel->index(0, 0, QModelIndex()), QString());
0206     }
0207 }
0208 
0209 void LessonStatisticsView::setCollapsedItems(const QStringList &collapsedItems, const QModelIndex &item, QString name)
0210 {
0211     if (!item.isValid()) {
0212         return;
0213     }
0214 
0215     int rowCount = model()->rowCount(item);
0216     if (rowCount > 0) {
0217         // Item has children and therefore expandable
0218         name += item.data().toString();
0219         if (collapsedItems.contains(name)) {
0220             collapse(item);
0221         } else {
0222             expand(item);
0223         }
0224         for (int row = 0; row < rowCount; ++row) {
0225             setCollapsedItems(collapsedItems, model()->index(row, 0, item), name + '/');
0226         }
0227     }
0228 }
0229 
0230 #include "moc_lessonstatisticsview.cpp"