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 _
20 from datetime
import datetime
, timedelta
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
):
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'
62 'query-changed': (gobject
.SIGNAL_RUN_FIRST
,
69 _ACTION_SINCE_YESTERDAY
= 2
71 _ACTION_THIS_MONTH
= 4
77 _ACTION_MY_FRIENDS
= 1
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)
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)
104 self
._when
_search
_combo
= self
._get
_when
_search
_combo
()
105 tool_item
= ToolComboBox(self
._when
_search
_combo
)
106 self
.insert(tool_item
, -1)
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)
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
)
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
)
150 def _add_widget(self
, widget
, expand
=False):
151 tool_item
= gtk
.ToolItem()
152 tool_item
.set_expand(expand
)
154 tool_item
.add(widget
)
157 self
.insert(tool_item
, -1)
160 def _build_query(self
):
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
)
168 mime_types
= type.mime_types
169 query
['mime_type'] = mime_types
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
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
:
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,
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
211 date
= date
.replace(year
=year
, month
=month
, day
=1)
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
,
250 if service_name
== current_value
:
251 current_value_index
= len(self
._what
_search
_combo
.get_model()) - 1
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
]:
259 appended_separator
= False
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
)
270 self
._what
_search
_combo
.set_active(current_value_index
)
272 self
._what
_search
_combo
.handler_unblock(self
._what
_combo
_changed
_sid
)
274 class EntryToolbar(gtk
.Toolbar
):
275 __gtype_name__
= 'EntryToolbar'
278 'entry-erased': (gobject
.SIGNAL_RUN_FIRST
,
284 gtk
.Toolbar
.__init
__(self
)
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)
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)
302 separator
= gtk
.SeparatorToolItem()
303 separator
.set_expand(True)
304 separator
.props
.draw
= False
305 self
.insert(separator
, -1)
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)
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
):
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:
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
:
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
362 self
._copy
.props
.sensitive
= True
363 self
._erase
.props
.sensitive
= True
364 if self
._jobject
.get_activities():
365 self
._resume
.props
.sensitive
= True
367 self
._resume
.props
.sensitive
= False
369 self
._refresh
_resume
_palette
()
371 class BackupToolbar(gtk
.Toolbar
):
372 __gtype_name__
= 'BackupToolbar'
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)
383 def _backup_clicked_cb(self
, button
):