~manishsinha/gnome-activity-journal/fixes-924988

« back to all changes in this revision

Viewing changes to src/main.py

  • Committer: Bazaar Package Importer
  • Author(s): Siegfried-Angel Gevatter Pujals, Siegfried-Angel Gevatter Pujals, Manish Sinha
  • Date: 2011-07-16 19:12:03 UTC
  • mfrom: (1.2.1 upstream) (5.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 7.
  • Revision ID: james.westby@ubuntu.com-20110716191203-wotprinloexpofrs
[ Siegfried-Angel Gevatter Pujals ]
* New upstream releases (Closes: #621011) (LP: #643795, #722227, #734412,
  #743054, #743125, #650917).
* debian/postinst:
   - Restart zeitgeist-daemon after installation, to ensure that
     the extension gets loaded (LP: #638217).
* debian/control:
   - Bump Zeitgeist dependency to 0.8.0.
   - Remove Tracker from Suggests, support for it has been disabled
     for now.
   - Bump Standards-Version to 3.9.2.
* debian/rules:
   - Remove build/ directory on clean.
* debian/copyright:
   - Update copyright years and add Stefano Candori and Collabora.

[ Manish Sinha ]
* debian/control:
   - Add Recommends on gstreamer0.10-plugins-base (LP: #705545).

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
# Copyright © 2009-2010 Seif Lotfy <seif@lotfy.com>
6
6
# Copyright © 2010 Siegfried Gevatter <siegfried@gevatter.com>
7
7
# Copyright © 2010 Randal Barlow <email.tehk@gmail.com>
 
8
# Copyright © 2011 Stefano Candori <stefano.candori@gmail.com>
8
9
#
9
10
# This program is free software: you can redistribute it and/or modify
10
11
# it under the terms of the GNU General Public License as published by
27
28
import datetime
28
29
import os
29
30
 
30
 
from activity_widgets import MultiViewContainer, TimelineViewContainer, ThumbViewContainer, PinnedPane
31
 
from supporting_widgets import DayButton, DayLabel, Toolbar, ContextMenu, AboutDialog, HandleBox, SearchBox, InformationContainer, PreferencesDialog
 
31
from activity_widgets import MultiViewContainer, TimelineViewContainer, ThumbViewContainer
 
32
from supporting_widgets import DayButton, DayLabel, Toolbar, SearchBox, PreferencesDialog, ContextMenu, ThrobberPopupButton, \
 
33
ContextMenuMolteplicity, NiceBar
32
34
from histogram import HistogramWidget
33
35
from store import Store, tdelta, STORE, CLIENT
34
36
from config import settings, get_icon_path, get_data_path, PluginManager
35
 
 
36
 
 
37
 
AUTOLOAD = True # Should the store request events in the background?
38
 
 
39
 
 
 
37
from Indicator import TrayIconManager
 
38
from common import SIZE_THUMBVIEW, SIZE_TIMELINEVIEW
 
39
 
 
40
#TODO granularity scrool, alignment timelineview_icon
 
41
#more metadata? use website cache as thumbpreview??
40
42
class ViewContainer(gtk.Notebook):
41
43
    __gsignals__ = {
42
44
        "new-view-added" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_PYOBJECT,)),
60
62
        self.tool_buttons = []
61
63
 
62
64
    def set_day(self, day, page=None):
 
65
        force_update = True
63
66
        if page == None:
64
67
            page = self.page
 
68
            force_update = False
65
69
        if hasattr(self.pages[page], "set_day"):
66
 
            self.pages[page].set_day(day, self.store)
 
70
            self.pages[page].set_day(day, self.store, force_update)
 
71
            
 
72
    def set_zoom(self, zoom):
 
73
        page = self.page
 
74
        if hasattr(self.pages[page], "set_zoom"):
 
75
            self.pages[page].set_zoom(zoom)
67
76
 
68
77
    def _register_new_view(self, viewstruct):
69
78
        self.append_page(viewstruct.view)
70
79
        self.pages.append(viewstruct.view)
71
80
        self.tool_buttons.append(viewstruct.button)
72
 
        viewstruct.button.connect("clicked", self.view_button_clicked, len(self.pages)-1)
 
81
        if(len(self.tool_buttons)) > 1:
 
82
            viewstruct.button.set_group(self.tool_buttons[0])  
 
83
        viewstruct.button.set_flags(gtk.CAN_FOCUS) 
 
84
        viewstruct.button.connect("toggled", self.view_button_toggled, len(self.pages)-1)
73
85
        viewstruct.view.show_all()
74
86
        return self.pages.index(viewstruct.view)
75
87
 
96
108
    def page(self):
97
109
        return self.get_current_page()
98
110
 
99
 
    def view_button_clicked(self, button, i):
100
 
        self.emit("view-button-clicked", button, i)
 
111
    def view_button_toggled(self, button, i):
 
112
        if not button.get_active():return
 
113
        button.grab_focus()
 
114
        self.emit("view-button-clicked", button, i)
101
115
 
102
116
    def set_view_page(self, i):
103
117
        self.set_current_page(i)
104
 
        for button in self.tool_buttons:
105
 
            button.set_sensitive(True)
106
 
        self.tool_buttons[i].set_sensitive(False)
107
 
 
108
 
 
109
 
class PanedContainer(gtk.HBox):
110
 
    def __init__(self):
111
 
        super(PanedContainer, self).__init__()
112
 
        self.pane1 = pane1 = gtk.HPaned()
113
 
        self.pane2 = pane2 = gtk.HPaned()
114
 
        pane1.add2(pane2)
115
 
        self.boxes = {}
116
 
        box1 = self.left_box = gtk.EventBox()
117
 
        box2 = self.center_box = gtk.EventBox()
118
 
        box3 = self.right_box = gtk.EventBox()
119
 
        pane1.pack1(box1, False, False)
120
 
        pane2.pack1(box2, False, True)
121
 
        pane2.pack2(box3, False, False)
122
 
        self.add(pane1)
123
 
 
124
 
        self.informationcontainer = InformationContainer()
125
 
        ContextMenu.informationwindow = self.informationcontainer
126
 
        self.h1 = handle = HandleBox()
127
 
        handle.add(self.informationcontainer)
128
 
        box3.add(handle)
129
 
        self.informationcontainer.connect("hide", self.on_hide)
130
 
        self.informationcontainer.connect("show", self.on_show)
131
 
        self.informationcontainer.set_size_request(100, 100)
132
 
        self.pinbox = PinnedPane()
133
 
        self.pinbox.connect("hide", self.on_hide)
134
 
        self.pinbox.connect("show", self.on_show)
135
 
        self.h2 = handle = HandleBox()
136
 
        handle.add(self.pinbox)
137
 
        box1.add(handle)
138
 
 
139
 
    def on_show(self, w, *args):
140
 
        self.pane1.set_position(-1)
141
 
        self.pane2.set_position(-1)
142
 
        handle = self.h1 if w == self.informationcontainer else self.h2
143
 
        handle.show()
144
 
        if w == self.informationcontainer:
145
 
            self.right_box.show()
146
 
        elif w == self.pinbox:
147
 
            self.left_box.show()
148
 
 
149
 
    def on_hide(self, w, *args):
150
 
        self.pane1.set_position(-1)
151
 
        self.pane2.set_position(-1)
152
 
        handle = self.h1 if w == self.informationcontainer else self.h2
153
 
        handle.hide()
154
 
        if w == self.informationcontainer:
155
 
            self.right_box.hide()
156
 
        elif w == self.pinbox:
157
 
            self.left_box.hide()
158
 
 
 
118
 
 
119
    def _register_default_view(self, view):
 
120
        toolbutton = Toolbar.get_toolbutton(view.icon_path, view.dsc_text)
 
121
        self._register_new_view(self.ViewStruct(view, toolbutton))
 
122
        self.set_view_page(0)
 
123
        
 
124
    def set_zoom_slider(self, hscale):
 
125
        #FIXME dirty hack
 
126
        for page in self.pages:
 
127
            page.set_slider(hscale)
 
128
            
 
129
    def toggle_erase_mode(self):
 
130
        for page in self.pages:
 
131
            page.toggle_erase_mode()
 
132
        
159
133
 
160
134
class PortalWindow(gtk.Window):
161
 
    __gsignals__ = {
162
 
        "day-set" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_PYOBJECT,)),
163
 
    }
164
 
 
165
 
 
 
135
    """
 
136
    The primary application window
 
137
    """
166
138
    def __init__(self):
167
139
        super(PortalWindow, self).__init__()
168
 
        self.__initialized = False
169
 
        self._requested_size = None
170
140
        # Important
171
141
        self._request_size()
172
142
        self.store = STORE
173
143
        self.day_iter = self.store.today
 
144
        self.pages_loaded = 0
 
145
        self.current_zoom = 1
 
146
        self.in_erase_mode = False
174
147
        self.view = ViewContainer(self.store)
175
148
        self.toolbar = Toolbar()
176
 
        map(self.view._register_new_view,
177
 
            (self.view.ViewStruct(MultiViewContainer(), Toolbar.get_toolbutton(get_data_path("multiview_icon.png"), _("Switch to MultiView"))),
178
 
             self.view.ViewStruct(ThumbViewContainer(), Toolbar.get_toolbutton(get_data_path("thumbview_icon.png"), _("Switch to ThumbView"))),
179
 
             self.view.ViewStruct(TimelineViewContainer(), Toolbar.get_toolbutton(get_data_path("timelineview_icon.png"), _("Switch to TimelineView")))
180
 
             ))
181
 
        self.view.set_view_page(0)
 
149
        default_views = (MultiViewContainer(), ThumbViewContainer(), TimelineViewContainer())
 
150
        default_views[0].connect("view-ready", self._on_view_ready)
 
151
        map(self.view._register_default_view, default_views)
182
152
        map(self.toolbar.add_new_view_button, self.view.tool_buttons[::-1])
183
 
        self.view.connect("new-view-added", lambda w, v: self.toolbar.add_new_view_button(v.button, len(self.view.tool_buttons)))
184
 
        self.panedcontainer = PanedContainer()
185
 
        self.preferences_dialog = PreferencesDialog()
 
153
        self.preferences_dialog = PreferencesDialog(parent=self)
 
154
        ContextMenu.set_parent_window(self)
 
155
        ContextMenuMolteplicity.set_parent_window(self)
186
156
        self.histogram = HistogramWidget()
187
157
        self.histogram.set_store(self.store)
188
 
        self.histogram.set_dates([self.day_iter.date])
189
 
        self.backward_button = DayButton(0)
190
 
        self.forward_button = DayButton(1, sensitive=False)
191
 
        self.searchbox = SearchBox
 
158
        self.backward_button, ev_backward_button = DayButton.new(0)
 
159
        self.forward_button, ev_forward_button = DayButton.new(1, sensitive=False)
 
160
        self.nicebar = NiceBar()
 
161
        self.nicebar_timeout = None
 
162
        
 
163
        # use a table for the spinner (otherwise the spinner is massive!)
 
164
        spinner_table = gtk.Table(3, 3, False)
 
165
        label = gtk.Label()
 
166
        label.set_markup(_("<span size=\"larger\"><b>Loading Journal...</b></span>"))
 
167
        vbox = gtk.VBox(False, 5)
 
168
        pix = gtk.gdk.pixbuf_new_from_file(get_data_path("zeitgeist-logo.svg"))
 
169
        pix = pix.scale_simple(100, 100, gtk.gdk.INTERP_BILINEAR)
 
170
        zlogo = gtk.image_new_from_pixbuf(pix)
 
171
        vbox.pack_start(zlogo, False, False)
 
172
        vbox.pack_start(label, True)
 
173
        spinner_table.attach(vbox, 1, 2, 1, 2, gtk.EXPAND, gtk.EXPAND)
 
174
        self.hscale = gtk.HScale(gtk.Adjustment(1.0, 0.0, 3.0, 1.0, 1.0, 0.0))
 
175
        self.hscale.set_size_request(120, -1)
 
176
        self.hscale.set_draw_value(False)
 
177
        al = gtk.Alignment(yalign=0.5)
 
178
        al.set_padding(0, 0, 8, 8)
 
179
        al.add(self.hscale)
 
180
        im_in = gtk.image_new_from_stock(gtk.STOCK_ZOOM_IN, gtk.ICON_SIZE_MENU)
 
181
        im_out =  gtk.image_new_from_stock(gtk.STOCK_ZOOM_OUT, gtk.ICON_SIZE_MENU)
 
182
        self.throbber_popup_button = ThrobberPopupButton()
192
183
        # Widget placement
193
 
        vbox = gtk.VBox()
194
 
        hbox = gtk.HBox()
195
 
        histogramhbox = gtk.HBox()
196
 
        hbox.pack_start(self.backward_button, False, False)
197
 
        hbox.pack_start(self.view, True, True, 6)
198
 
        hbox.pack_end(self.forward_button, False, False)
199
 
        hbox.set_border_width(4)
200
 
        vbox.pack_start(self.toolbar, False, False)
201
 
        self.panedcontainer.center_box.add(hbox)
202
 
        vbox.pack_start(self.panedcontainer, True, True, 2)
203
 
        histogramhbox.pack_end(self.histogram, True, True, 30)
204
 
        vbox.pack_end(histogramhbox, False, False)
205
 
        self.add(vbox)
206
 
        self.show_all()
207
 
        self.panedcontainer.informationcontainer.hide()
208
 
        self.panedcontainer.pinbox.hide()
 
184
        vbox = gtk.VBox(); hbox = gtk.HBox();self.scale_box = gtk.HBox();self.histogramhbox = gtk.HBox()
 
185
        vbox_general = gtk.VBox();scale_toolbar_box = gtk.HBox()
 
186
        hbox.pack_start(ev_backward_button, False, False); hbox.pack_start(self.view, True, True, 6)
 
187
        hbox.pack_end(ev_forward_button, False, False);
 
188
        self.scale_box.pack_start(im_out,False,False);self.scale_box.pack_start(al, False, False)
 
189
        self.scale_box.pack_start(im_in,False,False);self.scale_box.pack_end(gtk.SeparatorToolItem(),False,False)
 
190
        scale_toolbar_box.pack_start(self.toolbar); scale_toolbar_box.pack_end(self.throbber_popup_button,False,False);
 
191
        scale_toolbar_box.pack_end(self.scale_box, False, False);
 
192
        vbox.pack_start(scale_toolbar_box, False, False); vbox.pack_start(self.nicebar,False,False);vbox.pack_start(hbox, True, True, 5);
 
193
        self.histogramhbox.pack_end(self.histogram, True, True, 32);
 
194
        self.histogramhbox.set_sensitive(False)
 
195
        self.spinner_notebook = gtk.Notebook()
 
196
        self.spinner_notebook.set_show_tabs(False)
 
197
        self.spinner_notebook.set_show_border(False)
 
198
        self.spinner_notebook.append_page(spinner_table)
 
199
        self.spinner_notebook.append_page(vbox)
 
200
        vbox_general.pack_start(self.spinner_notebook)
 
201
        vbox_general.pack_end(self.histogramhbox, False, False)
 
202
        self.add(vbox_general)
 
203
        vbox_general.show_all()
 
204
        self.scale_box.hide()
 
205
        
 
206
        self.show()
 
207
        self.nicebar.hide()
 
208
        SearchBox.hide()
 
209
        
 
210
        #Tray Icon
 
211
        self.tray_manager = TrayIconManager(self)
209
212
        # Settings
210
213
        self.view.set_day(self.store.today)
211
 
        # Connections
 
214
        self.view.set_zoom_slider(self.hscale)
 
215
        # Signal connections
 
216
        self.view.connect("new-view-added", lambda w, v: self.toolbar.add_new_view_button(v.button, len(self.view.tool_buttons)))
212
217
        self.connect("destroy", self.quit)
213
218
        self.connect("delete-event", self.on_delete)
 
219
        self.toolbar.connect("previous", self.previous)
 
220
        self.toolbar.connect("jump-to-today", lambda w: self.set_date(datetime.date.today()))
 
221
        self.toolbar.connect("next", self.next)
 
222
        self.hscale.connect("value-changed", self._on_zoom_changed)
214
223
        self.backward_button.connect("clicked", self.previous)
215
224
        self.forward_button.connect("clicked", self.next)
 
225
        self.forward_button.connect("jump-to-today", lambda w: self.set_date(datetime.date.today()))
216
226
        self.histogram.connect("date-changed", lambda w, date: self.set_date(date))
217
227
        self.view.connect("view-button-clicked", self.on_view_button_click)
218
 
        self.toolbar.throbber.connect("clicked", self.show_about_window)
219
 
        self.toolbar.goto_today_button.connect("clicked", lambda w: self.set_date(datetime.date.today()))
220
 
        self.toolbar.pin_button.connect("clicked", lambda w: self.panedcontainer.pinbox.toggle_visibility())
221
228
        self.store.connect("update", self.histogram.histogram.set_store)
222
 
        self.searchbox.connect("search", self._on_search)
223
 
        self.searchbox.connect("clear", self._on_search_clear)
224
 
        self.set_title_from_date(self.day_iter.date)
225
 
        def setup(*args):
226
 
            self.histogram.set_dates(self.active_dates)
227
 
            self.histogram.scroll_to_end()
228
 
            if AUTOLOAD:
229
 
                self.store.request_last_n_days_events(90)
230
 
            return False
231
 
        gobject.timeout_add_seconds(1, setup)
232
 
        self.histogram.scroll_to_end()
233
 
        # hide unused widgets
234
 
        self.searchbox.hide()
 
229
        SearchBox.connect("search", self._on_search)
 
230
        self.throbber_popup_button.connect("toggle-erase-mode", self._on_toggle_erase_mode)
 
231
        SearchBox.connect("clear", self._on_search_clear)
235
232
        # Window configuration
236
233
        self.set_icon_name("gnome-activity-journal")
237
234
        self.set_icon_list(
241
238
                "hicolor/32x32/apps/gnome-activity-journal.png",
242
239
                "hicolor/48x48/apps/gnome-activity-journal.png",
243
240
                "hicolor/256x256/apps/gnome-activity-journal.png")])
 
