~kklimonda/ubuntu/natty/hamster-applet/lp.697667

« back to all changes in this revision

Viewing changes to src/hamster/hamsterdbus.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Coulson
  • Date: 2010-02-10 02:52:31 UTC
  • mfrom: (1.1.14 upstream)
  • Revision ID: james.westby@ubuntu.com-20100210025231-x0q5h4q7nlvihl09
Tags: 2.29.90-0ubuntu1
* New upstream version
  - workspace tracking - switch activity, when switching desktops
  - chart improvements - theme friendly and less noisier
  - for those without GNOME panel there is now a standalone version, 
    accessible via Applications -> Accessories -> Time Tracker
  - overview window remembers position
  - maintaining cursor on the selected row after edits / refreshes
  - descriptions once again in the main input field, delimited by comma
  - activity suggestion box now sorts items by recency (Patryk Zawadzki)
  - searching
  - simplified save report dialog, thanks to the what you see is what you 
    report revamp
  - overview/stats replaced with activities / totals and stats accessible 
    from totals
  - interactive graphs to drill down in totals
  - miscellaneous performance improvements
  - pixel-perfect graphs
* Updated 01_startup-fix.patch to apply to new source layout
* debian/control:
  - Add build-depend on gnome-doc-utils

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# - coding: utf-8 -
 
2
 
 
3
# Copyright (C) 2008, J. Félix Ontañón <fontanon at emergya dot es>
 
4
# Thanks to John Carr for helpful patching
 
5
 
 
6
# This file is part of Project Hamster.
 
7
 
 
8
# Project Hamster is free software: you can redistribute it and/or modify
 
9
# it under the terms of the GNU General Public License as published by
 
10
# the Free Software Foundation, either version 3 of the License, or
 
11
# (at your option) any later version.
 
12
 
 
13
# Project Hamster is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
# GNU General Public License for more details.
 
17
 
 
18
# You should have received a copy of the GNU General Public License
 
19
# along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
 
20
 
 
21
import logging
 
22
import dbus
 
23
import dbus.service
 
24
import datetime
 
25
from calendar import timegm
 
26
 
 
27
from configuration import runtime
 
28
 
 
29
# DBus service parameters
 
30
HAMSTER_URI = "org.gnome.Hamster"
 
31
 
 
32
 
 
33
class HamsterDbusController(dbus.service.Object):
 
34
    # Non-initialized current fact id
 
35
    current_fact_id = 0
 
36
 
 
37
    def __init__(self, bus_name):
 
38
        """HamsterDbusController encapsulates the dbus api logic
 
39
        for the hamster-applet and performs the necesary conversion
 
40
        between dbus types and hamster-applet data types
 
41
        """
 
42
        try:
 
43
            dbus.service.Object.__init__(self, bus_name, "/org/gnome/Hamster")
 
44
        except KeyError:
 
45
            # KeyError is thrown when the dbus interface is taken
 
46
            # that is there is other hamster running somewhere
 
47
            logging.warn("D-Bus interface registration failed - other hamster running somewhere")
 
48
 
 
49
    @staticmethod
 
50
    def _to_dbus_fact(fact):
 
51
        """Perform the conversion between fact database query and
 
52
        dbus supported data types
 
53
        """
 
54
        if not fact:
 
55
            return dbus.Dictionary({}, signature='sv')
 
56
 
 
57
        fact = dict(fact)
 
58
        for key in fact.keys():
 
59
            fact[key] = fact[key] or 0
 
60
 
 
61
            # make sure we return correct type where strings are expected
 
62
            if not fact[key] and key in ('name', 'category', 'description'):
 
63
                fact[key] = ''
 
64
 
 
65
            # convert times to gmtime
 
66
            if isinstance(fact[key], datetime.datetime) or isinstance(fact[key], datetime.date):
 
67
                fact[key] = timegm(fact[key].timetuple())
 
68
            elif isinstance(fact[key], datetime.timedelta) :
 
69
                fact[key] = fact[key].days * 24 * 60 * 60 + fact[key].seconds
 
70
 
 
71
        return fact
 
72
 
 
73
 
 
74
    @dbus.service.method(HAMSTER_URI, out_signature='a{sv}')
 
75
    def GetCurrentFact(self):
 
76
        """Gets the current displaying fact
 
77
        Returns Dict of:
 
78
        i id: Unique fact identifier
 
79
        s name: Activity name
 
80
        s category: Category name
 
81
        s description: Description of the fact
 
82
        u start_time: Seconds since epoch (timestamp)
 
83
        u end_time: Seconds since epoch (timestamp)
 
84
        u end_time: Seconds since epoch (timestamp)
 
85
        as tags: List of tags used
 
86
        """
 
