status/network: Add NMSection:icon-name property

Again no big surprise, a property that will soon correspond to the
quick toggle's icon.

It is more involved than the :checked property though, which is just
a simple boolean.

To keep it as simple as possible, we set up a binding group and use
that to bind the :icon-name property.

As state changes, we then update the group's source with the item
we deem to best represent the section as a whole at the given
moment.

That is (in that order):

 - the first active item
 - the most recently used item
 - the top-most visible item

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2408>
This commit is contained in:
Florian Müllner 2022-08-03 02:58:21 +02:00 committed by Marge Bot
parent b0df35babf
commit f96447079a

View File

@ -1279,10 +1279,12 @@ const NMSection = GObject.registerClass({
'checked': GObject.ParamSpec.boolean('checked', '', '',
GObject.ParamFlags.READWRITE,
false),
'icon-name': GObject.ParamSpec.string('icon-name', '', '',
GObject.ParamFlags.READWRITE,
''),
},
Signals: {
'activation-failed': {},
'icon-changed': {},
},
}, class NMSection extends GObject.Object {
constructor() {
@ -1297,6 +1299,10 @@ const NMSection = GObject.registerClass({
this.menu.addMenuItem(this._itemsSection);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._itemBinding = new GObject.BindingGroup();
this._itemBinding.bind('icon-name',
this, 'icon-name', GObject.BindingFlags.DEFAULT);
}
setClient(client) {
@ -1342,7 +1348,7 @@ const NMSection = GObject.registerClass({
`${this} already has an item for ${key}`);
item.connectObject(
'notify::is-active', () => this._updateChecked(),
'notify::is-active', () => this._sync(),
'notify::name', () => this._resortItem(item),
'destroy', () => this._removeItem(key),
this);
@ -1365,10 +1371,41 @@ const NMSection = GObject.registerClass({
this._sync();
}
*_getActiveItems() {
for (const item of this._itemSorter) {
if (item.is_active)
yield item;
}
}
_getPrimaryItem() {
// prefer active items
const [firstActive] = this._getActiveItems();
if (firstActive)
return firstActive;
// otherwise prefer the most-recently used
const [lastUsed] = this._itemSorter.itemsByMru();
if (lastUsed?.timestamp > 0)
return lastUsed;
// as a last resort, return the top-most visible item
for (const item of this._itemSorter) {
if (item.visible)
return item;
}
console.assert(!this.visible,
`${this} should not be visible when empty`);
return null;
}
_sync() {
this.visible = this._items.size > 0;
this._updateItemsVisibility();
this._updateChecked();
this._itemBinding.source = this._getPrimaryItem();
}
});
@ -1702,7 +1739,7 @@ class Indicator extends PanelMenu.SystemIndicator {
this._allSections.forEach(section => {
section.connectObject(
'activation-failed', () => this._onActivationFailed(),
'icon-changed', () => this._updateIcon(),
'notify::icon-name', () => this._updateIcon(),
this);
this.menu.addMenuItem(section.menu);
});