241
        gobject.idle_add(self.setup)
244
242
        gobject.idle_add(self.load_plugins)
245
243
 
246
244
    def load_plugins(self):
247
245
        self.plug_manager = PluginManager(CLIENT, STORE, self)
248
246
        self.preferences_dialog.notebook.show_all()
249
 
        self.toolbar.preference_button.connect("clicked", lambda *args: self.preferences_dialog.show())
 
247
        self.throbber_popup_button.preferences.connect("activate", lambda *args: self.preferences_dialog.show())
250
248
        self.preferences_dialog.plug_tree.set_items(self.plug_manager)
251
 
 
252
 
        return False
253
 
 
 
249
        return False
 
250
 
 
251
    def setup(self, *args):
 
252
        self.set_title_from_date(self.day_iter.date)
 
253
        self.histogram.set_dates(self.active_dates)
 
254
        self.histogram.scroll_to_end()
 
255
        return False
 
256
    
254
257
    def set_visibility(self, val):
255
258
        if val: self.show()
256
259
        else: self.hide()
273
276
        return dates
274
277
 
275
278
    def set_day(self, day):
276
 
        self.toolbar.do_throb()
 
279
        self.throbber_popup_button.image.animate_for_seconds(1)
277
280
        self.day_iter = day
278
281
        self.handle_button_sensitivity(day.date)
279
282
        self.view.set_day(day)
280
283
        self.histogram.set_dates(self.active_dates)
281
 
        # Set title
282
284
        self.set_title_from_date(day.date)
283
 
        self.emit("day-set", day)
284
285
 
285
286
    def set_date(self, date):
286
287
        self.set_day(self.store[date])
296
297
    def handle_button_sensitivity(self, date):
297
298
        today = datetime.date.today()
298
299
        if date == today:
299
 
            return self.forward_button.set_sensitive(False)
300
 
        elif date == today + tdelta(-1):
 
300
            self.forward_button.set_sensitive(False)
 
301
            self.toolbar.nextd_button.set_sensitive(False)
 
302
            self.toolbar.home_button.set_sensitive(False)
 
303
        else:
301
304
            self.forward_button.set_leading(True)
302
 
        else:
303
 
            self.forward_button.set_leading(False)
304
 
        self.forward_button.set_sensitive(True)
 
305
            self.forward_button.set_sensitive(True)
 
306
            self.toolbar.nextd_button.set_sensitive(True)
 
307
            self.toolbar.home_button.set_sensitive(True)
305
308
 
306
309
    def on_view_button_click(self, w, button, i):
307
310
        self.view.set_view_page(i)
308
311
        self.view.set_day(self.day_iter, page=i)
