File indexing completed on 2024-12-15 03:45:04
0001 /* 0002 SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: MIT 0005 */ 0006 0007 #include "selectionratiosource.h" 0008 #include "abstractdatasource_p.h" 0009 #include "logging_p.h" 0010 0011 #include <QDebug> 0012 #include <QHash> 0013 #include <QItemSelectionModel> 0014 #include <QSettings> 0015 #include <QStringList> 0016 #include <QTime> 0017 #include <QElapsedTimer> 0018 0019 #include <memory> 0020 0021 using namespace KUserFeedback; 0022 0023 namespace KUserFeedback { 0024 class SelectionRatioSourcePrivate : public AbstractDataSourcePrivate 0025 { 0026 public: 0027 SelectionRatioSourcePrivate(); 0028 ~SelectionRatioSourcePrivate() override; 0029 0030 void selectionChanged(); 0031 QString selectedValue() const; 0032 0033 QItemSelectionModel *model; 0034 QMetaObject::Connection monitorConnection; 0035 QString description; 0036 QString previousValue; 0037 QElapsedTimer lastChangeTime; 0038 QHash<QString, int> ratioSet; // data we are currently tracking 0039 QHash<QString, int> baseRatioSet; // data loaded from storage 0040 int role; 0041 }; 0042 0043 } 0044 0045 SelectionRatioSourcePrivate::SelectionRatioSourcePrivate() 0046 : model(nullptr) 0047 , role(Qt::DisplayRole) 0048 { 0049 } 0050 0051 SelectionRatioSourcePrivate::~SelectionRatioSourcePrivate() 0052 { 0053 QObject::disconnect(monitorConnection); 0054 } 0055 0056 void SelectionRatioSourcePrivate::selectionChanged() 0057 { 0058 if (!previousValue.isEmpty() && lastChangeTime.elapsed() > 1000) { 0059 ratioSet[previousValue] += lastChangeTime.elapsed() / 1000; 0060 } 0061 0062 lastChangeTime.start(); 0063 previousValue = selectedValue(); 0064 } 0065 0066 QString SelectionRatioSourcePrivate::selectedValue() const 0067 { 0068 const auto idxs = model->selectedIndexes(); 0069 if (!model->hasSelection() || idxs.isEmpty()) 0070 return QString(); 0071 Q_ASSERT(!idxs.isEmpty()); 0072 const auto idx = idxs.at(0); 0073 return idx.data(role).toString(); 0074 } 0075 0076 SelectionRatioSource::SelectionRatioSource(QItemSelectionModel* selectionModel, const QString& sampleName) 0077 : AbstractDataSource(sampleName, Provider::DetailedUsageStatistics, new SelectionRatioSourcePrivate) 0078 { 0079 Q_D(SelectionRatioSource); 0080 0081 d->model = selectionModel; 0082 Q_ASSERT(selectionModel); 0083 0084 d->monitorConnection = QObject::connect(selectionModel, &QItemSelectionModel::selectionChanged, [this]() { 0085 Q_D(SelectionRatioSource); 0086 d->selectionChanged(); 0087 }); 0088 d->lastChangeTime.start(); 0089 d->selectionChanged(); 0090 } 0091 0092 void SelectionRatioSource::setRole(int role) 0093 { 0094 Q_D(SelectionRatioSource); 0095 d->role = role; 0096 } 0097 0098 QString SelectionRatioSource::description() const 0099 { 0100 Q_D(const SelectionRatioSource); 0101 return d->description; 0102 } 0103 0104 void SelectionRatioSource::setDescription(const QString& desc) 0105 { 0106 Q_D(SelectionRatioSource); 0107 d->description = desc; 0108 } 0109 0110 QVariant SelectionRatioSource::data() 0111 { 0112 Q_D(SelectionRatioSource); 0113 d->selectionChanged(); 0114 0115 QVariantMap m; 0116 int total = 0; 0117 for (auto it = d->ratioSet.constBegin(); it != d->ratioSet.constEnd(); ++it) 0118 total += it.value() + d->baseRatioSet.value(it.key()); 0119 if (total <= 0) 0120 return m; 0121 0122 for (auto it = d->ratioSet.constBegin(); it != d->ratioSet.constEnd(); ++it) { 0123 double currentValue = it.value() + d->baseRatioSet.value(it.key()); 0124 QVariantMap v; 0125 v.insert(QStringLiteral("property"), currentValue / (double)(total)); 0126 m.insert(it.key(), v); 0127 } 0128 return m; 0129 } 0130 0131 void SelectionRatioSource::loadImpl(QSettings *settings) 0132 { 0133 Q_D(SelectionRatioSource); 0134 foreach (const auto &value, settings->childKeys()) { 0135 const auto amount = std::max(settings->value(value, 0).toInt(), 0); 0136 d->baseRatioSet.insert(value, amount); 0137 if (!d->ratioSet.contains(value)) 0138 d->ratioSet.insert(value, 0); 0139 } 0140 } 0141 0142 void SelectionRatioSource::storeImpl(QSettings *settings) 0143 { 0144 Q_D(SelectionRatioSource); 0145 d->selectionChanged(); 0146 0147 // note that a second process can have updated the data meanwhile! 0148 for (auto it = d->ratioSet.begin(); it != d->ratioSet.end(); ++it) { 0149 if (it.value() == 0) 0150 continue; 0151 const auto oldValue = std::max(settings->value(it.key(), 0).toInt(), 0); 0152 const auto newValue = oldValue + it.value(); 0153 settings->setValue(it.key(), newValue); 0154 *it = 0; 0155 d->baseRatioSet.insert(it.key(), newValue); 0156 } 0157 } 0158 0159 void SelectionRatioSource::resetImpl(QSettings* settings) 0160 { 0161 Q_D(SelectionRatioSource); 0162 d->baseRatioSet.clear(); 0163 d->ratioSet.clear(); 0164 settings->remove(QString()); 0165 }