File indexing completed on 2025-02-02 04:56:55
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 plugin to generate statistic 0008 * 0009 * @author Stephane MANKOWSKI 0010 */ 0011 #include "skgstatisticplugin.h" 0012 0013 #ifdef HAVE_UNAME 0014 # include <sys/utsname.h> 0015 #endif 0016 0017 #include <kaboutdata.h> 0018 #include <kactioncollection.h> 0019 #include <kpluginfactory.h> 0020 #include <kstandardaction.h> 0021 0022 #include <qapplication.h> 0023 #include <qcryptographichash.h> 0024 #include <qdesktopwidget.h> 0025 #include <qdir.h> 0026 #include <qjsondocument.h> 0027 #include <qscreen.h> 0028 0029 #include "skgmainpanel.h" 0030 #include "skgtraces.h" 0031 0032 /** 0033 * This plugin factory. 0034 */ 0035 K_PLUGIN_CLASS_WITH_JSON(SKGStatisticPlugin, "metadata.json") 0036 0037 SKGStatisticPlugin::SKGStatisticPlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) : 0038 SKGInterfacePlugin(iParent), m_currentDocument(nullptr) 0039 { 0040 Q_UNUSED(iWidget) 0041 m_timeInit = QDateTime::currentDateTime(); 0042 SKGTRACEINFUNC(10) 0043 0044 connect(SKGMainPanel::getMainPanel(), &SKGMainPanel::currentPageChanged, this, &SKGStatisticPlugin::pageChanged); 0045 connect(SKGMainPanel::getMainPanel(), &SKGMainPanel::pageOpened, this, &SKGStatisticPlugin::pageOpened); 0046 } 0047 0048 SKGStatisticPlugin::~SKGStatisticPlugin() 0049 { 0050 SKGTRACEINFUNC(10) 0051 // Set duration 0052 m_stats[QStringLiteral("avg.exec_time_sec")] = (m_stats.value(QStringLiteral("avg.exec_time_sec")).toDouble() * (m_stats.value(QStringLiteral("nb_launch")).toInt() - 1) + m_timeInit.secsTo(QDateTime::currentDateTime())) / m_stats.value(QStringLiteral("nb_launch")).toInt(); 0053 0054 // Write stat file 0055 writeStats(); 0056 0057 m_currentDocument = nullptr; 0058 } 0059 0060 bool SKGStatisticPlugin::setupActions(SKGDocument* iDocument) 0061 { 0062 SKGTRACEINFUNC(10) 0063 0064 m_currentDocument = iDocument; 0065 0066 setComponentName(QStringLiteral("skg_statistic"), title()); 0067 setXMLFile(QStringLiteral("skg_statistic.rc")); 0068 return true; 0069 } 0070 0071 void SKGStatisticPlugin::refresh() 0072 { 0073 SKGTRACEINFUNC(10) 0074 if (m_currentDocument != nullptr) { 0075 if (m_currentDocument->getMainDatabase() != nullptr) { 0076 static bool initialisationDone = false; 0077 if (!initialisationDone) { 0078 // Connect actions 0079 QMap<QString, QPointer<QAction> > actions = SKGMainPanel::getMainPanel()->getGlobalActions(); 0080 QStringList keys = actions.keys(); 0081 for (const auto& k : qAsConst(keys)) { 0082 QPointer<QAction> act = actions[k]; 0083 connect(act.data(), &QAction::triggered, this, &SKGStatisticPlugin::triggerAction); 0084 } 0085 initialisationDone = true; 0086 } 0087 0088 QString doc_id = m_currentDocument->getUniqueIdentifier(); 0089 if (m_docUniqueIdentifier != doc_id) { 0090 m_docUniqueIdentifier = doc_id; 0091 0092 // Initialize 0093 QString appname = KAboutData::applicationData().componentName(); 0094 auto dir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) ; 0095 QDir(dir).mkdir("statistics"); 0096 QString docUUID = QString(QCryptographicHash::hash(m_currentDocument->getCurrentFileName().toLatin1(), QCryptographicHash::Md5).toHex()); 0097 m_file = dir % "/statistics/" % docUUID % ".stats.txt"; 0098 0099 // Read previous stat file 0100 readStats(); 0101 0102 // Initial values 0103 if (!m_stats.contains(QStringLiteral("init.date"))) { 0104 m_stats[QStringLiteral("init.date")] = QDate::currentDate(); 0105 m_stats[QStringLiteral("init.qt_version")] = qVersion(); 0106 m_stats[QStringLiteral("init.app_name")] = appname; 0107 m_stats[QStringLiteral("init.app_version")] = KAboutData::applicationData().version(); 0108 } 0109 m_stats[QStringLiteral("nb_launch")] = m_stats.value(QStringLiteral("nb_launch")).toInt() + 1; 0110 0111 // Current values 0112 m_stats[QStringLiteral("current.date")] = QDate::currentDate(); 0113 m_stats[QStringLiteral("current.qt_version")] = qVersion(); 0114 m_stats[QStringLiteral("current.app_version")] = KAboutData::applicationData().version(); 0115 m_stats[QStringLiteral("current.language")] = QLocale::languageToString(QLocale().language()); 0116 m_stats[QStringLiteral("current.country")] = QLocale::countryToString(QLocale().country()); 0117 m_stats[QStringLiteral("current.country.code")] = QLocale().name().split(QStringLiteral("_")).at(0); 0118 m_stats[QStringLiteral("current.locale")] = QLocale().name(); 0119 0120 // OS 0121 #ifdef Q_OS_WIN32 0122 QString os = QStringLiteral("Windows"); 0123 #elif defined(Q_OS_FREEBSD) 0124 QString os = QStringLiteral("FreeBSD"); 0125 #elif defined(Q_OS_NETBSD) 0126 QString os = QStringLiteral("NetBSD"); 0127 #elif defined(Q_OS_OPENBSD) 0128 QString os = QStringLiteral("OpenBSD"); 0129 #elif defined(Q_OS_LINUX) 0130 QString os = QStringLiteral("Linux"); 0131 #elif defined(Q_OS_MAC) 0132 QString os = QStringLiteral("Mac OS"); 0133 #else 0134 QString os = QStringLiteral("Unknown"); 0135 #endif 0136 m_stats[QStringLiteral("current.os")] = os; 0137 QRect scr = QGuiApplication::primaryScreen()->geometry(); 0138 m_stats[QStringLiteral("current.screen")] = QString(SKGServices::intToString(scr.width()) % 'x' % SKGServices::intToString(scr.height())); 0139 0140 #ifdef HAVE_UNAME 0141 struct utsname buf {}; 0142 if (uname(&buf) != -1) { 0143 m_stats[QStringLiteral("current.os.machine")] = QString::fromLocal8Bit(buf.machine); 0144 m_stats[QStringLiteral("current.os.version")] = QString::fromLocal8Bit(buf.version); 0145 } 0146 #endif 0147 0148 // Nb calls 0149 QMap<QString, QPointer<QAction> > actions = SKGMainPanel::getMainPanel()->getGlobalActions(); 0150 QStringList keys = actions.keys(); 0151 for (const auto& k : qAsConst(keys)) { 0152 QPointer<QAction> act = actions[k]; 0153 if (act != nullptr) { 0154 QString id = "nb_call." % act->objectName(); 0155 if (!m_stats.contains(id)) { 0156 m_stats[id] = 0; 0157 } 0158 } 0159 } 0160 m_stats[QStringLiteral("document.uuid")] = docUUID; 0161 0162 // Set tables sizes 0163 QStringList tables; 0164 m_currentDocument->getTablesList(tables); 0165 for (const auto& t : qAsConst(tables)) { 0166 QString r; 0167 m_currentDocument->executeSingleSelectSqliteOrder("SELECT COUNT(1) FROM " % t, r); 0168 m_stats["count." % t] = SKGServices::stringToInt(r); 0169 } 0170 } 0171 } 0172 } 0173 } 0174 0175 void SKGStatisticPlugin::readStats() 0176 { 0177 m_stats.clear(); 0178 0179 // Read file 0180 QFile data(m_file); 0181 if (data.open(QFile::ReadOnly)) { 0182 // Parse json 0183 m_stats = QJsonDocument::fromJson(data.readAll()).toVariant().toMap(); 0184 data.close(); 0185 } 0186 } 0187 0188 void SKGStatisticPlugin::writeStats() 0189 { 0190 // Write it in file 0191 QFile data(m_file); 0192 if (data.open(QFile::WriteOnly | QFile::Truncate)) { 0193 // serialize json 0194 QJsonDocument serializer = QJsonDocument::fromVariant(m_stats); 0195 QByteArray doc = serializer.toJson(QJsonDocument::Indented); 0196 0197 data.write(doc); 0198 data.close(); 0199 } else { 0200 SKGTRACE << "ERROR: Impossible to write " << m_file << SKGENDL; 0201 } 0202 } 0203 0204 void SKGStatisticPlugin::triggerAction() 0205 { 0206 SKGTRACEINFUNC(10) 0207 auto* act = qobject_cast< QAction* >(sender()); 0208 if (act != nullptr) { 0209 QString id = "nb_call." % act->objectName(); 0210 SKGTRACEL(10) << "SKGStatisticPlugin::triggerAction " << id << "++" << SKGENDL; 0211 m_stats[id] = m_stats[id].toInt() + 1; 0212 } 0213 } 0214 0215 void SKGStatisticPlugin::pageChanged() 0216 { 0217 SKGTabPage::SKGPageHistoryItem currentPage = SKGMainPanel::getMainPanel()->currentPageHistoryItem(); 0218 if (!currentPage.plugin.isEmpty()) { 0219 QString id = "nb_activated_" % QString(currentPage.bookmarkID.isEmpty() ? QStringLiteral("page") : QStringLiteral("bookmark")) % "." % currentPage.plugin; 0220 m_stats[id] = m_stats[id].toInt() + 1; 0221 } 0222 } 0223 0224 void SKGStatisticPlugin::pageOpened() 0225 { 0226 SKGTabPage::SKGPageHistoryItem currentPage = SKGMainPanel::getMainPanel()->currentPageHistoryItem(); 0227 if (!currentPage.plugin.isEmpty()) { 0228 QString id = "nb_opened_" % QString(currentPage.bookmarkID.isEmpty() ? QStringLiteral("page") : QStringLiteral("bookmark")) % "." % currentPage.plugin; 0229 m_stats[id] = m_stats[id].toInt() + 1; 0230 } 0231 } 0232 0233 QString SKGStatisticPlugin::title() const 0234 { 0235 return i18nc("The title", "Statistic"); 0236 } 0237 0238 QString SKGStatisticPlugin::icon() const 0239 { 0240 return QStringLiteral("dialog-information"); 0241 } 0242 0243 QString SKGStatisticPlugin::toolTip() const 0244 { 0245 return title(); 0246 } 0247 0248 int SKGStatisticPlugin::getOrder() const 0249 { 0250 return 9999; 0251 } 0252 0253 bool SKGStatisticPlugin::isInPagesChooser() const 0254 { 0255 return false; 0256 } 0257 0258 #include <skgstatisticplugin.moc>