forked from quickshell/quickshell
		
	core/scriptmodel: add objectProp, allowing js objects to be compared
This commit is contained in:
		
							parent
							
								
									61f00a0442
								
							
						
					
					
						commit
						2e905f6447
					
				
					 2 changed files with 48 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,27 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
 | 
			
		|||
	auto iter = this->mValues.begin();
 | 
			
		||||
	auto newIter = newValues.begin();
 | 
			
		||||
 | 
			
		||||
	// TODO: cache this
 | 
			
		||||
	auto getCmpKey = [&](const QVariant& v) {
 | 
			
		||||
		if (v.canConvert<QVariantMap>()) {
 | 
			
		||||
			auto vMap = v.value<QVariantMap>();
 | 
			
		||||
			if (vMap.contains(this->cmpKey)) {
 | 
			
		||||
				return vMap.value(this->cmpKey);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return v;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	auto variantCmp = [&](const QVariant& a, const QVariant& b) {
 | 
			
		||||
		if (!this->cmpKey.isEmpty()) return getCmpKey(a) == getCmpKey(b);
 | 
			
		||||
		else return a == b;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	auto eqPredicate = [&](const QVariant& b) {
 | 
			
		||||
		return [&](const QVariant& a) { return variantCmp(a, b); };
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
		if (newIter == newValues.end()) {
 | 
			
		||||
			if (iter == this->mValues.end()) break;
 | 
			
		||||
| 
						 | 
				
			
			@ -40,18 +61,19 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
 | 
			
		|||
			this->endInsertRows();
 | 
			
		||||
 | 
			
		||||
			break;
 | 
			
		||||
		} else if (*newIter != *iter) {
 | 
			
		||||
			auto oldIter = std::find(iter, this->mValues.end(), *newIter);
 | 
			
		||||
		} else if (!variantCmp(*newIter, *iter)) {
 | 
			
		||||
			auto oldIter = std::find_if(iter, this->mValues.end(), eqPredicate(*newIter));
 | 
			
		||||
 | 
			
		||||
			if (oldIter != this->mValues.end()) {
 | 
			
		||||
				if (std::find(newIter, newValues.end(), *iter) == newValues.end()) {
 | 
			
		||||
				if (std::find_if(newIter, newValues.end(), eqPredicate(*iter)) == newValues.end()) {
 | 
			
		||||
					// Remove any entries we would otherwise move around that aren't in the new list.
 | 
			
		||||
					auto startIter = iter;
 | 
			
		||||
 | 
			
		||||
					do {
 | 
			
		||||
						++iter;
 | 
			
		||||
					} while (iter != this->mValues.end()
 | 
			
		||||
					         && std::find(newIter, newValues.end(), *iter) == newValues.end());
 | 
			
		||||
					         && std::find_if(newIter, newValues.end(), eqPredicate(*iter)) == newValues.end()
 | 
			
		||||
					);
 | 
			
		||||
 | 
			
		||||
					auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
 | 
			
		||||
					auto startIndex = static_cast<qint32>(std::distance(this->mValues.begin(), startIter));
 | 
			
		||||
| 
						 | 
				
			
			@ -66,7 +88,7 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
 | 
			
		|||
						++oldIter;
 | 
			
		||||
						++newIter;
 | 
			
		||||
					} while (oldIter != this->mValues.end() && newIter != newValues.end()
 | 
			
		||||
					         && *oldIter == *newIter);
 | 
			
		||||
					         && variantCmp(*oldIter, *newIter));
 | 
			
		||||
 | 
			
		||||
					auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
 | 
			
		||||
					auto oldStartIndex =
 | 
			
		||||
| 
						 | 
				
			
			@ -90,7 +112,8 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
 | 
			
		|||
				do {
 | 
			
		||||
					newIter++;
 | 
			
		||||
				} while (newIter != newValues.end()
 | 
			
		||||
				         && std::find(iter, this->mValues.end(), *newIter) == this->mValues.end());
 | 
			
		||||
				         && std::find_if(iter, this->mValues.end(), eqPredicate(*newIter))
 | 
			
		||||
				                == this->mValues.end());
 | 
			
		||||
 | 
			
		||||
				auto index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
 | 
			
		||||
				auto newIndex = static_cast<qint32>(std::distance(newValues.begin(), newIter));
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +146,13 @@ void ScriptModel::setValues(const QVariantList& newValues) {
 | 
			
		|||
	emit this->valuesChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ScriptModel::setObjectProp(const QString& objectProp) {
 | 
			
		||||
	if (objectProp == this->cmpKey) return;
 | 
			
		||||
	this->cmpKey = objectProp;
 | 
			
		||||
	this->updateValuesUnique(this->mValues);
 | 
			
		||||
	emit this->objectPropChanged();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qint32 ScriptModel::rowCount(const QModelIndex& parent) const {
 | 
			
		||||
	if (parent != QModelIndex()) return 0;
 | 
			
		||||
	return static_cast<qint32>(this->mValues.length());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,13 @@ class ScriptModel: public QAbstractListModel {
 | 
			
		|||
	/// > }
 | 
			
		||||
	/// > ```
 | 
			
		||||
	Q_PROPERTY(QVariantList values READ values WRITE setValues NOTIFY valuesChanged);
 | 
			
		||||
	/// The property that javascript objects passed into the model will be compared with.
 | 
			
		||||
	///
 | 
			
		||||
	/// For example, if `objectProp` is `"myprop"` then `{ myprop: "a", other: "y" }` and
 | 
			
		||||
	/// `{ myprop: "a", other: "z" }` will be considered equal.
 | 
			
		||||
	///
 | 
			
		||||
	/// Defaults to `""`, meaning no key.
 | 
			
		||||
	Q_PROPERTY(QString objectProp READ objectProp WRITE setObjectProp NOTIFY objectPropChanged);
 | 
			
		||||
	QML_ELEMENT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -79,15 +86,20 @@ public:
 | 
			
		|||
 | 
			
		||||
	void setValues(const QVariantList& newValues);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] QString objectProp() const { return this->cmpKey; }
 | 
			
		||||
	void setObjectProp(const QString& objectProp);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] qint32 rowCount(const QModelIndex& parent) const override;
 | 
			
		||||
	[[nodiscard]] QVariant data(const QModelIndex& index, qint32 role) const override;
 | 
			
		||||
	[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	void valuesChanged();
 | 
			
		||||
	void objectPropChanged();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	QVariantList mValues;
 | 
			
		||||
	QString cmpKey;
 | 
			
		||||
	bool hasActiveIterators = false;
 | 
			
		||||
 | 
			
		||||
	void updateValuesUnique(const QVariantList& newValues);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue