Merge lp:~nataliabidart/magicicada-gui/list-folders into lp:magicicada-gui

Proposed by Natalia Bidart
Status: Merged
Approved by: Facundo Batista
Approved revision: 43
Merged at revision: 35
Proposed branch: lp:~nataliabidart/magicicada-gui/list-folders
Merge into: lp:magicicada-gui
Diff against target: 1260 lines (+775/-115)
5 files modified
.bzrignore (+1/-0)
data/ui/gui.glade (+449/-40)
magicicada/__init__.py (+70/-10)
magicicada/tests/test_magicicada.py (+253/-65)
magicicada/tests/test_syncdaemon.py (+2/-0)
To merge this branch: bzr merge lp:~nataliabidart/magicicada-gui/list-folders
Reviewer Review Type Date Requested Status
Facundo Batista Approve
Review via email: mp+26447@code.launchpad.net

Description of the change

Implemented Folders and Shares to me functionality.

(Still pending Shares to others)

To post a comment you must log in.
Revision history for this message
Facundo Batista (facundo) wrote :
Download full text (3.2 KiB)

Got some errors (see below).

Also, testing it manually, when the folder/shares buttons become active?

===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_on_volume_clicked

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_on_volume_clicked_handles_none

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_on_volume_clicked_twice

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_volume_are_disabled_until_online

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_volume_are_enabled_until_offline

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_volume_close_emits_response_close

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeError: getattr(): attribute name must be string
===============================================================================
[ERROR]: magicicada.tests.test_magicicada._MagicicadaUIVolumeTestCase.test_volume_dialog_props

Traceback (most recent call last):
  File "/home/facundo/devel/reps/magicicada/review_list-folders/magicicada/tests/test_magicicada.py", line 637, in setUp
    self.volume = getattr(self.ui, self.name)
exceptions.TypeErr...

Read more...

review: Needs Fixing
42. By Natalia Bidart

Making trila avoiding tests for an Abstrac class.

43. By Natalia Bidart

Merged trunk in.

Revision history for this message
Facundo Batista (facundo) wrote :

