Warning, file /plasma/plasma-workspace/kcms/feedback/feedback.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
0003     SPDX-FileCopyrightText: 2019 Aleix Pol Gonzalez <aleixpol@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "feedback.h"
0009 #include "kcm_feedback_debug.h"
0010 
0011 #include <KConfigGroup>
0012 #include <KLocalizedString>
0013 #include <KPluginFactory>
0014 
0015 #include <QFileInfo>
0016 #include <QVector>
0017 
0018 #include <KUserFeedback/FeedbackConfigUiController>
0019 #include <KUserFeedback/Provider>
0020 
0021 #include "feedbackdata.h"
0022 #include "feedbacksettings.h"
0023 
0024 K_PLUGIN_FACTORY_WITH_JSON(FeedbackFactory, "kcm_feedback.json", registerPlugin<Feedback>(); registerPlugin<FeedbackData>();)
0025 
0026 struct Information {
0027     QString icon;
0028     QString kuserfeedbackComponent;
0029 };
0030 static QHash<QString, Information> s_programs = {
0031     {"plasmashell", {"plasmashell", "plasmashell"}},
0032     {"plasma-discover", {"plasmadiscover", "discover"}},
0033 };
0034 
0035 inline void swap(QJsonValueRef v1, QJsonValueRef v2)
0036 {
0037     QJsonValue temp(v1);
0038     v1 = QJsonValue(v2);
0039     v2 = temp;
0040 }
0041 
0042 Feedback::Feedback(QObject *parent, const KPluginMetaData &data, const QVariantList &args)
0043     : KQuickAddons::ManagedConfigModule(parent, data, args)
0044     // UserFeedback.conf is used by KUserFeedback which uses QSettings and won't go through globals
0045     , m_data(new FeedbackData(this))
0046 {
0047     qmlRegisterAnonymousType<FeedbackSettings>("org.kde.userfeedback.kcm", 1);
0048 
0049     QVector<QProcess *> processes;
0050     for (const auto &exec : s_programs.keys()) {
0051         QProcess *p = new QProcess(this);
0052         p->setProgram(exec);
0053         p->setArguments({QStringLiteral("--feedback")});
0054         p->start();
0055         connect(p, &QProcess::finished, this, &Feedback::programFinished);
0056         processes << p;
0057     }
0058 }
0059 
0060 Feedback::~Feedback() = default;
0061 
0062 void Feedback::programFinished(int exitCode)
0063 {
0064     auto mo = KUserFeedback::Provider::staticMetaObject;
0065     const int modeEnumIdx = mo.indexOfEnumerator("TelemetryMode");
0066     Q_ASSERT(modeEnumIdx >= 0);
0067     const auto modeEnum = mo.enumerator(modeEnumIdx);
0068 
0069     QProcess *p = qobject_cast<QProcess *>(sender());
0070     const QString program = p->program();
0071 
0072     if (exitCode) {
0073         qCWarning(KCM_FEEDBACK_DEBUG) << "Could not check" << program;
0074         return;
0075     }
0076 
0077     QTextStream stream(p);
0078     for (QString line; stream.readLineInto(&line);) {
0079         int sepIdx = line.indexOf(QLatin1String(": "));
0080         if (sepIdx < 0) {
0081             break;
0082         }
0083 
0084         const QString mode = line.left(sepIdx);
0085         bool ok;
0086         const int modeValue = modeEnum.keyToValue(qPrintable(mode), &ok);
0087         if (!ok) {
0088             qCWarning(KCM_FEEDBACK_DEBUG) << "error:" << mode << "is not a valid mode";
0089             continue;
0090         }
0091 
0092         const QString description = line.mid(sepIdx + 1);
0093         m_uses[modeValue][description] << s_programs[program].icon;
0094     }
0095     p->deleteLater();
0096     m_feedbackSources = {};
0097     for (auto it = m_uses.constBegin(), itEnd = m_uses.constEnd(); it != itEnd; ++it) {
0098         const auto modeUses = *it;
0099         for (auto itMode = modeUses.constBegin(), itModeEnd = modeUses.constEnd(); itMode != itModeEnd; ++itMode) {
0100             m_feedbackSources << QJsonObject({{"mode", it.key()}, {"icons", *itMode}, {"description", itMode.key()}});
0101         }
0102     }
0103     std::sort(m_feedbackSources.begin(), m_feedbackSources.end(), [](const QJsonValue &valueL, const QJsonValue &valueR) {
0104         const QJsonObject objL(valueL.toObject()), objR(valueR.toObject());
0105         const auto modeL = objL["mode"].toInt(), modeR = objR["mode"].toInt();
0106         return modeL < modeR || (modeL == modeR && objL["description"].toString() < objR["description"].toString());
0107     });
0108     Q_EMIT feedbackSourcesChanged();
0109 }
0110 
0111 bool Feedback::feedbackEnabled() const
0112 {
0113     KUserFeedback::Provider p;
0114     return p.isEnabled();
0115 }
0116 
0117 FeedbackSettings *Feedback::feedbackSettings() const
0118 {
0119     return m_data->settings();
0120 }
0121 
0122 QJsonArray Feedback::audits() const
0123 {
0124     QJsonArray ret;
0125     for (auto it = s_programs.constBegin(); it != s_programs.constEnd(); ++it) {
0126         QString feedbackLocation =
0127             QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + '/' + it->kuserfeedbackComponent + QStringLiteral("/kuserfeedback/audit");
0128 
0129         if (QFileInfo::exists(feedbackLocation)) {
0130             ret += QJsonObject{
0131                 {"program", it.key()},
0132                 {"audits", feedbackLocation},
0133             };
0134         }
0135     }
0136     return ret;
0137 }
0138 
0139 #include "feedback.moc"
0140 #include "moc_feedback.cpp"