mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-06-08 04:42:11 +00:00
ControlCenter: modularity!
This commit is contained in:
@@ -14,11 +14,13 @@ NBox {
|
||||
property var widgetModel: []
|
||||
property var availableWidgets: []
|
||||
property bool enableMoveBetweenSections: true
|
||||
property int maxWidgets: -1 // -1 means unlimited
|
||||
|
||||
property var widgetRegistry: null
|
||||
property string settingsDialogComponent: "BarWidgetSettingsDialog.qml"
|
||||
|
||||
readonly property real miniButtonSize: Style.baseWidgetSize * 0.65
|
||||
readonly property bool isAtMaxCapacity: maxWidgets > 0 && widgetModel.length >= maxWidgets
|
||||
|
||||
signal addWidget(string widgetId, string section)
|
||||
signal removeWidget(string section, int index)
|
||||
@@ -80,6 +82,16 @@ NBox {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
// Widget count indicator (when max is set)
|
||||
NText {
|
||||
visible: root.maxWidgets > 0
|
||||
text: "(" + widgetModel.length + "/" + root.maxWidgets + ")"
|
||||
pointSize: Style.fontSizeS
|
||||
color: root.isAtMaxCapacity ? Color.mError : Color.mOnSurfaceVariant
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: Style.marginXS
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
@@ -93,6 +105,7 @@ NBox {
|
||||
onSelected: key => comboBox.currentKey = key
|
||||
popupHeight: 340
|
||||
minimumWidth: 200
|
||||
enabled: !root.isAtMaxCapacity
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
@@ -114,12 +127,14 @@ NBox {
|
||||
colorFg: Color.mOnPrimary
|
||||
colorBgHover: Color.mSecondary
|
||||
colorFgHover: Color.mOnSecondary
|
||||
enabled: comboBox.currentKey !== ""
|
||||
tooltipText: I18n.tr("tooltips.add-widget")
|
||||
enabled: comboBox.currentKey !== "" && !root.isAtMaxCapacity
|
||||
tooltipText: root.isAtMaxCapacity
|
||||
? I18n.tr("tooltips.max-widgets-reached")
|
||||
: I18n.tr("tooltips.add-widget")
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.leftMargin: Style.marginS
|
||||
onClicked: {
|
||||
if (comboBox.currentKey !== "") {
|
||||
if (comboBox.currentKey !== "" && !root.isAtMaxCapacity) {
|
||||
addWidget(comboBox.currentKey, sectionId)
|
||||
comboBox.currentKey = ""
|
||||
}
|
||||
@@ -588,4 +603,4 @@ NBox {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,34 @@ ColumnLayout {
|
||||
id: root
|
||||
spacing: Style.marginL
|
||||
|
||||
property list<var> cardsModel: []
|
||||
property list<var> cardsDefault: [{
|
||||
"id": "profile-card",
|
||||
"text": "Profile",
|
||||
"enabled": true,
|
||||
"required": true
|
||||
}, {
|
||||
"id": "shortcuts-card",
|
||||
"text": "Shortcuts",
|
||||
"enabled": true,
|
||||
"required": false
|
||||
}, {
|
||||
"id": "weather-card",
|
||||
"text": "Weather",
|
||||
"enabled": true,
|
||||
"required": false
|
||||
}, {
|
||||
"id": "audio-card",
|
||||
"text": "Audio Sliders",
|
||||
"enabled": true,
|
||||
"required": false
|
||||
}, {
|
||||
"id": "media-sysmon-card",
|
||||
"text": "Media and System Monitor",
|
||||
"enabled": true,
|
||||
"required": false
|
||||
}]
|
||||
|
||||
// Handler for drag start - disables panel background clicks
|
||||
function handleDragStart() {
|
||||
var panel = PanelService.getPanel("settingsPanel")
|
||||
@@ -27,6 +55,60 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
function saveCards() {
|
||||
var toSave = []
|
||||
for (var i = 0; i < cardsModel.length; i++) {
|
||||
toSave.push({
|
||||
"id": cardsModel[i].id,
|
||||
"enabled": cardsModel[i].enabled
|
||||
})
|
||||
}
|
||||
Settings.data.controlCenter.cards = toSave
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Fill out availableWidgets ListModel
|
||||
availableWidgets.clear()
|
||||
ControlCenterWidgetRegistry.getAvailableWidgets().forEach(entry => {
|
||||
availableWidgets.append({
|
||||
"key": entry,
|
||||
"name": entry
|
||||
})
|
||||
})
|
||||
// Starts empty
|
||||
cardsModel = []
|
||||
|
||||
// Add the cards available in settings
|
||||
for (var i = 0; i < Settings.data.controlCenter.cards.length; i++) {
|
||||
const settingCard = Settings.data.controlCenter.cards[i]
|
||||
|
||||
for (var j = 0; j < cardsDefault.length; j++) {
|
||||
if (settingCard.id === cardsDefault[j].id) {
|
||||
var card = cardsDefault[j]
|
||||
card.enabled = settingCard.enabled
|
||||
cardsModel.push(card)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add any missing cards from default
|
||||
for (var i = 0; i < cardsDefault.length; i++) {
|
||||
var found = false
|
||||
for (var j = 0; j < cardsModel.length; j++) {
|
||||
if (cardsModel[j].id === cardsDefault[i].id) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cardsModel.push(cardsDefault[i])
|
||||
}
|
||||
}
|
||||
|
||||
saveCards()
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Style.marginL
|
||||
Layout.fillWidth: true
|
||||
@@ -70,11 +152,49 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
NToggle {
|
||||
label: I18n.tr("settings.control-center.audio-controls.label")
|
||||
description: I18n.tr("settings.control-center.audio-controls.description")
|
||||
checked: Settings.data.controlCenter.audioControlsEnabled
|
||||
onToggled: checked => Settings.data.controlCenter.audioControlsEnabled = checked
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL
|
||||
Layout.bottomMargin: Style.marginXL
|
||||
}
|
||||
|
||||
// Widgets Management Section
|
||||
ColumnLayout {
|
||||
spacing: Style.marginXXS
|
||||
Layout.fillWidth: true
|
||||
|
||||
NHeader {
|
||||
label: I18n.tr("settings.control-center.cards.section.label")
|
||||
description: I18n.tr("settings.control-center.cards.section.description")
|
||||
}
|
||||
|
||||
NReorderCheckboxes {
|
||||
Layout.fillWidth: true
|
||||
model: cardsModel
|
||||
onDragPotentialStarted: {
|
||||
root.handleDragStart()
|
||||
}
|
||||
onDragPotentialEnded: {
|
||||
root.handleDragEnd()
|
||||
}
|
||||
onItemToggled: function (index, enabled) {
|
||||
//Logger.log("ControlCenterTab", "Item", index, "toggled to", enabled)
|
||||
var newModel = cardsModel.slice()
|
||||
newModel[index] = Object.assign({}, newModel[index], {
|
||||
"enabled": enabled
|
||||
})
|
||||
cardsModel = newModel
|
||||
saveCards()
|
||||
}
|
||||
onItemsReordered: function (fromIndex, toIndex) {
|
||||
//Logger.log("ControlCenterTab", "Item moved from", fromIndex, "to", toIndex)
|
||||
var newModel = cardsModel.slice()
|
||||
var item = newModel.splice(fromIndex, 1)[0]
|
||||
newModel.splice(toIndex, 0, item)
|
||||
cardsModel = newModel
|
||||
saveCards()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NDivider {
|
||||
@@ -83,70 +203,66 @@ ColumnLayout {
|
||||
Layout.bottomMargin: Style.marginXL
|
||||
}
|
||||
|
||||
// NDivider {
|
||||
// Layout.fillWidth: true
|
||||
// Layout.topMargin: Style.marginXL
|
||||
// Layout.bottomMargin: Style.marginXL
|
||||
// }
|
||||
// Widgets Management Section
|
||||
ColumnLayout {
|
||||
spacing: Style.marginXXS
|
||||
Layout.fillWidth: true
|
||||
|
||||
// // Widgets Management Section
|
||||
// ColumnLayout {
|
||||
// spacing: Style.marginXXS
|
||||
// Layout.fillWidth: true
|
||||
NHeader {
|
||||
label: I18n.tr("settings.control-center.shortcuts.section.label")
|
||||
description: I18n.tr("settings.control-center.shortcuts.section.description")
|
||||
}
|
||||
|
||||
// NHeader {
|
||||
// label: I18n.tr("settings.control-center.quickSettings.section.label")
|
||||
// description: I18n.tr("settings.control-center.quickSettings.section.description")
|
||||
// }
|
||||
// Sections
|
||||
ColumnLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.topMargin: Style.marginM
|
||||
spacing: Style.marginM
|
||||
|
||||
// // Sections
|
||||
// ColumnLayout {
|
||||
// Layout.fillWidth: true
|
||||
// Layout.fillHeight: true
|
||||
// Layout.topMargin: Style.marginM
|
||||
// spacing: Style.marginM
|
||||
// Left
|
||||
SectionEditor {
|
||||
sectionName: I18n.tr("settings.control-center.shortcuts.sectionLeft")
|
||||
sectionId: "left"
|
||||
settingsDialogComponent: ""
|
||||
maxWidgets: 5
|
||||
widgetRegistry: ControlCenterWidgetRegistry
|
||||
widgetModel: Settings.data.controlCenter.shortcuts["left"]
|
||||
availableWidgets: availableWidgets
|
||||
enableMoveBetweenSections: false
|
||||
onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||
onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||
onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||
onDragPotentialStarted: root.handleDragStart()
|
||||
onDragPotentialEnded: root.handleDragEnd()
|
||||
}
|
||||
|
||||
// // Left
|
||||
// SectionEditor {
|
||||
// sectionName: I18n.tr("settings.control-center.quickSettings.sectionLeft")
|
||||
// sectionId: "left"
|
||||
// settingsDialogComponent: ""
|
||||
// widgetRegistry: ControlCenterWidgetRegistry
|
||||
// widgetModel: Settings.data.controlCenter.widgets["left"]
|
||||
// availableWidgets: availableWidgets
|
||||
// enableMoveBetweenSections: false
|
||||
// onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||
// onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||
// onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
// onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||
// onDragPotentialStarted: root.handleDragStart()
|
||||
// onDragPotentialEnded: root.handleDragEnd()
|
||||
// }
|
||||
// Right
|
||||
SectionEditor {
|
||||
sectionName: I18n.tr("settings.control-center.shortcuts.sectionRight")
|
||||
sectionId: "right"
|
||||
settingsDialogComponent: ""
|
||||
maxWidgets: 5
|
||||
widgetRegistry: ControlCenterWidgetRegistry
|
||||
widgetModel: Settings.data.controlCenter.shortcuts["right"]
|
||||
availableWidgets: availableWidgets
|
||||
enableMoveBetweenSections: false
|
||||
onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||
onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||
onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||
onDragPotentialStarted: root.handleDragStart()
|
||||
onDragPotentialEnded: root.handleDragEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // Right
|
||||
// SectionEditor {
|
||||
// sectionName: I18n.tr("settings.control-center.quickSettings.sectionRight")
|
||||
// sectionId: "right"
|
||||
// settingsDialogComponent: ""
|
||||
// widgetRegistry: ControlCenterWidgetRegistry
|
||||
// widgetModel: Settings.data.controlCenter.widgets["right"]
|
||||
// availableWidgets: availableWidgets
|
||||
// enableMoveBetweenSections: false
|
||||
// onAddWidget: (widgetId, section) => _addWidgetToSection(widgetId, section)
|
||||
// onRemoveWidget: (section, index) => _removeWidgetFromSection(section, index)
|
||||
// onReorderWidget: (section, fromIndex, toIndex) => _reorderWidgetInSection(section, fromIndex, toIndex)
|
||||
// onUpdateWidgetSettings: (section, index, settings) => _updateWidgetSettingsInSection(section, index, settings)
|
||||
// onDragPotentialStarted: root.handleDragStart()
|
||||
// onDragPotentialEnded: root.handleDragEnd()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// NDivider {
|
||||
// Layout.fillWidth: true
|
||||
// Layout.topMargin: Style.marginXL
|
||||
// Layout.bottomMargin: Style.marginXL
|
||||
// }
|
||||
NDivider {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.marginXL
|
||||
Layout.bottomMargin: Style.marginXL
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
// Signal functions
|
||||
@@ -165,55 +281,37 @@ ColumnLayout {
|
||||
})
|
||||
}
|
||||
}
|
||||
Settings.data.controlCenter.widgets[section].push(newWidget)
|
||||
Settings.data.controlCenter.shortcuts[section].push(newWidget)
|
||||
}
|
||||
|
||||
function _removeWidgetFromSection(section, index) {
|
||||
if (index >= 0 && index < Settings.data.controlCenter.widgets[section].length) {
|
||||
var newArray = Settings.data.controlCenter.widgets[section].slice()
|
||||
if (index >= 0 && index < Settings.data.controlCenter.shortcuts[section].length) {
|
||||
var newArray = Settings.data.controlCenter.shortcuts[section].slice()
|
||||
var removedWidgets = newArray.splice(index, 1)
|
||||
Settings.data.controlCenter.widgets[section] = newArray
|
||||
|
||||
// Check that we still have a control center
|
||||
if (removedWidgets[0].id === "ControlCenter" && BarService.lookupWidget("ControlCenter") === undefined) {
|
||||
ToastService.showWarning(I18n.tr("toast.missing-control-center.label"), I18n.tr("toast.missing-control-center.description"), 12000)
|
||||
}
|
||||
Settings.data.controlCenter.shortcuts[section] = newArray
|
||||
}
|
||||
}
|
||||
|
||||
function _reorderWidgetInSection(section, fromIndex, toIndex) {
|
||||
if (fromIndex >= 0 && fromIndex < Settings.data.controlCenter.widgets[section].length && toIndex >= 0 && toIndex < Settings.data.controlCenter.widgets[section].length) {
|
||||
if (fromIndex >= 0 && fromIndex < Settings.data.controlCenter.shortcuts[section].length && toIndex >= 0 && toIndex < Settings.data.controlCenter.shortcuts[section].length) {
|
||||
|
||||
// Create a new array to avoid modifying the original
|
||||
var newArray = Settings.data.controlCenter.widgets[section].slice()
|
||||
var newArray = Settings.data.controlCenter.shortcuts[section].slice()
|
||||
var item = newArray[fromIndex]
|
||||
newArray.splice(fromIndex, 1)
|
||||
newArray.splice(toIndex, 0, item)
|
||||
|
||||
Settings.data.controlCenter.widgets[section] = newArray
|
||||
//Logger.log("BarTab", "Widget reordered. New array:", JSON.stringify(newArray))
|
||||
Settings.data.controlCenter.shortcuts[section] = newArray
|
||||
}
|
||||
}
|
||||
|
||||
function _updateWidgetSettingsInSection(section, index, settings) {
|
||||
// Update the widget settings in the Settings data
|
||||
Settings.data.controlCenter.widgets[section][index] = settings
|
||||
//Logger.log("BarTab", `Updated widget settings for ${settings.id} in ${section} section`)
|
||||
Settings.data.controlCenter.shortcuts[section][index] = settings
|
||||
}
|
||||
|
||||
// Base list model for all combo boxes
|
||||
ListModel {
|
||||
id: availableWidgets
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Fill out availableWidgets ListModel
|
||||
availableWidgets.clear()
|
||||
ControlCenterWidgetRegistry.getAvailableWidgets().forEach(entry => {
|
||||
availableWidgets.append({
|
||||
"key": entry,
|
||||
"name": entry
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user