customIconPage.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* exported GeneralPage*/
  2. import Adw from 'gi://Adw';
  3. import Gtk from 'gi://Gtk';
  4. import GObject from 'gi://GObject';
  5. import Gio from 'gi://Gio';
  6. import GLib from 'gi://GLib';
  7. import {gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
  8. const IconData = GObject.registerClass({
  9. GTypeName: 'IconData',
  10. Properties: {
  11. 'id': GObject.ParamSpec.string(
  12. 'id',
  13. 'Id',
  14. 'A read and write string property',
  15. GObject.ParamFlags.READWRITE,
  16. ''
  17. ),
  18. 'name': GObject.ParamSpec.string(
  19. 'name',
  20. 'Name',
  21. 'A read and write string property',
  22. GObject.ParamFlags.READWRITE,
  23. ''
  24. ),
  25. 'at-name': GObject.ParamSpec.string(
  26. 'at-name',
  27. 'At Name',
  28. 'A read and write string property',
  29. GObject.ParamFlags.READWRITE,
  30. ''
  31. ),
  32. },
  33. }, class IconData extends GObject.Object {
  34. constructor(props = {}) {
  35. super(props);
  36. }
  37. get id() {
  38. if (this._id === 'undefined')
  39. this._id = null;
  40. return this._id;
  41. }
  42. set id(value) {
  43. if (this.id === value)
  44. return;
  45. this._id = value;
  46. this.notify('id');
  47. }
  48. get name() {
  49. if (this._name === 'undefined')
  50. this._name = null;
  51. return this._name;
  52. }
  53. set name(value) {
  54. if (this.name === value)
  55. return;
  56. this._name = value;
  57. this.notify('name');
  58. }
  59. get atName() {
  60. if (this._atName === 'undefined')
  61. this._atName = null;
  62. return this._atName;
  63. }
  64. set atName(value) {
  65. if (this.atName === value)
  66. return;
  67. this._atName = value;
  68. this.notify('at-name');
  69. }
  70. });
  71. export var CustomIconPage = GObject.registerClass(
  72. class AppIndicatorCustomIconPage extends Adw.PreferencesPage {
  73. _init(settings, settingsKey) {
  74. super._init({
  75. title: _('Custom Icons'),
  76. icon_name: 'custom-icons-symbolic',
  77. name: 'Custom Icons Page',
  78. });
  79. this._settings = settings;
  80. this._settingsKey = settingsKey;
  81. this.group = new Adw.PreferencesGroup();
  82. this.container = new Gtk.Box({
  83. halign: Gtk.Align.FILL,
  84. hexpand: true,
  85. orientation: Gtk.Orientation.VERTICAL,
  86. });
  87. this.listStore = new Gio.ListStore({
  88. item_type: IconData,
  89. });
  90. const initList = this._settings.get_value(this._settingsKey.CUSTOM_ICONS).deep_unpack();
  91. initList.forEach(pair => {
  92. let data = new IconData({
  93. id: pair[0],
  94. name: pair[1],
  95. atName: pair[2],
  96. });
  97. this.listStore.append(data);
  98. });
  99. this.listStore.append(new IconData({id: '', name: '', atName: ''}));
  100. this.selectionModel = new Gtk.SingleSelection({
  101. model: this.listStore,
  102. });
  103. this.columnView = new Gtk.ColumnView({
  104. hexpand: true,
  105. model: this.selectionModel,
  106. reorderable: false,
  107. });
  108. const columnTitles = [
  109. _('Indicator ID'),
  110. _('Icon Name'),
  111. _('Attention Icon Name'),
  112. ];
  113. const indicatorIdColumn = new Gtk.ColumnViewColumn({
  114. title: columnTitles[0],
  115. expand: true,
  116. });
  117. const iconNameColumn = new Gtk.ColumnViewColumn({
  118. title: columnTitles[1],
  119. expand: true,
  120. });
  121. const attentionIconNameColumn = new Gtk.ColumnViewColumn({
  122. title: columnTitles[2],
  123. expand: true,
  124. });
  125. const factoryId = new Gtk.SignalListItemFactory();
  126. factoryId.connect('setup', (_widget, item) => {
  127. const label = new Gtk.EditableLabel({text: ''});
  128. item.set_child(label);
  129. });
  130. factoryId.connect('bind', (_widget, item) => {
  131. const label = item.get_child();
  132. const data = item.get_item();
  133. label.set_text(data.id);
  134. label.bind_property('text', data, 'id', GObject.BindingFlags.SYNC_CREATE);
  135. label.connect('changed', () => this._autoSave(item));
  136. });
  137. const factoryName = new Gtk.SignalListItemFactory();
  138. factoryName.connect('setup', (_widget, item) => {
  139. const label = new Gtk.EditableLabel({text: ''});
  140. item.set_child(label);
  141. });
  142. factoryName.connect('bind', (_widget, item) => {
  143. const label = item.get_child();
  144. const data = item.get_item();
  145. label.set_text(data.name);
  146. label.bind_property('text', data, 'name', GObject.BindingFlags.SYNC_CREATE);
  147. label.connect('changed', () => this._autoSave(item));
  148. });
  149. const factoryItName = new Gtk.SignalListItemFactory();
  150. factoryItName.connect('setup', (_widget, item) => {
  151. const label = new Gtk.EditableLabel({text: ''});
  152. item.set_child(label);
  153. });
  154. factoryItName.connect('bind', (_widget, item) => {
  155. const label = item.get_child();
  156. const data = item.get_item();
  157. label.set_text(data.atName);
  158. label.bind_property('text', data, 'at-name', GObject.BindingFlags.SYNC_CREATE);
  159. label.connect('changed', () => this._autoSave(item));
  160. });
  161. indicatorIdColumn.set_factory(factoryId);
  162. iconNameColumn.set_factory(factoryName);
  163. attentionIconNameColumn.set_factory(factoryItName);
  164. this.columnView.append_column(indicatorIdColumn);
  165. this.columnView.append_column(iconNameColumn);
  166. this.columnView.append_column(attentionIconNameColumn);
  167. this.container.append(this.columnView);
  168. this.group.add(this.container);
  169. this.add(this.group);
  170. }
  171. _autoSave(item) {
  172. const storeLength = this.listStore.get_n_items();
  173. const newStore = [];
  174. for (let i = 0; i < storeLength; i++) {
  175. const currentItem = this.listStore.get_item(i);
  176. const id = currentItem.id;
  177. const name = currentItem.name;
  178. const atName = currentItem.atName;
  179. if (id && name)
  180. newStore.push([id, name, atName || '']);
  181. }
  182. this._settings.set_value(this._settingsKey.CUSTOM_ICONS,
  183. new GLib.Variant('a(sss)', newStore));
  184. const id = item.get_item().id;
  185. const name = item.get_item().name;
  186. /* dynamic new entry*/
  187. if (storeLength === 1 && (id || name))
  188. this.listStore.append(new IconData({id: '', name: '', atName: ''}));
  189. if (storeLength > 1) {
  190. if ((id || name) && item.get_position() >= storeLength - 1)
  191. this.listStore.append(new IconData({id: '', name: '', atName: ''}));
  192. }
  193. }
  194. _autoDelete(item) {
  195. const storeLength = this.listStore.get_n_items();
  196. const id = item.get_item().id;
  197. const name = item.get_item().name;
  198. if (storeLength > 1 && !id && !name &&
  199. item.get_position() < storeLength - 1)
  200. this.listStore.remove(item.get_position());
  201. }
  202. });