unity-scope-openweathermap-0.1+13.10.20130828/0000755000015700001700000000000012207374750021214 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/po/0000755000015700001700000000000012207374750021632 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/po/unity-scope-openweathermap.pot0000644000015700001700000000257612207374531027661 0ustar pbuserpbgroup00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-02-21 01:57+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../src/unity_openweathermap_daemon.py:35 #: ../data/openweathermap.scope.in.h:4 msgid "Search OpenWeatherMap" msgstr "" #: ../src/unity_openweathermap_daemon.py:36 msgid "Sorry, there is no OpenwWeatherMap forecast that matches your search." msgstr "" #: ../src/unity_openweathermap_daemon.py:37 msgid "Powered by OpenWeatherMap" msgstr "" #: ../src/unity_openweathermap_daemon.py:45 msgid "Weather Forecast" msgstr "" #: ../src/unity_openweathermap_daemon.py:96 msgid "Today" msgstr "" #: ../src/unity_openweathermap_daemon.py:114 msgid "Tomorrow" msgstr "" #: ../data/openweathermap.scope.in.h:1 msgid "openweathermap;weather;sky;forecast;" msgstr "" #: ../data/openweathermap.scope.in.h:2 msgid "Openweathermap" msgstr "" #: ../data/openweathermap.scope.in.h:3 msgid "Find OpenWeatherMap forecasts" msgstr "" unity-scope-openweathermap-0.1+13.10.20130828/po/POTFILES.in0000644000015700001700000000014512207374531023404 0ustar pbuserpbgroup00000000000000[encoding: UTF-8] src/unity_openweathermap_daemon.py [type: gettext/ini]data/openweathermap.scope.in unity-scope-openweathermap-0.1+13.10.20130828/MANIFEST.in0000644000015700001700000000007612207374531022752 0ustar pbuserpbgroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-openweathermap-0.1+13.10.20130828/tests/0000755000015700001700000000000012207374750022356 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/tests/test_openweathermap.py0000644000015700001700000000534512207374531027012 0ustar pbuserpbgroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- from gi.repository import Unity from unittest import TestCase import imp class ResultSet(Unity.ResultSet): def __init__(self): Unity.ResultSet.__init__(self) self.results = [] def do_add_result(self, result): self.results.append({'uri':result.uri, 'title':result.title, 'comment':result.comment, 'icon':result.icon_hint}) class ScopeTestCase(TestCase): def init_scope(self, scope_path): self.scope_module = imp.load_source('scope', scope_path) self.scope = self.scope_module.load_scope() def perform_query(self, query, filter_set = Unity.FilterSet.new()): result_set = ResultSet() ctx = Unity.SearchContext.create(query, 0, filter_set, None, result_set, None) s = self.scope.create_search_for_query(ctx) s.run() return result_set class TestOpenweathermap(ScopeTestCase): def setUp(self): self.init_scope('src/unity_openweathermap_daemon.py') def tearDown(self): self.scope = None self.scope_module = None def test_valid_searches(self): self.scope_module.SEARCH_URI = ['file:tests/data/mock_openweathermap_pass#', 'file:tests/data/mock_openweathermap_city_pass#'] expected_results = ['http://openweathermap.org/city/3026083', 'weather-snow', 'Chatillon, FR\n0°C / 33°F', 'heavy snow', 'http://openweathermap.org/city/3026083#Tomorrow', 'weather-clouds', 'Tomorrow\n257°C / 494°F', 'scattered clouds'] results = [] for s in ['query']: result_set = self.perform_query(s) results.append(result_set.results[0]['uri']) results.append(result_set.results[0]['icon']) results.append(result_set.results[0]['title']) results.append(result_set.results[0]['comment']) results.append(result_set.results[1]['uri']) results.append(result_set.results[1]['icon']) results.append(result_set.results[1]['title']) results.append(result_set.results[1]['comment']) self.assertEqual(results, expected_results) def test_failing_search(self): self.scope_module.SEARCH_URI = 'file:tests/data/mock_openweathermap_fail#' for s in ['query']: result_set = self.perform_query(s) self.assertEqual(len(result_set.results), 0) if __name__ == '__main__': unittest.main() unity-scope-openweathermap-0.1+13.10.20130828/tests/data/0000755000015700001700000000000012207374750023267 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/tests/data/mock_openweathermap_city_pass0000644000015700001700000000041212207374531031312 0ustar pbuserpbgroup00000000000000{"cod":"200","calctime":0.0298,"cnt":8,"list":[{"dt":1359193359,"temp":257.12,"night":253.17,"eve":252.85,"morn":252.95,"pressure":1016.05,"humidity":96.3,"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"speed":2.16,"deg":286}]} unity-scope-openweathermap-0.1+13.10.20130828/tests/data/mock_openweathermap_fail0000644000015700001700000000000612207374531030226 0ustar pbuserpbgroup00000000000000 unity-scope-openweathermap-0.1+13.10.20130828/tests/data/mock_openweathermap_pass0000644000015700001700000001116012207374531030264 0ustar pbuserpbgroup00000000000000{"message":"","cod":"200","type":"base","calctime":"","units":"metric","count":10,"list":[{"id":3026083,"coord":{"lat":48.802399,"lon":2.29346},"name":"Chatillon","main":{"temp":0.66000000000003,"pressure":996,"temp_min":0,"temp_max":1},"dt":1358793000,"date":"2013-01-21 18:30:00","wind":{"speed":2.1,"deg":330},"clouds":{"all":90},"weather":[{"id":602,"main":"Snow","description":"heavy snow","icon":"13n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"sys":{"country":"FR","population":32383},"url":"http:\/\/openweathermap.org\/city\/3026083"},{"id":3026046,"coord":{"lat":47.858509,"lon":4.57375},"name":"Chatillon-sur-Seine","main":{"temp":1.55,"temp_min":1.54,"temp_max":2.04,"pressure":979.54,"humidity":95.7},"dt":1358796365,"date":"2013-01-21 19:26:05","wind":{"speed":5.13,"deg":194,"gust":12.1},"clouds":{"all":91},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"sys":{"country":"FR","population":6939},"url":"http:\/\/openweathermap.org\/city\/3026046"},{"id":3026047,"coord":{"lat":48.034481,"lon":-1.67114},"name":"Chatillon-sur-Seiche","main":{"temp":2,"pressure":1000,"humidity":93,"temp_min":0.020000000000039,"temp_max":2},"dt":1358793000,"date":"2013-01-21 18:30:00","wind":{"speed":2.1,"deg":270},"clouds":{"all":40},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"}],"sys":{"country":"FR","population":6152},"url":"http:\/\/openweathermap.org\/city\/3026047"},{"id":3178905,"coord":{"lat":45.751659,"lon":7.61751},"name":"Chatillon","main":{"temp":-11.37,"temp_min":-11.39,"temp_max":-9.16,"pressure":755.15,"humidity":98.2},"dt":1358796181,"date":"2013-01-21 19:23:01","wind":{"speed":2.35,"deg":290,"gust":3.4},"clouds":{"all":99},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"sys":{"country":"IT","population":4712},"url":"http:\/\/openweathermap.org\/city\/3178905"},{"id":3026057,"coord":{"lat":46.12019,"lon":4.95817},"name":"Chatillon-sur-Chalaronne","main":{"temp":0.47000000000003,"temp_min":0.45000000000005,"temp_max":1.41,"pressure":982.4,"humidity":89.7},"dt":1358796177,"date":"2013-01-21 19:22:57","wind":{"speed":5.01,"deg":159,"gust":10.5},"clouds":{"all":64},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"sys":{"country":"FR","population":4660},"url":"http:\/\/openweathermap.org\/city\/3026057"},{"id":3026044,"coord":{"lat":46.661758,"lon":-0.23489},"name":"Chatillon-sur-Thouet","main":{"temp":-0.19999999999999,"temp_min":-0.23999999999995,"temp_max":0.97000000000003,"pressure":998.67,"humidity":96.5},"dt":1358795914,"date":"2013-01-21 19:18:34","wind":{"speed":3.97,"deg":273,"gust":7.2},"clouds":{"all":63},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"sys":{"country":"FR","population":2904},"url":"http:\/\/openweathermap.org\/city\/3026044"},{"id":3026089,"coord":{"lat":45.800911,"lon":5.84352},"name":"Chatillon","main":{"temp":2.16,"pressure":1001,"temp_min":1,"temp_max":3},"dt":1358793000,"date":"2013-01-21 18:30:00","wind":{"speed":5.1,"deg":180},"clouds":{"all":75},"weather":[{"id":602,"main":"Snow","description":"heavy snow","icon":"13n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"sys":{"country":"FR","population":2880},"url":"http:\/\/openweathermap.org\/city\/3026089"},{"id":3026053,"coord":{"lat":46.98735,"lon":1.17218},"name":"Chatillon-sur-Indre","main":{"temp":3,"pressure":997,"humidity":100,"temp_min":0.11000000000001,"temp_max":3},"dt":1358791200,"date":"2013-01-21 18:00:00","wind":{"speed":4.6,"deg":290,"var_beg":260,"var_end":340},"clouds":{"all":97},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"sys":{"country":"FR","population":2873},"url":"http:\/\/openweathermap.org\/city\/3026053"},{"id":3026074,"coord":{"lat":46.1432,"lon":5.7995},"name":"Chatillon-en-Michaille","main":{"temp":1.8,"pressure":1000,"temp_min":1,"temp_max":2.22},"dt":1358795667,"date":"2013-01-21 19:14:27","wind":{"speed":5.1,"deg":200},"clouds":{"all":75},"weather":[{"id":602,"main":"Snow","description":"heavy snow","icon":"13n"},{"id":701,"main":"Mist","description":"mist","icon":"50n"}],"sys":{"country":"FR","population":2668},"url":"http:\/\/openweathermap.org\/city\/3026074"},{"id":3026075,"coord":{"lat":45.883331,"lon":4.61667},"name":"Chatillon","main":{"temp":5,"pressure":1000,"temp_min":-0.34999999999997,"temp_max":5},"dt":1358793000,"date":"2013-01-21 18:30:00","wind":{"speed":3.6,"deg":210},"clouds":{"all":54},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"sys":{"country":"FR","population":2021},"url":"http:\/\/openweathermap.org\/city\/3026075"}]} unity-scope-openweathermap-0.1+13.10.20130828/src/0000755000015700001700000000000012207374750022003 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/src/unity_openweathermap_daemon.py0000644000015700001700000004401712207374531030152 0ustar pbuserpbgroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- # Copyright (C) 2013 David Callé # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License version 3, as published # by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranties of # MERCHANTABILITY, SATISFACTORY QUALITY, 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 this program. If not, see . from gi.repository import Unity, UnityExtras from gi.repository import Gio, GLib import urllib.parse import urllib.request import json import datetime import gettext from random import randrange APP_NAME = 'unity-scope-openweathermap' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Info.Openweathermap' UNIQUE_PATH = '/com/canonical/unity/scope/info/openweathermap' SEARCH_URI = ['http://openweathermap.org/data/2.1/find/', 'http://openweathermap.org/data/2.1/forecast/city/'] SEARCH_HINT = _('Search OpenWeatherMap') NO_RESULTS_HINT = _('Sorry, there is no OpenwWeatherMap forecast that matches your search.') PROVIDER_CREDITS = _('Powered by OpenWeatherMap') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR+'service-openweathermap.svg' DEFAULT_RESULT_ICON = SVG_DIR+'result-info.svg' DEFAULT_RESULT_MIMETYPE = 'text/html' DEFAULT_RESULT_TYPE = Unity.ResultType.DEFAULT c1 = {'id' :'weather', 'name' :_('Weather Forecast'), 'icon' :SVG_DIR+'group-info.svg', 'renderer':Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1] FILTERS = [] m1 = {'id' :'min_temp', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m2 = {'id' :'max_temp', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m3 = {'id' :'pressure', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m4 = {'id' :'humidity', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m5 = {'id' :'wind_speed', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m6 = {'id' :'wind_direction', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m7 = {'id' :'latitude', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m8 = {'id' :'longitude', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m9 = {'id' :'photo_hint', 'type' :'i', 'field':Unity.SchemaFieldType.OPTIONAL} EXTRA_METADATA = [m1, m2, m3, m4, m5, m6, m7, m8, m9] def weather_search(query, s_type): print (query) query = urllib.parse.quote(str(query)) data = None if not query or len(query) <= 1: return data if s_type == 'forecast': uri = "%s%s?mode=daily_compact&units=metric" % (SEARCH_URI[1], query) else: uri = "%sname?units=metric&type=like&q=%s" % (SEARCH_URI[0], query) print (uri) try: response = urllib.request.urlopen(uri).read() data = json.loads(response.decode('utf8')) except Exception as error: print (error) return data def get_icon(code): icons_map={'01d':'weather-clear', '01n':'weather-clear-night', '02d':'weather-few-clouds', '02n':'weather-few-clouds-night', '03d':'weather-clouds', '03n':'weather-clouds-night', '04d':'weather-overcast', '04n':'weather-overcast', '09d':'weather-showers-scattered', '09n':'weather-showers-scattered', '10d':'weather-showers', '10n':'weather-showers', '11d':'weather-storm', '11n':'weather-storm', '13d':'weather-snow', '13n':'weather-snow', '50d':'weather-fog', '50n':'weather-fog'} return icons_map[code] def search(search, filters): ''' Any search method returning results as a list of tuples. Available tuple fields: uri (string) icon (string) title (string) comment (string) dnd_uri (string) mimetype (string) category (int) result_type (Unity ResultType) extras metadata fields (variant) ''' results = [] place_data = weather_search(search, 'place') if not place_data or not "list" in place_data: return results uri, city_id, title, wind, icon, description = None, None, None, None, None, None try: description = place_data['list'][0]['weather'][0]['description'] icon = get_icon(place_data['list'][0]['weather'][0]['icon']) wind = place_data['list'][0]['wind']['speed'] temp_c = float(place_data['list'][0]['main']['temp']) temp_f = temp_c*(9.0/5.0)+32 temp = '%i%sC / %i%sF' % (int(temp_c), "\u00B0", int(temp_f), "\u00B0") name = place_data['list'][0]['name'] country = place_data['list'][0]['sys']['country'] title = name + ', ' + country + '\n' + temp city_id = place_data['list'][0]['id'] uri = place_data['list'][0]['url'] min_temp_c = float(place_data['list'][0]['main']['temp_min']) min_temp_f = min_temp_c*(9.0/5.0)+32 min_temp = '%i%sC / %i%sF' % (int(min_temp_c), "\u00B0", int(min_temp_f), "\u00B0") max_temp_c = float(place_data['list'][0]['main']['temp_max']) max_temp_f = max_temp_c*(9.0/5.0)+32 max_temp = '%i%sC / %i%sF' % (int(max_temp_c), "\u00B0", int(max_temp_f), "\u00B0") try: pressure = place_data['list'][0]['main']['pressure'] except: pressure = '' try: humidity = place_data['list'][0]['main']['humidity'] except: humidity = '' wind_speed = place_data['list'][0]['wind']['speed'] wind_direction = place_data['list'][0]['wind']['deg'] latitude = place_data['list'][0]['coord']['lat'] longitude = place_data['list'][0]['coord']['lon'] except Exception as error: print(error) return results if not uri or not city_id: return results photo_hint = randrange(20) results.append({'uri':uri, 'icon':icon, 'title':title, 'comment':description, 'min_temp':min_temp, 'max_temp':max_temp, 'pressure':str(pressure), 'humidity':str(humidity), 'wind_speed':str(wind_speed), 'wind_direction':str(wind_direction), 'latitude':str(latitude), 'longitude':str(longitude), 'photo_hint':photo_hint}) forecast = weather_search(city_id, 'forecast') if not forecast or not "list" in forecast: return results today = datetime.datetime.now().today() for i in range(0,4): if i == 0: day_name = _('Tomorrow') else: day = today + datetime.timedelta(days=i+1) day_name = day.strftime("%A") title, wind, icon, description = None, None, None, None try: description = forecast['list'][i]['weather'][0]['description'] icon = get_icon(forecast['list'][i]['weather'][0]['icon']) temp_c = float(forecast['list'][i]['temp']) temp_f = temp_c*(9.0/5.0)+32 temp = '%i%sC / %i%sF' % (int(temp_c), "\u00B0", int(temp_f), "\u00B0") title = day_name + '\n' + temp min_temp_c = float(forecast['list'][i]['morn']) min_temp_f = min_temp_c*(9.0/5.0)+32 min_temp = '%i%sC / %i%sF' % (int(min_temp_c), "\u00B0", int(min_temp_f), "\u00B0") max_temp_c = float(forecast['list'][i]['eve']) max_temp_f = max_temp_c*(9.0/5.0)+32 max_temp = '%i%sC / %i%sF' % (int(max_temp_c), "\u00B0", int(max_temp_f), "\u00B0") pressure = forecast['list'][i]['pressure'] humidity = forecast['list'][i]['humidity'] wind_speed = forecast['list'][i]['speed'] wind_direction = forecast['list'][i]['deg'] except Exception as error: print(error) return results uri += "#%s" % day_name photo_hint = randrange(20) results.append({'uri':uri, 'icon':icon, 'title':title, 'comment':description, 'min_temp':min_temp, 'max_temp':max_temp, 'pressure':str(pressure), 'humidity':str(humidity), 'wind_speed':str(wind_speed), 'wind_direction':str(wind_direction), 'latitude':str(latitude), 'longitude':str(longitude), 'photo_hint':photo_hint}) return results # Classes below this point establish communication # with Unity, you probably shouldn't modify them. class MySearch (Unity.ScopeSearchBase): def __init__(self, search_context): super (MySearch, self).__init__() self.set_search_context (search_context) def do_run (self): ''' Adds results to the model ''' try: result_set = self.search_context.result_set for i in search(self.search_context.search_query, self.search_context.filter_state): if not 'uri' in i or not i['uri'] or i['uri'] == '': continue if not 'icon' in i or not i['icon'] or i['icon'] == '': i['icon'] = DEFAULT_RESULT_ICON if not 'mimetype' in i or not i['mimetype'] or i['mimetype'] == '': i['mimetype'] = DEFAULT_RESULT_MIMETYPE if not 'result_type' in i or not i['result_type'] or i['result_type'] == '': i['result_type'] = DEFAULT_RESULT_TYPE if not 'category' in i or not i['category'] or i['category'] == '': i['category'] = 0 if not 'title' in i or not i['title']: i['title'] = '' if not 'comment' in i or not i['comment']: i['comment'] = '' if not 'dnd_uri' in i or not i['dnd_uri'] or i['dnd_uri'] == '': i['dnd_uri'] = i['uri'] i['provider_credits'] = GLib.Variant('s', PROVIDER_CREDITS) result_set.add_result(**i) except Exception as error: print (error) class Preview (Unity.ResultPreviewer): def get_image(self,rand, q, lat, lon): print (lat, lon) flick_map={'weather-clear':'clear', 'weather-clear-night':'clear', 'weather-few-clouds':'cloudy', 'weather-few-clouds-night':'cloudy', 'weather-clouds':'cloudy', 'weather-clouds-night':'cloudy', 'weather-overcast':'cloudy', 'weather-overcast':'cloudy', 'weather-showers-scattered':'rain', 'weather-showers-scattered':'rain', 'weather-showers':'rain', 'weather-showers':'rain', 'weather-storm':'storm', 'weather-storm':'storm', 'weather-snow':'snow', 'weather-snow':'snow', 'weather-fog':'fog', 'weather-fog':'fog'} license_list = ["All Rights Reserved", "Attribution-NonCommercial-ShareAlike License", "Attribution-NonCommercial License", "Attribution-NonCommercial-NoDerivs License", "Attribution License", "Attribution-ShareAlike License", "Attribution-NoDerivs License", "No known copyright restrictions", "United States Government Work"] image = None query = urllib.parse.quote(flick_map[q]) key = 'd87224f0b467093b2a87fd788d950e27' uri = 'http://secure.flickr.com/services/rest/?method=flickr.photos.search&nojsoncallback=1&per_page=20&api_key=%s&extras=url_m,owner_name,license&group_id=1463451@N25&format=json&tag_mode=all&tags=%s&bbox=%f,%f,%f,%f' % (key, query, round(float(lon) - 0.1, 2), round(float(lat) - 0.1, 2), round(float(lon) + 0.1, 2), round(float(lat) +0.1, 2)) print (uri) try: response = urllib.request.urlopen(uri).read() data = json.loads(response.decode('utf-8')) photo = min(rand, int(data['photos']['total'])-1) image = data['photos']['photo'][photo]['url_m'] owner = data['photos']['photo'][photo]['ownername'] license = license_list[int(data['photos']['photo'][photo]['license'])] link = 'https://www.flickr.com/photos/%s/%s' % (data['photos']['photo'][photo]['owner'], data['photos']['photo'][photo]['id']) except Exception as error: print (error) image, owner, license, link = None, None, None, None return image, owner, license, link def do_run(self): preview = Unity.GenericPreview.new(self.result.title.split('\n')[0], '', None) preview.props.subtitle = self.result.comment.capitalize() image, owner, license, link = self.get_image(self.result.metadata['photo_hint'].get_int32(), self.result.icon_hint, self.result.metadata['latitude'].get_string(), self.result.metadata['longitude'].get_string()) gfile_icon = Gio.file_new_for_path(PROVIDER_ICON) gicon = Gio.FileIcon.new (gfile_icon) open_action = Unity.PreviewAction.new("open", _("Open Weather Map"), gicon) preview.add_action(open_action) preview.add_info(Unity.InfoHint.new("min_temp", _("Minimum Temperature"), None, self.result.metadata['min_temp'].get_string())) preview.add_info(Unity.InfoHint.new("max_temp", _("Maximum Temperature"), None, self.result.metadata['max_temp'].get_string())) preview.add_info(Unity.InfoHint.new("wind_speed", _("Wind Speed"), None, self.result.metadata['wind_speed'].get_string() + ' m/s')) preview.add_info(Unity.InfoHint.new("wind_direction", _("Wind Direction"), None, self.result.metadata['wind_direction'].get_string() + "\u00B0")) if self.result.metadata['pressure'].get_string() != '': preview.add_info(Unity.InfoHint.new("pressure", _("Pressure"), None, self.result.metadata['pressure'].get_string() + ' hPa')) if self.result.metadata['humidity'].get_string() != '': preview.add_info(Unity.InfoHint.new("humidity", _("Humidity"), None, self.result.metadata['humidity'].get_string() + '%')) if image: preview.props.image_source_uri = image gfile_icon = Gio.file_new_for_path(SVG_DIR+'service-flickr.svg') gicon = Gio.FileIcon.new (gfile_icon) preview.add_info(Unity.InfoHint.new("photo_owner", _("Photo source"), gicon, 'Flickr')) preview.add_info(Unity.InfoHint.new("photo_owner", _("Photo credit"), None, owner)) preview.add_info(Unity.InfoHint.new("photo_license", _("Photo license"), None, license)) else: gfile_icon = Gio.file_new_for_path(SVG_DIR+'service-flickr.svg') gicon = Gio.FileIcon.new (gfile_icon) submit_action = Unity.PreviewAction.new("submit", _("Submit Photo"), gicon) preview.add_action(submit_action) return preview class Scope (Unity.AbstractScope): def __init__(self): Unity.AbstractScope.__init__(self) def do_get_search_hint (self): return SEARCH_HINT def do_get_schema (self): ''' Adds specific metadata fields ''' schema = Unity.Schema.new () if EXTRA_METADATA: for m in EXTRA_METADATA: schema.add_field(m['id'], m['type'], m['field']) #FIXME should be REQUIRED for credits schema.add_field('provider_credits', 's', Unity.SchemaFieldType.OPTIONAL) return schema def do_get_categories (self): ''' Adds categories ''' cs = Unity.CategorySet.new () if CATEGORIES: for c in CATEGORIES: cat = Unity.Category.new (c['id'], c['name'], Gio.ThemedIcon.new(c['icon']), c['renderer']) cs.add (cat) return cs def do_get_filters (self): ''' Adds filters ''' fs = Unity.FilterSet.new () # if FILTERS: # return fs def do_get_group_name (self): return GROUP_NAME def do_get_unique_name (self): return UNIQUE_PATH def do_create_search_for_query (self, search_context): se = MySearch (search_context) return se def do_create_previewer(self, result, metadata): rp = Preview() rp.set_scope_result(result) rp.set_search_metadata(metadata) return rp def do_activate(self, result, metadata, id): if not id: return Unity.ActivationResponse(handled=Unity.HandledType.SHOW_PREVIEW, goto_uri=result.uri) if id == 'submit': uri = 'https://www.flickr.com/groups/projectweather/' return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri=uri) return def load_scope(): return Scope() unity-scope-openweathermap-0.1+13.10.20130828/src/__init__.py0000644000015700001700000000000012207374531024077 0ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/setup.py0000644000015700001700000000127012207374531022723 0ustar pbuserpbgroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from distutils.core import setup from DistUtilsExtra.command import * setup(name='unity-scope-openweathermap', version='0.1', author='David Callé', author_email='davidc@framli.eu', url='http://launchpad.net/ubuntu-scopes', license='GNU General Public License (GPL)', data_files=[ ('share/dbus-1/services', ['data/unity-scope-openweathermap.service']), ('share/unity-scopes/openweathermap', ['src/unity_openweathermap_daemon.py']), ('share/unity-scopes/openweathermap', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n,}) unity-scope-openweathermap-0.1+13.10.20130828/setup.cfg0000644000015700001700000000022112207374531023025 0ustar pbuserpbgroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-openweathermap desktop_files=[('share/unity/scopes/info', ('data/openweathermap.scope.in',))] unity-scope-openweathermap-0.1+13.10.20130828/data/0000755000015700001700000000000012207374750022125 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/data/openweathermap.scope.in0000644000015700001700000000171312207374531026603 0ustar pbuserpbgroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Info.Openweathermap DBusPath=/com/canonical/unity/scope/info/openweathermap Icon=/usr/share/icons/unity-icon-theme/places/svg/service-openweathermap.svg _Keywords=openweathermap;weather;sky;forecast; RequiredMetadata= OptionalMetadata=min_temp[s];max_temp[s];pressure[s];humidity[s];wind_speed[s];wind_direction[s];latitude[s];longitude[s];photo_hint[i]; Loader=/usr/share/unity-scopes/openweathermap/unity_openweathermap_daemon.py Module=openweathermap.unity_openweathermap_daemon ModuleType=python3 RemoteContent=true Master=weather.scope Type=weather _Name=OpenWeatherMap _Description=This is an Ubuntu search plugin that enables weather forecasts from OpenWeatherMap to be searched and displayed in the Dash underneath the Info header. If you do not wish to search this content source, you can disable this search plugin. _SearchHint=Search OpenWeatherMap [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-openweathermap unity-scope-openweathermap-0.1+13.10.20130828/data/unity-scope-openweathermap.service0000644000015700001700000000024312207374531030777 0ustar pbuserpbgroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Info.Openweathermap Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s info/openweathermap.scope unity-scope-openweathermap-0.1+13.10.20130828/data/icons/0000755000015700001700000000000012207374750023240 5ustar pbuserpbgroup00000000000000unity-scope-openweathermap-0.1+13.10.20130828/data/icons/service-openweathermap.svg0000644000015700001700000003427012207374531030441 0ustar pbuserpbgroup00000000000000 image/svg+xml