unity-scope-tomboy-0.1+13.10.20130723/0000755000015700001700000000000012173420407017471 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/po/0000755000015700001700000000000012173420407020107 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/po/unity-scope-tomboy.pot0000644000015700001700000000215212173417267024433 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-03-01 11:25+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_tomboy_daemon.py:31 ../data/tomboy.scope.in.h:4 msgid "Search Tomboy notes" msgstr "" #: ../src/unity_tomboy_daemon.py:32 msgid "Sorry, there are no Tomboy notes that match your search." msgstr "" #: ../src/unity_tomboy_daemon.py:33 msgid "Powered by Tomboy" msgstr "" #: ../src/unity_tomboy_daemon.py:41 msgid "Notes" msgstr "" #: ../data/tomboy.scope.in.h:1 msgid "tomboy;note;notes;memo;" msgstr "" #: ../data/tomboy.scope.in.h:2 msgid "Tomboy" msgstr "" #: ../data/tomboy.scope.in.h:3 msgid "Find Tomboy notes" msgstr "" unity-scope-tomboy-0.1+13.10.20130723/po/POTFILES.in0000644000015700001700000000012512173417267021674 0ustar pbuserpbgroup00000000000000[encoding: UTF-8] src/unity_tomboy_daemon.py [type: gettext/ini]data/tomboy.scope.in unity-scope-tomboy-0.1+13.10.20130723/MANIFEST.in0000644000015700001700000000007612173417267021244 0ustar pbuserpbgroup00000000000000include MANIFEST.in include src/* include data/* include po/* unity-scope-tomboy-0.1+13.10.20130723/tests/0000755000015700001700000000000012173420407020633 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/tests/test_tomboy.py0000644000015700001700000000576412173417267023603 0ustar pbuserpbgroup00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- import imp from unittest import TestCase import dbusmock from gi.repository import Unity TOMBOY_BUS_NAME = 'org.gnome.Tomboy' TOMBOY_BUS_PATH = '/org/gnome/Tomboy/RemoteControl' TOMBOY_IFACE = 'org.gnome.Tomboy.RemoteControl' 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: 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 TestTomboy(dbusmock.DBusTestCase, ScopeTestCase): def setUp(self): self.init_scope('src/unity_tomboy_daemon.py') def tearDown(self): self.scope = None self.scope_module = None @classmethod def setUpClass(cls): """Set up a session bus running a mock version of the Tomboy remote control interface.""" cls.start_session_bus() cls.session_bus = cls.get_dbus() cls.tomboy_proc = cls.spawn_server( TOMBOY_BUS_NAME, TOMBOY_BUS_PATH, TOMBOY_IFACE) tomboy = cls.session_bus.get_object(TOMBOY_BUS_NAME, TOMBOY_BUS_PATH) tomboy.AddMethod(TOMBOY_IFACE, 'SearchNotes', 'sb', 'as', '''ret = [args[0]] if args[0] != 'invalid' else []''') tomboy.AddMethod(TOMBOY_IFACE, 'GetNoteChangeDate', 's', 'i', '''ret = 1356998400''') tomboy.AddMethod(TOMBOY_IFACE, 'GetTagsForNote', 's', 'as', '''ret = ['tag1', 'tag2']''') tomboy.AddMethod(TOMBOY_IFACE, 'GetNoteTitle', 's', 's', '''ret = '{} title'.format(args[0])''') tomboy.AddMethod(TOMBOY_IFACE, 'GetNoteContents', 's', 's', '''ret = '{} contents'.format(args[0])''') @classmethod def tearDownClass(cls): cls.tomboy_proc.terminate() cls.tomboy_proc.wait() super(TestTomboy, cls).tearDownClass() def test_valid_search(self): result_set = self.perform_query('foo') self.assertEqual(len(result_set.results), 1) result = result_set.results[0] self.assertEqual(result['title'], 'foo title') self.assertEqual(result['comment'], 'foo contents') def test_failing_search(self): result_set = self.perform_query('invalid') self.assertEqual(len(result_set.results), 0) if __name__ == '__main__': unittest.main() unity-scope-tomboy-0.1+13.10.20130723/tests/data/0000755000015700001700000000000012173420407021544 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/tests/data/mock_tomboy_fail0000644000015700001700000000000612173417267025012 0ustar pbuserpbgroup00000000000000 unity-scope-tomboy-0.1+13.10.20130723/tests/data/mock_tomboy_pass0000644000015700001700000000000012173417267025037 0ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/src/0000755000015700001700000000000012173420407020260 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/src/unity_tomboy_daemon.py0000644000015700001700000002057612173417267024742 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 from gi.repository import Gio, GLib import gettext import datetime import re import urllib.parse import urllib.request APP_NAME = 'unity-scope-tomboy' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Notes.Tomboy' UNIQUE_PATH = '/com/canonical/unity/scope/notes/tomboy' SEARCH_URI = '' SEARCH_HINT = _('Search Tomboy notes') NO_RESULTS_HINT = _('Sorry, there are no Tomboy notes that match your search.') PROVIDER_CREDITS = _('Powered by Tomboy') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR+'service-tomboy.svg' DEFAULT_RESULT_ICON = 'tomboy' DEFAULT_RESULT_MIMETYPE = 'application/x-desktop' DEFAULT_RESULT_TYPE = Unity.ResultType.PERSONAL c1 = {'id' :'recent', 'name' :_('Notes'), 'icon' :SVG_DIR+'group-notes.svg', 'renderer':Unity.CategoryRenderer.VERTICAL_TILE} CATEGORIES = [c1] FILTERS = [] m1 = {'id' :'last_changed', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} m2 = {'id' :'tags', 'type' :'s', 'field':Unity.SchemaFieldType.OPTIONAL} EXTRA_METADATA = [m1, m2] def get_dbus(name, path, iface): try: session_bus = Gio.bus_get_sync (Gio.BusType.SESSION, None) return Gio.DBusProxy.new_sync ( session_bus, 0, None, name, path, iface, None) except Exception as error: print (error) return None tomboy = get_dbus('org.gnome.Tomboy', '/org/gnome/Tomboy/RemoteControl', 'org.gnome.Tomboy.RemoteControl') 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 = [] if not tomboy: return results if search: tomboy_search = tomboy.SearchNotes('(sb)', search, False) else: tomboy_search = tomboy.ListAllNotes() for note in tomboy_search: timestamp = tomboy.GetNoteChangeDate('(s)', note) last_changed = datetime.datetime.fromtimestamp(timestamp).strftime('%x') # Has anyone ever seen Tomboy tags? try: tags = ','.join(tomboy.GetTagsForNote('(s)', note)) except Exception as error: print(error) tags = '' results.append({'uri':note, 'title':tomboy.GetNoteTitle('(s)', note), 'comment':tomboy.GetNoteContents('(s)', note), 'last_changed':GLib.Variant('s',last_changed), 'tags':GLib.Variant('s',tags)}) 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'] result_set.add_result(**i) except Exception as error: print (error) class Preview (Unity.ResultPreviewer): def do_run(self): preview = Unity.GenericPreview.new(self.result.title, self.result.comment.strip(), None) image = None try: link_search = re.search('https?://[^\s]*(\"|\'|\s|$)', self.result.comment.strip(), re.IGNORECASE) if link_search: link = urllib.request.urlopen(link_search.group(0)).read().decode('utf-8') image_search = re.search('https?://[^\s]*\.(jpg|png|gif)', link, re.IGNORECASE) if image_search: image = image_search.group(0) except Exception as error: print (error) try: link_search = re.search('https?://.*\.(jpg|png|gif)', self.result.comment.strip(), re.IGNORECASE) if link_search: image = link_search.group(0) except Exception as error: print (error) if image: im = Gio.FileIcon.new(Gio.file_new_for_uri(image)) preview.props.image = im if self.result.metadata and 'last_changed' in self.result.metadata and self.result.metadata['last_changed'].get_string() != '': preview.props.subtitle = self.result.metadata['last_changed'].get_string() view_action = Unity.PreviewAction.new("view", _("Edit"), None) preview.add_action(view_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): tomboy = get_dbus('org.gnome.Tomboy', '/org/gnome/Tomboy/RemoteControl', 'org.gnome.Tomboy.RemoteControl') tomboy.DisplayNote('(s)', result.uri) return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri=None) def load_scope(): return Scope() unity-scope-tomboy-0.1+13.10.20130723/src/__init__.py0000644000015700001700000000000012173417267022371 0ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/setup.py0000644000015700001700000000134512173417267021220 0ustar pbuserpbgroup00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from distutils.core import setup from DistUtilsExtra.command import * setup(name='unity-scope-tomboy', 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-tomboy.service']), # ('share/icons/unity-icon-theme/places/svg', ['data/icons/service-tomboy.svg']), ('share/unity-scopes/tomboy', ['src/unity_tomboy_daemon.py']), ('share/unity-scopes/tomboy', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n,}) unity-scope-tomboy-0.1+13.10.20130723/setup.cfg0000644000015700001700000000020212173417267021316 0ustar pbuserpbgroup00000000000000[build] i18n=True [build_i18n] domain=unity-scope-tomboy desktop_files=[('share/unity/scopes/notes', ('data/tomboy.scope.in',))] unity-scope-tomboy-0.1+13.10.20130723/data/0000755000015700001700000000000012173420407020402 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/data/unity-scope-tomboy.service0000644000015700001700000000022512173417267025563 0ustar pbuserpbgroup00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Notes.Tomboy Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py -s notes/tomboy.scope unity-scope-tomboy-0.1+13.10.20130723/data/icons/0000755000015700001700000000000012173420407021515 5ustar pbuserpbgroup00000000000000unity-scope-tomboy-0.1+13.10.20130723/data/tomboy.scope.in0000644000015700001700000000140412173417267023364 0ustar pbuserpbgroup00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Notes.Tomboy DBusPath=/com/canonical/unity/scope/notes/tomboy Icon=/usr/share/icons/unity-icon-theme/places/svg/group-notes.svg QueryBinary=tomboy _Keywords=tomboy;note;notes;memo; RequiredMetadata= OptionalMetadata=tags[s];last_changed[s]; Loader=/usr/share/unity-scopes/tomboy/unity_tomboy_daemon.py Module=tomboy.unity_tomboy_daemon ModuleType=python3 RemoteContent=false Type=notes _Name=Tomboy _Description=This is an Ubuntu search plugin that enables information from Tomboy to be searched and displayed in the Dash underneath the Notes header. If you do not wish to search this content source, you can disable this search plugin. _SearchHint=Search Tomboy notes [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-tomboy