Compare commits

...

5 commits

Author SHA1 Message Date
outfoxxed
fdbb86a06a
core/model: fix recursion in emptyInstance
Some checks failed
Build / Nix-4 (push) Has been cancelled
Build / Nix-5 (push) Has been cancelled
Build / Nix-6 (push) Has been cancelled
Build / Nix-7 (push) Has been cancelled
Build / Nix-8 (push) Has been cancelled
Build / Nix-9 (push) Has been cancelled
Build / Nix-10 (push) Has been cancelled
Build / Nix-11 (push) Has been cancelled
Build / Nix-12 (push) Has been cancelled
Build / Nix-13 (push) Has been cancelled
Build / Nix-14 (push) Has been cancelled
Build / Nix-15 (push) Has been cancelled
Build / Nix-16 (push) Has been cancelled
Build / Nix-17 (push) Has been cancelled
Build / Nix-18 (push) Has been cancelled
Build / Nix-19 (push) Has been cancelled
Build / Nix-20 (push) Has been cancelled
Build / Nix-21 (push) Has been cancelled
Build / Nix-22 (push) Has been cancelled
Build / Nix-23 (push) Has been cancelled
Build / Nix-24 (push) Has been cancelled
Build / Nix-25 (push) Has been cancelled
Build / Nix-26 (push) Has been cancelled
Build / Nix-27 (push) Has been cancelled
Build / Nix-28 (push) Has been cancelled
Build / Nix-29 (push) Has been cancelled
Build / Nix-30 (push) Has been cancelled
Build / Nix-31 (push) Has been cancelled
Build / Archlinux (push) Has been cancelled
Lint / Lint (push) Has been cancelled
2025-11-15 17:41:54 -08:00
outfoxxed
0a7dcf30ea
build: update clang tooling and reformat 2025-11-15 04:43:27 -08:00
outfoxxed
1552aca3df
build: fix new clang-tidy lints 2025-11-15 04:29:12 -08:00
outfoxxed
0a36e3ed40
ci: add qt6.10.0 checkout 2025-11-15 02:31:58 -08:00
outfoxxed
a00ff03944
services/pipewire: cache route device volumes to initialize nodes
Nodes referencing a device can be bound later than the device is
bound. If this happens, the node will not receive an initial route
device volume change event. This change caches the last known route
device volume and initializes the device with it if present.
2025-11-14 02:12:42 -08:00
46 changed files with 242 additions and 459 deletions

View file

@ -1,6 +1,6 @@
AlignArrayOfStructures: None
AlignAfterOpenBracket: BlockIndent
AllowShortBlocksOnASingleLine: Always
AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All

View file

@ -20,6 +20,7 @@ Checks: >
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-use-enum-class,
google-global-names-in-headers,
google-readability-casting,
google-runtime-int,
@ -63,6 +64,8 @@ CheckOptions:
readability-identifier-naming.ParameterCase: camelBack
readability-identifier-naming.VariableCase: camelBack
misc-const-correctness.WarnPointersAsPointers: false
# does not appear to work
readability-operators-representation.BinaryOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^='
readability-operators-representation.OverloadedOperators: '&&;&=;&;|;~;!;!=;||;|=;^;^='

View file

@ -6,7 +6,7 @@ jobs:
name: Nix
strategy:
matrix:
qtver: [qt6.9.2, qt6.9.1, qt6.9.0, qt6.8.3, qt6.8.2, qt6.8.1, qt6.8.0, qt6.7.3, qt6.7.2, qt6.7.1, qt6.7.0, qt6.6.3, qt6.6.2, qt6.6.1, qt6.6.0]
qtver: [qt6.10.0, qt6.9.2, qt6.9.1, qt6.9.0, qt6.8.3, qt6.8.2, qt6.8.1, qt6.8.0, qt6.7.3, qt6.7.2, qt6.7.1, qt6.7.0, qt6.6.3, qt6.6.2, qt6.6.1, qt6.6.0]
compiler: [clang, gcc]
runs-on: ubuntu-latest
permissions:

View file

@ -24,6 +24,7 @@ set shell id.
- Fixed volume control breaking with pipewire pro audio mode.
- Fixed escape sequence handling in desktop entries.
- Fixed volumes not initializing if a pipewire device was already loaded before its node.
## Packaging Changes

View file

