[hamster-applet] first steps towards a gnome shell extension
- From: Toms Baugis <tbaugis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hamster-applet] first steps towards a gnome shell extension
- Date: Thu, 7 Jul 2011 01:00:28 +0000 (UTC)
commit d8e7a228cc1e1fa9d6a02780de74458fa12c0a79
Author: Toms BauÄis <toms baugis gmail com>
Date: Thu Jul 7 03:58:08 2011 +0300
first steps towards a gnome shell extension
src/shell_extension/extension.js | 225 ++++++++++++++++++++++++++++++++++++
src/shell_extension/metadata.json | 7 +
src/shell_extension/stylesheet.css | 3 +
wscript | 4 +
4 files changed, 239 insertions(+), 0 deletions(-)
---
diff --git a/src/shell_extension/extension.js b/src/shell_extension/extension.js
new file mode 100644
index 0000000..8731273
--- /dev/null
+++ b/src/shell_extension/extension.js
@@ -0,0 +1,225 @@
+/*
+ * Simple Hamster extension for gnome-shell
+ * Copyright (c) 2011 Jerome Oufella <jerome oufella com>
+ * Copyright (c) 2011 Toms Baugis <toms baugis gmail com>
+ * Portions originate from the gnome-shell source code, Copyright (c)
+ * its respectives authors.
+ * This project is released under the GNU GPL License.
+ * See COPYING for details.
+ *
+ */
+
+const DBus = imports.dbus;
+const Lang = imports.lang;
+const St = imports.gi.St;
+const Shell = imports.gi.Shell;
+const Main = imports.ui.main;
+const PopupMenu = imports.ui.popupMenu;
+const PanelMenu = imports.ui.panelMenu;
+const Util = imports.misc.util;
+const Gettext = imports.gettext;
+const _ = Gettext.gettext;
+
+/* We use keybindings provided by default in the metacity GConf tree, and which
+ * are supported by default.
+ * Most probably not the smartest choice, time will tell.
+ */
+const _hamsterKeyBinding = 'run_command_12';
+
+
+
+const HamsterIface = {
+ name: 'org.gnome.Hamster',
+ methods: [
+ { name: 'GetTodaysFacts', inSignature: '', outSignature: 'a(iiissisasii)'},
+ { name: 'StopTracking', inSignature: 'i'},
+ ],
+ signals: [
+ {name: 'TagsChanged', inSignature: ''},
+ {name: 'FactsChanged', inSignature: ''},
+ {name: 'ActivitiesChanged', inSignature: ''},
+ {name: 'ToggleCalled', inSignature: ''},
+ ]
+};
+let HamsterProxy = DBus.makeProxyClass(HamsterIface);
+
+
+function fromDbusFact(fact) {
+ // converts a fact coming from dbus into a usable object
+ function UTCToLocal(timestamp) {
+ // TODO - is this really the way?!
+ let res = new Date(timestamp)
+ return new Date(res.setUTCMinutes(res.getUTCMinutes() + res.getTimezoneOffset()));
+ }
+ global.log(fact[1] + " ----- " + fact[2])
+
+ return {
+ name: fact[4],
+ startTime: UTCToLocal(fact[1]*1000),
+ endTime: fact[2] != 0 ? UTCToLocal(fact[2]*1000) : null,
+ description: fact[3],
+ activityId: fact[5],
+ category: fact[6],
+ tags: fact[7],
+ date: UTCToLocal(fact[8] * 1000),
+ delta: fact[9] / (60 * 60), // hours; TODO - want timedelta
+ id: fact[0]
+ }
+};
+
+
+/* Popup */
+function HamsterPopupMenuEntry() {
+ this._init.apply(this, arguments);
+}
+
+HamsterPopupMenuEntry.prototype = {
+ __proto__: PopupMenu.PopupBaseMenuItem.prototype,
+
+ _init: function(itemParams, entryParams) {
+ PopupMenu.PopupBaseMenuItem.prototype._init.call(this, itemParams);
+ this._textEntry = new St.Entry(entryParams);
+ this._textEntry.clutter_text.connect('activate',
+ Lang.bind(this, this._onEntryActivated));
+ this.addActor(this._textEntry);
+ },
+
+ _onEntryActivated: function() {
+ this.emit('activate');
+ this._textEntry.set_text('');
+ }
+};
+
+/* Panel button */
+function HamsterButton() {
+ this._init();
+}
+
+HamsterButton.prototype = {
+ __proto__: PanelMenu.Button.prototype,
+
+ _init: function() {
+ PanelMenu.Button.prototype._init.call(this, 0.0);
+
+ this._proxy = new HamsterProxy(DBus.session, 'org.gnome.Hamster', '/org/gnome/Hamster');
+
+ this._proxy.connect('FactsChanged', Lang.bind(this, this.onFactsChanged));
+ this._proxy.connect('ActivitiesChanged', Lang.bind(this, this.onActivitiesChanged));
+ this._proxy.connect('TagsChanged', Lang.bind(this, this.onTagsChanged));
+
+ this.panel_label = new St.Label({ style_class: 'hamster-label', text: _("Loading...") });
+ this.actor.set_child(this.panel_label);
+ Main.panel._centerBox.add(this.actor, { y_fill: true });
+
+ this.facts = null;
+ this.currentFact = null;
+
+ this.refresh();
+
+
+ /* Create all items in the dropdown menu: */
+ let item;
+
+ /* This one make the hamster applet appear */
+ item = new PopupMenu.PopupMenuItem(_("Show Hamster"));
+ item.connect('activate', function() {
+ let app = Shell.AppSystem.get_default().get_app(
+ 'hamster-time-tracker.desktop');
+ app.activate(-1);
+ });
+ this.menu.addMenuItem(item);
+
+ /* To stop tracking the current activity */
+ item = new PopupMenu.PopupMenuItem(_("Stop tracking"));
+ item.connect('activate', Lang.bind(this, this._onStopTracking));
+ this.menu.addMenuItem(item);
+
+ /* The activity item has a text entry field to quickly log something */
+ item = new HamsterPopupMenuEntry({ reactive: false }, {
+ name: 'searchEntry',
+ can_focus: true,
+ track_hover: false,
+ hint_text: _("Enter activity...")
+ });
+ item.connect('activate', Lang.bind(this, this._onActivityEntry));
+ this._activityEntry = item;
+ this.menu.addMenuItem(item);
+
+ /* Integrate previously defined menu to panel */
+ Main.panel._rightBox.insert_actor(this.actor, 0);
+ Main.panel._menus.addMenu(this.menu);
+
+ /* Install global keybinding to log something */
+ let shellwm = global.window_manager;
+ shellwm.takeover_keybinding(_hamsterKeyBinding);
+ shellwm.connect('keybinding::' + _hamsterKeyBinding,
+ Lang.bind(this, this._onGlobalKeyBinding));
+ },
+
+ onTagsChanged: function() {
+ this.refresh();
+ },
+
+ onFactsChanged: function() {
+ this.refresh();
+ },
+
+ onActivitiesChanged: function() {
+ this.refresh();
+ },
+
+
+ refresh: function() {
+ this._proxy.GetTodaysFactsRemote(Lang.bind(this, function(facts, err) {
+ this.facts = facts;
+
+ let fact = null;
+ if (facts) {
+ fact = fromDbusFact(facts[facts.length - 1]);
+ }
+
+ if (fact && !fact.endTime) {
+ this.currentFact = fact;
+
+ this.panel_label.text = fact.name + " " + Number(fact.delta).toPrecision(2) + "h";
+ } else {
+ this.panel_label.text = "No activity";
+ }
+ }));
+ },
+
+ _onStopTracking: function() {
+ let date = new Date()
+ date = new Date(date.setUTCMinutes(date.getUTCMinutes() - date.getTimezoneOffset())); // getting back to UTC
+
+ let epochSeconds = date.getTime() / 1000;
+ this._proxy.StopTrackingRemote(epochSeconds);
+ },
+
+ _onActivityEntry: function() {
+ let text = this._activityEntry._textEntry.get_text();
+ let cmdline = 'hamster-cli start "' + text + '"';
+ try {
+ Util.trySpawnCommandLine(cmdline);
+ this._activityLabel.set_text(' ' + text);
+ } catch (e) {
+ global.log('_onActivityEntry(): got exception: ' + e);
+ }
+ },
+
+ _onGlobalKeyBinding: function() {
+ this.menu.toggle();
+ this._activityEntry._textEntry.grab_key_focus();
+ }
+};
+
+
+function main(extensionMeta) {
+ /* Localization stuff */
+ let userExtensionLocalePath = extensionMeta.path + '/locale';
+ Gettext.bindtextdomain("hamster-applet", userExtensionLocalePath);
+ Gettext.textdomain("hamster-applet");
+
+ /* Create our button */
+ new HamsterButton();
+}
diff --git a/src/shell_extension/metadata.json b/src/shell_extension/metadata.json
new file mode 100644
index 0000000..4e3c23d
--- /dev/null
+++ b/src/shell_extension/metadata.json
@@ -0,0 +1,7 @@
+{
+"shell-version": ["3.0.2"],
+"uuid": "hamster gnome org",
+"name": "Hamster Menu",
+"url": "http://projecthamster.wordpress.com/",
+"description": "Shell extension for project hamster - the GNOME time tracker"
+}
diff --git a/src/shell_extension/stylesheet.css b/src/shell_extension/stylesheet.css
new file mode 100644
index 0000000..5644282
--- /dev/null
+++ b/src/shell_extension/stylesheet.css
@@ -0,0 +1,3 @@
+.hamster-label {
+ margin-left: 30px;
+}
diff --git a/wscript b/wscript
index 3402371..cba24a1 100644
--- a/wscript
+++ b/wscript
@@ -76,6 +76,10 @@ def build(bld):
bld.install_files('${DATADIR}/dockmanager/metadata',
'src/docky_control/2.1/hamster_control.py.info')
+ # gnome shell applet
+ bld.install_files('${DATADIR}/gnome-shell/extensions/hamster gnome org',
+ 'src/shell_extension/*')
+
bld.new_task_gen("subst",
source= "org.gnome.hamster.service.in",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]