From 6cf5b918ad54b4d674b410c6ce27a4bcb704aa76 Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Sat, 2 May 2015 17:48:01 +0200 Subject: Foundations. --- extension.js | 53 ++++++++++ geoclue.js | 86 ++++++++++++++++ gnome-shell-ISS_Above.desktop | 9 ++ metadata.json | 8 ++ place.js | 230 ++++++++++++++++++++++++++++++++++++++++++ stylesheet.css | 8 ++ 6 files changed, 394 insertions(+) create mode 100644 extension.js create mode 100644 geoclue.js create mode 100644 gnome-shell-ISS_Above.desktop create mode 100644 metadata.json create mode 100644 place.js create mode 100644 stylesheet.css diff --git a/extension.js b/extension.js new file mode 100644 index 0000000..260aef7 --- /dev/null +++ b/extension.js @@ -0,0 +1,53 @@ + +const St = imports.gi.St; +const Main = imports.ui.main; +const Tweener = imports.ui.tweener; + +let text, button; + +function _hideHello() { + Main.uiGroup.remove_actor(text); + text = null; +} + +function _showHello() { + if (!text) { + text = new St.Label({ style_class: 'helloworld-label', text: "Hello, world!" }); + Main.uiGroup.add_actor(text); + } + + text.opacity = 255; + + let monitor = Main.layoutManager.primaryMonitor; + + text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2), + monitor.y + Math.floor(monitor.height / 2 - text.height / 2)); + + Tweener.addTween(text, + { opacity: 0, + time: 2, + transition: 'easeOutQuad', + onComplete: _hideHello }); +} + +function init() { + button = new St.Bin({ style_class: 'panel-button', + reactive: true, + can_focus: true, + x_fill: true, + y_fill: false, + track_hover: true }); + let icon = new St.Icon({ icon_name: 'system-run-symbolic', + style_class: 'system-status-icon' }); + + button.set_child(icon); + button.connect('button-press-event', _showHello); +} + +function enable() { + Main.panel._rightBox.insert_child_at_index(button, 0); +} + +function disable() { + Main.panel._rightBox.remove_child(button); +} diff --git a/geoclue.js b/geoclue.js new file mode 100644 index 0000000..8cde221 --- /dev/null +++ b/geoclue.js @@ -0,0 +1,86 @@ +#!/usr/bin/gjs +// Requires .desktop file installed in $XDG_DATA_DIRS/applications + +const GLib = imports.gi.GLib; +const Gio = imports.gi.Gio; +const Geocode = imports.gi.GeocodeGlib; +const Lang = imports.lang; +const Mainloop = imports.mainloop; + +const AccuracyLevel = { + COUNTRY: 1, + CITY: 4, + NEIGHBORHOOD: 5, + STREET: 6, + EXACT: 8 +}; + +const ManagerIface = ' \ + \ + \ + \ + \ + \ +'; +const ManagerProxy = Gio.DBusProxy.makeProxyWrapper(ManagerIface); + +const ClientInterface = ' \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +'; +const ClientProxy = Gio.DBusProxy.makeProxyWrapper(ClientInterface); + +const LocationInterface = ' \ + \ + \ + \ + \ + \ + \ +'; +const LocationProxy = Gio.DBusProxy.makeProxyWrapper(LocationInterface); + + +function onLocationUpdated(proxy, sender, [oldPath, newPath]) { + let geoclueLocation = new LocationProxy(Gio.DBus.system, + "org.freedesktop.GeoClue2", + newPath); + let location = new Geocode.Location({ latitude: geoclueLocation.Latitude, + longitude: geoclueLocation.Longitude, + accuracy: geoclueLocation.Accuracy, + description: geoclueLocation.Description }); + print('location:'); + print('\tlatitude = ' + geoclueLocation.Latitude); + print('\tlongitude = ' + geoclueLocation.Longitude); + print('\taccuracy = ' + geoclueLocation.Accuracy); + print('\tdescription = ' + geoclueLocation.Description); + //this._updateLocation(location); + Mainloop.quit(); +} + +let _managerProxy = new ManagerProxy(Gio.DBus.system, + 'org.freedesktop.GeoClue2', '/org/freedesktop/GeoClue2/Manager'); + +let [clientAddr] = _managerProxy.GetClientSync(); + +let clientProxy = new ClientProxy(Gio.DBus.system, + 'org.freedesktop.GeoClue2', clientAddr); +clientProxy.DesktopId = 'geoclue-test-simple'; +clientProxy.DistanceThreshold = 10000; +clientProxy.RequestedAccuracyLevel = AccuracyLevel.EXACT; +let updatedId = clientProxy.connectSignal('LocationUpdated', + onLocationUpdated); +clientProxy.StartRemote(); + +Mainloop.run(); diff --git a/gnome-shell-ISS_Above.desktop b/gnome-shell-ISS_Above.desktop new file mode 100644 index 0000000..0870237 --- /dev/null +++ b/gnome-shell-ISS_Above.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Name=ISS Above Gnome-Shell extension +GenericName=ISS Above Gnome-Shell extension +Keywords=geolocation;gnome-shell +Exec=/home/matej/archiv/2015/projekty/ISS_Above@mcepl.cepl.eu/extension.js +Icon=mark-location-symbolic +NoDisplay=true +Terminal=false +Type=Application diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..36960bd --- /dev/null +++ b/metadata.json @@ -0,0 +1,8 @@ +{ + "shell-version": [ + "3.14.2" + ], + "uuid": "ISS_Above@mcepl.cepl.eu", + "name": "ISS Above", + "description": "Shows an icon when ISS is above you (+- 100km)" +} diff --git a/place.js b/place.js new file mode 100644 index 0000000..91dd178 --- /dev/null +++ b/place.js @@ -0,0 +1,230 @@ +/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */ +/* vim: set et ts=4 sw=4: */ +/* + * Copyright (c) 2014 Jonas Danielsson + * + * GNOME Maps is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * GNOME Maps is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with GNOME Maps; if not, see . + * + * Author: Jonas Danielsson + */ + +const Geocode = imports.gi.GeocodeGlib; +const GLib = imports.gi.GLib; +const Lang = imports.lang; +const Translations = imports.translations; + +const Place = new Lang.Class({ + Name: 'Place', + Extends: Geocode.Place, + + _init: function(params) { + this._population = params.population; + delete params.population; + + this._wiki = params.wiki; + delete params.wiki; + + this._openingHours = params.openingHours; + delete params.openingHours; + + this._wheelchair = params.wheelchair; + delete params.wheelchair; + + if (params.place) { + params = { osm_id: params.place.osm_id, + osm_type: params.place.osm_type, + name: params.place.name, + location: params.place.location, + bounding_box: params.place.bounding_box, + place_type: params.place.place_type, + street_address: params.place.street_address, + street: params.place.street, + building: params.place.building, + postal_code: params.place.postal_code, + area: params.place.area, + town: params.place.town, + state: params.place.state, + county: params.place.county, + country: params.place.country, + country_code: params.place.contry_code, + continent: params.place.continent }; + } + + for (let prop in params) + if (!params[prop]) + delete params[prop]; + + this.parent(params); + }, + + get uniqueID() { + return this.osm_type + '-' + this.osm_id; + }, + + set population(v) { + this._population = v; + }, + + get population() { + return this._population; + }, + + set wiki(v) { + this._wiki = v; + }, + + get wiki() { + return this._wiki; + }, + + set openingHours(v) { + this._openingHours = v; + }, + + get openingHours() { + return this._openingHours; + }, + + get openingHoursTranslated() { + return Translations.translateOpeningHours(this._openingHours); + }, + + set wheelchair(v) { + this._wheelchair = v; + }, + + get wheelchair() { + return this._wheelchair; + }, + + get wheelchairTranslated() { + return this._translateWheelchair(this._wheelchair); + }, + + _translateWheelchair: function(string) { + switch(string) { + /* Translators: + * This means wheelchairs have full unrestricted access. + */ + case 'yes': return _("yes"); + + /* Translators: + * This means wheelchairs have partial access (e.g some areas + * can be accessed and others not, areas requiring assistance + * by someone pushing up a steep gradient). + */ + case 'limited': return _("limited"); + + /* Translators: + * This means wheelchairs have no unrestricted access + * (e.g. stair only access). + */ + case 'no': return _("no"); + + /* Translators: + * This means that the way or area is designated or purpose built + * for wheelchairs (e.g. elevators designed for wheelchair access + * only). This is rarely used. + */ + case 'designated': return _("designated"); + + default: return null; + } + }, + + + toJSON: function() { + let bounding_box = null; + + if (this.bounding_box) { + bounding_box = { top: this.bounding_box.top, + bottom: this.bounding_box.bottom, + left: this.bounding_box.left, + right: this.bounding_box.right }; + } + + let location = { latitude: this.location.latitude, + longitude: this.location.longitude, + altitude: this.location.altitude, + accuracy: this.location.accuracy }; + + return { id: this.osm_id, + osm_type: this.osm_type, + name: this.name, + bounding_box: bounding_box, + this_type: this.this_type, + location: location, + street_address: this.street_address, + street: this.street, + building: this.building, + postal_code: this.postal_code, + area: this.area, + town: this.town, + state: this.state, + county: this.county, + country: this.country, + country_code: this.contry_code, + continent: this.continent, + population: this.population, + wiki: this.wiki, + wheelchair: this.wheelchair, + openingHours: this.openingHours }; + }, + + match: function(searchString) { + let name = this.name; + + searchString = GLib.utf8_normalize(searchString, -1, GLib.NormalizeMode.ALL); + if (searchString === null) + return false; + + if (searchString.length === 0) + return true; + + name = GLib.utf8_normalize(name, -1, GLib.NormalizeMode.ALL); + if (name === null) + return false; + + return name.toLowerCase().search(searchString.toLowerCase()) !== -1; + } +}); + +Place.fromJSON = function(obj) { + let props = { }; + + for (let key in obj) { + let prop = obj[key]; + + switch(key) { + case 'id': + props.osm_id = prop; + break; + + case 'location': + props.location = new Geocode.Location(prop); + break; + + case 'bounding_box': + if (prop) + props.bounding_box = new Geocode.BoundingBox(prop); + break; + + default: + if (prop !== null && prop !== undefined) + props[key] = prop; + break; + } + } + return new Place(props); +}; diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 0000000..432a360 --- /dev/null +++ b/stylesheet.css @@ -0,0 +1,8 @@ +.helloworld-label { + font-size: 36px; + font-weight: bold; + color: #ffffff; + background-color: rgba(10,10,10,0.7); + border-radius: 5px; + padding: .5em; +} -- cgit