Merge lp:~thisfred/u1db/u1todo-3 into lp:u1db

Proposed by Eric Casteleijn on 2012-04-23
Status: Merged
Merged at revision: 258
Proposed branch: lp:~thisfred/u1db/u1todo-3
Merge into: lp:u1db
Diff against target: 220 lines (+107/-16)
3 files modified
u1todo/test_u1todo.py (+34/-0)
u1todo/u1todo.py (+31/-0)
u1todo/ui.py (+42/-16)
To merge this branch: bzr merge lp:~thisfred/u1db/u1todo-3
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) 2012-04-23 Approve on 2012-04-25
Review via email: mp+103170@code.launchpad.net

Commit Message

- u1todo saves the done status when an item is checked or unchecked
- u1todo now saves to a real database, so todo items persist between sessions

Description of the Change

- u1todo saves the done status when an item is checked or unchecked
- u1todo now saves to a real database, so todo items persist between sessions

To post a comment you must log in.
Alejandro J. Cura (alecu) wrote :

Code looks fine, all tests pass.

review: Approve
lp:~thisfred/u1db/u1todo-3 updated on 2012-04-25
255. By Eric Casteleijn on 2012-04-25

merged trunk

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'u1todo/test_u1todo.py'
2--- u1todo/test_u1todo.py 2012-04-23 12:59:10 +0000
3+++ u1todo/test_u1todo.py 2012-04-23 20:47:18 +0000
4@@ -1,3 +1,19 @@
5+# Copyright 2012 Canonical Ltd.
6+#
7+# This file is part of u1db.
8+#
9+# u1db is free software: you can redistribute it and/or modify
10+# it under the terms of the GNU Lesser General Public License version 3
11+# as published by the Free Software Foundation.
12+#
13+# u1db is distributed in the hope that it will be useful,
14+# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+# GNU Lesser General Public License for more details.
17+#
18+# You should have received a copy of the GNU Lesser General Public License
19+# along with u1db. If not, see <http://www.gnu.org/licenses/>.
20+
21 """Tests for u1todo example application."""
22
23 from testtools import TestCase
24@@ -17,6 +33,13 @@
25 store.initialize_db()
26 self.assertEqual(INDEXES, dict(self.db.list_indexes()))
27
28+ def test_reinitialize_db(self):
29+ """Creates indexes."""
30+ store = TodoStore(self.db)
31+ store.new_task()
32+ store.initialize_db()
33+ self.assertEqual(INDEXES, dict(self.db.list_indexes()))
34+
35 def test_indexes_are_added(self):
36 """New indexes are added when a new store is created."""
37 store = TodoStore(self.db)
38@@ -89,6 +112,17 @@
39 store.delete_task(task)
40 self.assertRaises(KeyError, store.get_task, task.task_id)
41
42+ def test_get_all_tasks(self):
43+ store = TodoStore(self.db)
44+ store.initialize_db()
45+ task1 = store.new_task()
46+ task2 = store.new_task()
47+ task3 = store.new_task()
48+ task_ids = [task.task_id for task in store.get_all_tasks()]
49+ self.assertEqual(
50+ sorted([task1.task_id, task2.task_id, task3.task_id]),
51+ sorted(task_ids))
52+
53
54 class TaskTestCase(TestCase):
55 """Tests for Task."""
56
57=== modified file 'u1todo/u1todo.py'
58--- u1todo/u1todo.py 2012-04-23 12:59:10 +0000
59+++ u1todo/u1todo.py 2012-04-23 20:47:18 +0000
60@@ -1,6 +1,25 @@
61+# Copyright 2012 Canonical Ltd.
62+#
63+# This file is part of u1db.
64+#
65+# u1db is free software: you can redistribute it and/or modify
66+# it under the terms of the GNU Lesser General Public License version 3
67+# as published by the Free Software Foundation.
68+#
69+# u1db is distributed in the hope that it will be useful,
70+# but WITHOUT ANY WARRANTY; without even the implied warranty of
71+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72+# GNU Lesser General Public License for more details.
73+#
74+# You should have received a copy of the GNU Lesser General Public License
75+# along with u1db. If not, see <http://www.gnu.org/licenses/>.
76+
77 """u1todo example application."""
78
79 import json
80+import os
81+import xdg.BaseDirectory
82+from u1db.backends.sqlite_backend import SQLitePartialExpandDatabase
83
84 DONE = 'true'
85 NOT_DONE = 'false'
86@@ -13,6 +32,14 @@
87 }
88
89
90+def get_database():
91+ """Get the path that the database is stored in."""
92+ # TODO: Make this (at least somewhat) platform/backend independent.
93+ return SQLitePartialExpandDatabase(
94+ os.path.join(xdg.BaseDirectory.save_data_path("u1todo"),
95+ "u1todo.u1db"))
96+
97+
98 class TodoStore(object):
99 """The todo application backend."""
100
101@@ -70,6 +97,10 @@
102 # database.
103 self.db.put_doc(task.document)
104
105+ def get_all_tasks(self):
106+ return [
107+ Task(doc) for doc in self.db.get_from_index("done", ["*"])]
108+
109
110 class Task(object):
111 """A todo item."""
112
113=== modified file 'u1todo/ui.py'
114--- u1todo/ui.py 2012-04-23 12:59:10 +0000
115+++ u1todo/ui.py 2012-04-23 20:47:18 +0000
116@@ -1,7 +1,22 @@
117+# Copyright 2012 Canonical Ltd.
118+#
119+# This file is part of u1db.
120+#
121+# u1db is free software: you can redistribute it and/or modify
122+# it under the terms of the GNU Lesser General Public License version 3
123+# as published by the Free Software Foundation.
124+#
125+# u1db is distributed in the hope that it will be useful,
126+# but WITHOUT ANY WARRANTY; without even the implied warranty of
127+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128+# GNU Lesser General Public License for more details.
129+#
130+# You should have received a copy of the GNU Lesser General Public License
131+# along with u1db. If not, see <http://www.gnu.org/licenses/>.
132+
133 """User interface for the u1todo example application."""
134
135-from u1db.backends import inmemory
136-from u1todo import TodoStore
137+from u1todo import TodoStore, get_database
138 import os
139 import sys
140 from PyQt4 import QtGui, QtCore, uic
141@@ -21,26 +36,33 @@
142 class Main(QtGui.QMainWindow):
143 """Main window of our application."""
144
145- def __init__(self):
146+ def __init__(self, in_memory=False):
147 super(Main, self).__init__()
148 uifile = os.path.join(os.path.abspath(os.path.dirname(__file__)),
149 'u1todo.ui')
150 uic.loadUi(uifile, self)
151- db = inmemory.InMemoryDatabase("u1todo")
152+ db = get_database()
153 self.store = TodoStore(db)
154+ self.store.initialize_db()
155 self.connect_events()
156 self.item = None
157 self.delete_button.setEnabled(False)
158+ for task in self.store.get_all_tasks():
159+ self.add_task(task)
160
161 def connect_events(self):
162 """Hook up all the signal handlers."""
163- self.connect(
164- self.edit_button, QtCore.SIGNAL("clicked()"), self.update)
165- self.connect(
166- self.delete_button, QtCore.SIGNAL("clicked()"), self.delete)
167- self.connect(
168- self.list_widget, QtCore.SIGNAL("currentRowChanged(int)"),
169- self.row_changed)
170+ self.edit_button.clicked.connect(self.update)
171+ self.delete_button.clicked.connect(self.delete)
172+ self.list_widget.currentRowChanged.connect(self.row_changed)
173+ self.list_widget.itemChanged.connect(self.item_changed)
174+
175+ def item_changed(self, item):
176+ if item.checkState() == QtCore.Qt.Checked:
177+ item.task.done = True
178+ else:
179+ item.task.done = False
180+ self.store.save_task(item.task)
181
182 def update(self):
183 """Either add a new task or update an existing one."""
184@@ -48,9 +70,10 @@
185 if not text:
186 return
187 if self.item is None:
188- self.add_item(text)
189+ task = self.store.new_task(text)
190+ self.add_task(task)
191 else:
192- self.update_item(text)
193+ self.update_task_text(text)
194 self.line_edit.clear()
195 self.item = None
196
197@@ -61,17 +84,20 @@
198 if self.list_widget.count() == 0:
199 self.delete_button.setEnabled(False)
200
201- def add_item(self, text):
202+ def add_task(self, task):
203 """Add a new todo item."""
204- task = self.store.new_task(text)
205 item = UITask(task)
206 self.list_widget.addItem(item)
207 self.delete_button.setEnabled(True)
208
209- def update_item(self, text):
210+ def update_task_text(self, text):
211 """Edit an existing todo item."""
212 self.item.task.title = text
213+ # disconnect the signal temporarily while we change the title
214+ self.list_widget.itemChanged.disconnect(self.item_changed)
215 self.item.setText(text)
216+ # reconnect the signal after we changed the title
217+ self.list_widget.itemChanged.connect(self.item_changed)
218 self.store.save_task(self.item.task)
219
220 def row_changed(self, index):

Subscribers

People subscribed via source and target branches