87
        return HamsterDbusController._to_dbus_fact(runtime.storage.get_last_activity())
 
88
 
 
89
    @dbus.service.method(HAMSTER_URI, in_signature='i', out_signature='a{sv}')
 
90
    def GetFactById(self, fact_id):
 
91
        """Gets the current displaying fact
 
92
        Parameters:
 
93
        i id: Unique fact identifier
 
94
        Returns Dict of:
 
95
        i id: Unique fact identifier
 
96
        s name: Activity name
 
97
        s category: Category name
 
98
        s description: Description of the fact
 
99
        u start_time: Seconds since epoch (timestamp)
 
100
        u end_time: Seconds since epoch (timestamp)
 
101
        as tags: List of tags used
 
102
        """
 
103
        return HamsterDbusController._to_dbus_fact(runtime.storage.get_fact(fact_id))
 
104
 
 
105
    @dbus.service.method(HAMSTER_URI, in_signature='uu', out_signature='aa{sv}')
 
106
    def GetFacts(self, start_date, end_date):
 
107
        """Gets facts between the day of start_date and the day of end_date.
 
108
        Parameters:
 
109
        u start_date: Seconds since epoch (timestamp). Use 0 for today
 
110
        u end_date: Seconds since epoch (timestamp). Use 0 for today
 
111
        Returns Array of fact where fact it's Dict of:
 
112
        i id: Unique fact identifier
 
113
        s name: Activity name
 
114
        s category: Category name
 
115
        s description: Description of the fact
 
116
        u start_time: Seconds since epoch (timestamp)
 
117
        u end_time: Seconds since epoch (timestamp)
 
118
        as tags: List of tags used
 
119
        """
 
120
        #TODO: Assert start > end ?
 
121
        if start_date:
 
122
            start = datetime.datetime.utcfromtimestamp(start_date).date()
 
123
        else:
 
124
            start = datetime.date.today()
 
125
 
 
126
        if end_date:
 
127
            end = datetime.datetime.utcfromtimestamp(end_date).date()
 
128
        else:
 
129
            end = datetime.date.today()
 
130
 
 
131
        facts = dbus.Array([], signature='a{sv}')
 
132
        for fact in runtime.storage.get_facts(start, end):
 
133
            facts.append(HamsterDbusController._to_dbus_fact(fact))
 
134
 
 
135
        return facts
 
136
 
 
137
    @dbus.service.method(HAMSTER_URI, out_signature='a(ss)')
 
138
    def GetActivities(self):
 
139
        """Gets all defined activities with matching category
 
140
        Returns Array of:
 
141
        s activity: Activity name
 
142
        s category: Category name
 
143
        """
 
144
        activities = dbus.Array([], signature='(ss)')
 
145
        for act in runtime.storage.get_autocomplete_activities():
 
146
            activities.append((act['name'] or '', act['category'] or ''))
 
147
        return activities
 
148
 
 
149
    @dbus.service.method(HAMSTER_URI, out_signature='as')
 
150
    def GetTags(self):
 
151
        """Returns array of all active tags"""
 
152
        tags = dbus.Array([], signature='s')
 
153
 
 
154
        for tag in runtime.storage.get_tags():
 
155
            tags.append(tag['name'] or '')
 
156
        return tags
 
157
 
 
158
    @dbus.service.method(HAMSTER_URI, in_signature='s')
 
159
    def SetAutocompleteTags(self, tags):
 
160
        """Update autocomplete tags with the given comma-delimited list.
 
161
        If a tag is gone missing, it will be deleted if it has not been used.
 
162
        If it has been used, it will be marked as not to be used in autocomplete
 
163
        (and revived on first use). New tags will just appear.
 
164
        Parameters:
 
165
        s tags: Comma-separated tags ("tag1, tag2, tag3, and so, on")
 
166
        """
 
167
        runtime.storage.update_autocomplete_tags(tags)
 
168
 
 
169
    @dbus.service.method(HAMSTER_URI, out_signature='ss')
 
170
    def GetCurrentActivity(self):
 
171
        """Returns the Activity currently being used, or blanks if Hamster is not tracking currently
 
172
        s activity: Activity name
 
173
        s category: Category name
 
174
        """
 
175
        last_activity = runtime.storage.get_last_activity()
 
176
        if last_activity:
 
177
            return (last_activity['name'] or '', last_activity['category'] or '')
 
178
        else:
 
179
            return ('', '')
 
180
 
 
181
    @dbus.service.method(HAMSTER_URI, out_signature='as')
 
