unity-scope-gnote-0.1+13.10.20130723/0000755000175000017500000000000013414711036017111 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/tests/0000755000175000017500000000000013414711036020253 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/tests/test_gnote.py0000644000175000017500000000572713414710742023016 0ustar jeremyjeremy00000000000000#! /usr/bin/python3 # -*- coding: utf-8 -*- import imp from unittest import TestCase import dbusmock from gi.repository import Unity Gnote_BUS_NAME = 'org.gnome.Gnote' Gnote_BUS_PATH = '/org/gnome/Gnote/RemoteControl' Gnote_IFACE = 'org.gnome.Gnote.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 TestGnote(dbusmock.DBusTestCase, ScopeTestCase): def setUp(self): self.init_scope('src/unity_gnote_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 Gnote remote control interface.""" cls.start_session_bus() cls.session_bus = cls.get_dbus() cls.gnote_proc = cls.spawn_server( Gnote_BUS_NAME, Gnote_BUS_PATH, Gnote_IFACE) gnote = cls.session_bus.get_object(Gnote_BUS_NAME, Gnote_BUS_PATH) gnote.AddMethod(Gnote_IFACE, 'SearchNotes', 'sb', 'as', '''ret = [args[0]] if args[0] != 'invalid' else []''') gnote.AddMethod(Gnote_IFACE, 'GetNoteChangeDate', 's', 'i', '''ret = 1356998400''') gnote.AddMethod(Gnote_IFACE, 'GetTagsForNote', 's', 'as', '''ret = ['tag1', 'tag2']''') gnote.AddMethod(Gnote_IFACE, 'GetNoteTitle', 's', 's', '''ret = '{} title'.format(args[0])''') gnote.AddMethod(Gnote_IFACE, 'GetNoteContents', 's', 's', '''ret = '{} contents'.format(args[0])''') @classmethod def tearDownClass(cls): cls.gnote_proc.terminate() cls.gnote_proc.wait() super(TestGnote, 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-gnote-0.1+13.10.20130723/tests/data/0000755000175000017500000000000013414711036021164 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/tests/data/mock_gnote_fail0000644000175000017500000000000613414710742024226 0ustar jeremyjeremy00000000000000 unity-scope-gnote-0.1+13.10.20130723/tests/data/mock_gnote_pass0000644000175000017500000000000013414710742024253 0ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/setup.py0000644000175000017500000000134013414710742020624 0ustar jeremyjeremy00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- from distutils.core import setup from DistUtilsExtra.command import * setup(name='unity-scope-gnote', 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-gnote.service']), # ('share/icons/unity-icon-theme/places/svg', ['data/icons/service-tomboy.svg']), ('share/unity-scopes/gnote', ['src/unity_gnote_daemon.py']), ('share/unity-scopes/gnote', ['src/__init__.py']), ], cmdclass={'build': build_extra.build_extra, 'build_i18n': build_i18n.build_i18n,}) unity-scope-gnote-0.1+13.10.20130723/src/0000755000175000017500000000000013414711036017700 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/src/__init__.py0000644000175000017500000000000013414710742022002 0ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/src/unity_gnote_daemon.py0000644000175000017500000002054013414710742024145 0ustar jeremyjeremy00000000000000#! /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-gnote' LOCAL_PATH = '/usr/share/locale/' gettext.bindtextdomain(APP_NAME, LOCAL_PATH) gettext.textdomain(APP_NAME) _ = gettext.gettext GROUP_NAME = 'com.canonical.Unity.Scope.Notes.Gnote' UNIQUE_PATH = '/com/canonical/unity/scope/notes/gnote' SEARCH_URI = '' SEARCH_HINT = _('Search Gnote notes') NO_RESULTS_HINT = _('Sorry, there are no Gnote notes that match your search.') PROVIDER_CREDITS = _('Powered by Gnote') SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/' PROVIDER_ICON = SVG_DIR+'service-tomboy.svg' DEFAULT_RESULT_ICON = 'gnote' 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 gnote = get_dbus('org.gnome.Gnote', '/org/gnome/Gnote/RemoteControl', 'org.gnome.Gnote.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 gnote: return results if search: gnote_search = gnote.SearchNotes('(sb)', search, False) else: gnote_search = gnote.ListAllNotes() for note in gnote_search: timestamp = gnote.GetNoteChangeDate('(s)', note) last_changed = datetime.datetime.fromtimestamp(timestamp).strftime('%x') # Has anyone ever seen Gnote tags? try: tags = ','.join(gnote.GetTagsForNote('(s)', note)) except Exception as error: print(error) tags = '' results.append({'uri':note, 'title':gnote.GetNoteTitle('(s)', note), 'comment':gnote.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): gnote = get_dbus('org.gnome.Gnote', '/org/gnome/Gnote/RemoteControl', 'org.gnome.Gnote.RemoteControl') gnote.DisplayNote('(s)', result.uri) return Unity.ActivationResponse(handled=Unity.HandledType.HIDE_DASH, goto_uri=None) def load_scope(): return Scope() unity-scope-gnote-0.1+13.10.20130723/po/0000755000175000017500000000000013414711036017527 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/po/unity-scope-gnote.pot0000644000175000017500000000167413414710742023657 0ustar jeremyjeremy00000000000000# 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: 2019-01-07 22:50+0530\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_gnote_daemon.py:34 msgid "Search Gnote notes" msgstr "" #: ../src/unity_gnote_daemon.py:35 msgid "Sorry, there are no Gnote notes that match your search." msgstr "" #: ../src/unity_gnote_daemon.py:36 msgid "Powered by Gnote" msgstr "" #: ../src/unity_gnote_daemon.py:44 msgid "Notes" msgstr "" #: ../src/unity_gnote_daemon.py:172 msgid "Edit" msgstr "" unity-scope-gnote-0.1+13.10.20130723/po/POTFILES.in0000644000175000017500000000012313414710742021303 0ustar jeremyjeremy00000000000000[encoding: UTF-8] src/unity_gnote_daemon.py [type: gettext/ini]data/gnote.scope.in unity-scope-gnote-0.1+13.10.20130723/data/0000755000175000017500000000000013414711036020022 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/data/icons/0000755000175000017500000000000013414711036021135 5ustar jeremyjeremy00000000000000unity-scope-gnote-0.1+13.10.20130723/data/gnote.scope.in0000644000175000017500000000127013414710742022601 0ustar jeremyjeremy00000000000000[Scope] DBusName=com.canonical.Unity.Scope.Notes.Gnote DBusPath=/com/canonical/unity/scope/notes/gnote Icon= QueryBinary=gnote Keywords=gnote;note;notes;memo; RequiredMetadata= OptionalMetadata=tags[s];last_changed[s]; Loader=/usr/share/unity-scopes/gnote/unity_gnote_daemon.py Module=gnote.unity_gnote_daemon ModuleType=python3 RemoteContent=false Type=notes Name=gnote Description=This is an Ubuntu search plugin that enables information from Gnote 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 Gnote notes [Desktop Entry] X-Ubuntu-Gettext-Domain=unity-scope-gnote unity-scope-gnote-0.1+13.10.20130723/data/unity-scope-gnote.service0000644000175000017500000000026213414710742025000 0ustar jeremyjeremy00000000000000[D-BUS Service] Name=com.canonical.Unity.Scope.Notes.Gnote Exec=/usr/bin/python3 /usr/share/unity-scopes/scope-runner-dbus.py /usr/share/unity-scopes/gnote/unity_gnote_daemon.py unity-scope-gnote-0.1+13.10.20130723/setup.cfg0000644000175000017500000000020013414710742020725 0ustar jeremyjeremy00000000000000[build] i18n=True [build_i18n] domain=unity-scope-gnote desktop_files=[('share/unity/scopes/notes', ('data/gnote.scope.in',))] unity-scope-gnote-0.1+13.10.20130723/MANIFEST.in0000644000175000017500000000007613414710742020655 0ustar jeremyjeremy00000000000000include MANIFEST.in include src/* include data/* include po/*