Merge lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget into lp://qastaging/desktopcouch
- CouchWidget
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | dobey |
Proposed branch: | lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget |
Merge into: | lp://qastaging/desktopcouch |
Diff against target: | None lines |
To merge this branch: | bzr merge lp://qastaging/~rick-rickspencer3/desktopcouch/CouchWidget |
Related bugs: |
This proposal supersedes a proposal from 2009-07-23.
Commit message
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rick Spencer (rick-rickspencer3) wrote : Posted in a previous version of this proposal | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Ken VanDine (ken-vandine) wrote : Posted in a previous version of this proposal | # |
> additional widget code to address bug 403032
If you enter an id that doesn't exist it produces a traceback, you should handle that exception.
Traceback (most recent call last):
File "desktopcouch/
cw.
File "desktopcouch/
raise IndexError("id %s not found" %id)
IndexError: id asd not found
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rick Spencer (rick-rickspencer3) wrote : Posted in a previous version of this proposal | # |
> > additional widget code to address bug 403032
>
> If you enter an id that doesn't exist it produces a traceback, you should
> handle that exception.
>
> Traceback (most recent call last):
> File "desktopcouch/
> cw.selected_
> File "desktopcouch/
> raise IndexError("id %s not found" %id)
> IndexError: id asd not found
Actually, I throw raise that exception myself. From an API design POV, it seems that it shouldn't let the user try to select ids that don't exist.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Rick Spencer (rick-rickspencer3) : Posted in a previous version of this proposal | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
dobey (dobey) wrote : Posted in a previous version of this proposal | # |
> > > additional widget code to address bug 403032
> >
> > If you enter an id that doesn't exist it produces a traceback, you should
> > handle that exception.
> >
> > Traceback (most recent call last):
> > File "desktopcouch/
> > cw.selected_
> > File "desktopcouch/
> selected_record_ids
> > raise IndexError("id %s not found" %id)
> > IndexError: id asd not found
>
> Actually, I throw raise that exception myself. From an API design POV, it
> seems that it shouldn't let the user try to select ids that don't exist.
Raising the exception in the API is probably fine. The test app should handle it by showing a "User doesn't exist" error in the UI or something, I guess. The test app should do pretty much the same thing that any app using the API should do. Then in the future we can test the widget using the test app, and LDTP, so check for expected behaviors better, and avoid having the app exit due to an exception, in the middle of testing.
Unmerged revisions
Preview Diff
1 | === modified file 'desktopcouch/records/couchwidget.py' | |||
2 | --- desktopcouch/records/couchwidget.py 2009-07-15 19:05:43 +0000 | |||
3 | +++ desktopcouch/records/couchwidget.py 2009-07-23 18:00:29 +0000 | |||
4 | @@ -45,6 +45,7 @@ | |||
5 | 45 | self.__record_type = None | 45 | self.__record_type = None |
6 | 46 | self.__headings = None | 46 | self.__headings = None |
7 | 47 | self.__editable = False | 47 | self.__editable = False |
8 | 48 | self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) | ||
9 | 48 | 49 | ||
10 | 49 | @property | 50 | @property |
11 | 50 | def headings(self): | 51 | def headings(self): |
12 | @@ -210,6 +211,96 @@ | |||
13 | 210 | #add it to the list store | 211 | #add it to the list store |
14 | 211 | self.list_store.append(row) | 212 | self.list_store.append(row) |
15 | 212 | 213 | ||
16 | 214 | @property | ||
17 | 215 | def selected_rows(self): | ||
18 | 216 | """ selected_rows - returns a list of dictionaries | ||
19 | 217 | for each row selected. Note that the values are not | ||
20 | 218 | necessarily the complete dictionary for the records, but rather | ||
21 | 219 | are determined by the headings used for the CouchWidget. | ||
22 | 220 | |||
23 | 221 | To get the complete record, use selected_records, or for the record | ||
24 | 222 | ids, use selected_record_ids | ||
25 | 223 | |||
26 | 224 | This property is read only. | ||
27 | 225 | """ | ||
28 | 226 | |||
29 | 227 | #get the selected rows in the ListStore | ||
30 | 228 | selection = self.get_selection() | ||
31 | 229 | model, model_rows = selection.get_selected_rows() | ||
32 | 230 | |||
33 | 231 | rows = [] #list of rows to return | ||
34 | 232 | for mr in model_rows: | ||
35 | 233 | row = {} #a row to be added to the list of rows | ||
36 | 234 | iter = model.get_iter(mr) | ||
37 | 235 | |||
38 | 236 | #get the value for each heading and add it to the row | ||
39 | 237 | for i, h in enumerate(self.headings): | ||
40 | 238 | row[h] = model.get_value(iter,i) | ||
41 | 239 | |||
42 | 240 | #add the row to the list | ||
43 | 241 | rows.append(row) | ||
44 | 242 | return rows | ||
45 | 243 | |||
46 | 244 | @property | ||
47 | 245 | def selected_record_ids(self): | ||
48 | 246 | """ selected_record_ids - a list of document ids that are | ||
49 | 247 | selected in the CouchWidget. Throws an IndexError if | ||
50 | 248 | a specified id is not found in the list when setting | ||
51 | 249 | this property. | ||
52 | 250 | |||
53 | 251 | This property is read/write | ||
54 | 252 | |||
55 | 253 | """ | ||
56 | 254 | |||
57 | 255 | #get the selected rows in the ListStore | ||
58 | 256 | selection = self.get_selection() | ||
59 | 257 | model, model_rows = selection.get_selected_rows() | ||
60 | 258 | |||
61 | 259 | ids = [] # a list of ids to return | ||
62 | 260 | for mr in model_rows: | ||
63 | 261 | iter = model.get_iter(mr) | ||
64 | 262 | |||
65 | 263 | #add the id to the list | ||
66 | 264 | id_index = len(self.headings) #id is always last column | ||
67 | 265 | ids.append(model.get_value(iter,id_index)) | ||
68 | 266 | return ids | ||
69 | 267 | |||
70 | 268 | |||
71 | 269 | @selected_record_ids.setter | ||
72 | 270 | def selected_record_ids(self, indexes): | ||
73 | 271 | rows = [] #a list of rows to select | ||
74 | 272 | for id in indexes: | ||
75 | 273 | id_found = False #track if the id was found | ||
76 | 274 | |||
77 | 275 | for i,r in enumerate(self.list_store): | ||
78 | 276 | id_index = len(self.headings) #id is always last column | ||
79 | 277 | if r[id_index] == id: #id matched in ListModel | ||
80 | 278 | id_found = True #id was good | ||
81 | 279 | if r not in rows: #don't have duplicates to select | ||
82 | 280 | rows.append(i) | ||
83 | 281 | if not id_found: #stop if a requested id was not in the list | ||
84 | 282 | raise IndexError("id %s not found" %id) | ||
85 | 283 | |||
86 | 284 | #select the requested ids | ||
87 | 285 | selection = self.get_selection() | ||
88 | 286 | selection.unselect_all() | ||
89 | 287 | for r in rows: | ||
90 | 288 | selection.select_path(r) | ||
91 | 289 | |||
92 | 290 | @property | ||
93 | 291 | def selected_records(self): | ||
94 | 292 | """ selected_records - returns a list of Record objects | ||
95 | 293 | for those selected in the CouchWidget. | ||
96 | 294 | |||
97 | 295 | This property is read only. | ||
98 | 296 | |||
99 | 297 | """ | ||
100 | 298 | recs = [] #a list of records to return | ||
101 | 299 | for id in self.selected_record_ids: | ||
102 | 300 | #retrieve a record for each id | ||
103 | 301 | recs.append(Record(record_id = id, record_type = self.record_type)) | ||
104 | 302 | return recs | ||
105 | 303 | |||
106 | 213 | def __reset_model(self): | 304 | def __reset_model(self): |
107 | 214 | """ __reset_model - internal funciton, do not call directly. | 305 | """ __reset_model - internal funciton, do not call directly. |
108 | 215 | This function is typically called when properties are set | 306 | This function is typically called when properties are set |
109 | @@ -278,6 +369,27 @@ | |||
110 | 278 | else: #it has been saved | 369 | else: #it has been saved |
111 | 279 | self.__db.update_fields(id,{key:new_text}) | 370 | self.__db.update_fields(id,{key:new_text}) |
112 | 280 | 371 | ||
113 | 372 | def show_selected(widget, widgets): | ||
114 | 373 | """Test function for selection properties of CouchWidget""" | ||
115 | 374 | tv, cw = widgets | ||
116 | 375 | disp = "Rows:\n" | ||
117 | 376 | for r in cw.selected_rows: | ||
118 | 377 | disp += str(r) + "\n" | ||
119 | 378 | |||
120 | 379 | disp += "\n\n_Ids:\n" | ||
121 | 380 | for r in cw.selected_record_ids: | ||
122 | 381 | disp += str(r) + "\n" | ||
123 | 382 | |||
124 | 383 | disp += "\n\nRecords:\n" | ||
125 | 384 | for r in cw.selected_records: | ||
126 | 385 | disp += str(r) + "\n" | ||
127 | 386 | |||
128 | 387 | tv.get_buffer().set_text(disp) | ||
129 | 388 | |||
130 | 389 | def select_ids(widget, widgets): | ||
131 | 390 | entry, cw = widgets | ||
132 | 391 | cw.selected_record_ids = entry.get_text().split(",") | ||
133 | 392 | |||
134 | 281 | if __name__ == "__main__": | 393 | if __name__ == "__main__": |
135 | 282 | """creates a test CouchWidget if called directly""" | 394 | """creates a test CouchWidget if called directly""" |
136 | 283 | 395 | ||
137 | @@ -287,6 +399,11 @@ | |||
138 | 287 | win.connect("destroy",gtk.main_quit) | 399 | win.connect("destroy",gtk.main_quit) |
139 | 288 | win.show() | 400 | win.show() |
140 | 289 | 401 | ||
141 | 402 | #create a top level container | ||
142 | 403 | vbox = gtk.VBox(False, False) | ||
143 | 404 | vbox.show() | ||
144 | 405 | win.add(vbox) | ||
145 | 406 | |||
146 | 290 | #create a test widget with test database values | 407 | #create a test widget with test database values |
147 | 291 | cw = CouchWidget() | 408 | cw = CouchWidget() |
148 | 292 | cw.database = "couch_widget_test" | 409 | cw.database = "couch_widget_test" |
149 | @@ -313,6 +430,35 @@ | |||
150 | 313 | 430 | ||
151 | 314 | #show the control, add it to the window, and run the main loop | 431 | #show the control, add it to the window, and run the main loop |
152 | 315 | cw.show() | 432 | cw.show() |
154 | 316 | win.add(cw) | 433 | vbox.pack_start(cw, False, True) |
155 | 434 | |||
156 | 435 | #create a test display area | ||
157 | 436 | hbox = gtk.HBox(False, 5) | ||
158 | 437 | hbox.show() | ||
159 | 438 | tv = gtk.TextView() | ||
160 | 439 | tv.show() | ||
161 | 440 | cw.connect("cursor-changed",show_selected, (tv,cw)) | ||
162 | 441 | |||
163 | 442 | |||
164 | 443 | #create ui for testing selection | ||
165 | 444 | id_vbox = gtk.VBox(False, 5) | ||
166 | 445 | id_vbox.show() | ||
167 | 446 | |||
168 | 447 | entry = gtk.Entry() | ||
169 | 448 | entry.show() | ||
170 | 449 | |||
171 | 450 | btn = gtk.Button("select ids") | ||
172 | 451 | btn.show() | ||
173 | 452 | btn.connect("clicked", select_ids, (entry,cw)) | ||
174 | 453 | |||
175 | 454 | id_vbox.pack_start(entry, False, False) | ||
176 | 455 | id_vbox.pack_end(btn, False, False) | ||
177 | 456 | |||
178 | 457 | #pack up the window | ||
179 | 458 | hbox.pack_start(tv, False, False) | ||
180 | 459 | vbox.pack_end(hbox, False, False) | ||
181 | 460 | hbox.pack_end(id_vbox, False, False) | ||
182 | 461 | |||
183 | 462 | #run the test app | ||
184 | 317 | gtk.main() | 463 | gtk.main() |
185 | 318 | 464 |
additional widget code to address bug 403032