~submarine/unity-scope-manpages/trunk

« back to all changes in this revision

Viewing changes to src/unity_manpages_daemon.py

  • Committer: Mark Tully
  • Date: 2013-01-17 00:34:19 UTC
  • Revision ID: markjtully@gmail.com-20130117003419-bwlbnvfol6vlll80
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# Copyright(C) 2012 name <email>
 
5
# This program is free software: you can redistribute it and/or modify it
 
6
# under the terms of the GNU General Public License version 3, as published
 
7
# by the Free Software Foundation.
 
8
#
 
9
# This program is distributed in the hope that it will be useful, but
 
10
# WITHOUT ANY WARRANTY; without even the implied warranties of
 
11
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
12
# PURPOSE.  See the GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License along
 
15
# with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
 
 
17
from gi.repository import GLib, GObject, Gio, Gtk
 
18
from gi.repository import Unity, UnityExtras
 
19
import gettext
 
20
import subprocess
 
21
import re
 
22
import os
 
23
 
 
24
APP_NAME = 'unity-scope-manpages'
 
25
LOCAL_PATH = '/usr/share/locale/'
 
26
gettext.bindtextdomain(APP_NAME, LOCAL_PATH)
 
27
gettext.textdomain(APP_NAME)
 
28
_ = gettext.gettext
 
29
 
 
30
BUS_NAME = 'com.canonical.Unity.Scope.Development.Manpages'
 
31
BUS_PATH = '/com/canonical/unity/scope/development/manpages'
 
32
 
 
33
SVG_DIR = '/usr/share/icons/unity-icon-theme/places/svg/'
 
34
CAT_0_ICON = Gio.ThemedIcon.new(SVG_DIR + 'group-development.svg')
 
35
CAT_0_TITLE = _('Manpages')
 
36
 
 
37
NO_RESULTS_HINT = _('Sorry, there are no Manpages that match your search.')
 
38
SEARCH_HINT = _('Search Manpages')
 
39
SEARCH_URI = ''
 
40
 
 
41
 
 
42
class Daemon:
 
43
    '''
 
44
    Manpages Daemon sets up the lens & searches manpages on the system 
 
45
    for results matching query
 
46
    '''
 
47
 
 
48
    def __init__(self):
 
49
        self.scope = Unity.Scope.new(BUS_PATH, 'manpages')
 
50
        self.scope.props.search_hint = SEARCH_HINT
 
51
        self.scope.search_in_global = True
 
52
        cats = []
 
53
        cats.append(Unity.Category.new('cat_0',
 
54
                                       CAT_0_TITLE,
 
55
                                       CAT_0_ICON,
 
56
                                       Unity.CategoryRenderer.VERTICAL_TILE))
 
57
        self.scope.props.categories = cats
 
58
        self.preferences = Unity.PreferencesManager.get_default()
 
59
        self.preferences.connect('notify::remote-content-search', self._on_preference_changed)
 
60
        self.scope.connect('search-changed', self.on_search_changed)
 
61
        self.scope.export()
 
62
 
 
63
    def _on_preference_changed(self, *_):
 
64
        '''
 
65
        Called when a filter is clicked.  Queues a new search
 
66
        '''
 
67
        self.scope.queue_search_changed(Unity.SearchType.DEFAULT)
 
68
 
 
69
    def on_search_changed(self, scope, search, search_type, *_):
 
70
        '''
 
71
        Called when the search is changed.  Gets the search string and search
 
72
        type and passes it to update_results_model()
 
73
        Args:
 
74
          scope: the scope object
 
75
          search: the search string
 
76
          search_type: the search type (global or local)
 
77
        '''
 
78
        model = search.props.results_model
 
79
        model.clear()
 
80
        if self.preferences.props.remote_content_search != Unity.PreferencesManagerRemoteContent.ALL:
 
81
            search.finished()
 
82
            return
 
83
        search_string = search.props.search_string.strip()
 
84
        print 'Search changed to \'%s\'' % search_string
 
85
        self.update_results_model(search_string, model)
 
86
        search.set_reply_hint('no-results-hint',
 
87
                              GLib.Variant.new_string(NO_RESULTS_HINT))
 
88
        search.finished()
 
89
 
 
90
    def update_results_model(self, search, results):
 
91
        '''
 
92
        Searches for matching manpages and adds them to the results
 
93
        '''
 
94
        icon_hint = Gio.ThemedIcon.new("text-x-generic").to_string()
 
95
        result = []
 
96
        if len(search) > 2:   # don't run apropos for strings shorter than 3 chars
 
97
            apropos = subprocess.Popen(["apropos", search], stdout=subprocess.PIPE)
 
98
            os.waitpid(apropos.pid, 0)
 
99
            out = apropos.communicate()[0]
 
100
            for line in out.split("\n"):
 
101
                regex_apropos = re.compile('^(.+?)\s+\((\d+)\)\s+-\s(.+?)$')
 
102
                m = regex_apropos.match(line)
 
103
                if m:
 
104
                    result.append((m.group(1), m.group(2), m.group(3)))
 
105
        for res in result:
 
106
            uri = 'man:' + res[0] + '(' + res[1] + ')'
 
107
            icon_theme = Gtk.IconTheme()
 
108
            icon_info = icon_theme.lookup_icon(res[0], 128, 0)
 
109
            if icon_info:
 
110
                icon_hint = Gio.ThemedIcon.new(res[0]).to_string()
 
111
            results.append(uri=uri,
 
112
                           icon_hint=icon_hint,
 
113
                           category=0,
 
114
                           mimetype='x-scheme-handler/man',
 
115
                           title=res[0],
 
116
                           comment=res[2],
 
117
                           dnd_uri=uri,
 
118
                           result_type=Unity.ResultType.DEFAULT)
 
119
 
 
120
if __name__ == '__main__':
 
121
    daemon = UnityExtras.dbus_own_name(BUS_NAME, Daemon, None)
 
122
    if daemon:
 
123
        GLib.unix_signal_add_full(0, 2, lambda x: daemon.quit(), None)
 
124
        daemon.run([])