Files
bbedward ccbf1d38ad widgets: bump qml-common, rename Dank* prefixed widgets to D, add
deprecation notice to plugin compatibility shims

- When qml-common became a thing, we left qs.Widgets shims in place for
  plugin compatibility
- It's annoying to need to maintain them when qml-common has any change,
  add a warning so we can safely deprecate them in the future
- One shot rename the common stuff to D to make it shorter and nicer to
  write
2026-10-05 16:47:19 -04:00

236 lines
11 KiB
QML

import QtQuick
import qs.Common
import qs.DCommon.Widgets
import qs.Modules.Settings.Widgets
SettingsCard {
id: root
property string outputName: ""
property var outputData: null
readonly property bool isDisabled: {
void (DisplayConfigState.pendingNiriChanges);
return DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "disabled", false);
}
readonly property var hotCornersData: {
void (DisplayConfigState.pendingNiriChanges);
return DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "hotCorners", null);
}
title: I18n.tr("Compositor", "noun, wayland compositor, section title and launcher logo option fallback")
collapsible: true
expanded: false
SettingsToggleRow {
text: I18n.tr("Disable output")
enabled: checked || DisplayConfigState.canDisableOutput()
description: (!checked && !DisplayConfigState.canDisableOutput()) ? (Object.keys(DisplayConfigState.outputs).length <= 1 ? I18n.tr("Cannot disable the only output") : I18n.tr("At least one output must remain enabled")) : ""
checked: root.isDisabled
onToggled: checked => DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "disabled", checked)
}
SettingsToggleRow {
text: I18n.tr("Focus at startup")
enabled: !root.isDisabled
checked: DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "focusAtStartup", false)
onToggled: checked => DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "focusAtStartup", checked)
}
SettingsDropdownRow {
text: I18n.tr("Hot corners")
enabled: !root.isDisabled
currentValue: {
const data = root.hotCornersData;
if (!data)
return I18n.tr("Inherit", "inherit from global setting");
if (data.off)
return I18n.tr("Off");
const corners = data.corners || [];
if (corners.length === 0)
return I18n.tr("Inherit", "inherit from global setting");
if (corners.length === 4)
return I18n.tr("All");
return I18n.tr("Select", "verb, dropdown placeholder or option that opens a picker") + "…";
}
options: [I18n.tr("Inherit", "inherit from global setting"), I18n.tr("Off"), I18n.tr("All"), I18n.tr("Select", "verb, dropdown placeholder or option that opens a picker") + "…"]
onValueChanged: value => {
switch (value) {
case I18n.tr("Inherit", "inherit from global setting"):
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "hotCorners", null);
break;
case I18n.tr("Off"):
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "hotCorners", {
"off": true
});
break;
case I18n.tr("All"):
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "hotCorners", {
"corners": ["top-left", "top-right", "bottom-left", "bottom-right"]
});
break;
case I18n.tr("Select", "verb, dropdown placeholder or option that opens a picker") + "…":
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "hotCorners", {
"corners": []
});
break;
}
}
}
SettingsButtonGroupRow {
id: hotCornersGroup
readonly property var cornerKeys: ["top-left", "top-right", "bottom-left", "bottom-right"]
visible: !!root.hotCornersData && !root.hotCornersData.off && root.hotCornersData.corners !== undefined
enabled: !root.isDisabled
selectionMode: "multi"
checkEnabled: false
model: [I18n.tr("Top Left"), I18n.tr("Top Right"), I18n.tr("Bottom Left"), I18n.tr("Bottom Right")]
currentSelection: (root.hotCornersData?.corners ?? []).map(key => model[cornerKeys.indexOf(key)]).filter(label => label !== undefined)
onSelectionChanged: (index, selected) => {
const corners = currentSelection.map(label => cornerKeys[model.indexOf(label)]).filter(key => key !== undefined);
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "hotCorners", {
"corners": corners
});
}
}
SettingsRow {
title: I18n.tr("Layout overrides")
enabled: !root.isDisabled
body: Column {
width: parent.width
spacing: Theme.spacingM
Row {
width: parent.width
spacing: Theme.spacingM
DTextField {
outlined: true
leftIconName: "space_dashboard"
labelText: I18n.tr("Window gaps (px)")
width: (parent.width - parent.spacing) / 2
placeholderText: I18n.tr("Inherit", "inherit from global setting")
text: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", null);
if (layout?.gaps === undefined)
return "";
return layout.gaps.toString();
}
onEditingFinished: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", {}) || {};
const trimmed = text.trim();
if (!trimmed) {
delete layout.gaps;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", Object.keys(layout).length > 0 ? layout : null);
return;
}
const val = parseInt(trimmed);
if (isNaN(val) || val < 0)
return;
layout.gaps = val;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", layout);
}
}
DTextField {
outlined: true
leftIconName: "width_normal"
labelText: I18n.tr("Default width (%)", "niri output field label, default column width percent")
width: (parent.width - parent.spacing) / 2
placeholderText: I18n.tr("Inherit", "inherit from global setting")
text: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", null);
if (!layout?.defaultColumnWidth)
return "";
if (layout.defaultColumnWidth.type !== "proportion")
return "";
const percent = layout.defaultColumnWidth.value * 100;
return parseFloat(percent.toFixed(4)).toString();
}
onEditingFinished: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", {}) || {};
const trimmed = text.trim().replace("%", "");
if (!trimmed) {
delete layout.defaultColumnWidth;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", Object.keys(layout).length > 0 ? layout : null);
return;
}
const val = parseFloat(trimmed);
if (isNaN(val) || val <= 0 || val > 100)
return;
layout.defaultColumnWidth = {
"type": "proportion",
"value": parseFloat((val / 100).toFixed(6))
};
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", layout);
}
}
}
DTextField {
outlined: true
leftIconName: "view_column"
labelText: I18n.tr("Preset widths (%)", "niri output field label, preset column width percents")
supportingText: "33.33, 50, 66.67"
width: parent.width
placeholderText: I18n.tr("Inherit", "inherit from global setting")
text: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", null);
const presets = layout?.presetColumnWidths || [];
if (presets.length === 0)
return "";
return presets.filter(p => p.type === "proportion").map(p => parseFloat((p.value * 100).toFixed(4))).join(", ");
}
onEditingFinished: {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", {}) || {};
const trimmed = text.trim();
if (!trimmed) {
delete layout.presetColumnWidths;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", Object.keys(layout).length > 0 ? layout : null);
return;
}
const parts = trimmed.split(/[,\s]+/).filter(s => s);
const presets = [];
for (const part of parts) {
const val = parseFloat(part.replace("%", ""));
if (!isNaN(val) && val > 0 && val <= 100)
presets.push({
"type": "proportion",
"value": parseFloat((val / 100).toFixed(6))
});
}
if (presets.length === 0) {
delete layout.presetColumnWidths;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", Object.keys(layout).length > 0 ? layout : null);
return;
}
presets.sort((a, b) => a.value - b.value);
layout.presetColumnWidths = presets;
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", layout);
}
}
}
}
SettingsToggleRow {
text: I18n.tr("Center single column")
enabled: !root.isDisabled
property var layoutData: DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", null)
checked: layoutData?.alwaysCenterSingleColumn ?? false
onToggled: checked => {
const layout = DisplayConfigState.getNiriSetting(root.outputData, root.outputName, "layout", {}) || {};
if (checked) {
layout.alwaysCenterSingleColumn = true;
} else {
delete layout.alwaysCenterSingleColumn;
}
DisplayConfigState.setNiriSetting(root.outputData, root.outputName, "layout", Object.keys(layout).length > 0 ? layout : null);
}
}
}