Save presets

This commit is contained in:
Joey Yakimowich-Payne 2026-01-27 21:11:20 -07:00
commit b3a1d2b7f3
9 changed files with 542 additions and 4 deletions

View file

@ -144,12 +144,19 @@ QWidget *PipeWireGraphModel::nodeWidget(QtNodes::NodeId nodeId) const
slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
slider->setToolTip(QString("Volume"));
if (pipewireId != 0 && m_nodeVolumeState.contains(pipewireId)) {
const NodeVolumeState state = m_nodeVolumeState.value(pipewireId);
slider->setValue(static_cast<int>(state.volume * 100.0f));
muteButton->setChecked(state.mute);
}
const auto applyVolume = [this, pipewireId, slider, muteButton]() {
if (!m_controller || pipewireId == 0) {
return;
}
const float volume = static_cast<float>(slider->value()) / 100.0f;
m_controller->setNodeVolume(pipewireId, volume, muteButton->isChecked());
m_nodeVolumeState.insert(pipewireId, NodeVolumeState{volume, muteButton->isChecked()});
};
QObject::connect(slider, &QSlider::valueChanged, widget, [applyVolume](int) { applyVolume(); });
@ -694,6 +701,135 @@ void PipeWireGraphModel::loadLayout()
}
}
QJsonObject PipeWireGraphModel::layoutJson() const
{
QJsonObject root;
QJsonArray nodes;
for (auto it = m_layoutByStableId.cbegin(); it != m_layoutByStableId.cend(); ++it) {
QJsonObject item;
item["id"] = it.key();
item["x"] = it.value().x();
item["y"] = it.value().y();
nodes.append(item);
}
root["nodes"] = nodes;
QJsonObject view;
view["scale"] = m_viewScale;
view["center_x"] = m_viewCenter.x();
view["center_y"] = m_viewCenter.y();
root["view"] = view;
if (m_hasSplitterSizes && !m_splitterSizes.isEmpty()) {
QJsonArray splitter;
for (const auto size : m_splitterSizes) {
splitter.append(size);
}
root["splitter"] = splitter;
}
return root;
}
void PipeWireGraphModel::applyLayoutJson(const QJsonObject &root)
{
m_layoutByStableId.clear();
m_hasViewState = false;
m_hasSplitterSizes = false;
m_splitterSizes.clear();
const QJsonArray nodes = root.value("nodes").toArray();
applyLayoutData(nodes);
const QJsonObject view = root.value("view").toObject();
if (!view.isEmpty()) {
m_viewScale = view.value("scale").toDouble(1.0);
const double x = view.value("center_x").toDouble(0.0);
const double y = view.value("center_y").toDouble(0.0);
m_viewCenter = QPointF(x, y);
m_hasViewState = true;
}
const QJsonArray splitter = root.value("splitter").toArray();
if (!splitter.isEmpty()) {
QList<int> sizes;
sizes.reserve(splitter.size());
for (const auto &value : splitter) {
sizes.append(value.toInt());
}
if (!sizes.isEmpty()) {
m_splitterSizes = sizes;
m_hasSplitterSizes = true;
}
}
for (const auto &entry : m_nodes) {
const QtNodes::NodeId nodeId = entry.first;
const Potato::NodeInfo &info = entry.second;
if (!info.stableId.isEmpty() && m_layoutByStableId.contains(info.stableId)) {
const QPointF position = m_layoutByStableId.value(info.stableId);
m_positions[nodeId] = position;
Q_EMIT nodePositionUpdated(nodeId);
}
}
}
QHash<QString, NodeVolumeState> PipeWireGraphModel::volumeStates() const
{
QHash<QString, NodeVolumeState> result;
for (const auto &entry : m_nodes) {
const Potato::NodeInfo &info = entry.second;
if (info.stableId.isEmpty()) {
continue;
}
if (!m_nodeVolumeState.contains(info.id)) {
continue;
}
result.insert(info.stableId, m_nodeVolumeState.value(info.id));
}
return result;
}
void PipeWireGraphModel::applyVolumeStates(const QHash<QString, NodeVolumeState> &states)
{
if (!m_controller) {
return;
}
const QVector<Potato::NodeInfo> nodes = m_controller->nodes();
for (const auto &node : nodes) {
if (node.stableId.isEmpty() || !states.contains(node.stableId)) {
continue;
}
const NodeVolumeState state = states.value(node.stableId);
m_nodeVolumeState.insert(node.id, state);
m_controller->setNodeVolume(node.id, state.volume, state.mute);
auto nodeIt = m_pwToNode.find(node.id);
if (nodeIt == m_pwToNode.end()) {
continue;
}
auto widgetIt = m_nodeWidgets.find(nodeIt->second);
if (widgetIt == m_nodeWidgets.end()) {
continue;
}
QWidget *widget = widgetIt->second;
if (!widget) {
continue;
}
if (auto *slider = widget->findChild<QSlider*>()) {
slider->blockSignals(true);
slider->setValue(static_cast<int>(state.volume * 100.0f));
slider->blockSignals(false);
}
if (auto *button = widget->findChild<QToolButton*>()) {
button->blockSignals(true);
button->setChecked(state.mute);
button->blockSignals(false);
}
}
}
void PipeWireGraphModel::saveLayout() const
{
const QString path = layoutFilePath();