From 4af181c7899eccf8c180a88e2d40b16ad0a587b9 Mon Sep 17 00:00:00 2001 From: Thomas Liebetraut Date: Tue, 21 May 2013 05:43:31 +0200 Subject: [PATCH 1/4] Added gsettings support for the tea drawing times. --- extension.js | 79 ++++++++++++------- metadata.json | 2 +- ...gnome.shell.extensions.teatime.gschema.xml | 12 +++ 3 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 schemas/org.gnome.shell.extensions.teatime.gschema.xml diff --git a/extension.js b/extension.js index 98a1c29..649bbdc 100644 --- a/extension.js +++ b/extension.js @@ -24,13 +24,39 @@ const N_ = function(e) { return e; }; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); -// TODO: make this configurable via gsettings -const defaultTeaList = [ - {name : "Green tea", time : 180 }, - {name : "Black tea", time : 210 }, - {name : "Fruit tea", time : 7 * 60}, - {name : "White tea", time : 120} - ]; +const TEALIST_KEY = "steep-times" + + +function getSettings(schema) { + let extension = ExtensionUtils.getCurrentExtension(); + + schema = schema || extension.metadata['settings-schema']; + + const GioSSS = Gio.SettingsSchemaSource; + + // check if this extension was built with "make zip-file", and thus + // has the schema files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell (and therefore schemas are available + // in the standard folders) + let schemaDir = extension.dir.get_child('schemas'); + let schemaSource; + if (schemaDir.query_exists(null)) { + schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), + GioSSS.get_default(), + false); + } + else + schemaSource = GioSSS.get_default(); + + let schemaObj = schemaSource.lookup(schema, true); + if (!schemaObj) + throw new Error('Schema ' + schema + ' could not be found for extension ' + + extension.metadata.uuid + '. Please check your installation.'); + + return new Gio.Settings({ settings_schema: schemaObj }); +} + const TeaTime = new Lang.Class({ Name : 'TeaTime', @@ -39,6 +65,8 @@ const TeaTime = new Lang.Class({ _init : function() { this.parent(0.0, "TeaTime"); + this._settings = getSettings(); + this._logo = new St.Icon({ icon_name : 'utilities-teatime', style_class : 'system-status-icon' @@ -60,10 +88,10 @@ const TeaTime = new Lang.Class({ this._createMenu(); }, - _createMenu : function() { this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - this._addTeaList(); + this._settings.connect("changed::" + TEALIST_KEY, Lang.bind(this, this._updateTeaList)); + this._updateTeaList(); }, _formatTime : function(seconds) { let a = new Date(0,0,0); // important: hour needs to be set to zero in _locale_ time @@ -75,25 +103,22 @@ const TeaTime = new Lang.Class({ else return a.toLocaleFormat("%M:%S"); }, - _addTeaList : function(config, output) { - let item = new PopupMenu.PopupMenuItem(_("brewing times")); - item.label.add_style_class_name('display-subtitle'); - item.actor.reactive = false; - item.actor.can_focus = false; - this.menu.addMenuItem(item); - this._callbacks = []; - - defaultTeaList.sort(function(a, b) { - return -1 * (a.time < b.time) + (a.time > b.time); - }); + _updateTeaList : function(config, output) { + // make sure the menu is empty + this.menu.removeAll(); - for ( var i = 0; i < defaultTeaList.length; i++) { - let tea = defaultTeaList[i]; - let item = new PopupMenu.PopupMenuItem(this._formatTime(tea.time) + " - " + tea.name); - - this._callbacks.push( function() {this._initCountdown(tea.time); }); - item.connect('activate', Lang.bind(this, this._callbacks[i])); - this.menu.addMenuItem(item); + // fill with new teas + let list = this._settings.get_value(TEALIST_KEY); + for (let i = 0; i < list.n_children(); ++i) { + let item = list.get_child_value(i); + let teaname = item.get_child_value(0).get_string()[0]; + let time = item.get_child_value(1).get_uint32(); + + let menuItem = new PopupMenu.PopupMenuItem(teaname + ": " + this._formatTime(time)); + menuItem.connect('activate', Lang.bind(this, function() { + this._initCountdown(time); + })); + this.menu.addMenuItem(menuItem); } }, _showNotification : function(subject, text) { diff --git a/metadata.json b/metadata.json index fae136d..d55c672 100644 --- a/metadata.json +++ b/metadata.json @@ -1 +1 @@ -{"shell-version": ["3.6"], "uuid": "TeaTime@oleid.mescharet.de", "name": "TeaTime", "description": "A tea brewing timer"} +{"shell-version": ["3.6"], "uuid": "TeaTime@oleid.mescharet.de", "name": "TeaTime", "settings-schema": "org.gnome.shell.extensions.teatime", "description": "A tea brewing timer"} diff --git a/schemas/org.gnome.shell.extensions.teatime.gschema.xml b/schemas/org.gnome.shell.extensions.teatime.gschema.xml new file mode 100644 index 0000000..e4d1df2 --- /dev/null +++ b/schemas/org.gnome.shell.extensions.teatime.gschema.xml @@ -0,0 +1,12 @@ + + + + + { "Green tea": 180, "Black tea": 210, "Fruit tea": 420, "White tea": 120 } + Tea drawing times list + A mapping of a tea times to their corresponding drawing time in seconds. + + + + + From e3f238a2e3c540bba1e44a65c7ae4cc1928f4ce1 Mon Sep 17 00:00:00 2001 From: Thomas Liebetraut Date: Tue, 21 May 2013 19:07:35 +0200 Subject: [PATCH 2/4] Readonly prefs.js support --- prefs.js | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 prefs.js diff --git a/prefs.js b/prefs.js new file mode 100644 index 0000000..76c97cc --- /dev/null +++ b/prefs.js @@ -0,0 +1,129 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* Olaf Leidinger + Thomas Liebetraut +*/ + +const Gdk = imports.gi.Gdk; +const Gio = imports.gi.Gio; +const GLib = imports.gi.GLib; +const GnomeDesktop = imports.gi.GnomeDesktop; +const Mainloop = imports.mainloop; // timer +const St = imports.gi.St; +const Clutter = imports.gi.Clutter; + +const Lang = imports.lang; +const Gtk = imports.gi.Gtk; +const GObject = imports.gi.GObject; + +const Gettext = imports.gettext.domain('gnome-shell-extensions'); +const _ = Gettext.gettext; +const N_ = function(e) { return e; }; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +let settings; + +const SETTINGS_TEALIST_KEY = 'steep-times'; + + +function getSettings(schema) { + let extension = ExtensionUtils.getCurrentExtension(); + + schema = schema || extension.metadata['settings-schema']; + + const GioSSS = Gio.SettingsSchemaSource; + + // check if this extension was built with "make zip-file", and thus + // has the schema files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell (and therefore schemas are available + // in the standard folders) + let schemaDir = extension.dir.get_child('schemas'); + let schemaSource; + if (schemaDir.query_exists(null)) { + schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), + GioSSS.get_default(), + false); + } + else + schemaSource = GioSSS.get_default(); + + let schemaObj = schemaSource.lookup(schema, true); + if (!schemaObj) + throw new Error('Schema ' + schema + ' could not be found for extension ' + + extension.metadata.uuid + '. Please check your installation.'); + + return new Gio.Settings({ settings_schema: schemaObj }); +} + +const TeaTimePrefsWidget = new Lang.Class({ + Name : 'TeaTimePrefsWidget', + Extends : Gtk.Box, + + _init: function() { + this.parent({ orientation: Gtk.Orientation.VERTICAL }); + + this._tealist = new Gtk.ListStore(); + this._tealist.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT, Gtk.Adjustment]); + + this._settings = getSettings(); + this._settings.connect("changed::" + SETTINGS_TEALIST_KEY, Lang.bind(this, this._refresh)); + + this._initWindow(); + this.vexpand = true; + this._refresh(); + }, + _initWindow: function() { + this.treeview = new Gtk.TreeView({model: this._tealist, expand: true}); + this.add(this.treeview); + + let teaname = new Gtk.TreeViewColumn({ title: _("Tea"), expand: true }); + let renderer = new Gtk.CellRendererText({ editable: true }); + teaname.pack_start(renderer, true); + teaname.add_attribute(renderer, "text", 0); + this.treeview.append_column(teaname); + + let steeptime = new Gtk.TreeViewColumn({ title: _("Steep time") }); + let spinrenderer = new Gtk.CellRendererSpin({ editable: true }); + steeptime.pack_start(spinrenderer, true); + steeptime.add_attribute(spinrenderer, "adjustment", 2); + steeptime.add_attribute(spinrenderer, "text", 1); + this.treeview.append_column(steeptime); + + + this.toolbar = new Gtk.Toolbar({ icon_size: 1 }); + this.toolbar.get_style_context().add_class("inline-toolbar"); + this.add(this.toolbar); + this.addButton = new Gtk.ToolButton({ icon_name: "list-add-symbolic", use_action_appearance: false }); + this.toolbar.insert(this.addButton, -1); + this.removeButton = new Gtk.ToolButton({ icon_name: "list-remove-symbolic", use_action_appearance: false }); + this.toolbar.insert(this.removeButton, -1); + }, + _refresh: function() { + this._tealist.clear(); + + let list = this._settings.get_value(SETTINGS_TEALIST_KEY); + for (let i = 0; i < list.n_children(); ++i) { + let item = list.get_child_value(i); + let teaname = item.get_child_value(0).get_string()[0]; + let time = item.get_child_value(1).get_uint32(); + + let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: time }); + this._tealist.set(this._tealist.append(), [0, 1, 2], [teaname, time, adj]); + } + } + +}); + + +function init() { +} + +function buildPrefsWidget() { + let widget = new TeaTimePrefsWidget(); + + widget.show_all(); + return widget; +} + From 17d7c024d2d7aee48fadb811ce8c77cb20848b65 Mon Sep 17 00:00:00 2001 From: Thomas Liebetraut Date: Wed, 22 May 2013 01:55:30 +0200 Subject: [PATCH 3/4] Write support in prefs.js --- prefs.js | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/prefs.js b/prefs.js index 76c97cc..b2047ca 100644 --- a/prefs.js +++ b/prefs.js @@ -68,24 +68,44 @@ const TeaTimePrefsWidget = new Lang.Class({ this._tealist.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT, Gtk.Adjustment]); this._settings = getSettings(); + this._inhibitUpdate = true; this._settings.connect("changed::" + SETTINGS_TEALIST_KEY, Lang.bind(this, this._refresh)); this._initWindow(); this.vexpand = true; + this._inhibitUpdate = false; this._refresh(); + this._tealist.connect("row-changed", Lang.bind(this, this._save)); + this._tealist.connect("row-deleted", Lang.bind(this, this._save)); }, _initWindow: function() { this.treeview = new Gtk.TreeView({model: this._tealist, expand: true}); + this.treeview.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE); this.add(this.treeview); let teaname = new Gtk.TreeViewColumn({ title: _("Tea"), expand: true }); let renderer = new Gtk.CellRendererText({ editable: true }); + // When the renderer is done editing it's value, we first write + // the new value to the view's model, i.e. this._tealist. + // This makes life a little harder due to chaining of callbacks + // and the need for this._inhibitUpdate, but it feels a lot cleaner + // when the UI does not know about the config storage backend. + renderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) { + let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString)); + this._tealist.set(iter, [0], [newValue]); + })); teaname.pack_start(renderer, true); teaname.add_attribute(renderer, "text", 0); this.treeview.append_column(teaname); - let steeptime = new Gtk.TreeViewColumn({ title: _("Steep time") }); + let steeptime = new Gtk.TreeViewColumn({ title: _("Steep time"), min_width: 150 }); let spinrenderer = new Gtk.CellRendererSpin({ editable: true }); + // See comment above. + spinrenderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) { + let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString)); + this._tealist.set(iter, [1], [parseInt(newValue)]); + })); + steeptime.pack_start(spinrenderer, true); steeptime.add_attribute(spinrenderer, "adjustment", 2); steeptime.add_attribute(spinrenderer, "text", 1); @@ -96,14 +116,24 @@ const TeaTimePrefsWidget = new Lang.Class({ this.toolbar.get_style_context().add_class("inline-toolbar"); this.add(this.toolbar); this.addButton = new Gtk.ToolButton({ icon_name: "list-add-symbolic", use_action_appearance: false }); + this.addButton.connect("clicked", Lang.bind(this, this._addTea)); this.toolbar.insert(this.addButton, -1); this.removeButton = new Gtk.ToolButton({ icon_name: "list-remove-symbolic", use_action_appearance: false }); + this.removeButton.connect("clicked", Lang.bind(this, this._removeSelectedTea)); this.toolbar.insert(this.removeButton, -1); }, _refresh: function() { - this._tealist.clear(); - + // don't update the model if someone else is messing with the backend + if (this._inhibitUpdate) + return; + let list = this._settings.get_value(SETTINGS_TEALIST_KEY); + + // stop everyone from reacting to the changes we are about to produce + // in the model + this._inhibitUpdate = true; + + this._tealist.clear(); for (let i = 0; i < list.n_children(); ++i) { let item = list.get_child_value(i); let teaname = item.get_child_value(0).get_string()[0]; @@ -112,6 +142,51 @@ const TeaTimePrefsWidget = new Lang.Class({ let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: time }); this._tealist.set(this._tealist.append(), [0, 1, 2], [teaname, time, adj]); } + + this._inhibitUpdate = false; + }, + _addTea: function() { + let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: 1 }); + let item = this._tealist.append(); + this._tealist.set(item, [0, 1, 2], ["", 1, adj]); + this.treeview.set_cursor(this._tealist.get_path(item), this.treeview.get_column(0), true); + }, + _removeSelectedTea: function() { + let [selection, store] = this.treeview.get_selection().get_selected_rows(); + let iters = []; + for (let i = 0; i < selection.length; ++i) { + let [isSet, iter] = store.get_iter(selection[i]); + if (isSet) { + iters.push(iter); + } + } + // it's ok not to inhibit updates here as remove != change + iters.forEach(function(value, index, array) { + store.remove(value) } + ); + + this.treeview.get_selection().unselect_all(); + }, + _save: function(store, path_, iter_) { + // don't update the backend if someone else is messing with the model + if (this._inhibitUpdate) + return; + + let values = []; + this._tealist.foreach(function(store, path, iter) { + values.push(GLib.Variant.new_dict_entry( + GLib.Variant.new_string(store.get_value(iter, 0)), + GLib.Variant.new_uint32(store.get_value(iter, 1)))) + }); + let settingsValue = GLib.Variant.new_array(GLib.VariantType.new("{su}"), values); + + // all changes have happened through the UI, we can safely + // disable updating it here to avoid an infinite loop + this._inhibitUpdate = true; + + this._settings.set_value(SETTINGS_TEALIST_KEY, settingsValue); + + this._inhibitUpdate = false; } }); From 2b2c3f40be20521496b3128b63a78612827d8ac0 Mon Sep 17 00:00:00 2001 From: Thomas Liebetraut Date: Wed, 22 May 2013 02:33:09 +0200 Subject: [PATCH 4/4] Tidying everything up. --- extension.js | 60 +++++------------------------------- prefs.js | 87 ++++++++++++++++++++-------------------------------- utils.js | 53 ++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 105 deletions(-) create mode 100644 utils.js diff --git a/extension.js b/extension.js index 12776d3..a47a074 100644 --- a/extension.js +++ b/extension.js @@ -25,39 +25,7 @@ const N_ = function(e) { return e; }; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); - -const TEALIST_KEY = "steep-times" - - -function getSettings(schema) { - let extension = ExtensionUtils.getCurrentExtension(); - - schema = schema || extension.metadata['settings-schema']; - - const GioSSS = Gio.SettingsSchemaSource; - - // check if this extension was built with "make zip-file", and thus - // has the schema files in a subfolder - // otherwise assume that extension has been installed in the - // same prefix as gnome-shell (and therefore schemas are available - // in the standard folders) - let schemaDir = extension.dir.get_child('schemas'); - let schemaSource; - if (schemaDir.query_exists(null)) { - schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), - GioSSS.get_default(), - false); - } - else - schemaSource = GioSSS.get_default(); - - let schemaObj = schemaSource.lookup(schema, true); - if (!schemaObj) - throw new Error('Schema ' + schema + ' could not be found for extension ' - + extension.metadata.uuid + '. Please check your installation.'); - - return new Gio.Settings({ settings_schema: schemaObj }); -} +const Utils = Me.imports.utils; const TeaTime = new Lang.Class({ @@ -67,7 +35,7 @@ const TeaTime = new Lang.Class({ _init : function() { this.parent(0.0, "TeaTime"); - this._settings = getSettings(); + this._settings = Utils.getSettings(); this._logo = new St.Icon({ icon_name : 'utilities-teatime', @@ -75,7 +43,6 @@ const TeaTime = new Lang.Class({ }); // set timer widget - this._timer = new St.DrawingArea({ reactive : true }); @@ -92,31 +59,20 @@ const TeaTime = new Lang.Class({ }, _createMenu : function() { this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - this._settings.connect("changed::" + TEALIST_KEY, Lang.bind(this, this._updateTeaList)); + this._settings.connect("changed::" + Utils.TEATIME_STEEP_TIMES_KEY, + Lang.bind(this, this._updateTeaList)); this._updateTeaList(); }, - _formatTime : function(seconds) { - let a = new Date(0,0,0); // important: hour needs to be set to zero in _locale_ time - - a.setTime(a.getTime()+ seconds * 1000); // set time in msec, adding the time we want - - if (seconds > 3600) - return a.toLocaleFormat("%H:%M:%S"); - else - return a.toLocaleFormat("%M:%S"); - }, _updateTeaList : function(config, output) { // make sure the menu is empty this.menu.removeAll(); // fill with new teas - let list = this._settings.get_value(TEALIST_KEY); - for (let i = 0; i < list.n_children(); ++i) { - let item = list.get_child_value(i); - let teaname = item.get_child_value(0).get_string()[0]; - let time = item.get_child_value(1).get_uint32(); + let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack(); + for (let teaname in list) { + let time = list[teaname].get_uint32(); - let menuItem = new PopupMenu.PopupMenuItem(teaname + ": " + this._formatTime(time)); + let menuItem = new PopupMenu.PopupMenuItem(teaname + ": " + Utils.formatTime(time)); menuItem.connect('activate', Lang.bind(this, function() { this._initCountdown(time); })); diff --git a/prefs.js b/prefs.js index b2047ca..16b25ad 100644 --- a/prefs.js +++ b/prefs.js @@ -21,40 +21,13 @@ const N_ = function(e) { return e; }; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); - -let settings; - -const SETTINGS_TEALIST_KEY = 'steep-times'; +const Utils = Me.imports.utils; -function getSettings(schema) { - let extension = ExtensionUtils.getCurrentExtension(); - - schema = schema || extension.metadata['settings-schema']; - - const GioSSS = Gio.SettingsSchemaSource; - - // check if this extension was built with "make zip-file", and thus - // has the schema files in a subfolder - // otherwise assume that extension has been installed in the - // same prefix as gnome-shell (and therefore schemas are available - // in the standard folders) - let schemaDir = extension.dir.get_child('schemas'); - let schemaSource; - if (schemaDir.query_exists(null)) { - schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), - GioSSS.get_default(), - false); - } - else - schemaSource = GioSSS.get_default(); - - let schemaObj = schemaSource.lookup(schema, true); - if (!schemaObj) - throw new Error('Schema ' + schema + ' could not be found for extension ' - + extension.metadata.uuid + '. Please check your installation.'); - - return new Gio.Settings({ settings_schema: schemaObj }); +const Columns = { + TEA_NAME: 0, + STEEP_TIME: 1, + ADJUSTMENT: 2 } const TeaTimePrefsWidget = new Lang.Class({ @@ -65,11 +38,16 @@ const TeaTimePrefsWidget = new Lang.Class({ this.parent({ orientation: Gtk.Orientation.VERTICAL }); this._tealist = new Gtk.ListStore(); - this._tealist.set_column_types([GObject.TYPE_STRING, GObject.TYPE_INT, Gtk.Adjustment]); + this._tealist.set_column_types([ + GObject.TYPE_STRING, + GObject.TYPE_INT, + Gtk.Adjustment + ]); - this._settings = getSettings(); + this._settings = Utils.getSettings(); this._inhibitUpdate = true; - this._settings.connect("changed::" + SETTINGS_TEALIST_KEY, Lang.bind(this, this._refresh)); + this._settings.connect("changed::" + Utils.TEATIME_STEEP_TIMES_KEY, + Lang.bind(this, this._refresh)); this._initWindow(); this.vexpand = true; @@ -92,10 +70,10 @@ const TeaTimePrefsWidget = new Lang.Class({ // when the UI does not know about the config storage backend. renderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) { let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString)); - this._tealist.set(iter, [0], [newValue]); + this._tealist.set(iter, [Columns.TEA_NAME], [newValue]); })); teaname.pack_start(renderer, true); - teaname.add_attribute(renderer, "text", 0); + teaname.add_attribute(renderer, "text", Columns.TEA_NAME); this.treeview.append_column(teaname); let steeptime = new Gtk.TreeViewColumn({ title: _("Steep time"), min_width: 150 }); @@ -103,12 +81,12 @@ const TeaTimePrefsWidget = new Lang.Class({ // See comment above. spinrenderer.connect("edited", Lang.bind(this, function(renderer, pathString, newValue) { let [store, iter] = this._tealist.get_iter(Gtk.TreePath.new_from_string(pathString)); - this._tealist.set(iter, [1], [parseInt(newValue)]); + this._tealist.set(iter, [Columns.STEEP_TIME], [parseInt(newValue)]); })); steeptime.pack_start(spinrenderer, true); - steeptime.add_attribute(spinrenderer, "adjustment", 2); - steeptime.add_attribute(spinrenderer, "text", 1); + steeptime.add_attribute(spinrenderer, "adjustment", Columns.ADJUSTMENT); + steeptime.add_attribute(spinrenderer, "text", Columns.STEEP_TIME); this.treeview.append_column(steeptime); @@ -127,20 +105,20 @@ const TeaTimePrefsWidget = new Lang.Class({ if (this._inhibitUpdate) return; - let list = this._settings.get_value(SETTINGS_TEALIST_KEY); + let list = this._settings.get_value(Utils.TEATIME_STEEP_TIMES_KEY).unpack(); // stop everyone from reacting to the changes we are about to produce // in the model this._inhibitUpdate = true; this._tealist.clear(); - for (let i = 0; i < list.n_children(); ++i) { - let item = list.get_child_value(i); - let teaname = item.get_child_value(0).get_string()[0]; - let time = item.get_child_value(1).get_uint32(); - + for (let teaname in list) { + let time = list[teaname].get_uint32(); + let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: time }); - this._tealist.set(this._tealist.append(), [0, 1, 2], [teaname, time, adj]); + this._tealist.set(this._tealist.append(), + [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], + [teaname, time, adj]); } this._inhibitUpdate = false; @@ -148,8 +126,12 @@ const TeaTimePrefsWidget = new Lang.Class({ _addTea: function() { let adj = new Gtk.Adjustment({ lower: 1, step_increment: 1, upper: 65535, value: 1 }); let item = this._tealist.append(); - this._tealist.set(item, [0, 1, 2], ["", 1, adj]); - this.treeview.set_cursor(this._tealist.get_path(item), this.treeview.get_column(0), true); + this._tealist.set(item, + [Columns.TEA_NAME, Columns.STEEP_TIME, Columns.ADJUSTMENT], + ["", 1, adj]); + this.treeview.set_cursor(this._tealist.get_path(item), + this.treeview.get_column(Columns.TEA_NAME), + true); }, _removeSelectedTea: function() { let [selection, store] = this.treeview.get_selection().get_selected_rows(); @@ -175,8 +157,8 @@ const TeaTimePrefsWidget = new Lang.Class({ let values = []; this._tealist.foreach(function(store, path, iter) { values.push(GLib.Variant.new_dict_entry( - GLib.Variant.new_string(store.get_value(iter, 0)), - GLib.Variant.new_uint32(store.get_value(iter, 1)))) + GLib.Variant.new_string(store.get_value(iter, Columns.TEA_NAME)), + GLib.Variant.new_uint32(store.get_value(iter, Columns.STEEP_TIME)))) }); let settingsValue = GLib.Variant.new_array(GLib.VariantType.new("{su}"), values); @@ -184,11 +166,10 @@ const TeaTimePrefsWidget = new Lang.Class({ // disable updating it here to avoid an infinite loop this._inhibitUpdate = true; - this._settings.set_value(SETTINGS_TEALIST_KEY, settingsValue); + this._settings.set_value(Utils.TEATIME_STEEP_TIMES_KEY, settingsValue); this._inhibitUpdate = false; } - }); diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..6c17606 --- /dev/null +++ b/utils.js @@ -0,0 +1,53 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* Olaf Leidinger + Thomas Liebetraut +*/ + +const Gio = imports.gi.Gio; +const Lang = imports.lang; + +const ExtensionUtils = imports.misc.extensionUtils; +const Me = ExtensionUtils.getCurrentExtension(); + +const TEATIME_STEEP_TIMES_KEY = 'steep-times'; + +function getSettings(schema) { + let extension = ExtensionUtils.getCurrentExtension(); + + schema = schema || extension.metadata['settings-schema']; + + const GioSSS = Gio.SettingsSchemaSource; + + // check if this extension was built with "make zip-file", and thus + // has the schema files in a subfolder + // otherwise assume that extension has been installed in the + // same prefix as gnome-shell (and therefore schemas are available + // in the standard folders) + let schemaDir = extension.dir.get_child('schemas'); + let schemaSource; + if (schemaDir.query_exists(null)) { + schemaSource = GioSSS.new_from_directory(schemaDir.get_path(), + GioSSS.get_default(), + false); + } else { + schemaSource = GioSSS.get_default(); + } + + let schemaObj = schemaSource.lookup(schema, true); + if (!schemaObj) + throw new Error('Schema ' + schema + ' could not be found for extension ' + + extension.metadata.uuid + '. Please check your installation.'); + + return new Gio.Settings({ settings_schema: schemaObj }); +} + +function formatTime(seconds) { + let a = new Date(0,0,0); // important: hour needs to be set to zero in _locale_ time + + a.setTime(a.getTime()+ seconds * 1000); // set time in msec, adding the time we want + + if (seconds > 3600) + return a.toLocaleFormat("%H:%M:%S"); + else + return a.toLocaleFormat("%M:%S"); +}