Working on fremantlizing the simple_list
[quicknote] / src / notizen.py
1 #!/usr/bin/env python2.5
2 # -*- coding: utf-8 -*-
3
4 """
5  Copyright (C) 2007 Christoph Würstle
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation.
10 """
11
12 import time
13 import logging
14 import uuid
15
16 import gobject
17 import gtk
18 try:
19         import gtkspell
20 except ImportError:
21         gtkspell = None
22
23 import hildonize
24 import simple_list
25
26
27 try:
28         _
29 except NameError:
30         _ = lambda x: x
31
32
33 _moduleLogger = logging.getLogger("notizen")
34
35
36 class Notizen(gtk.HBox):
37
38         def __init__(self, db, topBox):
39                 self._db = db
40                 self._topBox = topBox
41                 self.noteId = -1
42                 self._pos = -1
43                 self._noteBody = None #Last notetext
44                 self._categoryName = ""
45
46                 gtk.HBox.__init__(self, homogeneous = False, spacing = 0)
47                 _moduleLogger.info("libnotizen, init")
48
49                 # Note list
50                 self._noteslist = simple_list.SimpleList()
51                 self._noteslist.set_eventfunction_cursor_changed(self._update_noteslist)
52                 self._noteslist.widget.set_size_request(250, -1)
53
54                 frame = gtk.Frame(_("Titles"))
55                 frame.add(self._noteslist.widget)
56
57                 buttonHBox = gtk.HBox()
58
59                 button = gtk.Button(stock = gtk.STOCK_ADD)
60                 button.connect("clicked", self._on_add_note, None)
61                 buttonHBox.pack_start(button, expand = True, fill = True, padding = 3)
62
63                 button = gtk.Button(stock = gtk.STOCK_DELETE)
64                 button.connect("clicked", self._on_delete_note, None)
65                 buttonHBox.pack_start(button, expand = True, fill = True, padding = 3)
66
67                 listVbox = gtk.VBox(homogeneous = False, spacing = 0)
68                 listVbox.pack_start(frame, expand = True, fill = True, padding = 3)
69                 listVbox.pack_start(buttonHBox, expand = False, fill = True, padding = 3)
70                 self.pack_start(listVbox, expand = False, fill = True, padding = 3)
71
72                 # Note view
73                 self._noteBodyView = gtk.TextView()
74                 self._noteBodyView.connect("focus-out-event", self.save_note, "focus-out-event")
75                 buf = self._noteBodyView.get_buffer()
76                 buf.set_text("")
77                 buf.connect("changed", self._on_note_changed, None)
78                 if gtkspell is not None:
79                         self._noteBodySpellChecker = gtkspell.Spell(self._noteBodyView)
80                 else:
81                         self._noteBodySpellChecker = None
82
83                 self._noteScrollWindow = gtk.ScrolledWindow()
84                 self._noteScrollWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
85                 self._noteScrollWindow.add(self._noteBodyView)
86                 hildonize.hildonize_scrollwindow_with_viewport(self._noteScrollWindow)
87
88                 frame = gtk.Frame(_("Note"))
89                 frame.add(self._noteScrollWindow)
90
91                 # History
92                 self._historyBox = gtk.HBox(homogeneous = False, spacing = 0)
93
94                 self._historyStatusLabel = gtk.Label(_("No History"))
95                 self._historyStatusLabel.set_alignment(0.0, 0.5)
96                 self._historyBox.pack_start(self._historyStatusLabel, expand = True, fill = True, padding = 3)
97
98                 button = gtk.Button(_("History"))
99                 button.connect("clicked", self._on_show_history, None)
100                 self._historyBox.pack_start(button, expand = True, fill = True, padding = 3)
101
102                 # Note and history stuff in same column
103                 noteVbox = gtk.VBox(homogeneous = False, spacing = 0)
104                 noteVbox.pack_start(frame, expand = True, fill = True, padding = 3)
105                 noteVbox.pack_start(self._historyBox, expand = False, fill = True, padding = 3)
106                 self.pack_start(noteVbox, expand = True, fill = True, padding = 3)
107
108                 self.load_notes()
109                 self._topBox.connect("reload_notes", self.load_notes)
110
111         def set_wordwrap(self, enableWordWrap):
112                 if enableWordWrap:
113                         self._noteScrollWindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
114                         self._noteBodyView.set_wrap_mode(gtk.WRAP_WORD)
115                 else:
116                         self._noteScrollWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
117                         self._noteBodyView.set_wrap_mode(gtk.WRAP_NONE)
118
119         def show_history_area(self, visible):
120                 if visible:
121                         self._historyBox.show()
122                 else:
123                         self._historyBox.hide()
124
125         def load_notes(self, data = None):
126                 _moduleLogger.info("load_notes params: pos:"+str(self._pos)+" noteid:"+str(self.noteId))
127                 self._noteslist.clear_items()
128                 self._noteslist.append_item(_("New Note..."), "new")
129
130                 self._categoryName = self._topBox.get_category()
131                 search = self._topBox.get_search_pattern()
132                 notes = self._db.searchNotes(search, self._categoryName)
133
134                 if notes is not None:
135                         for note in notes:
136                                 noteid, category, noteText = note
137                                 title = self._get_title(noteText)
138                                 self._noteslist.append_item(title, noteid)
139
140                 self.noteId = -1
141                 self._pos = -1
142                 self._noteBodyView.get_buffer().set_text("")
143
144         def save_note(self, widget = None, data = None, data2 = None):
145                 _moduleLogger.info("save_note params: pos:"+str(self._pos)+" noteid:"+str(self.noteId))
146                 #print "params:", data, data2
147                 buf = self._noteBodyView.get_buffer().get_text(self._noteBodyView.get_buffer().get_start_iter(), self._noteBodyView.get_buffer().get_end_iter())
148                 if buf is None or len(buf) == 0:
149                         return
150
151                 if buf == self._noteBody:
152                         return
153
154                 _moduleLogger.info("Saving note: "+buf)
155                 if self._pos == -1 or self.noteId == -1:
156                         self._pos = -1
157                         self.noteId = str(uuid.uuid4())
158                         self._db.saveNote(self.noteId, buf, self._categoryName)
159                         self._noteslist.append_item(self._get_title(buf), self.noteId)
160                         self._pos = self._noteslist.select_last_item()
161                 else:
162                         self._db.saveNote(self.noteId, buf, self._categoryName)
163
164                 self._topBox.define_this_category()
165
166         def _get_title(self, buf):
167                 """
168                 @returns the title of the current note
169                 """
170                 eol = buf.find("\n")
171                 if -1 == eol:
172                         eol = len(buf)
173                 title = buf[:eol]
174                 return title
175
176         def _set_focus(self):
177                 self._noteBodyView.grab_focus()
178                 return False
179
180         def _update_noteslist(self, data = None, data2 = None):
181                 if self._pos != -1:
182                         self.save_note()
183
184                 try:
185                         (pos, key, value) = self._noteslist.get_selection_data()
186                         if (pos == -1):
187                                 return
188                 except StandardError:
189                         if data != "new":
190                                 return
191                         key = None
192
193                 if key == "new" or data == "new":
194                         #both methods supported click add note or new note (first one disabled)
195                         self.noteId = str(uuid.uuid4())
196                         self._db.saveNote(self.noteId, "", self._categoryName)
197                         self._pos = -1
198                         self._noteslist.append_item("", self.noteId)
199                         self._noteBodyView.get_buffer().set_text("")
200                         self._pos = self._noteslist.select_last_item()
201                 else:
202                         self._pos = pos
203                         self.noteId, pcdatum, self._categoryName, self._noteBody = self._db.loadNote(key)
204                         self._historyStatusLabel.set_text(time.strftime(_("Last change: %d.%m.%y %H:%M"), time.localtime(pcdatum)))
205                         buf = self._noteBodyView.get_buffer()
206                         buf.set_text(self._noteBody)
207
208                 gobject.timeout_add(200, self._set_focus)
209
210         def _on_note_changed(self, widget = None, data = None):
211                 if self._pos == -1 or self.noteId == -1:
212                         return
213
214                 buf = self._noteBodyView.get_buffer().get_text(self._noteBodyView.get_buffer().get_start_iter(), self._noteBodyView.get_buffer().get_end_iter())
215
216                 title = self._get_title(buf)
217                 value, key = self._noteslist.get_item(self._pos)
218
219                 if value != title:
220                         self._noteslist.change_item(self._pos, title, self.noteId)
221
222         def _on_add_note(self, widget = None, data = None):
223                 self._update_noteslist("new")
224
225         def _on_delete_note(self, widget = None, data = None):
226                 if (self.noteId == -1):
227                         return
228                 mbox = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, _("Really delete?"))
229                 response = mbox.run()
230                 mbox.hide()
231                 mbox.destroy()
232                 if response == gtk.RESPONSE_YES:
233                         self._db.delNote(self.noteId)
234                         self.noteId = -1
235                         self._noteslist.remove_item(self._pos)
236                         self._pos = -1
237                         self._noteBodyView.get_buffer().set_text("")
238
239         def _on_show_history(self, widget = None, data = None, label = None):
240                 if self.noteId == -1:
241                         mbox =  gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, _("No note selected."))
242                         response = mbox.run()
243                         mbox.hide()
244                         mbox.destroy()
245                         return
246
247                 rows = self._db.getNoteHistory(self.noteId)
248
249                 import history
250                 dialog = history.Dialog()
251
252                 lastNoteStr = ""
253                 for row in rows:
254                         daten = row[4][1]
255                         if daten != "" and lastNoteStr != daten:
256                                 lastNoteStr = daten
257                                 dialog.noteHistory.append([row[0], row[1], row[2], row[3], daten+"\n"])
258
259                 dialog.vbox.show_all()
260                 dialog.set_size_request(600, 380)
261
262                 if dialog.run() == gtk.RESPONSE_ACCEPT:
263                         print "saving"
264                         self.save_note()
265                         data = dialog.get_selected_row()
266                         if data is not None:
267                                 self._db.speichereSQL(data[2], data[3].split(" <<Tren-ner>> "), rowid = self.noteId)
268                                 _moduleLogger.info("loading History")
269                                 self._update_noteslist()
270
271                 dialog.destroy()