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 AlignArrayOfStructures: None
AlignAfterOpenBracket: BlockIndent AlignAfterOpenBracket: BlockIndent
AllowShortBlocksOnASingleLine: Always AllowShortBlocksOnASingleLine: Empty
AllowShortCaseLabelsOnASingleLine: true AllowShortCaseLabelsOnASingleLine: true
AllowShortEnumsOnASingleLine: true AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All AllowShortFunctionsOnASingleLine: All

View file

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

View file

@ -6,7 +6,7 @@ jobs:
name: Nix name: Nix
strategy: strategy:
matrix: 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] compiler: [clang, gcc]
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:

View file

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

View file

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

6
flake.lock generated
View file

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

View file

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

View file

@ -22,8 +22,8 @@ class PixmapCacheIconEngine: public QIconEngine {
QIcon::Mode /*unused*/, QIcon::Mode /*unused*/,
QIcon::State /*unused*/ QIcon::State /*unused*/
) override { ) override {
qFatal( qFatal()
) << "Unexpected icon paint request bypassed pixmap method. Please report this as a bug."; << "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 { 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(); auto* runDir = QsPaths::instance()->instanceRunDir();
if (!runDir) { if (!runDir) {
qCCritical(logLogging qCCritical(
logLogging
) << "Could not start filesystem logging as the runtime directory could not be created."; ) << "Could not start filesystem logging as the runtime directory could not be created.";
return; return;
} }
@ -372,7 +373,8 @@ void ThreadLogging::initFs() {
auto* detailedFile = new QFile(detailedPath); auto* detailedFile = new QFile(detailedPath);
if (!file->open(QFile::ReadWrite | QFile::Truncate)) { if (!file->open(QFile::ReadWrite | QFile::Truncate)) {
qCCritical(logLogging qCCritical(
logLogging
) << "Could not start filesystem logger as the log file could not be created:" ) << "Could not start filesystem logger as the log file could not be created:"
<< path; << path;
delete file; delete file;
@ -383,7 +385,8 @@ void ThreadLogging::initFs() {
// buffered by WriteBuffer // buffered by WriteBuffer
if (!detailedFile->open(QFile::ReadWrite | QFile::Truncate | QFile::Unbuffered)) { 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:" ) << "Could not start detailed filesystem logger as the log file could not be created:"
<< detailedPath; << detailedPath;
delete detailedFile; delete detailedFile;
@ -746,11 +749,11 @@ bool EncodedLogReader::readVarInt(quint32* slot) {
if (!this->reader.skip(1)) return false; if (!this->reader.skip(1)) return false;
*slot = qFromLittleEndian(n); *slot = qFromLittleEndian(n);
} else if ((bytes[1] != 0xff || bytes[2] != 0xff) && readLength >= 3) { } 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; if (!this->reader.skip(3)) return false;
*slot = qFromLittleEndian(n); *slot = qFromLittleEndian(n);
} else if (readLength == 7) { } 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; if (!this->reader.skip(7)) return false;
*slot = qFromLittleEndian(n); *slot = qFromLittleEndian(n);
} else return false; } else return false;

View file

@ -1,81 +1,14 @@
#include "model.hpp" #include "model.hpp"
#include <qabstractitemmodel.h> #include <qbytearray.h>
#include <qhash.h> #include <qhash.h>
#include <qnamespace.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 { QHash<int, QByteArray> UntypedObjectModel::roleNames() const {
return {{Qt::UserRole, "modelData"}}; 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() { UntypedObjectModel* UntypedObjectModel::emptyInstance() {
static auto* instance = new UntypedObjectModel(nullptr); // NOLINT static auto* instance = new ObjectModel<void>(nullptr);
return instance; return instance;
} }

View file

@ -2,7 +2,7 @@
#include <functional> #include <functional>
#include <bit> #include <QtCore/qtmetamacros.h>
#include <qabstractitemmodel.h> #include <qabstractitemmodel.h>
#include <qcontainerfwd.h> #include <qcontainerfwd.h>
#include <qobject.h> #include <qobject.h>
@ -49,14 +49,11 @@ class UntypedObjectModel: public QAbstractListModel {
public: public:
explicit UntypedObjectModel(QObject* parent): QAbstractListModel(parent) {} 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]] QHash<int, QByteArray> roleNames() const override;
[[nodiscard]] QList<QObject*> values() const { return this->valuesList; } [[nodiscard]] virtual QList<QObject*> values() = 0;
void removeAt(qsizetype index);
Q_INVOKABLE qsizetype indexOf(QObject* object); Q_INVOKABLE virtual qsizetype indexOf(QObject* object) const = 0;
static UntypedObjectModel* emptyInstance(); static UntypedObjectModel* emptyInstance();
@ -71,15 +68,6 @@ signals:
/// Sent immediately after an object is removed from the list. /// Sent immediately after an object is removed from the list.
void objectRemovedPost(QObject* object, qsizetype index); 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: private:
static qsizetype valuesCount(QQmlListProperty<QObject>* property); static qsizetype valuesCount(QQmlListProperty<QObject>* property);
static QObject* valueAt(QQmlListProperty<QObject>* property, qsizetype index); static QObject* valueAt(QQmlListProperty<QObject>* property, qsizetype index);
@ -90,14 +78,20 @@ class ObjectModel: public UntypedObjectModel {
public: public:
explicit ObjectModel(QObject* parent): UntypedObjectModel(parent) {} explicit ObjectModel(QObject* parent): UntypedObjectModel(parent) {}
[[nodiscard]] QVector<T*>& valueList() { return *std::bit_cast<QVector<T*>*>(&this->valuesList); } [[nodiscard]] const QList<T*>& valueList() const { return this->mValuesList; }
[[nodiscard]] QList<T*>& valueList() { return this->mValuesList; }
[[nodiscard]] const QVector<T*>& valueList() const {
return *std::bit_cast<const QVector<T*>*>(&this->valuesList);
}
void insertObject(T* object, qsizetype index = -1) { 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) { void insertObjectSorted(T* object, const std::function<bool(T*, T*)>& compare) {
@ -110,17 +104,71 @@ public:
} }
auto idx = iter - list.begin(); 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 // Assumes only one instance of a specific value
void diffUpdate(const QVector<T*>& newValues) { void diffUpdate(const QList<T*>& newValues) {
this->UntypedObjectModel::diffUpdate(*std::bit_cast<const QVector<QObject*>*>(&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() { static ObjectModel<T>* emptyInstance() {
return static_cast<ObjectModel<T>*>(UntypedObjectModel::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", "model.hpp",
"elapsedtimer.hpp", "elapsedtimer.hpp",
"desktopentry.hpp", "desktopentry.hpp",
"objectrepeater.hpp",
"qsmenu.hpp", "qsmenu.hpp",
"retainable.hpp", "retainable.hpp",
"popupanchor.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(); auto* shellDir = this->shellRunDir();
if (!shellDir) { if (!shellDir) {
qCCritical(logPaths qCCritical(
logPaths
) << "Could not create by-id symlink as the shell runtime path could not be created."; ) << "Could not create by-id symlink as the shell runtime path could not be created.";
} else { } else {
auto shellPath = shellDir->filePath(runDir->dirName()); auto shellPath = shellDir->filePath(runDir->dirName());
@ -378,7 +379,8 @@ void QsPaths::createLock() {
qCDebug(logPaths) << "Created instance lock at" << path; qCDebug(logPaths) << "Created instance lock at" << path;
} }
} else { } else {
qCCritical(logPaths qCCritical(
logPaths
) << "Could not create instance lock, as the instance runtime directory could not be created."; ) << "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)) { for (auto& name: dir.entryList(QDir::Files | QDir::NoDotAndDotDot)) {
if (name == "qmldir") { if (name == "qmldir") {
qCDebug(logQmlScanner qCDebug(
logQmlScanner
) << "Found qmldir file, qmldir synthesization will be disabled for directory" ) << "Found qmldir file, qmldir synthesization will be disabled for directory"
<< path; << path;
seenQmldir = true; seenQmldir = true;

View file

@ -72,8 +72,8 @@ void ScriptModel::updateValuesUnique(const QVariantList& newValues) {
do { do {
++iter; ++iter;
} while (iter != this->mValues.end() } 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 index = static_cast<qint32>(std::distance(this->mValues.begin(), iter));
auto startIndex = static_cast<qint32>(std::distance(this->mValues.begin(), startIter)); 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 { [[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 { [[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); this->d->minidumpFd = memfd_create("quickshell:minidump", MFD_CLOEXEC);
if (this->d->minidumpFd == -1) { if (this->d->minidumpFd == -1) {
qCCritical(logCrashHandler qCCritical(
logCrashHandler
) << "Failed to allocate minidump memfd, minidumps will be saved in the working directory."; ) << "Failed to allocate minidump memfd, minidumps will be saved in the working directory.";
createHandler(MinidumpDescriptor(".")); createHandler(MinidumpDescriptor("."));
} else { } else {
@ -71,7 +72,8 @@ void CrashHandler::setRelaunchInfo(const RelaunchInfo& info) {
this->d->infoFd = memfd_create("quickshell:instance_info", MFD_CLOEXEC); this->d->infoFd = memfd_create("quickshell:instance_info", MFD_CLOEXEC);
if (this->d->infoFd == -1) { if (this->d->infoFd == -1) {
qCCritical(logCrashHandler qCCritical(
logCrashHandler
) << "Failed to allocate instance info memfd, crash recovery will not work."; ) << "Failed to allocate instance info memfd, crash recovery will not work.";
return; return;
} }
@ -79,7 +81,8 @@ void CrashHandler::setRelaunchInfo(const RelaunchInfo& info) {
QFile file; QFile file;
if (!file.open(this->d->infoFd, QFile::ReadWrite)) { if (!file.open(this->d->infoFd, QFile::ReadWrite)) {
qCCritical(logCrashHandler qCCritical(
logCrashHandler
) << "Failed to open instance info memfd, crash recovery will not work."; ) << "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); mainLayout->addSpacing(textHeight);
if (qtVersionMatches) { 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 { } else {
mainLayout->addWidget(new QLabel( 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) void DBusPropertyGroup::tryUpdateProperty(
const { DBusPropertyCore* property,
const QVariant& variant
) const {
property->mExists = true; property->mExists = true;
auto error = property->store(variant); auto error = property->store(variant);

View file

@ -217,7 +217,7 @@ protected:
private: private:
[[nodiscard]] constexpr Owner* owner() const { [[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 return std::bit_cast<Owner*>(self - offset()); // NOLINT
} }

View file

@ -36,7 +36,8 @@ void IpcServer::start() {
auto path = run->filePath("ipc.sock"); auto path = run->filePath("ipc.sock");
new IpcServer(path); new IpcServer(path);
} else { } else {
qCCritical(logIpc qCCritical(
logIpc
) << "Could not start IPC server as the instance runtime path could not be created."; ) << "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()) { if (!manifestPath.isEmpty()) {
qWarning( qWarning()
) << "Config manifests (manifest.conf) are deprecated and will be removed in a future " << "Config manifests (manifest.conf) are deprecated and will be removed in a future "
"release."; "release.";
qWarning() << "Consider using symlinks to a subfolder of quickshell's XDG config dirs."; qWarning() << "Consider using symlinks to a subfolder of quickshell's XDG config dirs.";
auto file = QFile(manifestPath); auto file = QFile(manifestPath);
@ -130,7 +130,8 @@ int locateConfigFile(CommandState& cmd, QString& path) {
if (path.isEmpty()) { if (path.isEmpty()) {
if (name == "default") { if (name == "default") {
qCCritical(logBare qCCritical(
logBare
) << "Could not find \"default\" config directory or shell.qml in any valid config path."; ) << "Could not find \"default\" config directory or shell.qml in any valid config path.";
} else { } else {
qCCritical(logBare) << "Could not find" << name qCCritical(logBare) << "Could not find" << name

View file

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

View file

@ -117,10 +117,12 @@ void NotificationServer::tryRegister() {
if (success) { if (success) {
qCInfo(logNotifications) << "Registered notification server with dbus."; qCInfo(logNotifications) << "Registered notification server with dbus.";
} else { } else {
qCWarning(logNotifications qCWarning(
logNotifications
) << "Could not register notification server at org.freedesktop.Notifications, presumably " ) << "Could not register notification server at org.freedesktop.Notifications, presumably "
"because one is already registered."; "because one is already registered.";
qCWarning(logNotifications qCWarning(
logNotifications
) << "Registration will be attempted again if the active service is unregistered."; ) << "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()) { if (!meta->hasSetPermission()) {
qCCritical(logDefaults qCCritical(
logDefaults
) << "Cannot set default node as write+execute permissions are missing for" ) << "Cannot set default node as write+execute permissions are missing for"
<< meta; << meta;
return false; return false;

View file

@ -107,7 +107,7 @@ void PwDevice::addDeviceIndexPairs(const spa_pod* param) {
qint32 device = 0; qint32 device = 0;
qint32 index = 0; qint32 index = 0;
spa_pod* props = nullptr; const spa_pod* props = nullptr;
// clang-format off // clang-format off
quint32 id = SPA_PARAM_Route; 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. // Insert into the main map as well, staging's purpose is to remove old entries.
this->routeDeviceIndexes.insert(device, index); 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 qCDebug(logDevice).nospace() << "Registered device/index pair for " << this
<< ": [device: " << device << ", index: " << index << ']'; << ": [device: " << device << ", index: " << index << ']';
emit this->routeVolumesChanged(device, volumeProps); 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() { void PwDevice::polled() {
// It is far more likely that the list content has not come in yet than it having no entries, // 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. // 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(); void waitForDevice();
[[nodiscard]] bool waitingForDevice() const; [[nodiscard]] bool waitingForDevice() const;
[[nodiscard]] bool tryLoadVolumeProps(qint32 routeDevice, PwVolumeProps& volumeProps);
signals: signals:
void deviceReady(); void deviceReady();
void routeVolumesChanged(qint32 routeDevice, const PwVolumeProps& volumeProps); 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); onParam(void* data, qint32 seq, quint32 id, quint32 index, quint32 next, const spa_pod* param);
QHash<qint32, qint32> routeDeviceIndexes; QHash<qint32, qint32> routeDeviceIndexes;
QHash<qint32, PwVolumeProps> routeDeviceVolumes;
QList<qint32> stagingIndexes; QList<qint32> stagingIndexes;
void addDeviceIndexPairs(const spa_pod* param); 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); this->device = this->registry->devices.value(id);
if (this->device == nullptr) { if (this->device == nullptr) {
qCCritical(logNode qCCritical(
logNode
) << this ) << this
<< "has a device.id property that does not corrospond to a device object. Id:" << id; << "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); auto id = QString::fromUtf8(routeDevice).toInt(&ok);
if (!ok) { if (!ok) {
qCCritical(logNode qCCritical(
logNode
) << self ) << self
<< "has a card.profile.device property but the value is not an integer. Value:" << id; << "has a card.profile.device property but the value is not an integer. Value:" << id;
} }
self->routeDevice = id; self->routeDevice = id;
if (self->boundData) self->boundData->onDeviceChanged();
} else { } else {
qCCritical(logNode) << self << "has attached device" << self->device qCCritical(logNode) << self << "has attached device" << self->device
<< "but no card.profile.device property."; << "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) { void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
if ((info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) != 0) { if ((info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) != 0) {
for (quint32 i = 0; i < info->n_params; i++) { 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 (id == SPA_PARAM_Props && index == 0) {
if (this->node->shouldUseDevice()) { if (this->node->shouldUseDevice()) {
qCDebug(logNode) << "Skipping node volume props update for" << this->node 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; return;
} }

View file

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

View file

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

View file

@ -231,4 +231,4 @@ void AuthRequest::cancel(const QString& reason) {
// NOLINTEND(readability-make-member-function-const) // NOLINTEND(readability-make-member-function-const)
} // namespace qs::service::polkit } // 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) { if (wire >= UPowerDeviceType::Unknown && wire <= UPowerDeviceType::BluetoothGeneric) {
return DBusResult(static_cast<UPowerDeviceType::Enum>(wire)); return DBusResult(static_cast<UPowerDeviceType::Enum>(wire));
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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