Now it's ok, but please active the buttons on SD's start.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.bzrignore'
2--- .bzrignore 1970-01-01 00:00:00 +0000
3+++ .bzrignore 2010-05-31 22:49:23 +0000
4@@ -0,0 +1,1 @@
5+_trial_temp
6
7=== modified file 'data/ui/gui.glade'
8--- data/ui/gui.glade 2010-05-27 12:34:26 +0000
9+++ data/ui/gui.glade 2010-05-31 22:49:23 +0000
10@@ -2,33 +2,70 @@
11 <interface>
12 <requires lib="gtk+" version="2.16"/>
13 <!-- interface-naming-policy project-wide -->
14+ <object class="GtkListStore" id="folders_store">
15+ <columns>
16+ <!-- column-name node -->
17+ <column type="gchararray"/>
18+ <!-- column-name path -->
19+ <column type="gchararray"/>
20+ <!-- column-name suggested_path -->
21+ <column type="gchararray"/>
22+ <!-- column-name subscribed -->
23+ <column type="gboolean"/>
24+ <!-- column-name volume -->
25+ <column type="gchararray"/>
26+ </columns>
27+ </object>
28+ <object class="GtkListStore" id="contentq_store">
29+ <columns>
30+ <!-- column-name operation -->
31+ <column type="gchararray"/>
32+ <!-- column-name path -->
33+ <column type="gchararray"/>
34+ <!-- column-name share -->
35+ <column type="gchararray"/>
36+ <!-- column-name node -->
37+ <column type="gchararray"/>
38+ </columns>
39+ </object>
40 <object class="GtkListStore" id="metaq_store">
41 <columns>
42 <!-- column-name operation -->
43 <column type="gchararray"/>
44 <!-- column-name path -->
45 <column type="gchararray"/>
46+ <!-- column-name share -->
47+ <column type="gchararray"/>
48 <!-- column-name node -->
49 <column type="gchararray"/>
50- <!-- column-name share -->
51- <column type="gchararray"/>
52 </columns>
53 </object>
54- <object class="GtkListStore" id="contentq_store">
55+ <object class="GtkListStore" id="shares_to_me_store">
56 <columns>
57- <!-- column-name Operation -->
58- <column type="gchararray"/>
59- <!-- column-name Path -->
60- <column type="gchararray"/>
61- <!-- column-name Node -->
62- <column type="gchararray"/>
63- <!-- column-name Share -->
64+ <!-- column-name accepted -->
65+ <column type="gboolean"/>
66+ <!-- column-name access_level -->
67+ <column type="gchararray"/>
68+ <!-- column-name free_bytes -->
69+ <column type="gchararray"/>
70+ <!-- column-name name -->
71+ <column type="gchararray"/>
72+ <!-- column-name node_id -->
73+ <column type="gchararray"/>
74+ <!-- column-name other_username -->
75+ <column type="gchararray"/>
76+ <!-- column-name other_visible_name -->
77+ <column type="gchararray"/>
78+ <!-- column-name path -->
79+ <column type="gchararray"/>
80+ <!-- column-name volume_id -->
81 <column type="gchararray"/>
82 </columns>
83 </object>
84 <object class="GtkWindow" id="main_window">
85 <property name="width_request">800</property>
86 <property name="height_request">600</property>
87+ <property name="visible">True</property>
88 <property name="title" translatable="yes">Magicicada</property>
89 <property name="window_position">center</property>
90 <signal name="destroy" handler="on_main_window_destroy"/>
91@@ -145,6 +182,71 @@
92 <property name="homogeneous">True</property>
93 </packing>
94 </child>
95+ <child>
96+ <object class="GtkSeparatorToolItem" id="separator">
97+ <property name="visible">True</property>
98+ </object>
99+ <packing>
100+ <property name="expand">False</property>
101+ <property name="homogeneous">True</property>
102+ </packing>
103+ </child>
104+ <child>
105+ <object class="GtkToolButton" id="folders">
106+ <property name="visible">True</property>
107+ <property name="sensitive">False</property>
108+ <property name="label" translatable="yes">Folders</property>
109+ <property name="use_underline">True</property>
110+ <property name="stock_id">gtk-directory</property>
111+ <signal name="clicked" handler="on_folders_clicked"/>
112+ </object>
113+ <packing>
114+ <property name="expand">False</property>
115+ <property name="homogeneous">True</property>
116+ </packing>
117+ </child>
118+ <child>
119+ <object class="GtkToolButton" id="shares_to_me">
120+ <property name="visible">True</property>
121+ <property name="sensitive">False</property>
122+ <property name="label" translatable="yes">Shares to me</property>
123+ <property name="use_underline">True</property>
124+ <property name="stock_id">gtk-network</property>
125+ <signal name="clicked" handler="on_shares_to_me_clicked"/>
126+ </object>
127+ <packing>
128+ <property name="expand">False</property>
129+ <property name="homogeneous">True</property>
130+ </packing>
131+ </child>
132+ <child>
133+ <object class="GtkToolButton" id="shares_to_others">
134+ <property name="visible">True</property>
135+ <property name="sensitive">False</property>
136+ <property name="label" translatable="yes">Shares to others</property>
137+ <property name="use_underline">True</property>
138+ <property name="stock_id">gtk-network</property>
139+ <signal name="clicked" handler="on_shares_to_others_clicked"/>
140+ </object>
141+ <packing>
142+ <property name="expand">False</property>
143+ <property name="homogeneous">True</property>
144+ </packing>
145+ </child>
146+ <child>
147+ <object class="GtkToolButton" id="raw_metadata">
148+ <property name="visible">True</property>
149+ <property name="sensitive">False</property>
150+ <property name="label" translatable="yes">Metadata</property>
151+ <property name="use_underline">True</property>
152+ <property name="stock_id">gtk-find</property>
153+ <signal name="clicked" handler="on_raw_metadata_clicked"/>
154+ </object>
155+ <packing>
156+ <property name="expand">False</property>
157+ <property name="homogeneous">True</property>
158+ </packing>
159+ </child>
160 </object>
161 <packing>
162 <property name="expand">False</property>
163@@ -199,7 +301,6 @@
164 </object>
165 <packing>
166 <property name="expand">False</property>
167- <property name="padding">3</property>
168 <property name="position">0</property>
169 </packing>
170 </child>
171@@ -215,6 +316,7 @@
172 </object>
173 <packing>
174 <property name="expand">False</property>
175+ <property name="padding">3</property>
176 <property name="position">2</property>
177 </packing>
178 </child>
179@@ -279,24 +381,24 @@
180 </object>
181 </child>
182 <child>
183+ <object class="GtkTreeViewColumn" id="metaq_share">
184+ <property name="title">Share</property>
185+ <property name="expand">True</property>
186+ <child>
187+ <object class="GtkCellRendererText" id="cellrenderertext4"/>
188+ <attributes>
189+ <attribute name="text">2</attribute>
190+ </attributes>
191+ </child>
192+ </object>
193+ </child>
194+ <child>
195 <object class="GtkTreeViewColumn" id="metaq_node">
196 <property name="title">Node</property>
197 <property name="expand">True</property>
198 <child>
199 <object class="GtkCellRendererText" id="cellrenderertext3"/>
200 <attributes>
201- <attribute name="text">2</attribute>
202- </attributes>
203- </child>
204- </object>
205- </child>
206- <child>
207- <object class="GtkTreeViewColumn" id="metaq_share">
208- <property name="title">Share</property>
209- <property name="expand">True</property>
210- <child>
211- <object class="GtkCellRendererText" id="cellrenderertext4"/>
212- <attributes>
213 <attribute name="text">3</attribute>
214 </attributes>
215 </child>
216@@ -371,24 +473,24 @@
217 </object>
218 </child>
219 <child>
220+ <object class="GtkTreeViewColumn" id="contentq_share">
221+ <property name="title">Share</property>
222+ <property name="expand">True</property>
223+ <child>
224+ <object class="GtkCellRendererText" id="cellrenderertext8"/>
225+ <attributes>
226+ <attribute name="text">2</attribute>
227+ </attributes>
228+ </child>
229+ </object>
230+ </child>
231+ <child>
232 <object class="GtkTreeViewColumn" id="contentq_node">
233 <property name="title">Node</property>
234 <property name="expand">True</property>
235 <child>
236 <object class="GtkCellRendererText" id="cellrenderertext7"/>
237 <attributes>
238- <attribute name="text">2</attribute>
239- </attributes>
240- </child>
241- </object>
242- </child>
243- <child>
244- <object class="GtkTreeViewColumn" id="contentq_share">
245- <property name="title">Share</property>
246- <property name="expand">True</property>
247- <child>
248- <object class="GtkCellRendererText" id="cellrenderertext8"/>
249- <attributes>
250 <attribute name="text">3</attribute>
251 </attributes>
252 </child>
253@@ -426,13 +528,25 @@
254 <property name="type_hint">normal</property>
255 <property name="has_separator">False</property>
256 <property name="program_name">Magicicada</property>
257- <property name="copyright" translatable="yes">Copyright 2010 Natalia Bidart &lt;natalia.bidart@gmail.com&gt;
258-Copyright 2010 Facundo Batista &lt;facundo@taniquetil.com.ar&gt;
259-</property>
260+ <property name="copyright" translatable="yes">Copyright 2010 Chicharreros
261+Copyright 2010 Natalia Bidart &lt;natalia.bidart@gmail.com&gt;
262+Copyright 2010 Facundo Batista &lt;facundo@taniquetil.com.ar&gt;</property>
263 <property name="website">http://launchpad.net/magicicada</property>
264- <property name="license" translatable="yes">GPL v3.0</property>
265+ <property name="license" translatable="yes">GNU General Public License
266+
267+This program is free software: you can redistribute it and/or modify it
268+under the terms of the GNU General Public License version 3, as published
269+by the Free Software Foundation.
270+
271+This program is distributed in the hope that it will be useful, but
272+WITHOUT ANY WARRANTY; without even the implied warranties of
273+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
274+PURPOSE. See the GNU General Public License for more details.
275+
276+You should have received a copy of the GNU General Public License along
277+with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.</property>
278 <property name="authors">Natalia Bidart &lt;natalia.bidart@gmail.com&gt;
279-Facundo Batista &lt;facundo.batista@gmail.com&gt;</property>
280+Facundo Batista &lt;facundo@taniquetil.com.ar&gt;</property>
281 <child internal-child="vbox">
282 <object class="GtkVBox" id="dialog-vbox1">
283 <property name="visible">True</property>
284@@ -454,4 +568,299 @@
285 </object>
286 </child>
287 </object>
288+ <object class="GtkDialog" id="folders_dialog">
289+ <property name="width_request">600</property>
290+ <property name="height_request">300</property>
291+ <property name="border_width">5</property>
292+ <property name="title" translatable="yes">Folders</property>
293+ <property name="modal">True</property>
294+ <property name="window_position">center</property>
295+ <property name="type_hint">normal</property>
296+ <property name="skip_taskbar_hint">True</property>
297+ <property name="has_separator">False</property>
298+ <child internal-child="vbox">
299+ <object class="GtkVBox" id="dialog-vbox2">
300+ <property name="visible">True</property>
301+ <property name="spacing">2</property>
302+ <child>
303+ <object class="GtkScrolledWindow" id="scrolledwindow3">
304+ <property name="visible">True</property>
305+ <property name="can_focus">True</property>
306+ <property name="hscrollbar_policy">automatic</property>
307+ <child>
308+ <object class="GtkTreeView" id="folders_view">
309+ <property name="visible">True</property>
310+ <property name="can_focus">True</property>
311+ <property name="model">folders_store</property>
312+ <property name="headers_clickable">False</property>
313+ <property name="rules_hint">True</property>
314+ <property name="search_column">0</property>
315+ <property name="enable_grid_lines">both</property>
316+ <property name="enable_tree_lines">True</property>
317+ <child>
318+ <object class="GtkTreeViewColumn" id="folders_node">
319+ <property name="resizable">True</property>
320+ <property name="title">Node</property>
321+ <property name="expand">True</property>
322+ <child>
323+ <object class="GtkCellRendererText" id="cellrenderertext9"/>
324+ <attributes>
325+ <attribute name="text">0</attribute>
326+ </attributes>
327+ </child>
328+ </object>
329+ </child>
330+ <child>
331+ <object class="GtkTreeViewColumn" id="folders_path">
332+ <property name="resizable">True</property>
333+ <property name="title">Path</property>
334+ <property name="expand">True</property>
335+ <child>
336+ <object class="GtkCellRendererText" id="cellrenderertext10"/>
337+ <attributes>
338+ <attribute name="text">1</attribute>
339+ </attributes>
340+ </child>
341+ </object>
342+ </child>
343+ <child>
344+ <object class="GtkTreeViewColumn" id="folders_suggested_path">
345+ <property name="resizable">True</property>
346+ <property name="title">Suggested Path</property>
347+ <property name="expand">True</property>
348+ <child>
349+ <object class="GtkCellRendererText" id="cellrenderertext11"/>
350+ <attributes>
351+ <attribute name="text">2</attribute>
352+ </attributes>
353+ </child>
354+ </object>
355+ </child>
356+ <child>
357+ <object class="GtkTreeViewColumn" id="folders_subscribed">
358+ <property name="resizable">True</property>
359+ <property name="title">Subscribed</property>
360+ <property name="expand">True</property>
361+ <child>
362+ <object class="GtkCellRendererToggle" id="cellrenderertoggle1"/>
363+ <attributes>
364+ <attribute name="active">3</attribute>
365+ </attributes>
366+ </child>
367+ </object>
368+ </child>
369+ <child>
370+ <object class="GtkTreeViewColumn" id="folders_volume">
371+ <property name="resizable">True</property>
372+ <property name="title">Volume</property>
373+ <property name="expand">True</property>
374+ <child>
375+ <object class="GtkCellRendererText" id="cellrenderertext12"/>
376+ <attributes>
377+ <attribute name="text">4</attribute>
378+ </attributes>
379+ </child>
380+ </object>
381+ </child>
382+ </object>
383+ </child>
384+ </object>
385+ <packing>
386+ <property name="position">1</property>
387+ </packing>
388+ </child>
389+ <child internal-child="action_area">
390+ <object class="GtkHButtonBox" id="dialog-action_area2">
391+ <property name="visible">True</property>
392+ <property name="layout_style">end</property>
393+ <child>
394+ <object class="GtkButton" id="folders_close">
395+ <property name="label">gtk-close</property>
396+ <property name="visible">True</property>
397+ <property name="can_focus">False</property>
398+ <property name="receives_default">False</property>
399+ <property name="use_stock">True</property>
400+ <signal name="clicked" handler="on_folders_close_clicked"/>
401+ </object>
402+ <packing>
403+ <property name="expand">False</property>
404+ <property name="fill">False</property>
405+ <property name="position">0</property>
406+ </packing>
407+ </child>
408+ </object>
409+ <packing>
410+ <property name="expand">False</property>
411+ <property name="pack_type">end</property>
412+ <property name="position">0</property>
413+ </packing>
414+ </child>
415+ </object>
416+ </child>
417+ <action-widgets>
418+ <action-widget response="0">folders_close</action-widget>
419+ </action-widgets>
420+ </object>
421+ <object class="GtkDialog" id="shares_to_me_dialog">
422+ <property name="width_request">600</property>
423+ <property name="height_request">300</property>
424+ <property name="border_width">5</property>
425+ <property name="title" translatable="yes">Shares to me</property>
426+ <property name="modal">True</property>
427+ <property name="window_position">center</property>
428+ <property name="type_hint">normal</property>
429+ <property name="has_separator">False</property>
430+ <child internal-child="vbox">
431+ <object class="GtkVBox" id="dialog-vbox3">
432+ <property name="visible">True</property>
433+ <property name="spacing">2</property>
434+ <child>
435+ <object class="GtkScrolledWindow" id="scrolledwindow4">
436+ <property name="visible">True</property>
437+ <property name="can_focus">True</property>
438+ <property name="hscrollbar_policy">automatic</property>
439+ <property name="vscrollbar_policy">automatic</property>
440+ <child>
441+ <object class="GtkTreeView" id="shares_to_me_view">
442+ <property name="visible">True</property>
443+ <property name="can_focus">True</property>
444+ <property name="model">shares_to_me_store</property>
445+ <property name="rules_hint">True</property>
446+ <property name="enable_grid_lines">both</property>
447+ <property name="enable_tree_lines">True</property>
448+ <child>
449+ <object class="GtkTreeViewColumn" id="shares_to_me_name">
450+ <property name="title">Name</property>
451+ <property name="expand">True</property>
452+ <child>
453+ <object class="GtkCellRendererText" id="cellrenderertext15"/>
454+ <attributes>
455+ <attribute name="text">3</attribute>
456+ </attributes>
457+ </child>
458+ </object>
459+ </child>
460+ <child>
461+ <object class="GtkTreeViewColumn" id="shares_to_me_other">
462+ <property name="title">Other</property>
463+ <property name="expand">True</property>
464+ <child>
465+ <object class="GtkCellRendererText" id="cellrenderertext19"/>
466+ <attributes>
467+ <attribute name="text">6</attribute>
468+ </attributes>
469+ </child>
470+ </object>
471+ </child>
472+ <child>
473+ <object class="GtkTreeViewColumn" id="shates_to_me_accepted">
474+ <property name="title">Accepted</property>
475+ <property name="expand">True</property>
476+ <child>
477+ <object class="GtkCellRendererToggle" id="cellrenderertoggle2"/>
478+ <attributes>
479+ <attribute name="activatable">0</attribute>
480+ </attributes>
481+ </child>
482+ </object>
483+ </child>
484+ <child>
485+ <object class="GtkTreeViewColumn" id="shares_to_me_access_level">
486+ <property name="title">Access Level</property>
487+ <property name="expand">True</property>
488+ <child>
489+ <object class="GtkCellRendererText" id="cellrenderertext13"/>
490+ <attributes>
491+ <attribute name="text">1</attribute>
492+ </attributes>
493+ </child>
494+ </object>
495+ </child>
496+ <child>
497+ <object class="GtkTreeViewColumn" id="shares-to_me_free_bytes">
498+ <property name="title">Free bytes</property>
499+ <property name="expand">True</property>
500+ <child>
501+ <object class="GtkCellRendererText" id="cellrenderertext14"/>
502+ <attributes>
503+ <attribute name="text">2</attribute>
504+ </attributes>
505+ </child>
506+ </object>
507+ </child>
508+ <child>
509+ <object class="GtkTreeViewColumn" id="shares_to_me_node">
510+ <property name="title">Node</property>
511+ <property name="expand">True</property>
512+ <child>
513+ <object class="GtkCellRendererText" id="cellrenderertext16"/>
514+ <attributes>
515+ <attribute name="text">4</attribute>
516+ </attributes>
517+ </child>
518+ </object>
519+ </child>
520+ <child>
521+ <object class="GtkTreeViewColumn" id="shares_to_me_path">
522+ <property name="title">Path</property>
523+ <property name="expand">True</property>
524+ <child>
525+ <object class="GtkCellRendererText" id="cellrenderertext18"/>
526+ <attributes>
527+ <attribute name="text">7</attribute>
528+ </attributes>
529+ </child>
530+ </object>
531+ </child>
532+ <child>
533+ <object class="GtkTreeViewColumn" id="shares_to_me_volume">
534+ <property name="title">Volume</property>
535+ <property name="expand">True</property>
536+ <child>
537+ <object class="GtkCellRendererText" id="cellrenderertext17"/>
538+ <attributes>
539+ <attribute name="text">8</attribute>
540+ </attributes>
541+ </child>
542+ </object>
543+ </child>
544+ </object>
545+ </child>
546+ </object>
547+ <packing>
548+ <property name="position">1</property>
549+ </packing>
550+ </child>
551+ <child internal-child="action_area">
552+ <object class="GtkHButtonBox" id="dialog-action_area3">
553+ <property name="visible">True</property>
554+ <property name="layout_style">end</property>
555+ <child>
556+ <object class="GtkButton" id="shares_to_me_close">
557+ <property name="label">gtk-close</property>
558+ <property name="visible">True</property>
559+ <property name="can_focus">True</property>
560+ <property name="receives_default">True</property>
561+ <property name="use_stock">True</property>
562+ <signal name="clicked" handler="on_shares_to_me_close_clicked"/>
563+ </object>
564+ <packing>
565+ <property name="expand">False</property>
566+ <property name="fill">False</property>
567+ <property name="position">0</property>
568+ </packing>
569+ </child>
570+ </object>
571+ <packing>
572+ <property name="expand">False</property>
573+ <property name="pack_type">end</property>
574+ <property name="position">0</property>
575+ </packing>
576+ </child>
577+ </object>
578+ </child>
579+ <action-widgets>
580+ <action-widget response="0">shares_to_me_close</action-widget>
581+ </action-widgets>
582+ </object>
583 </interface>
584
585=== modified file 'magicicada/__init__.py'
586--- magicicada/__init__.py 2010-05-28 12:33:53 +0000
587+++ magicicada/__init__.py 2010-05-31 22:49:23 +0000
588@@ -64,26 +64,37 @@
589
590 widgets = (
591 'start', 'stop', 'connect', 'disconnect', # toolbar buttons
592+ 'folders', 'folders_dialog',
593+ 'folders_store', 'folders_close', # folders
594+ 'shares_to_me', 'shares_to_me_dialog',
595+ 'shares_to_me_store', 'shares_to_me_close', # shares_to_me
596+ 'shares_to_others', # toolbar buttons
597+ 'raw_metadata', # more toolbar buttons
598 'is_started', 'is_connected', 'is_online', # status bar images
599 'status_label', 'status_icon', # status label and systray icon
600 'metaq_view', 'contentq_view', # queues tree views
601 'metaq_store', 'contentq_store', # queues list stores
602- 'main_window', 'about_dialog',
603+ 'about_dialog', # dialogs
604+ 'main_window'
605 )
606 for widget in widgets:
607 obj = self.builder.get_object(widget)
608 setattr(self, widget, obj)
609 assert obj is not None, '%s must not be None' % widget
610
611+ self.volumes = (self.folders, self.shares_to_me, self.shares_to_others)
612+ self.windows = (self.main_window, self.about_dialog,
613+ self.folders_dialog)
614+
615 icon_filename = get_data_file('media', 'logo-016.png')
616+ self._icon = gtk.gdk.pixbuf_new_from_file(icon_filename)
617 self.status_icon.set_from_file(icon_filename)
618- self.main_window.set_icon_from_file(icon_filename)
619+ for w in self.windows:
620+ w.set_icon(self._icon)
621
622 about_filename = get_data_file('media', 'logo-128.png')
623 self.about_dialog.set_logo(gtk.gdk.pixbuf_new_from_file(about_filename))
624
625- self.main_window.show()
626-
627 self.sd = syncdaemon_class()
628 self.sd.on_started_callback = self.on_started
629 self.sd.on_stopped_callback = self.on_stopped
630@@ -95,8 +106,9 @@
631 self.sd.content_queue_changed_callback = self.on_content_queue_changed
632 self.sd.meta_queue_changed_callback = self.on_meta_queue_changed
633
634- self.widget_enabled = lambda w: \
635- w.get_property('visible') and w.is_sensitive()
636+ self.widget_is_visible = lambda w: w.get_property('visible')
637+ self.widget_enabled = lambda w: self.widget_is_visible(w) and \
638+ w.is_sensitive()
639
640 self.update()
641
642@@ -105,8 +117,6 @@
643 def on_main_window_destroy(self, widget, data=None):
644 """Called when the MagicicadaWindow is closed."""
645 # Clean up code for saving application state should be added here.
646- if self.widget_enabled(self.stop):
647- self.on_stop_clicked(self.stop)
648 self.sd.shutdown()
649 self.on_destroy()
650
651@@ -145,9 +155,55 @@
652 self.disconnect.set_sensitive(False)
653 self.sd.disconnect()
654
655+ def on_folders_close_clicked(self, widget, data=None):
656+ """Close the folders dialog."""
657+ self.folders_dialog.response(gtk.RESPONSE_CLOSE)
658+
659+ def on_folders_clicked(self, widget, data=None):
660+ """List user folders."""
661+ items = self.sd.folders
662+ if items is None:
663+ items = []
664+
665+ self.folders_store.clear()
666+ for item in items:
667+ row = (item.node, item.path, item.suggested_path,
668+ item.subscribed, item.volume)
669+ self.folders_store.append(row)
670+
671+ res = self.folders_dialog.run()
672+ self.folders_dialog.hide()
673+
674+ def on_shares_to_me_close_clicked(self, widget, data=None):
675+ """Close the shares_to_me dialog."""
676+ self.shares_to_me_dialog.response(gtk.RESPONSE_CLOSE)
677+
678+ def on_shares_to_me_clicked(self, widget, data=None):
679+ """List shares to the user."""
680+ items = self.sd.shares_to_me
681+ if items is None:
682+ items = []
683+
684+ self.shares_to_me_store.clear()
685+ for item in items:
686+ #free_bytes = 0 if item.free_bytes is None else item.free_bytes
687+ row = (item.accepted, item.access_level, item.free_bytes, item.name,
688+ item.node_id, item.other_username, item.other_visible_name,
689+ item.path, item.volume_id)
690+ self.shares_to_me_store.append(row)
691+
692+ res = self.shares_to_me_dialog.run()
693+ self.shares_to_me_dialog.hide()
694+
695+ def on_shares_to_others_clicked(self, widget, data=None):
696+ """List user shares to others."""
697+
698+ def on_raw_metadata_clicked(self, widget, data=None):
699+ """Show raw metadata for a path choosen by the user."""
700+
701 def on_status_icon_activate(self, widget, data=None):
702 """Systray icon was clicked."""
703- if self.main_window.get_property('visible'):
704+ if self.widget_is_visible(self.main_window):
705 self.main_window.hide()
706 else:
707 self.main_window.show()
708@@ -201,9 +257,13 @@
709 """Callback'ed when syncadaemon is online."""
710 self.is_online.set_sensitive(True)
711 self._activate_indicator(self.is_online)
712+ for v in self.volumes:
713+ v.set_sensitive(True)
714
715 def on_offline(self, *args, **kwargs):
716 """Callback'ed when syncadaemon is offline."""
717+ for v in self.volumes:
718+ v.set_sensitive(False)
719 self._activate_indicator(self.is_online, sensitive=False)
720
721 def on_status_changed(self, name=None, description=None,
722@@ -224,7 +284,7 @@
723 queue_store = getattr(self, '%sq_store' % queue_name)
724 queue_store.clear()
725 for item in items:
726- row = (item.operation, item.path, item.node, item.share)
727+ row = (item.operation, item.path, item.share, item.node)
728 queue_store.append(row)
729
730 if not queue_view.is_sensitive() and len(items) > 0:
731
732=== modified file 'magicicada/tests/test_magicicada.py'
733--- magicicada/tests/test_magicicada.py 2010-05-27 12:21:19 +0000
734+++ magicicada/tests/test_magicicada.py 2010-05-31 22:49:23 +0000
735@@ -20,14 +20,30 @@
736
737 from functools import wraps
738
739+import gobject
740+import gtk
741 import pango
742
743 from twisted.trial.unittest import TestCase
744
745 from magicicada import MagicicadaUI, CONTENT_QUEUE, META_QUEUE, syncdaemon
746-from magicicada.dbusiface import QueueData
747+from magicicada.dbusiface import QueueData, FolderData, ShareData
748 from magicicada.helpers import NO_OP
749
750+def process_gtk_pendings():
751+ while gtk.events_pending(): gtk.main_iteration()
752+
753+def close_dialog((dialog, test)):
754+ """Call the 'test', close 'dialog'."""
755+ try:
756+ process_gtk_pendings()
757+ test()
758+ process_gtk_pendings()
759+ finally:
760+ dialog.response(gtk.RESPONSE_CLOSE)
761+ process_gtk_pendings()
762+ return False # do not be called again
763+
764
765 class FakedSyncdaemon(object):
766 """A faked syncdaemon."""
767@@ -36,6 +52,7 @@
768 self.current_state = syncdaemon.State()
769 self.meta_queue = []
770 self.content_queue = []
771+ self.folders = []
772
773 self.on_started_callback = NO_OP
774 self.on_stopped_callback = NO_OP
775@@ -47,6 +64,7 @@
776 self.content_queue_changed_callback = NO_OP
777 self.meta_queue_changed_callback = NO_OP
778 self.shutdown = NO_OP
779+
780 self.start = lambda: setattr(self.current_state, 'is_started', True)
781 self.quit = lambda: setattr(self.current_state, 'is_started', False)
782 self.connect = lambda: setattr(self.current_state, 'is_connected', True)
783@@ -79,6 +97,35 @@
784 self.ui.on_connect_clicked(self.ui.connect)
785 self.ui.on_connected()
786
787+ def build_some_data(self, data_type, limit=5):
788+ """Build some data using named_tuple 'data_type'."""
789+ attrs = data_type._fields
790+ result = []
791+ for i in xrange(limit):
792+ kwargs = dict([(attr, '%s %i' % (attr, i)) for attr in attrs])
793+ result.append(data_type(**kwargs))
794+ return result
795+
796+ def assert_store_correct(self, store, items):
797+ """Test that 'store' has 'items' as content."""
798+ msg = 'amount of rows for %s must be %s (got %s).'
799+ self.assertEqual(len(store), len(items),
800+ msg % (store, len(items), len(store)))
801+ # assert rows content equal to items content
802+ tree_iter = store.get_iter_root()
803+ tmp = list(reversed(items))
804+ msg = "column %i ('%s') must be '%s' (got '%s' instead)"
805+ while tree_iter is not None:
806+ head = tmp.pop()
807+ for i, field in enumerate(head._fields):
808+ actual, = store.get(tree_iter, i)
809+ expected = getattr(head, field)
810+ if store.get_column_type(i).name == 'gboolean':
811+ expected = bool(expected)
812+ self.assertEqual(expected, actual, msg % (i, field, expected, actual))
813+
814+ tree_iter = store.iter_next(tree_iter)
815+
816 def assert_indicator_disabled(self, indicator):
817 """Test that 'indicator' is not sensitive."""
818 self.assertFalse(indicator.is_sensitive(), 'indicator is not sensitive')
819@@ -114,21 +161,26 @@
820 'syncdaemon.shutdown must be called at destroy time.')
821
822 def test_main_window_is_visible(self):
823- """UI can be created."""
824- self.assertTrue(self.ui.main_window.get_property('visible'))
825+ """UI can be created and main_window is visible."""
826+ self.assertTrue(self.ui.widget_is_visible(self.ui.main_window))
827+
828+ def test_windows_have_correct_icon(self):
829+ """Every window has the icon set."""
830+ for w in self.ui.windows:
831+ self.assertEqual(w.get_icon(), self.ui._icon)
832
833 def test_start_connect_are_visible(self):
834 """Start and Connect buttons are visible."""
835- self.assertTrue(self.ui.start.get_property('visible'))
836+ self.assertTrue(self.ui.widget_is_visible(self.ui.start))
837 self.assertTrue(self.ui.start.is_sensitive())
838
839- self.assertTrue(self.ui.connect.get_property('visible'))
840+ self.assertTrue(self.ui.widget_is_visible(self.ui.connect))
841 self.assertFalse(self.ui.connect.is_sensitive())
842
843 def test_stop_disconnect_are_not_visible(self):
844 """Start and Connect buttons are visible."""
845- self.assertFalse(self.ui.stop.get_property('visible'))
846- self.assertFalse(self.ui.disconnect.get_property('visible'))
847+ self.assertFalse(self.ui.widget_is_visible(self.ui.stop))
848+ self.assertFalse(self.ui.widget_is_visible(self.ui.disconnect))
849
850 def test_indicators_are_non_sensitive(self):
851 """Test default sensitivity for indicators."""
852@@ -151,9 +203,9 @@
853 """Test on_start_clicked."""
854 self.ui.on_start_clicked(self.ui.start)
855
856- self.assertTrue(self.ui.start.get_property('visible'))
857+ self.assertTrue(self.ui.widget_is_visible(self.ui.start))
858 self.assertFalse(self.ui.start.is_sensitive())
859- self.assertFalse(self.ui.stop.get_property('visible'))
860+ self.assertFalse(self.ui.widget_is_visible(self.ui.stop))
861
862 self.assert_indicator_loading(self.ui.is_started)
863 self.assert_indicator_disabled(self.ui.is_connected)
864@@ -170,9 +222,9 @@
865 self.do_start() # need to be started
866 self.ui.on_connect_clicked(self.ui.connect)
867
868- self.assertTrue(self.ui.connect.get_property('visible'))
869+ self.assertTrue(self.ui.widget_is_visible(self.ui.connect))
870 self.assertFalse(self.ui.connect.is_sensitive())
871- self.assertFalse(self.ui.disconnect.get_property('visible'))
872+ self.assertFalse(self.ui.widget_is_visible(self.ui.disconnect))
873
874 self.assert_indicator_ready(self.ui.is_started)
875 self.assert_indicator_loading(self.ui.is_connected)
876@@ -193,13 +245,13 @@
877
878 self.assertFalse(self._called, 'on_disconnect_clicked was not called.')
879
880- self.assertFalse(self.ui.start.get_property('visible'))
881- self.assertTrue(self.ui.stop.get_property('visible'))
882+ self.assertFalse(self.ui.widget_is_visible(self.ui.start))
883+ self.assertTrue(self.ui.widget_is_visible(self.ui.stop))
884 self.assertFalse(self.ui.stop.is_sensitive())
885
886- self.assertTrue(self.ui.connect.get_property('visible'))
887+ self.assertTrue(self.ui.widget_is_visible(self.ui.connect))
888 self.assertFalse(self.ui.connect.is_sensitive())
889- self.assertFalse(self.ui.disconnect.get_property('visible'))
890+ self.assertFalse(self.ui.widget_is_visible(self.ui.disconnect))
891
892 def test_on_stop_clicked_if_connected(self):
893 """Test on_stop_clicked."""
894@@ -220,8 +272,8 @@
895 self.do_connect()
896 self.ui.on_disconnect_clicked(self.ui.disconnect)
897
898- self.assertFalse(self.ui.connect.get_property('visible'))
899- self.assertTrue(self.ui.disconnect.get_property('visible'))
900+ self.assertFalse(self.ui.widget_is_visible(self.ui.connect))
901+ self.assertTrue(self.ui.widget_is_visible(self.ui.disconnect))
902 self.assertFalse(self.ui.disconnect.is_sensitive())
903
904 def test_on_disconnect_clicked_disconnects_syncdaemon(self):
905@@ -237,7 +289,7 @@
906 def test_main_window_is_hid_when_icon_clicked(self):
907 """Main window is hid when the systray icon is clicked."""
908 self.ui.on_status_icon_activate(self.ui.status_icon)
909- self.assertFalse(self.ui.main_window.get_property('visible'),
910+ self.assertFalse(self.ui.widget_is_visible(self.ui.main_window),
911 'main_window should be invisible when icon clicked.')
912
913 def test_main_window_is_shown_when_clicked_after_hidden(self):
914@@ -245,7 +297,7 @@
915 self.ui.on_status_icon_activate(self.ui.status_icon) # hide
916 self.ui.on_status_icon_activate(self.ui.status_icon) # show
917 msg = 'main_window should be visible when icon clicked after hidden.'
918- self.assertTrue(self.ui.main_window.get_property('visible'), msg)
919+ self.assertTrue(self.ui.widget_is_visible(self.ui.main_window), msg)
920
921
922 def skip_abstract_class(test):
923@@ -253,7 +305,7 @@
924 @wraps(test)
925 def inner(klass):
926 """Execute 'test' only if not in an abstract class."""
927- if klass.queue is not None:
928+ if klass.name is not None:
929 test(klass)
930 return inner
931
932@@ -261,54 +313,32 @@
933 class _MagicicadaUIQueueTestCase(MagicicadaUITestCase):
934 """Abstratc UI test cases for queue tree views."""
935
936- queue = None
937+ name = None
938
939 def setUp(self):
940 """Init."""
941 super(_MagicicadaUIQueueTestCase, self).setUp()
942- if self.queue is None:
943+ if self.name is None:
944 return
945 self.sd_changed = getattr(self.ui.sd,
946- '%s_queue_changed_callback' % self.queue)
947+ '%s_queue_changed_callback' % self.name)
948 self.ui_changed = getattr(self.ui,
949- 'on_%s_queue_changed' % self.queue)
950- self.queue_store = getattr(self.ui, '%sq_store' % self.queue)
951- self.queue_view = getattr(self.ui, '%sq_view' % self.queue)
952+ 'on_%s_queue_changed' % self.name)
953+ self.queue_store = getattr(self.ui, '%sq_store' % self.name)
954+ self.queue_view = getattr(self.ui, '%sq_view' % self.name)
955
956 def build_some_data(self, limit=5):
957- """Build some data to pass to queue changed callback and related."""
958- items = []
959- for i in xrange(limit):
960- cq = QueueData(operation='operation %i' % i,
961- path='path %i' % i, node='node %i' % i,
962- share='share %i' % i)
963- items.append(cq)
964- return items
965-
966- def assert_queue_store_correct(self, queue_store, items):
967- """Test that 'queue_store' has 'items' as content."""
968- msg = 'amount of rows for %s must be %s (got %s).'
969- self.assertEqual(len(queue_store), len(items),
970- msg % (queue_store, len(items), len(queue_store)))
971- # assert rows content equal to items content
972- tree_iter = queue_store.get_iter_root()
973- tmp = list(reversed(items))
974- while tree_iter is not None:
975- expected = tmp.pop()
976-
977- op, path, node, share = queue_store.get(tree_iter, 0, 1, 2, 3)
978- self.assertEqual(expected.operation, op)
979- self.assertEqual(expected.path, path)
980- self.assertEqual(expected.node, node)
981- self.assertEqual(expected.share, share)
982-
983- tree_iter = queue_store.iter_next(tree_iter)
984+ """Build some data to act as queue data."""
985+ kwargs = dict(data_type=QueueData, limit=limit)
986+ res = super(_MagicicadaUIQueueTestCase, self).build_some_data(**kwargs)
987+ # operation path share node
988+ return res
989
990 @skip_abstract_class
991 def test_callback_is_connected(self):
992 """Queue changed callback is connected."""
993 self.assertEqual(self.sd_changed, self.ui_changed,
994- '%s queue callback must be set' % self.queue)
995+ '%s queue callback must be set' % self.name)
996
997 @skip_abstract_class
998 def test_model_is_binded(self):
999@@ -316,20 +346,20 @@
1000 actual = self.queue_view.get_model()
1001 msg = 'model for view %s differs from %s'
1002 self.assertEqual(self.queue_store, actual,
1003- msg % (self.queue, self.queue_store))
1004+ msg % (self.name, self.queue_store))
1005
1006 @skip_abstract_class
1007 def test_on_queue_changed_updates_view(self):
1008 """On queue changed the view is updated."""
1009 items = self.build_some_data()
1010 self.sd_changed(items)
1011- self.assert_queue_store_correct(self.queue_store, items)
1012+ self.assert_store_correct(self.queue_store, items)
1013
1014 @skip_abstract_class
1015 def test_on_queue_changed_handles_none(self):
1016 """On queue changed handles None as items."""
1017 self.sd_changed(None)
1018- self.assert_queue_store_correct(self.queue_store, [])
1019+ self.assert_store_correct(self.queue_store, [])
1020
1021 @skip_abstract_class
1022 def test_model_is_cleared_before_updating(self):
1023@@ -356,16 +386,16 @@
1024 def test_update_is_correct_for_queue(self):
1025 """Correctly updates the queue state."""
1026 data = self.build_some_data()
1027- setattr(self.ui.sd, '%s_queue' % self.queue, data)
1028+ setattr(self.ui.sd, '%s_queue' % self.name, data)
1029
1030 self.ui.update()
1031
1032- self.assert_queue_store_correct(self.queue_store, data)
1033+ self.assert_store_correct(self.queue_store, data)
1034
1035 @skip_abstract_class
1036 def test_on_stopped_updates_queue(self):
1037 """On SD stoppped, the UI updates the queue state."""
1038- cb = 'on_%s_queue_changed' % self.queue
1039+ cb = 'on_%s_queue_changed' % self.name
1040 self.patch(self.ui, cb, self.set_called)
1041 self.ui.on_stopped()
1042 self.assertTrue(self._called,
1043@@ -375,13 +405,13 @@
1044 class MagicicadaUIContentQueueTestCase(_MagicicadaUIQueueTestCase):
1045 """UI test cases for content queue view."""
1046
1047- queue = CONTENT_QUEUE
1048+ name = CONTENT_QUEUE
1049
1050
1051 class MagicicadaUIMetaQueueTestCase(_MagicicadaUIQueueTestCase):
1052 """UI test cases for meta queue view."""
1053
1054- queue = META_QUEUE
1055+ name = META_QUEUE
1056
1057
1058 class MagicicadaUIStatusTestCase(MagicicadaUITestCase):
1059@@ -472,7 +502,7 @@
1060
1061
1062 class MagicicadaUIConnectionTestCase(MagicicadaUITestCase):
1063- """UI test cases for."""
1064+ """UI test cases for connection buttons/indicators."""
1065
1066 def assert_indicator_is_updated_correctly(self, indicator):
1067 """Test that correctly updates the 'indicator'."""
1068@@ -503,7 +533,7 @@
1069 else:
1070 self.assertFalse(self.ui.connect.is_sensitive(),
1071 'connect must be disabled when %s' % cs)
1072- self.assertTrue(self.ui.connect.get_property('visible'),
1073+ self.assertTrue(self.ui.widget_is_visible(self.ui.connect),
1074 'connect must be visible when %s' % cs)
1075 actual = self.ui.widget_enabled(getattr(self.ui, indicator))
1076 self.assertFalse(actual,
1077@@ -562,7 +592,7 @@
1078 self.ui.on_stopped()
1079
1080 self.assertTrue(self.ui.start.is_sensitive())
1081- self.assertTrue(self.ui.start.get_property('visible'))
1082+ self.assertTrue(self.ui.widget_is_visible(self.ui.start))
1083 self.assert_indicator_disabled(self.ui.is_started)
1084 self.assert_indicator_disabled(self.ui.is_connected)
1085 self.assert_indicator_disabled(self.ui.is_online)
1086@@ -593,3 +623,161 @@
1087 """Correctly updates the indicators and buttons state."""
1088 for i in ('is_started', 'is_connected', 'is_online'):
1089 self.assert_indicator_is_updated_correctly(i)
1090+
1091+
1092+class _MagicicadaUIVolumeTestCase(MagicicadaUITestCase):
1093+ """Abstract UI test cases for volumes (folders/shares)."""
1094+
1095+ name = None
1096+ data_type = None
1097+
1098+ def setUp(self):
1099+ """Init."""
1100+ super(_MagicicadaUIVolumeTestCase, self).setUp()
1101+ if self.name is None:
1102+ return
1103+ self.volume = getattr(self.ui, self.name)
1104+ self.volume_store = getattr(self.ui, '%s_store' % self.name)
1105+ self.volume_dialog_name = '%s_dialog' % self.name
1106+ self.volume_dialog = getattr(self.ui, self.volume_dialog_name)
1107+ self.on_volume_clicked = getattr(self.ui, 'on_%s_clicked' % self.name)
1108+
1109+ def build_some_data(self, limit=5):
1110+ """Build some data to act as volume."""
1111+ kwargs = dict(data_type=self.data_type, limit=limit)
1112+ res = super(_MagicicadaUIVolumeTestCase, self).build_some_data(**kwargs)
1113+ return res
1114+
1115+ def assert_volume_availability(self, enabled):
1116+ """Check volume availability according to 'enabled'."""
1117+ self.assertTrue(self.ui.widget_is_visible(self.volume),
1118+ '%s should be visible' % self.name)
1119+ sensitive = self.volume.is_sensitive()
1120+ msg = '%s should %sbe sensitive'
1121+ self.assertTrue(sensitive if enabled else not sensitive,
1122+ msg % (self.name, '' if enabled else 'not '))
1123+
1124+ @skip_abstract_class
1125+ def test_volume_are_disabled_until_online(self):
1126+ """Folders and shares are disabled until online."""
1127+ # disabled at startup
1128+ self.assert_volume_availability(enabled=False)
1129+
1130+ # disabled even if connected
1131+ self.do_connect()
1132+ self.assert_volume_availability(enabled=False)
1133+
1134+ # enabled when online
1135+ self.ui.on_online()
1136+ self.assert_volume_availability(enabled=True)
1137+
1138+ @skip_abstract_class
1139+ def test_volume_are_enabled_until_offline(self):
1140+ """Folders and shares are enabled until offline."""
1141+ self.do_connect()
1142+ self.ui.on_online()
1143+
1144+ # disabled when offline
1145+ self.ui.on_offline()
1146+ self.assert_volume_availability(enabled=False)
1147+
1148+ @skip_abstract_class
1149+ def test_volume_close_emits_response_close(self):
1150+ """Test volume close button emits RESPONSE_CLOSE when clicked."""
1151+ self.response = None
1152+ def record_response(value):
1153+ """Record the response received."""
1154+ self.response = value
1155+ self.patch(self.volume_dialog, 'response', record_response)
1156+
1157+ volume_close = '%s_close' % self.name
1158+ getattr(self.ui, volume_close).clicked()
1159+ self.assertEqual(gtk.RESPONSE_CLOSE, self.response,
1160+ '%s should emit RESPONSE_CLOSE.' % volume_close)
1161+
1162+ @skip_abstract_class
1163+ def test_on_volume_clicked(self):
1164+ """Test on_volume_clicked."""
1165+ self.assertFalse(self.ui.widget_is_visible(self.volume_dialog),
1166+ '%s should not be visible.' % self.volume_dialog_name)
1167+
1168+ def test():
1169+ """Perform the test per se before closing the dialog."""
1170+ self.assertTrue(self.ui.widget_is_visible(self.volume_dialog),
1171+ '%s should be visible.' % self.volume_dialog_name)
1172+ self.assert_store_correct(self.volume_store, items)
1173+
1174+ items = self.build_some_data()
1175+ setattr(self.ui.sd, self.name, items)
1176+ gobject.timeout_add(100, close_dialog,
1177+ (self.volume_dialog, test))
1178+ self.on_volume_clicked(self.volume)
1179+
1180+ # dialog was closed already
1181+ self.assertFalse(self.ui.widget_is_visible(self.volume_dialog),
1182+ '%s should not be visible.' % self.volume_dialog_name)
1183+
1184+ @skip_abstract_class
1185+ def test_on_volume_clicked_twice(self):
1186+ """Test on_volume_clicked twice."""
1187+
1188+ def test():
1189+ """Perform the test per se before closing the dialog."""
1190+ self.assertTrue(self.ui.widget_is_visible(self.volume_dialog),
1191+ '%s should be visible.' % self.volume_dialog_name)
1192+ self.assert_store_correct(self.volume_store, items)
1193+
1194+ items = self.build_some_data()
1195+ setattr(self.ui.sd, self.name, items)
1196+
1197+ gobject.timeout_add(100, close_dialog,
1198+ (self.volume_dialog, test))
1199+ self.on_volume_clicked(self.volume)
1200+
1201+ gobject.timeout_add(100, close_dialog,
1202+ (self.volume_dialog, test))
1203+ self.on_volume_clicked(self.volume)
1204+
1205+ @skip_abstract_class
1206+ def test_on_volume_clicked_handles_none(self):
1207+ """On volume clicked handles None as items."""
1208+ setattr(self.ui.sd, self.name, None)
1209+ test = lambda: self.assert_store_correct(self.volume_store, [])
1210+ gobject.timeout_add(100, close_dialog,
1211+ (self.volume_dialog, test))
1212+ self.on_volume_clicked(self.volume)
1213+
1214+ @skip_abstract_class
1215+ def test_volume_dialog_props(self):
1216+ """The volume dialog has correct properties."""
1217+ size = self.volume_dialog.size_request()
1218+ self.assertEquals((600, 300), size)
1219+
1220+ self.assertTrue(self.volume_dialog.get_modal(),
1221+ '%s must be modal.' % self.volume_dialog_name)
1222+
1223+ position = self.volume_dialog.get_property('window-position')
1224+ self.assertEqual(gtk.WIN_POS_CENTER, position,
1225+ '%s must be centered.' % self.volume_dialog_name)
1226+
1227+ actual = self.volume_dialog.get_title()
1228+ expected = self.name.replace('_', ' ').capitalize()
1229+ msg = '%s title must be %s (got %s instead)'
1230+ self.assertEqual(expected, actual,
1231+ msg % (self.volume_dialog_name, expected, actual))
1232+
1233+
1234+class MagicicadaUIFoldersTestCase(_MagicicadaUIVolumeTestCase):
1235+ """UI test cases for folders."""
1236+
1237+ name = 'folders'
1238+ data_type = FolderData # node path suggested_path subscribed volume
1239+
1240+
1241+class MagicicadaUISharesToMeTestCase(_MagicicadaUIVolumeTestCase):
1242+ """UI test cases for shares_to_me."""
1243+
1244+ name = 'shares_to_me'
1245+ data_type = ShareData # accepted access_level free_bytes name node_id
1246+ # other_username other_visible_name path volume_id
1247+
1248
1249=== modified file 'magicicada/tests/test_syncdaemon.py'
1250--- magicicada/tests/test_syncdaemon.py 2010-05-31 00:31:17 +0000
1251+++ magicicada/tests/test_syncdaemon.py 2010-05-31 22:49:23 +0000
1252@@ -306,6 +306,8 @@
1253 class MetaQueueChangedTests(BaseTest):
1254 """Check the MetaQueueChanged handling."""
1255
1256+ timeout = 3
1257+
1258 def setUp(self):
1259 """Set up."""
1260 BaseTest.setUp(self)

Subscribers

People subscribed via source and target branches

to all changes: