Work around change in Python 2.5
[memo.git] / Window.py
blob75763ed7f13db2b29793607a3fdfcf3972e49ff1
1 import rox
2 from rox import g, TRUE, FALSE, app_options
3 from rox.Menu import Menu
4 from rox.options import Option
5 import gobject
7 import dbus_notify
8 import pretty_time, time
9 import timer
10 from Alarm import Alarm
12 time_format = Option('time_format', 'text')
13 main_sticky = Option('main_sticky', 1)
15 menu = Menu('main', [
16 (_('/Add Memo...'), 'new_memo', ''),
17 (_('/Show All...'), 'show_all_memos', ''),
18 ('/', '', '<Separator>'),
19 (_('/Options...'), 'show_options',''),
20 (_('/Help'), 'help', ''),
21 (_('/Quit'), 'destroy', ''),
24 class Window(rox.Window):
25 drag_start = None
27 def __init__(self, memo_list):
28 rox.Window.__init__(self)
29 self.set_wmclass('Memo', 'Memo')
30 self.set_title('Memo')
31 self.set_resizable(False)
32 if hasattr(self, 'set_deletable'):
33 self.set_deletable(False)
34 #self.set_type_hint(g.gdk.WINDOW_TYPE_HINT_DIALOG)
36 self.tips = g.Tooltips()
38 if main_sticky.int_value:
39 self.stick()
41 self.memo_list = memo_list
42 self.last_day = None
44 vbox = g.VBox(FALSE, 0)
45 self.add(vbox)
47 hbox = g.HBox(False, 0)
48 vbox.pack_start(hbox, expand = False)
50 self.time_label = g.Label('')
51 self.time_button = g.Button()
52 self.time_button.add(self.time_label)
53 self.time_button.unset_flags(g.CAN_FOCUS)
54 hbox.pack_start(self.time_button, expand = True)
56 hbox.pack_start(timer.TimerButton(), expand = False)
58 self.list = g.TreeView(memo_list.visible)
59 vbox.pack_start(self.list, expand = TRUE)
60 self.list.unset_flags(g.CAN_FOCUS)
62 cell = g.CellRendererText()
63 column = g.TreeViewColumn('Time', cell, text = 0)
64 cell.set_property('xalign', 1)
65 self.list.append_column(column)
67 cell = g.CellRendererText()
68 column = g.TreeViewColumn('Message', cell, text = 1)
69 self.list.append_column(column)
71 self.list.set_headers_visible(FALSE)
73 sel = self.list.get_selection()
74 sel.set_mode(g.SELECTION_NONE)
76 def activate(view, path, column):
77 memo = memo_list.visible.get_memo_by_path(path)
78 from EditBox import EditBox
79 EditBox(memo).show()
81 self.add_events(g.gdk.BUTTON_PRESS_MASK)
82 self.list.connect('button-press-event', self.button_press)
83 self.list.connect('row-activated', activate)
84 self.time_button.add_events(g.gdk.BUTTON1_MOTION_MASK)
85 self.time_button.connect('button-press-event', self.button_press)
86 self.time_button.connect('motion-notify-event', self.button_motion)
87 self.time_button.connect('clicked', self.time_button_clicked)
89 menu.attach(self, self)
91 self.update()
92 gobject.timeout_add(10000, self.update) # Update clock
94 self.timeout = None # For next alarm
95 self.alert_box = None
96 self.show_all_box = None
97 self.save_box = None
98 self.prime()
100 # If we had more than one window, we'd need a remove too...
101 memo_list.watchers.append(self.prime)
102 app_options.add_notify(self.options_changed)
104 vbox.show_all()
106 def time_button_clicked(self, widget):
107 ev = g.get_current_event()
108 if ev.type == g.gdk.MOTION_NOTIFY and self.drag_start:
109 # Fake release from motion handler
110 self.begin_move_drag(1, self.drag_start[0], self.drag_start[1], ev.time)
111 self.drag_start = None
112 else:
113 self.new_memo()
115 def show_options(self):
116 rox.edit_options()
118 def options_changed(self):
119 if time_format.has_changed:
120 self.update()
122 if main_sticky.int_value:
123 self.stick()
124 else:
125 self.unstick()
127 def update(self):
128 if time_format.value == 'text':
129 text = pretty_time.rough_time(time.time())
130 self.tips.set_tip(self.time_button,
131 time.strftime('%H:%M %a %Y-%m-%d'))
132 else:
133 # Note: importing gtk breaks strftime for am/pm
134 text = time.strftime('%a %d-%b-%Y ') + \
135 pretty_time.str_time()
136 self.tips.set_tip(self.time_button, None)
137 self.time_label.set_text(text)
139 t = time.localtime()
140 year, month, day, hour, minute, second, weekday, julian, dst = t
141 if self.last_day != day:
142 if self.last_day is not None:
143 self.memo_list.new_day()
144 self.last_day = day
146 return TRUE
148 def new_memo(self, widget = None):
149 from EditBox import EditBox
150 EditBox().show()
152 def help(self):
153 from rox import filer
154 filer.open_dir(rox.app_dir + '/Help')
156 def button_press(self, widget, event):
157 if event.type != g.gdk.BUTTON_PRESS:
158 return
159 elif event.button == 2 or event.button == 3:
160 menu.popup(self, event)
161 return 1
162 self.drag_start = map(int, (event.x_root, event.y_root))
163 return 0
165 def button_motion(self, widget, mev):
166 if self.drag_start is None: return
167 pos = map(int, (mev.x_root, mev.y_root))
168 if self.time_button.drag_check_threshold(*(self.drag_start + pos)):
169 self.time_button.released()
170 if self.drag_start:
171 # Release event was ignored (outside the button)
172 self.time_button_clicked(widget)
174 def show_all_memos(self):
175 if self.show_all_box:
176 self.show_all_box.present()
177 return
178 def destroyed(widget): self.show_all_box = None
179 from ShowAll import ShowAll
180 self.show_all_box = ShowAll()
181 self.show_all_box.connect('destroy', destroyed)
182 self.show_all_box.show()
184 # Deal with any missed alarms
185 # Set a timeout for the next alarm
186 def prime(self):
187 if self.alert_box:
188 return # Don't do anything until closed
190 missed, delay = self.memo_list.catch_up()
191 if missed:
192 if dbus_notify.is_available():
193 for m in missed:
194 dbus_notify.notify(m)
195 else:
196 # Show the first one.
197 self.alert_box = Alarm(missed[0])
198 def destroyed(widget):
199 self.alert_box = None
200 self.prime()
201 self.alert_box.connect('destroy', destroyed)
202 g.gdk.beep()
203 g.gdk.flush()
204 time.sleep(0.3)
205 g.gdk.beep()
206 g.gdk.flush()
207 time.sleep(1)
208 self.alert_box.show()
209 if delay:
210 self.schedule(delay)
212 def timeout_cb(self):
213 gobject.source_remove(self.timeout)
214 self.timeout = 0
215 self.prime()
216 return 0
218 def schedule(self, delay):
219 if self.timeout:
220 gobject.source_remove(self.timeout)
222 # Avoid overflows - don't resched more than a day ahead
223 if delay > 60 * 60 * 24:
224 delay = 60 * 60 * 24
226 self.timeout = gobject.timeout_add(int(1000 * delay), self.timeout_cb)