File indexing completed on 2024-04-28 16:30:32
0001 /*************************************************************************** 0002 * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr 0003 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 ***************************************************************************/ 0006 /** @file 0007 * A report class for document 0008 * 0009 * @author Stephane MANKOWSKI 0010 */ 0011 #include "skgreport.h" 0012 0013 #include <grantlee/engine.h> 0014 #include <grantlee/metatype.h> 0015 #include <grantlee/qtlocalizer.h> 0016 #include <grantlee/templateloader.h> 0017 0018 #include <kaboutdata.h> 0019 #include <kcolorscheme.h> 0020 0021 #include <qdir.h> 0022 #include <qfile.h> 0023 #include <qfont.h> 0024 #include <qfontdatabase.h> 0025 #include <qstandardpaths.h> 0026 #include <qurl.h> 0027 #include "qregularexpression.h" 0028 #include <QRandomGenerator> 0029 0030 #include "skgdocument.h" 0031 #include "skgobjectbase.h" 0032 #include "skgtraces.h" 0033 0034 GRANTLEE_BEGIN_LOOKUP(SKGObjectBase) 0035 Q_UNUSED(object) 0036 Q_UNUSED(property) 0037 GRANTLEE_END_LOOKUP 0038 0039 SKGReport::SKGReport(SKGDocument* iDocument) 0040 : m_document(iDocument), m_previous(nullptr), m_pointSize(10) 0041 { 0042 SKGTRACEINFUNC(1) 0043 0044 // Grantlee initialization 0045 Grantlee::registerMetaType<SKGObjectBase>(); 0046 } 0047 0048 SKGReport::~SKGReport() 0049 { 0050 SKGTRACEINFUNC(1) 0051 if (m_previous != nullptr) { 0052 delete m_previous; 0053 m_previous = nullptr; 0054 } 0055 } 0056 0057 SKGDocument* SKGReport::getDocument() const 0058 { 0059 return m_document; 0060 } 0061 0062 void SKGReport::setPeriod(const QString& iPeriod) 0063 { 0064 if (iPeriod != m_cache[QStringLiteral("period")]) { 0065 cleanCache(false); 0066 if (m_previous != nullptr) { 0067 delete m_previous; 0068 m_previous = nullptr; 0069 } 0070 m_cache[QStringLiteral("period")] = iPeriod; 0071 emit changed(); 0072 } 0073 } 0074 0075 QString SKGReport::getPeriod() 0076 { 0077 QString month = m_cache.value(QStringLiteral("period")).toString(); 0078 if (month.isEmpty()) { 0079 month = QDate::currentDate().toString(QStringLiteral("yyyy-MM")); 0080 m_cache[QStringLiteral("period")] = month; 0081 } 0082 return month; 0083 } 0084 0085 void SKGReport::setSqlFilter(const QString& iFilter) 0086 { 0087 if (iFilter != m_cache[QStringLiteral("filter")]) { 0088 cleanCache(false); 0089 m_cache[QStringLiteral("filter")] = iFilter; 0090 emit changed(); 0091 } 0092 } 0093 0094 QString SKGReport::getSqlFilter() 0095 { 0096 return m_cache.value(QStringLiteral("filter")).toString();; 0097 } 0098 0099 QString SKGReport::getPreviousPeriod() 0100 { 0101 QString previousmonth = m_cache.value(QStringLiteral("previousperiod")).toString(); 0102 if (previousmonth.isEmpty()) { 0103 QString period = getPeriod(); 0104 if (!period.isEmpty()) { 0105 previousmonth = SKGServices::getNeighboringPeriod(period); 0106 } 0107 m_cache[QStringLiteral("previousperiod")] = previousmonth; 0108 } 0109 return previousmonth; 0110 } 0111 0112 SKGReport* SKGReport::getPrevious() 0113 { 0114 if (m_previous == nullptr) { 0115 m_previous = m_document->getReport(); 0116 m_previous->setPeriod(getPreviousPeriod()); 0117 } 0118 return m_previous; 0119 } 0120 0121 void SKGReport::setTipsOfDay(const QStringList& iTipsOfDays) 0122 { 0123 m_tipsOfTheDay = iTipsOfDays; 0124 0125 emit changed(); 0126 } 0127 0128 QString SKGReport::getTipOfDay() const 0129 { 0130 auto tips = getTipsOfDay(); 0131 auto tip = tips.count() > 0 ? SKGServices::htmlToString(tips.at(QRandomGenerator::global()->bounded(tips.size()))) : QString(); 0132 return tip; 0133 } 0134 0135 QStringList SKGReport::getTipsOfDay() const 0136 { 0137 return m_tipsOfTheDay; 0138 } 0139 0140 QVariantHash SKGReport::getContextProperty() 0141 { 0142 QVariantHash mapping; 0143 addItemsInMapping(mapping); 0144 0145 if (m_document != nullptr) { 0146 mapping.insert(QStringLiteral("document"), QVariant::fromValue<QObject*>(m_document)); 0147 } 0148 return mapping; 0149 } 0150 0151 void SKGReport::addItemsInMapping(QVariantHash& iMapping) 0152 { 0153 iMapping.insert(QStringLiteral("report"), QVariant::fromValue<QObject*>(this)); 0154 iMapping.insert(QStringLiteral("current_date"), QDate::currentDate()); 0155 KColorScheme scheme(QPalette::Normal, KColorScheme::Window); 0156 iMapping.insert(QStringLiteral("color_negativetext"), scheme.foreground(KColorScheme::NegativeText).color().name().right(6)); 0157 iMapping.insert(QStringLiteral("color_positivetext"), scheme.foreground(KColorScheme::PositiveText).color().name().right(6)); 0158 iMapping.insert(QStringLiteral("color_neutraltext"), scheme.foreground(KColorScheme::NeutralText).color().name().right(6)); 0159 iMapping.insert(QStringLiteral("color_normaltext"), scheme.foreground(KColorScheme::NormalText).color().name().right(6)); 0160 iMapping.insert(QStringLiteral("color_inactivetext"), scheme.foreground(KColorScheme::InactiveText).color().name().right(6)); 0161 iMapping.insert(QStringLiteral("color_activetext"), scheme.foreground(KColorScheme::ActiveText).color().name().right(6)); 0162 iMapping.insert(QStringLiteral("color_linktext"), scheme.foreground(KColorScheme::LinkText).color().name().right(6)); 0163 iMapping.insert(QStringLiteral("color_visitedtext"), scheme.foreground(KColorScheme::VisitedText).color().name().right(6)); 0164 iMapping.insert(QStringLiteral("color_normalbackground"), scheme.background(KColorScheme::NormalBackground).color().name().right(6)); 0165 iMapping.insert(QStringLiteral("color_activebackground"), scheme.background(KColorScheme::ActiveBackground).color().name().right(6)); 0166 0167 QFont generalFont = QFontDatabase::systemFont(QFontDatabase::GeneralFont); 0168 iMapping.insert(QStringLiteral("font_family"), generalFont.family()); 0169 0170 QString dir = "file://" % QFileInfo(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/infopage/kde_infopage.css"))).dir().absolutePath() % '/'; 0171 { 0172 QFile file(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kf5/infopage/kde_infopage.css"))); 0173 if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0174 iMapping.insert(QStringLiteral("kde_infopage_css"), QString(file.readAll()).replace(QStringLiteral("url("), "url(" % dir)); 0175 } 0176 } 0177 0178 KAboutData about = KAboutData::applicationData(); 0179 iMapping.insert(QStringLiteral("about_welcome"), i18nc("Welcome message", "Welcome to %1", about.displayName())); 0180 iMapping.insert(QStringLiteral("about_programname"), about.displayName()); 0181 iMapping.insert(QStringLiteral("about_version"), about.version()); 0182 iMapping.insert(QStringLiteral("about_bugaddress"), about.bugAddress()); 0183 iMapping.insert(QStringLiteral("about_copyrightstatement"), about.copyrightStatement()); 0184 iMapping.insert(QStringLiteral("about_homepage"), about.homepage()); 0185 iMapping.insert(QStringLiteral("about_shortdescription"), about.shortDescription()); 0186 iMapping.insert(QStringLiteral("about_othertext"), about.otherText()); 0187 iMapping.insert(QStringLiteral("about_did_you_know"), i18nc("Title for tips of the day", "Did you know …?")); 0188 } 0189 0190 SKGError SKGReport::getReportFromTemplate(SKGReport* iReport, const QString& iFile, QString& oHtml) 0191 { 0192 SKGError err; 0193 SKGTRACEINFUNCRC(10, err) 0194 0195 // Prepare grantlee engine 0196 Grantlee::Engine gEngine; 0197 gEngine.addDefaultLibrary(QStringLiteral("grantlee_skgfilters")); 0198 0199 QSharedPointer<Grantlee::FileSystemTemplateLoader> gLoader = QSharedPointer<Grantlee::FileSystemTemplateLoader>(new Grantlee::FileSystemTemplateLoader()); 0200 gLoader->setTemplateDirs(QStringList(QFileInfo(iFile).dir().absolutePath())); 0201 gEngine.addTemplateLoader(gLoader); 0202 0203 Grantlee::Template gTemplate = gEngine.loadByName(QFileInfo(iFile).fileName()); 0204 if (gTemplate->error() != 0u) { 0205 err = SKGError(gTemplate->error(), gTemplate->errorString()); 0206 } else { 0207 QVariantHash mapping; 0208 if (iReport != nullptr) { 0209 mapping = iReport->getContextProperty(); 0210 } 0211 Grantlee::Context gContext(mapping); 0212 0213 // Generation 0214 { 0215 SKGTRACEINFUNCRC(10, err) 0216 oHtml = gTemplate->render(&gContext); 0217 QRegularExpression rx(QStringLiteral("\\n\\s*\\n")); 0218 oHtml = oHtml.replace(rx, QStringLiteral("\n")); 0219 if (gTemplate->error() != 0u) { 0220 err = SKGError(gTemplate->error(), gTemplate->errorString()); 0221 } 0222 } 0223 } 0224 return err; 0225 } 0226 0227 void SKGReport::cleanCache(bool iEmitSignal) 0228 { 0229 QString month = m_cache.value(QStringLiteral("period")).toString(); 0230 QString filter = m_cache.value(QStringLiteral("filter")).toString(); 0231 m_cache.clear(); 0232 if (!month.isEmpty()) { 0233 m_cache[QStringLiteral("period")] = month; 0234 } 0235 if (!filter.isEmpty()) { 0236 m_cache[QStringLiteral("filter")] = filter; 0237 } 0238 if (iEmitSignal) { 0239 emit changed(); 0240 } 0241 } 0242 0243 void SKGReport::addParameter(const QString& iName, const QVariant& ivalue) 0244 { 0245 m_parameters[iName] = ivalue; 0246 } 0247 0248 void SKGReport::setPointSize(int iPointSize) 0249 { 0250 m_pointSize = iPointSize; 0251 emit changed(); 0252 } 0253 0254 int SKGReport::getPointSize() const 0255 { 0256 return m_pointSize; 0257 }