File indexing completed on 2024-05-12 05:09:21
0001 /*************************************************************************** 0002 Copyright (C) 2021 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "collectionsizereport.h" 0026 #include "../document.h" 0027 #include "../tellico_debug.h" 0028 0029 #include <KLocalizedString> 0030 0031 #include <QDateTime> 0032 #include <QApplication> 0033 #include <QVBoxLayout> 0034 #include <QChartView> 0035 #include <QLineSeries> 0036 #include <QDateTimeAxis> 0037 #include <QValueAxis> 0038 0039 using namespace QtCharts; 0040 using Tellico::CollectionSizeReport; 0041 0042 CollectionSizeReport::CollectionSizeReport() : ChartReport() { 0043 } 0044 0045 QString CollectionSizeReport::title() const { 0046 return i18n("Collection Size"); 0047 } 0048 0049 QWidget* CollectionSizeReport::createWidget() { 0050 // create a new widget every time 0051 Data::CollPtr coll = Data::Document::self()->collection(); 0052 Q_ASSERT(coll); 0053 0054 const QString cdate = QStringLiteral("cdate"); 0055 if(!coll->hasField(cdate)) { 0056 myDebug() << "No cdate field in collection"; 0057 return nullptr; 0058 } 0059 0060 int emptyCount = 0; 0061 QMap<QString, int> entryDateCounts; 0062 foreach(Data::EntryPtr entry, coll->entries()) { 0063 auto date = entry->field(cdate); 0064 if(date.isEmpty()) { 0065 emptyCount++; 0066 } else { 0067 entryDateCounts[date]++; 0068 } 0069 } 0070 0071 auto series = new QLineSeries; 0072 const QStringList dates = entryDateCounts.keys(); // already sorted 0073 int totalCount = emptyCount; // assume empty values predate earliest date 0074 foreach(const QString& date, dates) { 0075 QDateTime momentInTime; 0076 momentInTime.setDate(QDate::fromString(date, Qt::ISODate)); 0077 if(momentInTime.isValid()) { 0078 auto msecs = momentInTime.toMSecsSinceEpoch(); 0079 // for a step chart, add a point just before this one with the previous total 0080 series->append(msecs-1, totalCount); 0081 totalCount += entryDateCounts.value(date); 0082 series->append(msecs, totalCount); 0083 } 0084 } 0085 // add current date 0086 QDateTime now = QDateTime::currentDateTimeUtc(); 0087 series->append(now.toMSecsSinceEpoch(), coll->entryCount()); 0088 series->setName(i18n("Total entries: %1", coll->entryCount())); 0089 0090 auto chart = new QChart; 0091 chart->addSeries(series); 0092 chart->setTitle(i18n("Collection Size Over Time")); 0093 chart->setTheme(qApp->palette().color(QPalette::Window).lightnessF() < 0.25 ? QChart::ChartThemeDark 0094 : QChart::ChartThemeLight); 0095 QFont f = chart->titleFont(); 0096 int fontSize = f.pointSize(); 0097 if(fontSize > 0) { 0098 f.setPointSize(qRound(fontSize * 1.3)); 0099 } else { 0100 f.setPixelSize(qRound(f.pixelSize() * 1.3)); 0101 } 0102 f.setWeight(QFont::Bold); 0103 chart->setTitleFont(f); 0104 0105 QPen pen = series->pen(); 0106 pen.setWidth(3); 0107 series->setPen(pen); 0108 0109 auto axisX = new QDateTimeAxis; 0110 axisX->setTickCount(10); 0111 axisX->setFormat(QStringLiteral("MMM yyyy")); 0112 chart->addAxis(axisX, Qt::AlignBottom); 0113 series->attachAxis(axisX); 0114 0115 auto axisY = new QValueAxis; 0116 axisY->setLabelFormat(QStringLiteral("%d")); 0117 axisY->setTitleText(i18n("Collection Size")); 0118 chart->addAxis(axisY, Qt::AlignLeft); 0119 series->attachAxis(axisY); 0120 if(axisY->max() < 5) axisY->setMax(5); 0121 axisY->applyNiceNumbers(); 0122 0123 auto widget = new QWidget; 0124 auto layout = new QVBoxLayout(widget); 0125 layout->setMargin(0); 0126 layout->setSpacing(0); 0127 auto chartView = new QChartView(chart, widget); 0128 chartView->setRenderHint(QPainter::Antialiasing); 0129 // avoid a transparent frame around the chart 0130 chartView->setBackgroundBrush(chart->backgroundBrush()); 0131 layout->addWidget(chartView); 0132 widget->setLayout(layout); 0133 return widget; 0134 }