309
312
        self.histogram.set_dates(self.active_dates)
310
 
        self.set_title_from_date(self.day_iter.date)
 
313
        self.set_title_from_date(self.day_iter.date)        
 
314
        if i == 0:
 
315
            self.scale_box.hide()
 
316
        else:
 
317
            self.view.set_zoom(self.current_zoom)
 
318
            self.scale_box.show()
311
319
 
312
 
    def show_about_window(self, *args):
313
 
        aboutwindow = AboutDialog()
314
 
        aboutwindow.set_transient_for(self)
315
 
        aboutwindow.run()
316
 
        aboutwindow.destroy()
 
320
    def _on_view_ready(self, view):
 
321
        if self.pages_loaded == view.num_pages - 1:
 
322
            self.histogramhbox.set_sensitive(True)
 
323
            self.spinner_notebook.set_current_page(1)
 
324
        else:
 
325
            self.pages_loaded += 1
317
326
 
318
327
    def _on_search(self, box, results):
319
328
        dates = []
337
346
        if settings["window_height"] and settings["window_height"] <= screen[3]:
338
347
            size[1] = settings["window_height"]
339
348
 
340
 
        self.set_geometry_hints(min_width=800, min_height=360)
 
349
        self.set_geometry_hints(min_width=1024, min_height=360)