182
    def GetCategories(self):
 
183
        """Gets all defined categories
 
184
        Returns Array of:
 
185
        s category: Category name
 
186
        """
 
187
        categories = dbus.Array([], signature='s')
 
188
        for cat in runtime.storage.get_category_list():
 
189
            categories.append(cat['name'] or '')
 
190
        return categories
 
191
 
 
192
    @dbus.service.method(HAMSTER_URI, in_signature='suu', out_signature='i')
 
193
    def AddFact(self, activity, start_time, end_time):
 
194
        """Add a new fact
 
195
        Parameters:
 
196
        s activity: Activity name with optional category, description and tags
 
197
                    in the form
 
198
                    'activity_name[@category_name][,description][#tag1 #tagN]'
 
199
                    Activity, matching category and tags will be refered or
 
200
                    created on the fly.
 
201
        u start_time: Seconds since epoch (timestamp). Use 0 for 'now'
 
202
        u end_time: Seconds since epoch (timestamp). Use 0 for ongoing task
 
203
        """
 
204
        #TODO: Assert start > end ?
 
205
        start, end = None, None
 
206
 
 
207
        if start_time:
 
208
            start = datetime.datetime.utcfromtimestamp(start_time)
 
209
        if end_time:
 
210
            end = datetime.datetime.utcfromtimestamp(end_time)
 
211
 
 
212
        return runtime.storage.add_fact(activity, "", start, end)
 
213
 
 
214
    @dbus.service.method(HAMSTER_URI, in_signature='ss')
 
215
    def AddActivity(self, activity, category):
 
216
        """Add a new activity
 
217
        Parameters:
 
218
        s activity: Activity name
 
219
        s category: Category name. It will be created if it doesn't exists
 
220
                    Use '' for Unsorted activity
 
221
        """
 
222
        category_id = None
 
223
 
 
224
        if category:
 
225
            category_id = runtime.storage.get_category_by_name(category) \
 
226
                    or runtime.storage.add_category(category)
 
227
 
 
228
        runtime.storage.add_activity(activity, category_id)
 
229
 
 
230
    @dbus.service.method(HAMSTER_URI, in_signature='s')
 
231
    def AddCategory(self, category):
 
232
        """Add a new category
 
233
        Parameters:
 
234
        s category: category name
 
235
        """
 
236
        if category and not runtime.storage.get_category_by_name(category):
 
237
            runtime.storage.add_category(category)
 
238
 
 
239
    @dbus.service.method(HAMSTER_URI)
 
240
    def StopTracking(self):
 
241
        """Stops the current fact tracking"""
 
242
        last_activity = runtime.storage.get_last_activity()
 
243
        if last_activity:
 
244
            runtime.storage.touch_fact(last_activity)
 
245
 
 
246
    @dbus.service.method(HAMSTER_URI, in_signature='i')
 
247
    def RemoveFact(self, fact_id):
 
248
        """Removes a fact
 
249
        Parameters:
 
250
        i id: Unique fact identifier
 
251
        """
 
252
        runtime.storage.remove_fact(fact_id)
 
253
 
 
254
    @dbus.service.method(HAMSTER_URI, in_signature='ss')
 
255
    def RemoveActivity(self, activity_name, category):
 
256
        """Removes an activity
 
257
        Parameters:
 
258
        s activity: Activity name
 
259
        s category: Category name. Use '' for Unsorted activity
 
260
        """
 
261
        category_id = runtime.storage.get_category_by_name(category)
 
262
        activity = runtime.storage.get_activity_by_name(activity_name, category_id)
 
263
 
 
264
        if activity:
 
265
            runtime.storage.remove_activity(activity['id'])
 
266
 
 
267
    @dbus.service.method(HAMSTER_URI, in_signature='s')
 
268
    def RemoveCategory(self, category):
 
269
        """Removes a category
 
270
        Parameters:
 
271
        s category: Category name
 
272
        """
 
273
        category_id = runtime.storage.get_category_by_name(category)
 
274
        if category_id:
 
275
            runtime.storage.remove_category(category_id)
 
276
 
 
277
    @dbus.service.signal(HAMSTER_URI, signature='i')
 
278
    def FactUpdated(self, fact_id):
 
279
        """Notifies fact changes
 
280
        Parameters:
 
281
        i id: Unique fact identifier
 
282
        """
 
283
        self.current_fact_id = fact_id
 
284
 
 
285
    @dbus.service.signal(HAMSTER_URI)
 
286
    def TrackingStopped(self):
 
287
        """Notifies the fact tracking has been stopped"""
 
288
        self.current_fact_id = 0