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"