File indexing completed on 2024-05-12 16:45:36
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 <QApplication> 0032 #include <QVBoxLayout> 0033 #include <QChartView> 0034 #include <QLineSeries> 0035 #include <QDateTimeAxis> 0036 #include <QValueAxis> 0037 0038 using namespace QtCharts; 0039 using Tellico::CollectionSizeReport; 0040 0041 CollectionSizeReport::CollectionSizeReport() : ChartReport() { 0042 } 0043 0044 QString CollectionSizeReport::title() const { 0045 return i18n("Collection Size"); 0046 } 0047 0048 QWidget* CollectionSizeReport::createWidget() { 0049 // create a new widget every time 0050 Data::CollPtr coll = Data::Document::self()->collection(); 0051 Q_ASSERT(coll); 0052 0053 const QString cdate = QStringLiteral("cdate"); 0054 if(!coll->hasField(cdate)) { 0055 myDebug() << "No cdate field in collection"; 0056 return nullptr; 0057 } 0058 0059 int emptyCount = 0; 0060 QMap<QString, int> entryDateCounts; 0061 foreach(Data::EntryPtr entry, coll->entries()) { 0062 auto date = entry->field(cdate); 0063 if(date.isEmpty()) { 0064 emptyCount++; 0065 } else { 0066 entryDateCounts[date]++; 0067 } 0068 } 0069 0070 auto series = new QLineSeries; 0071 const QStringList dates = entryDateCounts.keys(); // already sorted 0072 int totalCount = emptyCount; // assume empty values predate earliest date 0073 foreach(const QString& date, dates) { 0074 QDateTime momentInTime; 0075 momentInTime.setDate(QDate::fromString(date, Qt::ISODate)); 0076 if(momentInTime.isValid()) { 0077 auto msecs = momentInTime.toMSecsSinceEpoch(); 0078 // for a step chart, add a point just before this one with the previous total 0079 series->append(msecs-1, totalCount); 0080 totalCount += entryDateCounts.value(date); 0081 series->append(msecs, totalCount); 0082 } 0083 } 0084 // add current date 0085 QDateTime now = QDateTime::currentDateTimeUtc(); 0086 series->append(now.toMSecsSinceEpoch(), coll->entryCount()); 0087 series->setName(i18n("Total entries: %1", coll->entryCount())); 0088 0089 auto chart = new QChart; 0090 chart->addSeries(series); 0091 chart->setTitle(i18n("Collection Size Over Time")); 0092 chart->setTheme(qApp->palette().color(QPalette::Window).lightnessF() < 0.25 ? QChart::ChartThemeDark 0093 : QChart::ChartThemeLight); 0094 QFont f = chart->titleFont(); 0095 int fontSize = f.pointSize(); 0096 if(fontSize > 0) { 0097 f.setPointSize(qRound(fontSize * 1.3)); 0098 } else { 0099 f.setPixelSize(qRound(f.pixelSize() * 1.3)); 0100 } 0101 f.setWeight(QFont::Bold); 0102 chart->setTitleFont(f); 0103 0104 QPen pen = series->pen(); 0105 pen.setWidth(3); 0106 series->setPen(pen); 0107 0108 auto axisX = new QDateTimeAxis; 0109 axisX->setTickCount(10); 0110 axisX->setFormat(QStringLiteral("MMM yyyy")); 0111 chart->addAxis(axisX, Qt::AlignBottom); 0112 series->attachAxis(axisX); 0113 0114 auto axisY = new QValueAxis; 0115 axisY->setLabelFormat(QStringLiteral("%d")); 0116 axisY->setTitleText(i18n("Collection Size")); 0117 chart->addAxis(axisY, Qt::AlignLeft); 0118 series->attachAxis(axisY); 0119 if(axisY->max() < 5) axisY->setMax(5); 0120 axisY->applyNiceNumbers(); 0121 0122 auto widget = new QWidget; 0123 auto layout = new QVBoxLayout(widget); 0124 layout->setMargin(0); 0125 layout->setSpacing(0); 0126 auto chartView = new QChartView(chart, widget); 0127 chartView->setRenderHint(QPainter::Antialiasing); 0128 // avoid a transparent frame around the chart 0129 chartView->setBackgroundBrush(chart->backgroundBrush()); 0130 layout->addWidget(chartView); 0131 widget->setLayout(layout); 0132 return widget; 0133 }