Adapt to sugar API changes. This makes the colors ugly,
[journal-activity.git] / journaltoolbox.py
blobf446a3a7d9a9f644cb41a4af33691c8a25b8d7cb
1 # Copyright (C) 2007, One Laptop Per Child
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 from gettext import gettext as _
18 import logging
19 import time
20 from datetime import datetime, timedelta
22 import gobject
23 import gtk
25 import backup
27 from sugar.graphics import units
28 from sugar.graphics.xocolor import XoColor
29 from sugar.graphics.toolbox import Toolbox
30 from sugar.graphics.toolcombobox import ToolComboBox
31 from sugar.graphics.toolbutton import ToolButton
32 from sugar.graphics.combobox import ComboBox
33 from sugar.graphics.menuitem import MenuItem
34 from sugar import activity
35 from sugar.objects import objecttype
36 from sugar.datastore import datastore
38 class JournalToolbox(Toolbox):
39 def __init__(self):
40 Toolbox.__init__(self)
42 self.search_toolbar = SearchToolbar()
43 self.add_toolbar(_('Search'), self.search_toolbar)
44 self.search_toolbar.show()
46 self.entry_toolbar = EntryToolbar()
47 self.add_toolbar(_('Entry'), self.entry_toolbar)
48 self.entry_toolbar.show()
50 self.backup_toolbar = BackupToolbar()
51 self.add_toolbar(_('Backup'), self.backup_toolbar)
52 self.backup_toolbar.show()
54 #self.create_toolbar = CreateToolbar()
55 #self.add_toolbar(_('Create'), self.create_toolbar)
56 #self.create_toolbar.show()
58 class SearchToolbar(gtk.Toolbar):
59 __gtype_name__ = 'SearchToolbar'
61 __gsignals__ = {
62 'query-changed': (gobject.SIGNAL_RUN_FIRST,
63 gobject.TYPE_NONE,
64 ([object]))
67 _ACTION_ANYTIME = 0
68 _ACTION_TODAY = 1
69 _ACTION_SINCE_YESTERDAY = 2
70 _ACTION_THIS_WEEK = 3
71 _ACTION_THIS_MONTH = 4
72 _ACTION_THIS_YEAR = 5
74 _ACTION_ANYTHING = 0
76 _ACTION_EVERYBODY = 0
77 _ACTION_MY_FRIENDS = 1
78 _ACTION_MY_CLASS = 2
80 def __init__(self):
81 gtk.Toolbar.__init__(self)
83 self._volume_id = None
85 search_icon = gtk.image_new_from_icon_name('system-search',
86 gtk.ICON_SIZE_SMALL_TOOLBAR)
87 self._add_widget(search_icon)
89 separator = gtk.SeparatorToolItem()
90 self.insert(separator, -1)
91 separator.show()
93 self._search_entry = gtk.Entry()
94 self._search_entry.connect('activate', self._search_entry_activated_cb)
95 self._add_widget(self._search_entry, expand=True)
97 self._what_search_combo = ComboBox()
98 self._what_combo_changed_sid = \
99 self._what_search_combo.connect('changed', self._combo_changed_cb)
100 tool_item = ToolComboBox(self._what_search_combo)
101 self.insert(tool_item, -1)
102 tool_item.show()
104 self._when_search_combo = self._get_when_search_combo()
105 tool_item = ToolComboBox(self._when_search_combo)
106 self.insert(tool_item, -1)
107 tool_item.show()
109 # TODO: enable it when the DS supports saving the buddies.
110 #self._with_search_combo = self._get_with_search_combo()
111 #tool_item = ToolComboBox(self._with_search_combo)
112 #self.insert(tool_item, -1)
113 #tool_item.show()
115 self._query = self._build_query()
117 self.refresh_filters()
119 def _get_when_search_combo(self):
120 when_search = ComboBox()
121 when_search.append_item(self._ACTION_ANYTIME, _('Anytime'))
122 when_search.append_separator()
123 when_search.append_item(self._ACTION_TODAY, _('Today'))
124 when_search.append_item(self._ACTION_SINCE_YESTERDAY,
125 _('Since yesterday'))
126 when_search.append_item(self._ACTION_THIS_WEEK, _('This week'))
127 when_search.append_item(self._ACTION_THIS_MONTH, _('This month'))
128 when_search.append_item(self._ACTION_THIS_YEAR, _('This year'))
129 when_search.set_active(0)
130 when_search.connect('changed', self._combo_changed_cb)
131 return when_search
133 def _get_with_search_combo(self):
134 with_search = ComboBox()
135 with_search.append_item(self._ACTION_EVERYBODY, _('Anyone'))
136 with_search.append_separator()
137 with_search.append_item(self._ACTION_MY_FRIENDS,
138 _('My friends'), 'theme:stock-open')
139 with_search.append_item(self._ACTION_MY_CLASS,
140 _('My class'), 'theme:stock-open')
141 with_search.append_separator()
143 # TODO: Ask the model for buddies.
144 with_search.append_item(3, 'Dan', 'theme:stock-buddy') #, XoColor('#6afbf4,#fc5f68'))
146 with_search.set_active(0)
147 with_search.connect('changed', self._combo_changed_cb)
148 return with_search
150 def _add_widget(self, widget, expand=False):
151 tool_item = gtk.ToolItem()
152 tool_item.set_expand(expand)
154 tool_item.add(widget)
155 widget.show()
157 self.insert(tool_item, -1)
158 tool_item.show()
160 def _build_query(self):
161 query = {}
162 if self._volume_id:
163 query['mountpoints'] = [self._volume_id]
164 if self._what_search_combo.props.value:
165 value = self._what_search_combo.props.value
166 type = objecttype.get_registry().get_type(value)
167 if type:
168 mime_types = type.mime_types
169 query['mime_type'] = mime_types
170 else:
171 query['activity'] = self._what_search_combo.props.value
172 if self._when_search_combo.props.value:
173 date_from, date_to = self._get_date_range()
174 query['mtime'] = {'start': date_from, 'end': date_to}
175 if self._search_entry.props.text:
176 query['query'] = self._search_entry.props.text
178 return query
180 def _get_date_range(self):
181 today = datetime.today().replace(hour=0, minute=0, second=0)
182 if self._when_search_combo.props.value == self._ACTION_TODAY:
183 date_range = (today,
184 today.replace(hour=23, minute=59, second=59))
185 elif self._when_search_combo.props.value == self._ACTION_SINCE_YESTERDAY:
186 date_range = (today - timedelta(1),
187 today.replace(hour=23, minute=59, second=59))
188 elif self._when_search_combo.props.value == self._ACTION_THIS_WEEK:
189 date_range = (today - timedelta(today.weekday()),
190 today.replace(hour=23, minute=59, second=59) + \
191 timedelta(6 - today.weekday()))
192 elif self._when_search_combo.props.value == self._ACTION_THIS_MONTH:
193 date_range = (today - timedelta(today.day - 1),
194 today.replace(hour=23, minute=59, second=59) + \
195 timedelta(self._days_in_month(today) - today.day))
196 elif self._when_search_combo.props.value == self._ACTION_THIS_YEAR:
197 date_range = (today.replace(month=1, day=1),
198 today.replace(month=12, day=31, hour=23, minute=59,
199 second=59))
201 return (date_range[0].isoformat(),
202 date_range[1].isoformat())
204 def _days_in_month(self, date):
205 year, month = date.year, date.month
206 if month == 12:
207 year += 1
208 month = 1
209 else:
210 month += 1
211 date = date.replace(year=year, month=month, day=1)
212 date -= timedelta(1)
213 return date.day
215 def _combo_changed_cb(self, combo):
216 new_query = self._build_query()
217 if self._query != new_query:
218 self._query = new_query
219 self.emit('query-changed', self._query)
221 def _search_entry_activated_cb(self, search_entry):
222 new_query = self._build_query()
223 if self._query != new_query:
224 self._query = new_query
225 self.emit('query-changed', self._query)
227 def set_volume_id(self, volume_id):
228 self._volume_id = volume_id
229 new_query = self._build_query()
230 if self._query != new_query:
231 self._query = new_query
232 self.emit('query-changed', self._query)
234 def refresh_filters(self):
235 current_value = self._what_search_combo.props.value
236 current_value_index = 0
238 self._what_search_combo.remove_all()
239 self._what_search_combo.append_item(self._ACTION_ANYTHING, _('Anything'))
241 appended_separator = False
242 for service_name in datastore.get_unique_values('activity'):
243 activity_info = activity.get_registry().get_activity(service_name)
244 if not activity_info is None:
245 if not appended_separator:
246 self._what_search_combo.append_separator()
247 appended_separator = True
248 self._what_search_combo.append_item(service_name, activity_info.name,
249 activity_info.icon)
250 if service_name == current_value:
251 current_value_index = len(self._what_search_combo.get_model()) - 1
253 types = []
254 for mime_type in datastore.get_unique_values('mime_type'):
255 type = objecttype.get_registry().get_type_for_mime(mime_type)
256 if type and type.type_id not in [t.type_id for t in types]:
257 types.append(type)
259 appended_separator = False
260 for type in types:
261 if not appended_separator:
262 self._what_search_combo.append_separator()
263 appended_separator = True
264 self._what_search_combo.append_item(type.type_id, type.name, type.icon)
265 if type.type_id == current_value:
266 current_value_index = len(self._what_search_combo.get_model()) - 1
268 self._what_search_combo.handler_block(self._what_combo_changed_sid)
269 try:
270 self._what_search_combo.set_active(current_value_index)
271 finally:
272 self._what_search_combo.handler_unblock(self._what_combo_changed_sid)
274 class EntryToolbar(gtk.Toolbar):
275 __gtype_name__ = 'EntryToolbar'
277 __gsignals__ = {
278 'entry-erased': (gobject.SIGNAL_RUN_FIRST,
279 gobject.TYPE_NONE,
280 ([]))
283 def __init__(self):
284 gtk.Toolbar.__init__(self)
286 self._jobject = None
288 self._resume = ToolButton('zoom-activity')
289 self._resume.set_tooltip(_('Resume'))
290 self._resume.props.sensitive = False
291 self._resume.connect('clicked', self._resume_clicked_cb)
292 self.insert(self._resume, -1)
293 self._resume.show()
295 self._copy = ToolButton('edit-copy')
296 self._copy.set_tooltip(_('Copy to clipboard'))
297 self._copy.props.sensitive = False
298 self._copy.connect('clicked', self._copy_clicked_cb)
299 self.insert(self._copy, -1)
300 self._copy.show()
302 separator = gtk.SeparatorToolItem()
303 separator.set_expand(True)
304 separator.props.draw = False
305 self.insert(separator, -1)
306 separator.show()
308 self._erase = ToolButton('erase')
309 self._erase.set_tooltip(_('Erase'))
310 self._erase.props.sensitive = False
311 self._erase.connect('clicked', self._erase_clicked_cb)
312 self.insert(self._erase, -1)
313 self._erase.show()
315 def _resume_clicked_cb(self, button):
316 self._jobject.resume()
318 def _copy_clicked_cb(self, button):
319 clipboard = gtk.Clipboard()
320 clipboard.set_with_data([('text/uri-list', 0, 0)],
321 self._clipboard_get_func_cb,
322 self._clipboard_clear_func_cb)
324 def _clipboard_get_func_cb(self, clipboard, selection_data, info, data):
325 selection_data.set('text/uri-list', 8, self._jobject.file_path)
327 def _clipboard_clear_func_cb(self, clipboard, data):
328 pass
330 def _erase_clicked_cb(self, button):
331 datastore.delete(self._jobject.object_id)
332 self.emit('entry-erased')
334 def _resume_menu_item_activate_cb(self, menu_item, service_name):
335 self._jobject.resume(service_name)
337 def _refresh_resume_palette(self):
338 palette = self._resume.get_palette()
340 for i in range(0, palette.menu_item_count()):
341 palette.remove_menu_item(i)
343 if self._jobject is None:
344 return
346 for activity in self._jobject.get_activities():
347 menu_item = MenuItem(activity.name, activity.icon)
348 menu_item.connect('activate', self._resume_menu_item_activate_cb,
349 activity.service_name)
350 palette.insert_menu_item(menu_item)
352 def set_jobject(self, jobject):
353 if jobject == self._jobject:
354 return
355 self._jobject = jobject
357 if self._jobject is None:
358 self._erase.props.sensitive = False
359 self._copy.props.sensitive = False
360 self._resume.props.sensitive = False
361 else:
362 self._copy.props.sensitive = True
363 self._erase.props.sensitive = True
364 if self._jobject.get_activities():
365 self._resume.props.sensitive = True
366 else:
367 self._resume.props.sensitive = False
369 self._refresh_resume_palette()
371 class BackupToolbar(gtk.Toolbar):
372 __gtype_name__ = 'BackupToolbar'
374 def __init__(self):
375 gtk.Toolbar.__init__(self)
377 self._backup = ToolButton('document-save')
378 self._backup.set_tooltip(_('Backup'))
379 self._backup.connect('clicked', self._backup_clicked_cb)
380 self.insert(self._backup, -1)
381 self._backup.show()
383 def _backup_clicked_cb(self, button):
384 backup.backup_gui()