mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
Merge pull request #478 from lonerOrz/feature/widget-usage-badge
feat(settings): Add usage badges to widget selector
This commit is contained in:
@@ -222,7 +222,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "Widget-Positionierung",
|
||||
"description": "Widgets per Drag & Drop innerhalb jeder Sektion neu anordnen oder Add/Remove-Buttons zum Verwalten verwenden."
|
||||
"description": "Widgets per Drag & Drop neu anordnen. Abzeichen zeigen die Verwendung an: [L]inks, [M]itte, [R]echts."
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "Widgets positioning",
|
||||
"description": "Drag and drop widgets to reorder them within each section, or use the add/remove buttons to manage widgets."
|
||||
"description": "Drag and drop widgets to reorder them. Badges indicate usage: [L]eft, [C]enter, [R]ight."
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "Posicionamiento de widgets",
|
||||
"description": "Arrastra y suelta widgets para reordenarlos dentro de cada sección, o usa los botones de añadir/eliminar para gestionar los widgets."
|
||||
"description": "Arrastra y suelta widgets para reordenarlos. Las insignias indican el uso: [I]zquierda, [C]entro, [D]erecha."
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "Positionnement des widgets",
|
||||
"description": "Glissez-déposez les widgets pour les réorganiser dans chaque section, ou utilisez les boutons ajouter/supprimer pour gérer les widgets."
|
||||
"description": "Faites glisser et déposez les widgets pour les réorganiser. Les badges indiquent l'utilisation : [G]auche, [C]entre, [D]roite."
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "Posicionamento dos widgets",
|
||||
"description": "Arraste e solte os widgets para reordená-los em cada seção, ou use os botões de adicionar/remover para gerenciar os widgets."
|
||||
"description": "Arraste e solte widgets para reordená-los. Os emblemas indicam o uso: [E]squerda, [C]entro, [D]ireita."
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
"widgets": {
|
||||
"section": {
|
||||
"label": "小部件定位",
|
||||
"description": "拖放小部件以在每个部分内重新排序,或使用添加/删除按钮管理小部件。"
|
||||
"description": "拖放小部件以重新排序。徽章表示使用情况:[L]左、[C]中、[R]右。"
|
||||
}
|
||||
},
|
||||
"monitors": {
|
||||
|
||||
@@ -303,9 +303,7 @@ ColumnLayout {
|
||||
Layout.bottomMargin: Style.marginXL
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
// Signal functions
|
||||
// ---------------------------------
|
||||
function _addWidgetToSection(widgetId, section) {
|
||||
var newWidget = {
|
||||
"id": widgetId
|
||||
@@ -375,19 +373,51 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
// Data model functions
|
||||
function getWidgetLocations(widgetId) {
|
||||
if (!BarService)
|
||||
return []
|
||||
const instances = BarService.getAllRegisteredWidgets()
|
||||
const locations = {}
|
||||
for (var i = 0; i < instances.length; i++) {
|
||||
if (instances[i].widgetId === widgetId) {
|
||||
const section = instances[i].section
|
||||
if (section === "left")
|
||||
locations["L"] = true
|
||||
else if (section === "center")
|
||||
locations["C"] = true
|
||||
else if (section === "right")
|
||||
locations["R"] = true
|
||||
}
|
||||
}
|
||||
return Object.keys(locations).join('')
|
||||
}
|
||||
|
||||
function updateAvailableWidgetsModel() {
|
||||
availableWidgets.clear()
|
||||
const widgets = BarWidgetRegistry.getAvailableWidgets()
|
||||
widgets.forEach(entry => {
|
||||
availableWidgets.append({
|
||||
"key": entry,
|
||||
"name": entry,
|
||||
"badgeLocations": getWidgetLocations(entry)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Base list model for all combo boxes
|
||||
ListModel {
|
||||
id: availableWidgets
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Fill out availableWidgets ListModel
|
||||
availableWidgets.clear()
|
||||
BarWidgetRegistry.getAvailableWidgets().forEach(entry => {
|
||||
availableWidgets.append({
|
||||
"key": entry,
|
||||
"name": entry
|
||||
})
|
||||
})
|
||||
updateAvailableWidgetsModel()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: BarService
|
||||
function onActiveWidgetsChanged() {
|
||||
updateAvailableWidgetsModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ Singleton {
|
||||
// Key format: "screenName|section|widgetId|index"
|
||||
property var widgetInstances: ({})
|
||||
|
||||
signal activeWidgetsChanged()
|
||||
|
||||
signal barReadyChanged(string screenName)
|
||||
|
||||
// Simple timer that run once when the widget structure has changed
|
||||
@@ -68,6 +70,7 @@ Singleton {
|
||||
timerCheckVisualizer.restart()
|
||||
|
||||
Logger.log("BarService", "Registered widget:", key)
|
||||
root.activeWidgetsChanged()
|
||||
}
|
||||
|
||||
// Unregister a widget instance
|
||||
@@ -75,6 +78,7 @@ Singleton {
|
||||
const key = [screenName, section, widgetId, index].join("|")
|
||||
delete widgetInstances[key]
|
||||
Logger.log("BarService", "Unregistered widget:", key)
|
||||
root.activeWidgetsChanged()
|
||||
}
|
||||
|
||||
// Lookup a specific widget instance (returns the actual QML instance)
|
||||
|
||||
@@ -20,6 +20,7 @@ RowLayout {
|
||||
property string currentKey: ""
|
||||
property string placeholder: ""
|
||||
property string searchPlaceholder: I18n.tr("placeholders.search")
|
||||
property Component delegate: null
|
||||
|
||||
readonly property real preferredHeight: Style.baseWidgetSize * 1.1
|
||||
|
||||
@@ -187,43 +188,79 @@ RowLayout {
|
||||
horizontalPolicy: ScrollBar.AlwaysOff
|
||||
verticalPolicy: ScrollBar.AsNeeded
|
||||
|
||||
delegate: ItemDelegate {
|
||||
width: listView.width
|
||||
hoverEnabled: true
|
||||
highlighted: ListView.view.currentIndex === index
|
||||
delegate: root.delegate ? root.delegate : defaultDelegate
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
ListView.view.currentIndex = index
|
||||
Component {
|
||||
id: defaultDelegate
|
||||
ItemDelegate {
|
||||
id: delegateRoot
|
||||
width: listView.width
|
||||
hoverEnabled: true
|
||||
highlighted: ListView.view.currentIndex === index
|
||||
|
||||
onHoveredChanged: {
|
||||
if (hovered) {
|
||||
ListView.view.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.selected(filteredModel.get(index).key)
|
||||
combo.currentIndex = root.findIndexByKeyInFiltered(filteredModel.get(index).key)
|
||||
combo.popup.close()
|
||||
}
|
||||
onClicked: {
|
||||
root.selected(filteredModel.get(index).key)
|
||||
combo.currentIndex = root.findIndexByKeyInFiltered(filteredModel.get(index).key)
|
||||
combo.popup.close()
|
||||
}
|
||||
|
||||
contentItem: NText {
|
||||
text: name
|
||||
pointSize: Style.fontSizeM
|
||||
color: highlighted ? Color.mOnTertiary : Color.mOnSurface
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
contentItem: RowLayout {
|
||||
width: parent.width
|
||||
spacing: Style.marginM
|
||||
|
||||
NText {
|
||||
text: name
|
||||
pointSize: Style.fontSizeM
|
||||
color: highlighted ? Color.mOnTertiary : Color.mOnSurface
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: Style.marginS
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
||||
Repeater {
|
||||
model: badgeLocations
|
||||
|
||||
delegate: NBox {
|
||||
width: Style.baseWidgetSize * 0.7
|
||||
height: Style.baseWidgetSize * 0.7
|
||||
color: "transparent"
|
||||
radius: Style.radiusS
|
||||
border.width: 0
|
||||
|
||||
NText {
|
||||
anchors.centerIn: parent
|
||||
text: modelData
|
||||
pointSize: Style.fontSizeXXS
|
||||
font.weight: Style.fontWeightBold
|
||||
color: highlighted ? Color.mOnTertiary : Color.mOnSurface
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
width: listView.width
|
||||
color: highlighted ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusS
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
background: Rectangle {
|
||||
width: listView.width
|
||||
color: highlighted ? Color.mTertiary : Color.transparent
|
||||
radius: Style.radiusS
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
duration: Style.animationFast
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user