341
350
        self.resize(size[0], size[1])
342
 
        self._requested_size = size
 
351
        self._requested_size = size     
 
352
             
 
353
    def _on_zoom_changed(self, hscale):
 
354
        self.current_zoom = int(hscale.get_value())
 
355
        self.view.set_zoom(self.current_zoom) 
 
356
        
 
357
    def _on_toggle_erase_mode(self, *args):
 
358
        self.in_erase_mode = not self.in_erase_mode
 
359
        if self.in_erase_mode:
 
360
            if self.nicebar_timeout:
 
361
                gobject.source_remove(self.nicebar_timeout)
 
362
                self.nicebar_timeout = None
 
363
            hand = gtk.gdk.Cursor(gtk.gdk.PIRATE) 
 
364
            message = _("Erase Mode is active")
 
365
            background = NiceBar.ALERTBACKGROUND
 
366
            stock = gtk.STOCK_DIALOG_WARNING
 
367
        else:
 
368
            hand = gtk.gdk.Cursor(gtk.gdk.ARROW)
 
369
            message = _("Erase Mode deactivated")
 
370
            background = NiceBar.NORMALBACKGROUND
 
371
            stock = gtk.STOCK_DIALOG_INFO 
 
372
            self.nicebar_timeout = gobject.timeout_add(3000, self.nicebar.remove_message)
 
373
            
 
374
        self.nicebar.display_message(message, background=background, stock=stock)
 
375
        self.window.set_cursor(hand)
 
376
        self.view.toggle_erase_mode()              
343
377
 
344
378
    def set_title_from_date(self, date):
345
379
        pages = self.view.pages[0].num_pages
368
402
        x, y = self.get_size()
369
403
        settings["window_width"] = x
370
404
        settings["window_height"] = y
 
405
        if settings.get("tray_icon", False):
 
406
            self.set_visibility(False)
 
407
            return True
 
408
 
 
409
    def quit_and_save(self, *args):
 
410
        x, y = self.get_size()
 
411
        settings["window_width"] = x
 
412
        settings["window_height"] = y
 
413
        gtk.main_quit()
371
414
 
372
415
    def quit(self, *args):
373
416
        gtk.main_quit()