@ -8,7 +8,12 @@ let
inherit sha256;
}) {};
in rec {
latest = qt6_9_0;
latest = qt6_10_0;
qt6_10_0 = byCommit {
commit = "c5ae371f1a6a7fd27823bc500d9390b38c05fa55";
sha256 = "18g0f8cb9m8mxnz9cf48sks0hib79b282iajl2nysyszph993yp0";
};
qt6_9_2 = byCommit {
commit = "e9f00bd893984bc8ce46c895c3bf7cac95331127";

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1758690382,
"narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
"lastModified": 1762977756,
"narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e643668fd71b949c53f8626614b21ff71a07379d",
"rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55",
"type": "github"
},
"original": {

View file

@ -24,7 +24,6 @@ qt_add_library(quickshell-core STATIC
elapsedtimer.cpp
desktopentry.cpp
desktopentrymonitor.cpp
objectrepeater.cpp
platformmenu.cpp
qsmenu.cpp
retainable.cpp

View file

@ -22,8 +22,8 @@ class PixmapCacheIconEngine: public QIconEngine {
QIcon::Mode /*unused*/,
QIcon::State /*unused*/
) override {
qFatal(
) << "Unexpected icon paint request bypassed pixmap method. Please report this as a bug.";
qFatal()
<< "Unexpected icon paint request bypassed pixmap method. Please report this as a bug.";
}
QPixmap pixmap(const QSize& size, QIcon::Mode /*unused*/, QIcon::State /*unused*/) override {

View file

@ -361,7 +361,8 @@ void ThreadLogging::initFs() {
auto* runDir = QsPaths::instance()->instanceRunDir();
if (!runDir) {
qCCritical(logLogging
qCCritical(
logLogging
) << "Could not start filesystem logging as the runtime directory could not be created.";
return;
}
@ -372,7 +373,8 @@ void ThreadLogging::initFs() {
auto* detailedFile = new QFile(detailedPath);
if (!file->open(QFile::ReadWrite | QFile::Truncate)) {
qCCritical(logLogging
qCCritical(
logLogging
) << "Could not start filesystem logger as the log file could not be created:"
<< path;
delete file;
@ -383,7 +385,8 @@ void ThreadLogging::initFs() {
// buffered by WriteBuffer
if (!detailedFile->open(QFile::ReadWrite | QFile::Truncate | QFile::Unbuffered)) {
qCCritical(logLogging
qCCritical(
logLogging
) << "Could not start detailed filesystem logger as the log file could not be created:"
<< detailedPath;
delete detailedFile;
@ -746,11 +749,11 @@ bool EncodedLogReader::readVarInt(quint32* slot) {
if (!this->reader.skip(1)) return false;
*slot = qFromLittleEndian(n);
} else if ((bytes[1] != 0xff || bytes[2] != 0xff) && readLength >= 3) {
auto n = *reinterpret_cast<quint16*>(bytes.data() + 1);
auto n = *reinterpret_cast<quint16*>(bytes.data() + 1); // NOLINT
if (!this->reader.skip(3)) return false;
*slot = qFromLittleEndian(n);
} else if (readLength == 7) {
auto n = *reinterpret_cast<quint32*>(bytes.data() + 3);
auto n = *reinterpret_cast<quint32*>(bytes.data() + 3); // NOLINT
if (!this->reader.skip(7)) return false;
*slot = qFromLittleEndian(n);
} else return false;

View file

@ -1,81 +1,14 @@
#include "model.hpp"
#include <qabstractitemmodel.h>
#include <qbytearray.h>
#include <qhash.h>
#include <qnamespace.h>
#include <qobject.h>
#include <qqmllist.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qvariant.h>
qint32 UntypedObjectModel::rowCount(const QModelIndex& parent) const {
if (parent != QModelIndex()) return 0;
return static_cast<qint32>(this->valuesList.length());
}
QVariant UntypedObjectModel::data(const QModelIndex& index, qint32 role) const {
if (role != Qt::UserRole) return QVariant();
return QVariant::fromValue(this->valuesList.at(index.row()));
}
QHash<int, QByteArray> UntypedObjectModel::roleNames() const {
return {{Qt::UserRole, "modelData"}};
}
void UntypedObjectModel::insertObject(QObject* object, qsizetype index) {
auto iindex = index == -1 ? this->valuesList.length() : index;
emit this->objectInsertedPre(object, iindex);
auto intIndex = static_cast<qint32>(iindex);
this->beginInsertRows(QModelIndex(), intIndex, intIndex);
this->valuesList.insert(iindex, object);
this->endInsertRows();
emit this->valuesChanged();
emit this->objectInsertedPost(object, iindex);
}
void UntypedObjectModel::removeAt(qsizetype index) {
auto* object = this->valuesList.at(index);
emit this->objectRemovedPre(object, index);
auto intIndex = static_cast<qint32>(index);
this->beginRemoveRows(QModelIndex(), intIndex, intIndex);
this->valuesList.removeAt(index);
this->endRemoveRows();
emit this->valuesChanged();
emit this->objectRemovedPost(object, index);
}
bool UntypedObjectModel::removeObject(const QObject* object) {
auto index = this->valuesList.indexOf(object);
if (index == -1) return false;
this->removeAt(index);
return true;
}
void UntypedObjectModel::diffUpdate(const QVector<QObject*>& newValues) {
for (qsizetype i = 0; i < this->valuesList.length();) {
if (newValues.contains(this->valuesList.at(i))) i++;
else this->removeAt(i);
}
qsizetype oi = 0;
for (auto* object: newValues) {
if (this->valuesList.length() == oi || this->valuesList.at(oi) != object) {
this->insertObject(object, oi);
}
oi++;
}
}
qsizetype UntypedObjectModel::indexOf(QObject* object) { return this->valuesList.indexOf(object); }
UntypedObjectModel* UntypedObjectModel::emptyInstance() {
static auto* instance = new UntypedObjectModel(nullptr); // NOLINT
static auto* instance = new ObjectModel<void>(nullptr);
return instance;
}

View file

@ -2,7 +2,7 @@
#include <functional>
#include <bit>
#include <QtCore/qtmetamacros.h>
#include <qabstractitemmodel.h>
#include <qcontainerfwd.h>
#include <qobject.h>
@ -49,14 +49,11 @@ class UntypedObjectModel: public QAbstractListModel {
public:
explicit UntypedObjectModel(QObject* parent): QAbstractListModel(parent) {}
[[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;
[[nodiscard]] QList<QObject*> values() const { return this->valuesList; }
void removeAt(qsizetype index);
[[nodiscard]] virtual QList<QObject*> values() = 0;
Q_INVOKABLE qsizetype indexOf(QObject* object);
Q_INVOKABLE virtual qsizetype indexOf(QObject* object) const = 0;
static UntypedObjectModel* emptyInstance();
@ -71,15 +68,6 @@ signals:
/// Sent immediately after an object is removed from the list.
void objectRemovedPost(QObject* object, qsizetype index);
protected:
void insertObject(QObject* object, qsizetype index = -1);
bool removeObject(const QObject* object);
// Assumes only one instance of a specific value
void diffUpdate(const QVector<QObject*>& newValues);
QVector<QObject*> valuesList;
private:
static qsizetype valuesCount(QQmlListProperty<QObject>* property);
static QObject* valueAt(QQmlListProperty<QObject>* property, qsizetype index);
@ -90,14 +78,20 @@ class ObjectModel: public UntypedObjectModel {
public:
explicit ObjectModel(QObject* parent): UntypedObjectModel(parent) {}
[[nodiscard]] QVector<T*>& valueList() { return *std::bit_cast<QVector<T*>*>(&this->valuesList); }
[[nodiscard]] const QVector<T*>& valueList() const {
return *std::bit_cast<const QVector<T*>*>(&this->valuesList);
}
[[nodiscard]] const QList<T*>& valueList() const { return this->mValuesList; }
[[nodiscard]] QList<T*>& valueList() { return this->mValuesList; }
void insertObject(T* object, qsizetype index = -1) {
this->UntypedObjectModel::insertObject(object, index);
auto iindex = index == -1 ? this->mValuesList.length() : index;
emit this->objectInsertedPre(object, iindex);
auto intIndex = static_cast<qint32>(iindex);
this->beginInsertRows(QModelIndex(), intIndex, intIndex);
this->mValuesList.insert(iindex, object);
this->endInsertRows();
emit this->valuesChanged();
emit this->objectInsertedPost(object, iindex);
}
void insertObjectSorted(T* object, const std::function<bool(T*, T*)>& compare) {
@ -110,17 +104,71 @@ public:
}
auto idx = iter - list.begin();
this->UntypedObjectModel::insertObject(object, idx);
this->insertObject(object, idx);
}
void removeObject(const T* object) { this->UntypedObjectModel::removeObject(object); }
bool removeObject(const T* object) {
auto index = this->mValuesList.indexOf(object);
if (index == -1) return false;
this->removeAt(index);
return true;
}
void removeAt(qsizetype index) {
auto* object = this->mValuesList.at(index);
emit this->objectRemovedPre(object, index);
auto intIndex = static_cast<qint32>(index);
this->beginRemoveRows(QModelIndex(), intIndex, intIndex);
this->mValuesList.removeAt(index);
this->endRemoveRows();
emit this->valuesChanged();
emit this->objectRemovedPost(object, index);
}
// Assumes only one instance of a specific value
void diffUpdate(const QVector<T*>& newValues) {
this->UntypedObjectModel::diffUpdate(*std::bit_cast<const QVector<QObject*>*>(&newValues));
void diffUpdate(const QList<T*>& newValues) {
for (qsizetype i = 0; i < this->mValuesList.length();) {
if (newValues.contains(this->mValuesList.at(i))) i++;
else this->removeAt(i);
}
qsizetype oi = 0;
for (auto* object: newValues) {
if (this->mValuesList.length() == oi || this->mValuesList.at(oi) != object) {
this->insertObject(object, oi);
}
oi++;
}
}
static ObjectModel<T>* emptyInstance() {
return static_cast<ObjectModel<T>*>(UntypedObjectModel::emptyInstance());
}
[[nodiscard]] qint32 rowCount(const QModelIndex& parent) const override {
if (parent != QModelIndex()) return 0;
return static_cast<qint32>(this->mValuesList.length());
}
[[nodiscard]] QVariant data(const QModelIndex& index, qint32 role) const override {
if (role != Qt::UserRole) return QVariant();
// Values must be QObject derived, but we can't assert that here without breaking forward decls,
// so no static_cast.
return QVariant::fromValue(reinterpret_cast<QObject*>(this->mValuesList.at(index.row())));
}
qsizetype indexOf(QObject* object) const override {
return this->mValuesList.indexOf(reinterpret_cast<T*>(object));
}
[[nodiscard]] QList<QObject*> values() override {
return *reinterpret_cast<QList<QObject*>*>(&this->mValuesList);
}
private:
QList<T*> mValuesList;
};

View file

@ -21,7 +21,6 @@ headers = [
"model.hpp",
"elapsedtimer.hpp",
"desktopentry.hpp",
"objectrepeater.hpp",
"qsmenu.hpp",
"retainable.hpp",
"popupanchor.hpp",

View file

@ -1,190 +0,0 @@
#include "objectrepeater.hpp"
#include <utility>
#include <qabstractitemmodel.h>
#include <qcontainerfwd.h>
#include <qhash.h>
#include <qlogging.h>
#include <qobject.h>
#include <qqmlcomponent.h>
#include <qqmlcontext.h>
#include <qqmlengine.h>
#include <qqmllist.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qvariant.h>
QVariant ObjectRepeater::model() const { return this->mModel; }
void ObjectRepeater::setModel(QVariant model) {
if (model == this->mModel) return;
if (this->itemModel != nullptr) {
QObject::disconnect(this->itemModel, nullptr, this, nullptr);
}
this->mModel = std::move(model);
emit this->modelChanged();
this->reloadElements();
}
void ObjectRepeater::onModelDestroyed() {
this->mModel.clear();
this->itemModel = nullptr;
emit this->modelChanged();
this->reloadElements();
}
QQmlComponent* ObjectRepeater::delegate() const { return this->mDelegate; }
void ObjectRepeater::setDelegate(QQmlComponent* delegate) {
if (delegate == this->mDelegate) return;
if (this->mDelegate != nullptr) {
QObject::disconnect(this->mDelegate, nullptr, this, nullptr);
}
this->mDelegate = delegate;
if (delegate != nullptr) {
QObject::connect(
this->mDelegate,
&QObject::destroyed,
this,
&ObjectRepeater::onDelegateDestroyed
);
}
emit this->delegateChanged();
this->reloadElements();
}
void ObjectRepeater::onDelegateDestroyed() {
this->mDelegate = nullptr;
emit this->delegateChanged();
this->reloadElements();
}
void ObjectRepeater::reloadElements() {
for (auto i = this->valuesList.length() - 1; i >= 0; i--) {
this->removeComponent(i);
}
if (this->mDelegate == nullptr || !this->mModel.isValid()) return;
if (this->mModel.canConvert<QAbstractItemModel*>()) {
auto* model = this->mModel.value<QAbstractItemModel*>();
this->itemModel = model;
this->insertModelElements(model, 0, model->rowCount() - 1); // -1 is fine
// clang-format off
QObject::connect(model, &QObject::destroyed, this, &ObjectRepeater::onModelDestroyed);
QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &ObjectRepeater::onModelRowsInserted);
QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &ObjectRepeater::onModelRowsRemoved);
QObject::connect(model, &QAbstractItemModel::rowsMoved, this, &ObjectRepeater::onModelRowsMoved);
QObject::connect(model, &QAbstractItemModel::modelAboutToBeReset, this, &ObjectRepeater::onModelAboutToBeReset);
// clang-format on
} else if (this->mModel.canConvert<QQmlListReference>()) {
auto values = this->mModel.value<QQmlListReference>();
auto len = values.count();
for (auto i = 0; i != len; i++) {
this->insertComponent(i, {{"modelData", QVariant::fromValue(values.at(i))}});
}
} else if (this->mModel.canConvert<QVector<QVariant>>()) {
auto values = this->mModel.value<QVector<QVariant>>();
for (auto& value: values) {
this->insertComponent(this->valuesList.length(), {{"modelData", value}});
}
} else {
qCritical() << this
<< "Cannot create components as the model is not compatible:" << this->mModel;
}
}
void ObjectRepeater::insertModelElements(QAbstractItemModel* model, int first, int last) {
auto roles = model->roleNames();
auto roleDataVec = QVector<QModelRoleData>();
for (auto id: roles.keys()) {
roleDataVec.push_back(QModelRoleData(id));
}
auto values = QModelRoleDataSpan(roleDataVec);
auto props = QVariantMap();
for (auto i = first; i != last + 1; i++) {
auto index = model->index(i, 0);
model->multiData(index, values);
for (auto [id, name]: roles.asKeyValueRange()) {
props.insert(name, *values.dataForRole(id));
}
this->insertComponent(i, props);
props.clear();
}
}
void ObjectRepeater::onModelRowsInserted(const QModelIndex& parent, int first, int last) {
if (parent != QModelIndex()) return;
this->insertModelElements(this->itemModel, first, last);
}
void ObjectRepeater::onModelRowsRemoved(const QModelIndex& parent, int first, int last) {
if (parent != QModelIndex()) return;
for (auto i = last; i != first - 1; i--) {
this->removeComponent(i);
}
}
void ObjectRepeater::onModelRowsMoved(
const QModelIndex& sourceParent,
int sourceStart,
int sourceEnd,
const QModelIndex& destParent,
int destStart
) {
auto hasSource = sourceParent != QModelIndex();
auto hasDest = destParent != QModelIndex();
if (!hasSource && !hasDest) return;
if (hasSource) {
this->onModelRowsRemoved(sourceParent, sourceStart, sourceEnd);
}
if (hasDest) {
this->onModelRowsInserted(destParent, destStart, destStart + (sourceEnd - sourceStart));
}
}
void ObjectRepeater::onModelAboutToBeReset() {
auto last = static_cast<int>(this->valuesList.length() - 1);
this->onModelRowsRemoved(QModelIndex(), 0, last); // -1 is fine
}
void ObjectRepeater::insertComponent(qsizetype index, const QVariantMap& properties) {
auto* context = QQmlEngine::contextForObject(this);
auto* instance = this->mDelegate->createWithInitialProperties(properties, context);
if (instance == nullptr) {
qWarning().noquote() << this->mDelegate->errorString();
qWarning() << this << "failed to create object for model data" << properties;
} else {
QQmlEngine::setObjectOwnership(instance, QQmlEngine::CppOwnership);
instance->setParent(this);
}
this->insertObject(instance, index);
}
void ObjectRepeater::removeComponent(qsizetype index) {
auto* instance = this->valuesList.at(index);
this->removeAt(index);
delete instance;
}

View file

@ -1,85 +0,0 @@
#pragma once
#include <qabstractitemmodel.h>
#include <qobject.h>
#include <qqmlcomponent.h>
#include <qqmlintegration.h>
#include <qtmetamacros.h>
#include <qtypes.h>
#include <qvariant.h>
#include "model.hpp"
///! A Repeater / for loop / map for non Item derived objects.
/// > [!ERROR] Removed in favor of @@QtQml.Models.Instantiator
///
/// The ObjectRepeater creates instances of the provided delegate for every entry in the
/// given model, similarly to a @@QtQuick.Repeater but for non visual types.
class ObjectRepeater: public ObjectModel<QObject> {
Q_OBJECT;
/// The model providing data to the ObjectRepeater.
///
/// Currently accepted model types are `list<T>` lists, javascript arrays,
/// and [QAbstractListModel] derived models, though only one column will be repeated
/// from the latter.
///
/// Note: @@ObjectModel is a [QAbstractListModel] with a single column.
///
/// [QAbstractListModel]: https://doc.qt.io/qt-6/qabstractlistmodel.html
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged);
/// The delegate component to repeat.
///
/// The delegate is given the same properties as in a Repeater, except `index` which
/// is not currently implemented.
///
/// If the model is a `list<T>` or javascript array, a `modelData` property will be
/// exposed containing the entry from the model. If the model is a [QAbstractListModel],
/// the roles from the model will be exposed.
///
/// Note: @@ObjectModel has a single role named `modelData` for compatibility with normal lists.
///
/// [QAbstractListModel]: https://doc.qt.io/qt-6/qabstractlistmodel.html
Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged);
Q_CLASSINFO("DefaultProperty", "delegate");
QML_ELEMENT;
QML_UNCREATABLE("ObjectRepeater has been removed in favor of QtQml.Models.Instantiator.");
public:
explicit ObjectRepeater(QObject* parent = nullptr): ObjectModel(parent) {}
[[nodiscard]] QVariant model() const;
void setModel(QVariant model);
[[nodiscard]] QQmlComponent* delegate() const;
void setDelegate(QQmlComponent* delegate);
signals:
void modelChanged();
void delegateChanged();
private slots:
void onDelegateDestroyed();
void onModelDestroyed();
void onModelRowsInserted(const QModelIndex& parent, int first, int last);
void onModelRowsRemoved(const QModelIndex& parent, int first, int last);
void onModelRowsMoved(
const QModelIndex& sourceParent,
int sourceStart,
int sourceEnd,
const QModelIndex& destParent,
int destStart
);
void onModelAboutToBeReset();
private:
void reloadElements();
void insertModelElements(QAbstractItemModel* model, int first, int last);
void insertComponent(qsizetype index, const QVariantMap& properties);
void removeComponent(qsizetype index);
QVariant mModel;
QAbstractItemModel* itemModel = nullptr;
QQmlComponent* mDelegate = nullptr;
};

View file

@ -175,7 +175,8 @@ void QsPaths::linkRunDir() {
auto* shellDir = this->shellRunDir();
if (!shellDir) {
qCCritical(logPaths
qCCritical(
logPaths
) << "Could not create by-id symlink as the shell runtime path could not be created.";
} else {
auto shellPath = shellDir->filePath(runDir->dirName());
@ -378,7 +379,8 @@ void QsPaths::createLock() {
qCDebug(logPaths) << "Created instance lock at" << path;
}
} else {
qCCritical(logPaths
qCCritical(
logPaths
) << "Could not create instance lock, as the instance runtime directory could not be created.";
}
}

View file

@ -38,7 +38,8 @@ void QmlScanner::scanDir(const QDir& dir) {
for (auto& name: dir.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
if (name == "qmldir") {
qCDebug(logQmlScanner
qCDebug(
logQmlScanner
) << "Found qmldir file, qmldir synthesization will be disabled for directory"
<< path;
seenQmldir = true;

View file

@ -72,8 +72,8 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
do {
++iter;
} while (iter != this->mValues.end()
&& std::find_if(newIter, newValues.end(), eqPredicate(*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));

View file

@ -29,7 +29,7 @@ struct StringLiteral16 {
}
[[nodiscard]] constexpr const QChar* qCharPtr() const noexcept {
return std::bit_cast<const QChar*>(&this->value);
return std::bit_cast<const QChar*>(&this->value); // NOLINT
}
[[nodiscard]] Q_ALWAYS_INLINE operator QString() const noexcept {

View file

@ -55,7 +55,8 @@ void CrashHandler::init() {
this->d->minidumpFd = memfd_create("quickshell:minidump", MFD_CLOEXEC);
if (this->d->minidumpFd == -1) {
qCCritical(logCrashHandler
qCCritical(
logCrashHandler
) << "Failed to allocate minidump memfd, minidumps will be saved in the working directory.";
createHandler(MinidumpDescriptor("."));
} else {
@ -71,7 +72,8 @@ void CrashHandler::setRelaunchInfo(const RelaunchInfo& info) {
this->d->infoFd = memfd_create("quickshell:instance_info", MFD_CLOEXEC);
if (this->d->infoFd == -1) {
qCCritical(logCrashHandler
qCCritical(
logCrashHandler
) << "Failed to allocate instance info memfd, crash recovery will not work.";
return;
}
@ -79,7 +81,8 @@ void CrashHandler::setRelaunchInfo(const RelaunchInfo& info) {
QFile file;
if (!file.open(this->d->infoFd, QFile::ReadWrite)) {
qCCritical(logCrashHandler
qCCritical(
logCrashHandler
) << "Failed to open instance info memfd, crash recovery will not work.";
}

View file

@ -66,7 +66,8 @@ CrashReporterGui::CrashReporterGui(QString reportFolder, int pid)
mainLayout->addSpacing(textHeight);
if (qtVersionMatches) {
mainLayout->addWidget(new QLabel("Please open a bug report for this issue via github or email.")
mainLayout->addWidget(
new QLabel("Please open a bug report for this issue via github or email.")
);
} else {
mainLayout->addWidget(new QLabel(

View file

@ -214,8 +214,10 @@ void DBusPropertyGroup::updatePropertySet(const QVariantMap& properties, bool co
}
}
void DBusPropertyGroup::tryUpdateProperty(DBusPropertyCore* property, const QVariant& variant)
const {
void DBusPropertyGroup::tryUpdateProperty(
DBusPropertyCore* property,
const QVariant& variant
) const {
property->mExists = true;
auto error = property->store(variant);

View file

@ -217,7 +217,7 @@ protected:
private:
[[nodiscard]] constexpr Owner* owner() const {
auto* self = std::bit_cast<char*>(this);
auto* self = std::bit_cast<char*>(this); // NOLINT
return std::bit_cast<Owner*>(self - offset()); // NOLINT
}

View file

@ -36,7 +36,8 @@ void IpcServer::start() {
auto path = run->filePath("ipc.sock");
new IpcServer(path);
} else {
qCCritical(logIpc
qCCritical(
logIpc
) << "Could not start IPC server as the instance runtime path could not be created.";
}
}

View file

@ -90,9 +90,9 @@ int locateConfigFile(CommandState& cmd, QString& path) {
}
if (!manifestPath.isEmpty()) {
qWarning(
) << "Config manifests (manifest.conf) are deprecated and will be removed in a future "
"release.";
qWarning()
<< "Config manifests (manifest.conf) are deprecated and will be removed in a future "
"release.";
qWarning() << "Consider using symlinks to a subfolder of quickshell's XDG config dirs.";
auto file = QFile(manifestPath);
@ -130,7 +130,8 @@ int locateConfigFile(CommandState& cmd, QString& path) {
if (path.isEmpty()) {
if (name == "default") {
qCCritical(logBare
qCCritical(
logBare
) << "Could not find \"default\" config directory or shell.qml in any valid config path.";
} else {
qCCritical(logBare) << "Could not find" << name

View file

@ -43,9 +43,11 @@ int parseCommand(int argc, char** argv, CommandState& state) {
->excludes(path);
group->add_option("-m,--manifest", state.config.manifest)
->description("[DEPRECATED] Path to a quickshell manifest.\n"
"If a manifest is specified, configs named by -c will point to its entries.\n"
"Defaults to $XDG_CONFIG_HOME/quickshell/manifest.conf")
->description(
"[DEPRECATED] Path to a quickshell manifest.\n"
"If a manifest is specified, configs named by -c will point to its entries.\n"
"Defaults to $XDG_CONFIG_HOME/quickshell/manifest.conf"
)
->envname("QS_MANIFEST")
->excludes(path);
@ -54,8 +56,10 @@ int parseCommand(int argc, char** argv, CommandState& state) {
->description("Operate on the most recently launched instance instead of the oldest");
group->add_flag("--any-display", state.config.anyDisplay)
->description("If passed, instances will not be filtered by the display connection they "
"were launched on.");
->description(
"If passed, instances will not be filtered by the display connection they "
"were launched on."
);
}
return group;
@ -79,9 +83,11 @@ int parseCommand(int argc, char** argv, CommandState& state) {
auto* group = noGroup ? cmd : cmd->add_option_group(noDisplay ? "" : "Logging");
group->add_flag("--no-color", state.log.noColor)
->description("Disables colored logging.\n"
"Colored logging can also be disabled by specifying a non empty value "
"for the NO_COLOR environment variable.");
->description(
"Disables colored logging.\n"
"Colored logging can also be disabled by specifying a non empty value "
"for the NO_COLOR environment variable."
);
group->add_flag("--log-times", state.log.timestamp)
->description("Log timestamps with each message.");
@ -90,9 +96,11 @@ int parseCommand(int argc, char** argv, CommandState& state) {
->description("Log rules to apply, in the format of QT_LOGGING_RULES.");
group->add_flag("-v,--verbose", [&](size_t count) { state.log.verbosity = count; })
->description("Increases log verbosity.\n"
"-v will show INFO level internal logs.\n"
"-vv will show DEBUG level internal logs.");
->description(
"Increases log verbosity.\n"
"-v will show INFO level internal logs.\n"
"-vv will show DEBUG level internal logs."
);
auto* hgroup = cmd->add_option_group("");
hgroup->add_flag("--no-detailed-logs", state.log.sparse);
@ -102,9 +110,11 @@ int parseCommand(int argc, char** argv, CommandState& state) {
auto* group = cmd->add_option_group("Instance Selection");
group->add_option("-i,--id", state.instance.id)
->description("The instance id to operate on.\n"
"You may also use a substring the id as long as it is unique, "
"for example \"abc\" will select \"abcdefg\".");
->description(
"The instance id to operate on.\n"
"You may also use a substring the id as long as it is unique, "
"for example \"abc\" will select \"abcdefg\"."
);
group->add_option("--pid", state.instance.pid)
->description("The process id of the instance to operate on.");
@ -161,9 +171,11 @@ int parseCommand(int argc, char** argv, CommandState& state) {
auto* sub = cli->add_subcommand("list", "List running quickshell instances.");
auto* all = sub->add_flag("-a,--all", state.instance.all)
->description("List all instances.\n"
"If unspecified, only instances of"
"the selected config will be listed.");
->description(
"List all instances.\n"
"If unspecified, only instances of"
"the selected config will be listed."
);
sub->add_flag("-j,--json", state.output.json, "Output the list as a json.");
@ -239,8 +251,10 @@ int parseCommand(int argc, char** argv, CommandState& state) {
->allow_extra_args();
sub->add_flag("-s,--show", state.ipc.showOld)
->description("Print information about a function or target if given, or all available "
"targets if not.");
->description(
"Print information about a function or target if given, or all available "
"targets if not."
);
auto* instance = addInstanceSelection(sub);
addConfigSelection(sub, true)->excludes(instance);

View file

@ -199,7 +199,8 @@ void GreetdConnection::onSocketReady() {
// Special case this error in case a session was already running.
// This cancels and restarts the session.
if (errorType == "error" && desc == "a session is already being configured") {
qCDebug(logGreetd
qCDebug(
logGreetd
) << "A session was already in progress, cancelling it and starting a new one.";
this->setActive(false);
this->setActive(true);

View file

@ -117,10 +117,12 @@ void NotificationServer::tryRegister() {
if (success) {
qCInfo(logNotifications) << "Registered notification server with dbus.";
} else {
qCWarning(logNotifications
qCWarning(
logNotifications
) << "Could not register notification server at org.freedesktop.Notifications, presumably "
"because one is already registered.";
qCWarning(logNotifications
qCWarning(
logNotifications
) << "Registration will be attempted again if the active service is unregistered.";
}
}

View file

@ -201,7 +201,8 @@ bool PwDefaultTracker::setConfiguredDefault(const char* key, const QString& valu
}
if (!meta->hasSetPermission()) {
qCCritical(logDefaults
qCCritical(
logDefaults
) << "Cannot set default node as write+execute permissions are missing for"
<< meta;
return false;

View file

@ -107,7 +107,7 @@ void PwDevice::addDeviceIndexPairs(const spa_pod* param) {
qint32 device = 0;
qint32 index = 0;
spa_pod* props = nullptr;
const spa_pod* props = nullptr;
// clang-format off
quint32 id = SPA_PARAM_Route;
@ -125,12 +125,22 @@ void PwDevice::addDeviceIndexPairs(const spa_pod* param) {
// Insert into the main map as well, staging's purpose is to remove old entries.
this->routeDeviceIndexes.insert(device, index);
// Used for initial node volume if the device is bound before the node
// (e.g. multiple nodes pointing to the same device)
this->routeDeviceVolumes.insert(device, volumeProps);
qCDebug(logDevice).nospace() << "Registered device/index pair for " << this
<< ": [device: " << device << ", index: " << index << ']';
emit this->routeVolumesChanged(device, volumeProps);
}
bool PwDevice::tryLoadVolumeProps(qint32 routeDevice, PwVolumeProps& volumeProps) {
if (!this->routeDeviceVolumes.contains(routeDevice)) return false;
volumeProps = this->routeDeviceVolumes.value(routeDevice);
return true;
}
void PwDevice::polled() {
// It is far more likely that the list content has not come in yet than it having no entries,
// and there isn't a way to check in the case that there *aren't* actually any entries.

View file

@ -32,6 +32,8 @@ public:
void waitForDevice();
[[nodiscard]] bool waitingForDevice() const;
[[nodiscard]] bool tryLoadVolumeProps(qint32 routeDevice, PwVolumeProps& volumeProps);
signals:
void deviceReady();
void routeVolumesChanged(qint32 routeDevice, const PwVolumeProps& volumeProps);
@ -46,6 +48,7 @@ private:
onParam(void* data, qint32 seq, quint32 id, quint32 index, quint32 next, const spa_pod* param);
QHash<qint32, qint32> routeDeviceIndexes;
QHash<qint32, PwVolumeProps> routeDeviceVolumes;
QList<qint32> stagingIndexes;
void addDeviceIndexPairs(const spa_pod* param);

View file

@ -172,7 +172,8 @@ void PwNode::initProps(const spa_dict* props) {
this->device = this->registry->devices.value(id);
if (this->device == nullptr) {
qCCritical(logNode
qCCritical(
logNode
) << this
<< "has a device.id property that does not corrospond to a device object. Id:" << id;
}
@ -212,12 +213,14 @@ void PwNode::onInfo(void* data, const pw_node_info* info) {
auto id = QString::fromUtf8(routeDevice).toInt(&ok);
if (!ok) {
qCCritical(logNode
qCCritical(
logNode
) << self
<< "has a card.profile.device property but the value is not an integer. Value:" << id;
}
self->routeDevice = id;
if (self->boundData) self->boundData->onDeviceChanged();
} else {
qCCritical(logNode) << self << "has attached device" << self->device
<< "but no card.profile.device property.";
@ -277,6 +280,15 @@ PwNodeBoundAudio::PwNodeBoundAudio(PwNode* node): QObject(node), node(node) {
}
}
void PwNodeBoundAudio::onDeviceChanged() {
PwVolumeProps volumeProps;
if (this->node->device->tryLoadVolumeProps(this->node->routeDevice, volumeProps)) {
qCDebug(logNode) << "Initializing volume props for" << this->node
<< "with known values from backing device.";
this->updateVolumeProps(volumeProps);
}
}
void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
if ((info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) != 0) {
for (quint32 i = 0; i < info->n_params; i++) {
@ -299,7 +311,8 @@ void PwNodeBoundAudio::onSpaParam(quint32 id, quint32 index, const spa_pod* para
if (id == SPA_PARAM_Props && index == 0) {
if (this->node->shouldUseDevice()) {
qCDebug(logNode) << "Skipping node volume props update for" << this->node
<< "in favor of device updates.";
<< "in favor of device updates from routeDevice" << this->node->routeDevice
<< "of" << this->node->device;
return;
}

View file

@ -169,6 +169,7 @@ public:
virtual ~PwNodeBoundData() = default;
Q_DISABLE_COPY_MOVE(PwNodeBoundData);
virtual void onDeviceChanged() {};
virtual void onInfo(const pw_node_info* /*info*/) {}
virtual void onSpaParam(quint32 /*id*/, quint32 /*index*/, const spa_pod* /*param*/) {}
virtual void onUnbind() {}
@ -182,6 +183,7 @@ class PwNodeBoundAudio
public:
explicit PwNodeBoundAudio(PwNode* node);
void onDeviceChanged() override;
void onInfo(const pw_node_info* info) override;
void onSpaParam(quint32 id, quint32 index, const spa_pod* param) override;
void onUnbind() override;

View file

@ -143,7 +143,8 @@ void PolkitAgentImpl::activateAuthenticationRequest() {
if (obj) identities.append(obj);
}
if (identities.isEmpty()) {
qCWarning(logPolkit
qCWarning(
logPolkit
) << "no supported identities available for authentication request, cancelling.";
req->cancel("Error requesting authentication: no supported identities available.");
delete req;

View file

@ -231,4 +231,4 @@ void AuthRequest::cancel(const QString& reason) {
// NOLINTEND(readability-make-member-function-const)
} // namespace qs::service::polkit
// NOLINTEND(readability-identifier-naming,misc-use-anonymous-namespace)
// NOLINTEND(readability-identifier-naming,misc-use-anonymous-namespace)

View file

@ -126,8 +126,8 @@ DBusDataTransform<UPowerDeviceState::Enum>::fromWire(quint32 wire) {
);
}
DBusResult<UPowerDeviceType::Enum> DBusDataTransform<UPowerDeviceType::Enum>::fromWire(quint32 wire
) {
DBusResult<UPowerDeviceType::Enum>
DBusDataTransform<UPowerDeviceType::Enum>::fromWire(quint32 wire) {
if (wire >= UPowerDeviceType::Unknown && wire <= UPowerDeviceType::BluetoothGeneric) {
return DBusResult(static_cast<UPowerDeviceType::Enum>(wire));
}

View file

@ -66,7 +66,8 @@ PowerProfiles::PowerProfiles() {
auto bus = QDBusConnection::systemBus();
if (!bus.isConnected()) {
qCWarning(logPowerProfiles
qCWarning(
logPowerProfiles
) << "Could not connect to DBus. PowerProfiles services will not work.";
}
@ -79,7 +80,8 @@ PowerProfiles::PowerProfiles() {
);
if (!this->service->isValid()) {
qCDebug(logPowerProfiles
qCDebug(
logPowerProfiles
) << "PowerProfilesDaemon is not currently running, attempting to start it.";
dbus::tryLaunchService(this, bus, "org.freedesktop.UPower.PowerProfiles", [this](bool success) {
@ -103,13 +105,15 @@ void PowerProfiles::init() {
void PowerProfiles::setProfile(PowerProfile::Enum profile) {
if (!this->properties.isConnected()) {
qCCritical(logPowerProfiles
qCCritical(
logPowerProfiles
) << "Cannot set power profile: power-profiles-daemon not accessible or not running";
return;
}
if (profile == PowerProfile::Performance && !this->bHasPerformanceProfile) {
qCCritical(logPowerProfiles
qCCritical(
logPowerProfiles
) << "Cannot request performance profile as it is not present for this device.";
return;
} else if (profile < PowerProfile::PowerSaver || profile > PowerProfile::Performance) {
@ -135,8 +139,9 @@ PowerProfilesQml::PowerProfilesQml(QObject* parent): QObject(parent) {
return instance->bHasPerformanceProfile.value();
});
this->bDegradationReason.setBinding([instance]() { return instance->bDegradationReason.value(); }
);
this->bDegradationReason.setBinding([instance]() {
return instance->bDegradationReason.value();
});
this->bHolds.setBinding([instance]() { return instance->bHolds.value(); });
}

View file

@ -414,7 +414,8 @@ WlBuffer* LinuxDmabufManager::createDmabuf(
if (modifiers.modifiers.isEmpty()) {
if (!modifiers.implicit) {
qCritical(logDmabuf
qCritical(
logDmabuf
) << "Failed to create gbm_bo: format supports no implicit OR explicit modifiers.";
return nullptr;
}

View file

@ -65,7 +65,8 @@ void HyprlandWindow::setOpacity(qreal opacity) {
if (opacity == this->mOpacity) return;
if (opacity < 0.0 || opacity > 1.0) {
qmlWarning(this
qmlWarning(
this
) << "Cannot set HyprlandWindow.opacity to a value larger than 1.0 or smaller than 0.0";
return;
}

View file

@ -165,7 +165,8 @@ WlrScreencopyContext::OutputTransformQuery::~OutputTransformQuery() {
if (this->isInitialized()) this->release();
}
void WlrScreencopyContext::OutputTransformQuery::setScreen(QtWaylandClient::QWaylandScreen* screen
void WlrScreencopyContext::OutputTransformQuery::setScreen(
QtWaylandClient::QWaylandScreen* screen
) {
// cursed hack
class QWaylandScreenReflector: public QtWaylandClient::QWaylandScreen {

View file

@ -79,8 +79,8 @@ void WlSessionLock::updateSurfaces(bool show, WlSessionLock* old) {
auto* instance = qobject_cast<WlSessionLockSurface*>(instanceObj);
if (instance == nullptr) {
qWarning(
) << "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
qWarning()
<< "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
if (instanceObj != nullptr) instanceObj->deleteLater();
this->unlock();
return;

View file

@ -8,6 +8,6 @@
class QSWaylandSessionLockIntegration: public QtWaylandClient::QWaylandShellIntegration {
public:
bool initialize(QtWaylandClient::QWaylandDisplay* /* display */) override { return true; }
QtWaylandClient::QWaylandShellSurface* createShellSurface(QtWaylandClient::QWaylandWindow* window
) override;
QtWaylandClient::QWaylandShellSurface*
createShellSurface(QtWaylandClient::QWaylandWindow* window) override;
};

View file

@ -33,8 +33,8 @@ signals:
protected:
explicit ToplevelManager();
void zwlr_foreign_toplevel_manager_v1_toplevel(::zwlr_foreign_toplevel_handle_v1* toplevel
) override;
void
zwlr_foreign_toplevel_manager_v1_toplevel(::zwlr_foreign_toplevel_handle_v1* toplevel) override;
private slots:
void onToplevelReady();

View file

@ -15,8 +15,8 @@ public:
~LayerShellIntegration() override;
Q_DISABLE_COPY_MOVE(LayerShellIntegration);
QtWaylandClient::QWaylandShellSurface* createShellSurface(QtWaylandClient::QWaylandWindow* window
) override;
QtWaylandClient::QWaylandShellSurface*
createShellSurface(QtWaylandClient::QWaylandWindow* window) override;
};
} // namespace qs::wayland::layershell

View file

@ -30,8 +30,8 @@ namespace qs::wayland::layershell {
namespace {
[[nodiscard]] QtWayland::zwlr_layer_shell_v1::layer toWaylandLayer(const WlrLayer::Enum& layer
) noexcept {
[[nodiscard]] QtWayland::zwlr_layer_shell_v1::layer
toWaylandLayer(const WlrLayer::Enum& layer) noexcept {
switch (layer) {
case WlrLayer::Background: return QtWayland::zwlr_layer_shell_v1::layer_background;
case WlrLayer::Bottom: return QtWayland::zwlr_layer_shell_v1::layer_bottom;
@ -42,8 +42,8 @@ namespace {
return QtWayland::zwlr_layer_shell_v1::layer_top;
}
[[nodiscard]] QtWayland::zwlr_layer_surface_v1::anchor toWaylandAnchors(const Anchors& anchors
) noexcept {
[[nodiscard]] QtWayland::zwlr_layer_surface_v1::anchor
toWaylandAnchors(const Anchors& anchors) noexcept {
quint32 wl = 0;
if (anchors.mLeft) wl |= QtWayland::zwlr_layer_surface_v1::anchor_left;
if (anchors.mRight) wl |= QtWayland::zwlr_layer_surface_v1::anchor_right;
@ -146,8 +146,8 @@ LayerSurface::LayerSurface(LayerShellIntegration* shell, QtWaylandClient::QWayla
if (waylandScreen != nullptr) {
output = waylandScreen->output();
} else {
qWarning(
) << "Layershell screen does not corrospond to a real screen. Letting the compositor pick.";
qWarning()
<< "Layershell screen does not corrospond to a real screen. Letting the compositor pick.";
}
}

View file

@ -12,8 +12,8 @@ namespace qs::widgets {
MarginWrapperManager::MarginWrapperManager(QObject* parent): WrapperManager(parent) {
this->bTopMargin.setBinding([this] {
return this->bExtraMargin
+ (this->bOverrides.value().testFlag(TopMargin) ? this->bTopMarginOverride : this->bMargin
);
+ (this->bOverrides.value().testFlag(TopMargin) ? this->bTopMarginOverride
: this->bMargin);
});
this->bBottomMargin.setBinding([this] {

View file

@ -67,7 +67,8 @@ void ProxyPopupWindow::updateTransientParent() {
void ProxyPopupWindow::onParentUpdated() { this->updateTransientParent(); }
void ProxyPopupWindow::setScreen(QuickshellScreenInfo* /*unused*/) {
qmlWarning(this
qmlWarning(
this
) << "Cannot set screen of popup window, as that is controlled by the parent window";
}