Merge lp:~tomdroid-dev/tomdroid/sync-ui into lp:~tomdroid-maintainers/tomdroid/main
- sync-ui
- Merge into main
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Olivier Bilodeau | ||||
Approved revision: | 241 | ||||
Merged at revision: | 186 | ||||
Proposed branch: | lp:~tomdroid-dev/tomdroid/sync-ui | ||||
Merge into: | lp:~tomdroid-maintainers/tomdroid/main | ||||
Diff against target: |
4072 lines (+3072/-290) 40 files modified
.classpath (+3/-0) AndroidManifest.xml (+24/-9) data/tomdroid-4.svg (+612/-0) default.properties (+1/-1) res/anim/pulse.xml (+10/-0) res/drawable/syncbutton_background.xml (+16/-0) res/drawable/syncbutton_background_focus.xml (+4/-0) res/drawable/syncbutton_background_pressed.xml (+4/-0) res/layout/actionbar.xml (+84/-0) res/layout/main.xml (+10/-4) res/layout/main_list_item.xml (+25/-6) res/layout/note_view.xml (+32/-14) res/menu/main.xml (+6/-8) res/values/arrays.xml (+11/-0) res/values/strings.xml (+13/-2) res/xml/preferences.xml (+18/-0) src/org/tomdroid/Note.java (+36/-6) src/org/tomdroid/NoteManager.java (+45/-9) src/org/tomdroid/NoteProvider.java (+5/-2) src/org/tomdroid/sync/ServiceAuth.java (+33/-0) src/org/tomdroid/sync/SyncManager.java (+106/-0) src/org/tomdroid/sync/SyncService.java (+196/-0) src/org/tomdroid/sync/sd/NoteHandler.java (+2/-1) src/org/tomdroid/sync/sd/SdCardSyncService.java (+68/-44) src/org/tomdroid/sync/web/AnonymousConnection.java (+62/-0) src/org/tomdroid/sync/web/OAuthConnection.java (+278/-0) src/org/tomdroid/sync/web/SnowySyncService.java (+232/-0) src/org/tomdroid/sync/web/WebConnection.java (+139/-0) src/org/tomdroid/ui/Actionbar.java (+69/-0) src/org/tomdroid/ui/PreferencesActivity.java (+217/-0) src/org/tomdroid/ui/SyncMessageHandler.java (+158/-0) src/org/tomdroid/ui/Tomdroid.java (+122/-179) src/org/tomdroid/ui/ViewNote.java (+36/-4) src/org/tomdroid/util/NoteContentBuilder.java (+2/-1) src/org/tomdroid/util/NoteListCursorAdapter.java (+113/-0) src/org/tomdroid/util/Preferences.java (+112/-0) src/org/tomdroid/util/XmlUtils.java (+58/-0) src/org/tomdroid/xml/NoteContentHandler.java (+1/-0) tests/org/tomdroid/NoteManagerTest.java (+74/-0) tests/org/tomdroid/NoteTest.java (+35/-0) |
||||
To merge this branch: | bzr merge lp:~tomdroid-dev/tomdroid/sync-ui | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Olivier Bilodeau | Approve | ||
Review via email: mp+33434@code.launchpad.net |
Commit message
Note synchronization support (SD Card and Tomboy Web)
Description of the change
The changes made in the sync-ui branch are of great value to the end users and do not seem to have any obvious bugs. Time to do a 0.4 release!
Not only does the new code introduce a visual progress feedback while syncing, but is also using an Actionbar as lately proposed by the Android developers from Google.
Olivier Bilodeau (plaxx) wrote : | # |
Benoit Garret (benoit.garret) wrote : | # |
It's also my fault the merge hasn't been done before, I haven't followed through with Rodja, mainly due to a lack of time on my part.
1) No new commits have been done on the web-sync branch, so the sync-ui supersedes it. This merge request is the right one.
2) commons-codec is needed by signpost. I pulled everything because it was easier, but I believe only a small set of its functionality is needed. We could rip out the parts that interest us and cut down a lot on the size.
3) When I began working with signpost, a few bugs prevented it from working with snowy and ubuntu one, that's why I kept a patched copy. It's just a matter of looking if there's been a release with the fixes I submitted upstream.
4) As far as I know, only Rodja and I worked on this. I suggest we both go through the files and put the notices on the files we know we created.
- 234. By Rodja
-
Modified copyright headers in files I've worked
- 235. By Benoit Garret
-
Add copyright and license headers in files I've worked on
- 236. By Benoit Garret
-
Removed commons-codec and signpost git, using the jar as bugs with Android have been fixed
Benoit Garret (benoit.garret) wrote : | # |
Every point you've (Olivier) mentioned should be solved now. I originally included commons-codec because the version shipped with Android was buggy and messed with the Authorization headers, but signpost got a custom implementation since then.
You're now welcome to play with the branch ;-), I'm really looking forward to the day this is merged.
Olivier Bilodeau (plaxx) wrote : | # |
Thanks for addressing my concerns quickly. I'll be trying it on my phone in the next couple of day.
Olivier Bilodeau (plaxx) wrote : | # |
Hi guys,
I played with the branch for a couple of minutes tonight. Here are my comments:
5) I upgraded and my notes were all still there. However any attempts to open a note resulted in a parsing error. I'm guessing that something changed about the database. If not db then appending note-content tags or not? I would recommend dropping the database on upgrade. It's easy, notes should be on sdcard because sync never existed and nothing should be only in the db since you can't create content yet (oh and we are not 1.0).
6) I'm also unsure about the sync button.. It was not obvious to me at first that I needed to hit that to sync. It's a bit small and the animation for SD card notes was only a dot blinking in the middle. Is that normal? Nothing turning? But this is minor and could be reworked later.
7) Lastly, I'm unsure about the black text on white background for the note list (I haven't tested notes yet since they crash). It is quite the opposite as most android apps (especially the natives one), well.. at least, on my phone (normal android UI). I might revert these changes unless convinced otherwise (or provide an option?).
By the way, I don't want to sound like I'm dumping all this burden on you guys, I'll look into fixing stuff myself but I don't have time now.
I'll be testing more soon. The sync goodness! I can't wait!
Rodja (trappe) wrote : | # |
Hi Oliver,
Thank you for looking at this branch.
5) I'm not aware of any db schema changes. I guess the issue you experienced happens if you change from sd-card notes to web sync... but I've no time to investigate this further right now. Benoit, could you help?
6a) I have decided to follow Google's blog article about the Twitter App: http://
6b) SD card syncing is very fast so the turning animation is rather a quick jump from 0% to 100%.
7) All newer Google Apps like the Gallery, Android Market, Clock, Google Talk, Google Goggles, ... and the thrid party Apps where Google was involved like Amazon MP3 and the offical Twitter App use a light theme. I think this is a trend Tomdroid should follow.
Olivier Bilodeau (plaxx) wrote : | # |
Quick note to say that I asked about the color changes to the tomdroid-dev mailing list.
Rodja (trappe) wrote : | # |
Hi Oliver,
5) I've now implemented a simple drop of the local database when switching sync methods. Should fix your issue.
I'm not aware of any other issues or ToDo's which may prevent merging. Please tell me if anything else must be done.
Olivier Bilodeau (plaxx) wrote : | # |
Ok, thanks, I'll re-test this week and let you know.
For color and style, based on the feedback, we will move forward with what
you have done.
On Sun, Sep 26, 2010 at 8:16 AM, Rodja <email address hidden> wrote:
> Hi Oliver,
>
> 5) I've now implemented a simple drop of the local database when switching
> sync methods. Should fix your issue.
>
> I'm not aware of any other issues or ToDo's which may prevent merging.
> Please tell me if anything else must be done.
> --
> https:/
> You are reviewing the proposed merge of lp:~tomdroid-dev/tomdroid/sync-ui
> into lp:tomdroid.
>
--
Olivier Bilodeau <email address hidden>
Olivier Bilodeau (plaxx) wrote : | # |
Performed some tests:
- 1.6 emulator SD Card sync - ok
- 1.6 emulator with QA note set (public.img) - ok
- 2.1 emulator SD Card sync - ok
- 2.1 emulator with QA note set (public.img) - ok
- 1.6 ADP1 SD Card sync - ok
- 1.6 ADP1 with personal note set - ok
Tomorrow or saturday I'll be entering release mode. Now, I'm heading for bug triage and building the NEWS file, actually I will need your help for that as I'm afraid some noteworthy changes and contributors will be lost in all the various branches..
Contributors I have for now: Benoit Garret, Rodja Trappe, Matt Stevenson, Guilherme Salgado
NEWS: I'll start something in lp:tomdroid and you guys send me a patch if I'm missing something new or proper attribution.
Anyone tested the recently launched tomboy-online service? I know I will but only after releasing 0.4.0.
Preview Diff
1 | === modified file '.classpath' |
2 | --- .classpath 2010-01-25 05:01:42 +0000 |
3 | +++ .classpath 2010-10-03 12:21:44 +0000 |
4 | @@ -3,5 +3,8 @@ |
5 | <classpathentry kind="src" path="src"/> |
6 | <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> |
7 | <classpathentry kind="src" path="gen"/> |
8 | + <classpathentry kind="lib" path="lib/signpost-core-1.2.1.1.jar"/> |
9 | + <classpathentry kind="lib" path="lib/signpost-commonshttp4-1.2.1.1.jar"/> |
10 | <classpathentry kind="output" path="bin"/> |
11 | + <classpathentry kind="src" path="tests"/> |
12 | </classpath> |
13 | |
14 | === modified file 'AndroidManifest.xml' |
15 | --- AndroidManifest.xml 2010-02-18 04:36:08 +0000 |
16 | +++ AndroidManifest.xml 2010-10-03 12:21:44 +0000 |
17 | @@ -2,14 +2,16 @@ |
18 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
19 | package="org.tomdroid" |
20 | android:versionName="0.3.1" android:versionCode="4"> |
21 | - |
22 | - <uses-sdk android:minSdkVersion="3" /> |
23 | |
24 | + <uses-sdk android:minSdkVersion="3" |
25 | + android:targetSdkVersion="4" /> |
26 | + |
27 | + <supports-screens android:anyDensity="true" /> |
28 | + |
29 | <application |
30 | android:icon="@drawable/icon" |
31 | android:label="@string/app_name" |
32 | - android:debuggable="false" |
33 | - > |
34 | + android:theme="@android:style/Theme.Light.NoTitleBar"> |
35 | |
36 | <activity android:label="@string/app_name" |
37 | android:name=".ui.Tomdroid" |
38 | @@ -19,6 +21,12 @@ |
39 | <action android:name="android.intent.action.MAIN" /> |
40 | <category android:name="android.intent.category.LAUNCHER" /> |
41 | </intent-filter> |
42 | + <intent-filter> |
43 | + <action android:name="android.intent.action.VIEW" /> |
44 | + <category android:name="android.intent.category.DEFAULT" /> |
45 | + <category android:name="android.intent.category.BROWSABLE" /> |
46 | + <data android:scheme="tomdroid" /> |
47 | + </intent-filter> |
48 | </activity> |
49 | |
50 | <activity android:name=".ui.ViewNote"> |
51 | @@ -29,12 +37,19 @@ |
52 | <data android:mimeType="vnd.android.cursor.item/vnd.tomdroid.note" /> |
53 | </intent-filter> |
54 | </activity> |
55 | - |
56 | - |
57 | |
58 | <provider android:name="NoteProvider" |
59 | android:authorities="org.tomdroid.notes" |
60 | /> |
61 | -</application> |
62 | - <uses-permission android:name="android.permission.INTERNET" /> |
63 | -</manifest> |
64 | \ No newline at end of file |
65 | + |
66 | + <activity android:name=".ui.PreferencesActivity" android:label="@string/app_name"> |
67 | + |
68 | + </activity> |
69 | + |
70 | + <uses-library android:name="android.test.runner" /> |
71 | + </application> |
72 | + |
73 | + <uses-permission android:name="android.permission.INTERNET" /> |
74 | +<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="org.tomdroid"></instrumentation> |
75 | + |
76 | +</manifest> |
77 | |
78 | === added file 'data/tomdroid-4.svg' |
79 | --- data/tomdroid-4.svg 1970-01-01 00:00:00 +0000 |
80 | +++ data/tomdroid-4.svg 2010-10-03 12:21:44 +0000 |
81 | @@ -0,0 +1,612 @@ |
82 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
83 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
84 | + |
85 | +<svg |
86 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
87 | + xmlns:cc="http://creativecommons.org/ns#" |
88 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
89 | + xmlns:svg="http://www.w3.org/2000/svg" |
90 | + xmlns="http://www.w3.org/2000/svg" |
91 | + xmlns:xlink="http://www.w3.org/1999/xlink" |
92 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
93 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
94 | + width="48" |
95 | + height="48" |
96 | + id="svg2394" |
97 | + sodipodi:version="0.32" |
98 | + inkscape:version="0.47 r22583" |
99 | + version="1.0" |
100 | + sodipodi:docname="tomdroid-4.png" |
101 | + inkscape:output_extension="org.inkscape.output.svg.inkscape" |
102 | + inkscape:export-filename="/data/code/android/web-sync/res/drawable/tomdroid-4.png" |
103 | + inkscape:export-xdpi="90" |
104 | + inkscape:export-ydpi="90"> |
105 | + <defs |
106 | + id="defs2396"> |
107 | + <inkscape:perspective |
108 | + sodipodi:type="inkscape:persp3d" |
109 | + inkscape:vp_x="0 : 526.18109 : 1" |
110 | + inkscape:vp_y="0 : 1000 : 0" |
111 | + inkscape:vp_z="744.09448 : 526.18109 : 1" |
112 | + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" |
113 | + id="perspective2402" /> |
114 | + <linearGradient |
115 | + id="linearGradient6377"> |
116 | + <stop |
117 | + id="stop6379" |
118 | + offset="0" |
119 | + style="stop-color:#fff27e;stop-opacity:1;" /> |
120 | + <stop |
121 | + id="stop6381" |
122 | + offset="1" |
123 | + style="stop-color:#edd400;stop-opacity:1;" /> |
124 | + </linearGradient> |
125 | + <linearGradient |
126 | + id="linearGradient2966"> |
127 | + <stop |
128 | + style="stop-color:#ffd1d1;stop-opacity:1;" |
129 | + offset="0" |
130 | + id="stop2968" /> |
131 | + <stop |
132 | + id="stop3006" |
133 | + offset="0.5" |
134 | + style="stop-color:#ff1d1d;stop-opacity:1;" /> |
135 | + <stop |
136 | + style="stop-color:#6f0000;stop-opacity:1;" |
137 | + offset="1" |
138 | + id="stop2970" /> |
139 | + </linearGradient> |
140 | + <linearGradient |
141 | + id="linearGradient2974"> |
142 | + <stop |
143 | + style="stop-color:#c1c1c1;stop-opacity:1;" |
144 | + offset="0" |
145 | + id="stop2976" /> |
146 | + <stop |
147 | + style="stop-color:#acacac;stop-opacity:1;" |
148 | + offset="1" |
149 | + id="stop2978" /> |
150 | + </linearGradient> |
151 | + <linearGradient |
152 | + id="linearGradient2994"> |
153 | + <stop |
154 | + style="stop-color:#000000;stop-opacity:1;" |
155 | + offset="0" |
156 | + id="stop2996" /> |
157 | + <stop |
158 | + style="stop-color:#c9c9c9;stop-opacity:1;" |
159 | + offset="1" |
160 | + id="stop2998" /> |
161 | + </linearGradient> |
162 | + <inkscape:perspective |
163 | + id="perspective2705" |
164 | + inkscape:persp3d-origin="24 : 16 : 1" |
165 | + inkscape:vp_z="48 : 24 : 1" |
166 | + inkscape:vp_y="0 : 1000 : 0" |
167 | + inkscape:vp_x="0 : 24 : 1" |
168 | + sodipodi:type="inkscape:persp3d" /> |
169 | + <inkscape:perspective |
170 | + id="perspective3103" |
171 | + inkscape:persp3d-origin="60 : 46.666667 : 1" |
172 | + inkscape:vp_z="120 : 70 : 1" |
173 | + inkscape:vp_y="0 : 1000 : 0" |
174 | + inkscape:vp_x="0 : 70 : 1" |
175 | + sodipodi:type="inkscape:persp3d" /> |
176 | + <radialGradient |
177 | + gradientUnits="userSpaceOnUse" |
178 | + gradientTransform="matrix(1,0,0,0.361345,0,22.29694)" |
179 | + r="5.2591065" |
180 | + fy="31.780704" |
181 | + fx="39.907337" |
182 | + cy="31.780704" |
183 | + cx="39.907337" |
184 | + id="radialGradient6423" |
185 | + xlink:href="#linearGradient6417" |
186 | + inkscape:collect="always" /> |
187 | + <radialGradient |
188 | + gradientUnits="userSpaceOnUse" |
189 | + gradientTransform="matrix(10.88255,-6.454846e-8,0,11.39737,-433.5968,-381.3811)" |
190 | + r="20.21875" |
191 | + fy="35.90107" |
192 | + fx="43.875" |
193 | + cy="35.90107" |
194 | + cx="43.875" |
195 | + id="radialGradient6413" |
196 | + xlink:href="#linearGradient6407" |
197 | + inkscape:collect="always" /> |
198 | + <radialGradient |
199 | + r="21.626934" |
200 | + fy="35.915409" |
201 | + fx="45.150326" |
202 | + cy="35.915409" |
203 | + cx="45.150326" |
204 | + gradientTransform="matrix(1.669712,0,1.702451e-8,1.220484,-30.23773,-11.79928)" |
205 | + gradientUnits="userSpaceOnUse" |
206 | + id="radialGradient6405" |
207 | + xlink:href="#linearGradient6377" |
208 | + inkscape:collect="always" /> |
209 | + <linearGradient |
210 | + gradientUnits="userSpaceOnUse" |
211 | + y2="67.031342" |
212 | + x2="26.130388" |
213 | + y1="14.08672" |
214 | + x1="26.213203" |
215 | + id="linearGradient5615" |
216 | + xlink:href="#linearGradient5609" |
217 | + inkscape:collect="always" /> |
218 | + <linearGradient |
219 | + id="linearGradient5609" |
220 | + inkscape:collect="always"> |
221 | + <stop |
222 | + id="stop5611" |
223 | + offset="0" |
224 | + style="stop-color:white;stop-opacity:1;" /> |
225 | + <stop |
226 | + id="stop5613" |
227 | + offset="1" |
228 | + style="stop-color:white;stop-opacity:0;" /> |
229 | + </linearGradient> |
230 | + <linearGradient |
231 | + id="linearGradient3342"> |
232 | + <stop |
233 | + id="stop3344" |
234 | + offset="0" |
235 | + style="stop-color:#fff27e;stop-opacity:1;" /> |
236 | + <stop |
237 | + id="stop3346" |
238 | + offset="1" |
239 | + style="stop-color:#edd400;stop-opacity:1;" /> |
240 | + </linearGradient> |
241 | + <linearGradient |
242 | + id="linearGradient6407" |
243 | + inkscape:collect="always"> |
244 | + <stop |
245 | + id="stop6409" |
246 | + offset="0" |
247 | + style="stop-color:white;stop-opacity:1;" /> |
248 | + <stop |
249 | + id="stop6411" |
250 | + offset="1" |
251 | + style="stop-color:white;stop-opacity:0;" /> |
252 | + </linearGradient> |
253 | + <linearGradient |
254 | + id="linearGradient6417" |
255 | + inkscape:collect="always"> |
256 | + <stop |
257 | + id="stop6419" |
258 | + offset="0" |
259 | + style="stop-color:black;stop-opacity:1;" /> |
260 | + <stop |
261 | + id="stop6421" |
262 | + offset="1" |
263 | + style="stop-color:black;stop-opacity:0;" /> |
264 | + </linearGradient> |
265 | + <linearGradient |
266 | + id="linearGradient3326"> |
267 | + <stop |
268 | + style="stop-color:#ffd1d1;stop-opacity:1;" |
269 | + offset="0" |
270 | + id="stop3328" /> |
271 | + <stop |
272 | + id="stop3330" |
273 | + offset="0.5" |
274 | + style="stop-color:#ff1d1d;stop-opacity:1;" /> |
275 | + <stop |
276 | + style="stop-color:#6f0000;stop-opacity:1;" |
277 | + offset="1" |
278 | + id="stop3332" /> |
279 | + </linearGradient> |
280 | + <linearGradient |
281 | + id="linearGradient3319"> |
282 | + <stop |
283 | + style="stop-color:#c1c1c1;stop-opacity:1;" |
284 | + offset="0" |
285 | + id="stop3321" /> |
286 | + <stop |
287 | + style="stop-color:#acacac;stop-opacity:1;" |
288 | + offset="1" |
289 | + id="stop3323" /> |
290 | + </linearGradient> |
291 | + <linearGradient |
292 | + inkscape:collect="always" |
293 | + id="linearGradient2984"> |
294 | + <stop |
295 | + style="stop-color:#e7e2b8;stop-opacity:1;" |
296 | + offset="0" |
297 | + id="stop2986" /> |
298 | + <stop |
299 | + style="stop-color:#e7e2b8;stop-opacity:0;" |
300 | + offset="1" |
301 | + id="stop2988" /> |
302 | + </linearGradient> |
303 | + <linearGradient |
304 | + id="linearGradient3308"> |
305 | + <stop |
306 | + style="stop-color:#000000;stop-opacity:1;" |
307 | + offset="0" |
308 | + id="stop3310" /> |
309 | + <stop |
310 | + style="stop-color:#c9c9c9;stop-opacity:1;" |
311 | + offset="1" |
312 | + id="stop3312" /> |
313 | + </linearGradient> |
314 | + <inkscape:perspective |
315 | + id="perspective3305" |
316 | + inkscape:persp3d-origin="24 : 16 : 1" |
317 | + inkscape:vp_z="48 : 24 : 1" |
318 | + inkscape:vp_y="0 : 1000 : 0" |
319 | + inkscape:vp_x="0 : 24 : 1" |
320 | + sodipodi:type="inkscape:persp3d" /> |
321 | + <linearGradient |
322 | + inkscape:collect="always" |
323 | + xlink:href="#linearGradient2966" |
324 | + id="linearGradient4272" |
325 | + gradientUnits="userSpaceOnUse" |
326 | + gradientTransform="translate(-5.669292,0)" |
327 | + x1="48.90625" |
328 | + y1="17.376184" |
329 | + x2="50.988335" |
330 | + y2="22.250591" /> |
331 | + <linearGradient |
332 | + inkscape:collect="always" |
333 | + xlink:href="#linearGradient2974" |
334 | + id="linearGradient4274" |
335 | + gradientUnits="userSpaceOnUse" |
336 | + gradientTransform="translate(-5.669292,0)" |
337 | + x1="46" |
338 | + y1="19.8125" |
339 | + x2="47.6875" |
340 | + y2="22.625" /> |
341 | + <radialGradient |
342 | + inkscape:collect="always" |
343 | + xlink:href="#linearGradient2984" |
344 | + id="radialGradient4276" |
345 | + gradientUnits="userSpaceOnUse" |
346 | + gradientTransform="matrix(2.923565,0,0,2.029717,-61.55532,-27.88417)" |
347 | + cx="29.053354" |
348 | + cy="27.640751" |
349 | + fx="29.053354" |
350 | + fy="27.640751" |
351 | + r="3.2408544" /> |
352 | + <linearGradient |
353 | + inkscape:collect="always" |
354 | + xlink:href="#linearGradient2994" |
355 | + id="linearGradient4278" |
356 | + gradientUnits="userSpaceOnUse" |
357 | + gradientTransform="translate(-5.825542,0.125)" |
358 | + x1="25.71875" |
359 | + y1="31.046875" |
360 | + x2="25.514589" |
361 | + y2="30.703125" /> |
362 | + <inkscape:perspective |
363 | + id="perspective5044" |
364 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
365 | + inkscape:vp_z="1 : 0.5 : 1" |
366 | + inkscape:vp_y="0 : 1000 : 0" |
367 | + inkscape:vp_x="0 : 0.5 : 1" |
368 | + sodipodi:type="inkscape:persp3d" /> |
369 | + <inkscape:perspective |
370 | + id="perspective5252" |
371 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
372 | + inkscape:vp_z="1 : 0.5 : 1" |
373 | + inkscape:vp_y="0 : 1000 : 0" |
374 | + inkscape:vp_x="0 : 0.5 : 1" |
375 | + sodipodi:type="inkscape:persp3d" /> |
376 | + <inkscape:perspective |
377 | + id="perspective5278" |
378 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
379 | + inkscape:vp_z="1 : 0.5 : 1" |
380 | + inkscape:vp_y="0 : 1000 : 0" |
381 | + inkscape:vp_x="0 : 0.5 : 1" |
382 | + sodipodi:type="inkscape:persp3d" /> |
383 | + <inkscape:perspective |
384 | + id="perspective5380" |
385 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
386 | + inkscape:vp_z="1 : 0.5 : 1" |
387 | + inkscape:vp_y="0 : 1000 : 0" |
388 | + inkscape:vp_x="0 : 0.5 : 1" |
389 | + sodipodi:type="inkscape:persp3d" /> |
390 | + <inkscape:perspective |
391 | + id="perspective5404" |
392 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
393 | + inkscape:vp_z="1 : 0.5 : 1" |
394 | + inkscape:vp_y="0 : 1000 : 0" |
395 | + inkscape:vp_x="0 : 0.5 : 1" |
396 | + sodipodi:type="inkscape:persp3d" /> |
397 | + <inkscape:perspective |
398 | + id="perspective5433" |
399 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
400 | + inkscape:vp_z="1 : 0.5 : 1" |
401 | + inkscape:vp_y="0 : 1000 : 0" |
402 | + inkscape:vp_x="0 : 0.5 : 1" |
403 | + sodipodi:type="inkscape:persp3d" /> |
404 | + <inkscape:perspective |
405 | + id="perspective5459" |
406 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
407 | + inkscape:vp_z="1 : 0.5 : 1" |
408 | + inkscape:vp_y="0 : 1000 : 0" |
409 | + inkscape:vp_x="0 : 0.5 : 1" |
410 | + sodipodi:type="inkscape:persp3d" /> |
411 | + <inkscape:perspective |
412 | + id="perspective5509" |
413 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
414 | + inkscape:vp_z="1 : 0.5 : 1" |
415 | + inkscape:vp_y="0 : 1000 : 0" |
416 | + inkscape:vp_x="0 : 0.5 : 1" |
417 | + sodipodi:type="inkscape:persp3d" /> |
418 | + <inkscape:perspective |
419 | + id="perspective5564" |
420 | + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" |
421 | + inkscape:vp_z="1 : 0.5 : 1" |
422 | + inkscape:vp_y="0 : 1000 : 0" |
423 | + inkscape:vp_x="0 : 0.5 : 1" |
424 | + sodipodi:type="inkscape:persp3d" /> |
425 | + </defs> |
426 | + <sodipodi:namedview |
427 | + id="base" |
428 | + pagecolor="#ffffff" |
429 | + bordercolor="#666666" |
430 | + borderopacity="1.0" |
431 | + inkscape:pageopacity="0.0" |
432 | + inkscape:pageshadow="2" |
433 | + inkscape:zoom="7.9195959" |
434 | + inkscape:cx="25.379657" |
435 | + inkscape:cy="34.644751" |
436 | + inkscape:document-units="px" |
437 | + inkscape:current-layer="layer1" |
438 | + showgrid="false" |
439 | + inkscape:window-width="1280" |
440 | + inkscape:window-height="976" |
441 | + inkscape:window-x="0" |
442 | + inkscape:window-y="25" |
443 | + inkscape:window-maximized="1" /> |
444 | + <metadata |
445 | + id="metadata2399"> |
446 | + <rdf:RDF> |
447 | + <cc:Work |
448 | + rdf:about=""> |
449 | + <dc:format>image/svg+xml</dc:format> |
450 | + <dc:type |
451 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
452 | + <dc:title></dc:title> |
453 | + <dc:date>2009-04-02</dc:date> |
454 | + <dc:creator> |
455 | + <cc:Agent> |
456 | + <dc:title>Olivier Bilodeau</dc:title> |
457 | + </cc:Agent> |
458 | + </dc:creator> |
459 | + <dc:description>A mashup of Tomboy's icon and Android's logo. Both available under free licences.</dc:description> |
460 | + </cc:Work> |
461 | + </rdf:RDF> |
462 | + </metadata> |
463 | + <g |
464 | + inkscape:label="Calque 1" |
465 | + inkscape:groupmode="layer" |
466 | + id="layer1"> |
467 | + <g |
468 | + id="g4242" |
469 | + transform="translate(-0.1684169,3.5830001)"> |
470 | + <path |
471 | + sodipodi:nodetypes="ccccccccccc" |
472 | + id="rect1975" |
473 | + d="m 10.301452,14.596007 28.649253,0.353553 c 0.762577,0 1.24391,0.576646 1.376493,1.193837 0,0 4.40133,19.815144 4.40133,19.815144 0,0 0.01246,6.347622 0.01246,6.347622 0,0.661386 -0.613915,1.193837 -1.376492,1.193837 l -37.4768304,0 C 5.1250868,43.5 4.5111713,42.967549 4.5111713,42.306163 L 4.4999999,36.139247 8.9249601,15.789844 c 0.3093592,-0.661386 0.6139156,-1.193837 1.3764919,-1.193837 z" |
474 | + style="fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" /> |
475 | + <rect |
476 | + ry="0.67937863" |
477 | + rx="0.67937863" |
478 | + y="35.957905" |
479 | + x="5.1146202" |
480 | + height="7.0714951" |
481 | + width="39.048077" |
482 | + id="rect2851" |
483 | + style="opacity:0.37078654;fill:#f57900;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /> |
484 | + <path |
485 | + sodipodi:nodetypes="ccccccc" |
486 | + id="path2853" |
487 | + d="m 5.0643333,36.53243 c 0,0 0.1508618,-0.53033 0.704022,-0.574524 l 37.5646027,0 c 0.754309,0 0.804596,0.751301 0.804596,0.751301 0,0 0.0236,-1.619573 -1.283871,-1.619573 l -36.4118845,0 c -1.0057457,0.08839 -1.3774652,0.779883 -1.3774652,1.442796 z" |
488 | + style="opacity:0.16292138;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /> |
489 | + <path |
490 | + id="path4730" |
491 | + d="m 10.3125,15.59375 c -0.151316,0 -0.09946,-0.02674 -0.15625,0.03125 -0.05088,0.05195 -0.155811,0.275085 -0.28125,0.53125 -0.014579,0.02977 -0.016184,0.03029 -0.03125,0.0625 L 5.5,36.125 l 0,0.0625 0,6.125 C 5.5,42.35657 5.572368,42.5 5.875,42.5 l 37.5,0 c 0.302632,0 0.375,-0.143429 0.375,-0.1875 0,0 -0.03035,-6.068147 -0.03125,-6.25 -2.51e-4,-0.0011 4.27e-4,-0.09183 0,-0.09375 C 43.625157,35.547912 39.34375,16.375 39.34375,16.375 39.2872,16.111751 39.174175,15.9375 38.9375,15.9375 l -28.625,-0.34375 z" |
492 | + style="opacity:0.4831461;fill:none;stroke:url(#linearGradient5615);stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" /> |
493 | + <path |
494 | + sodipodi:nodetypes="cccc" |
495 | + id="path6415" |
496 | + d="M 44.194174,35.681088 C 43.814854,34.425759 43.31029,31.880389 43.31029,31.880389 l -8.927222,3.181981 c 5.745243,0 8.573669,-0.265165 9.811106,0.618718 z" |
497 | + style="opacity:0.46629214;fill:url(#radialGradient6423);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /> |
498 | + <path |
499 | + style="fill:url(#radialGradient6405);fill-opacity:1;fill-rule:evenodd;stroke:#c4a000;stroke-width:0.99999964px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" |
500 | + d="m 8.7832195,16.426565 -4.13483,18.029279 c 0,0 21.4716075,0.125001 29.2755775,0.125001 7.980569,0 11.155067,-2.96842 11.155067,-2.96842 0,0 -1.006743,-0.453488 -2.325109,-4.966721 0,0 -2.403785,-10.500389 -2.403785,-10.500389 -0.463441,-1.186401 -0.856206,-1.663669 -1.75639,-1.65625 l -27.78125,0 c -1.7452746,0.03209 -1.7364187,0.835552 -2.0292805,1.9375 z" |
501 | + id="path2524" |
502 | + sodipodi:nodetypes="cczczcccc" /> |
503 | + <path |
504 | + id="path6403" |
505 | + d="m 10.8125,15.5 c -0.640289,0.01823 -0.708297,0.09979 -0.75,0.15625 C 10.01913,15.71497 9.9124269,16.076338 9.75,16.6875 L 5.90625,33.46875 c 1.6944357,0.0098 20.570644,0.125 28.03125,0.125 3.866286,0 6.517278,-0.714302 8.1875,-1.40625 1.054074,-0.436687 1.113325,-0.577029 1.4375,-0.8125 -0.490628,-0.789905 -1.105041,-2.122597 -1.78125,-4.4375 -6.51e-4,-0.02083 -6.51e-4,-0.04167 0,-0.0625 0,0 -2.305929,-10.042349 -2.375,-10.34375 C 39.192263,15.983448 39.024353,15.680487 38.9375,15.59375 38.85065,15.50701 38.86595,15.49776 38.59375,15.5 l -27.75,0 -0.03125,0 z" |
506 | + style="opacity:0.46629214;fill:none;stroke:url(#radialGradient6413);stroke-width:0.99999964px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> |
507 | + <path |
508 | + style="opacity:0.26404497;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
509 | + d="m 5.0643333,38.53243 c 0,0 0.1508618,-0.53033 0.704022,-0.574524 l 37.5646027,0 c 0.754309,0 0.804596,0.751301 0.804596,0.751301 0,0 0.0236,-1.619573 -1.283871,-1.619573 l -36.4118845,0 c -1.0057457,0.08839 -1.3774652,0.779883 -1.3774652,1.442796 z" |
510 | + id="path6359" |
511 | + sodipodi:nodetypes="ccccccc" /> |
512 | + <path |
513 | + sodipodi:nodetypes="ccccccc" |
514 | + id="path6361" |
515 | + d="m 5.0643333,40.53243 c 0,0 0.1508618,-0.53033 0.704022,-0.574524 l 37.5646027,0 c 0.754309,0 0.804596,0.751301 0.804596,0.751301 0,0 0.0236,-1.619573 -1.283871,-1.619573 l -36.4118845,0 c -1.0057457,0.08839 -1.3774652,0.779883 -1.3774652,1.442796 z" |
516 | + style="opacity:0.26404497;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" /> |
517 | + <path |
518 | + style="opacity:0.26404497;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
519 | + d="m 5.0643333,42.53243 c 0,0 0.1508618,-0.53033 0.704022,-0.574524 l 37.5646027,0 c 0.754309,0 0.804596,0.751301 0.804596,0.751301 0,0 0.0236,-1.619573 -1.283871,-1.619573 l -36.4118845,0 c -1.0057457,0.08839 -1.3774652,0.779883 -1.3774652,1.442796 z" |
520 | + id="path6363" |
521 | + sodipodi:nodetypes="ccccccc" /> |
522 | + </g> |
523 | + <g |
524 | + id="g4166-6" |
525 | + transform="matrix(1.0098472,0,0,0.98902752,-298.47562,-483.65964)" |
526 | + style="fill:#c4a000;fill-opacity:1;stroke:none" /> |
527 | + <g |
528 | + id="g3106" |
529 | + inkscape:label="Layer 1" |
530 | + transform="matrix(0.9894224,0,0,0.9894224,86.886011,8.4726515)"> |
531 | + <g |
532 | + transform="translate(-299.00515,-503.07627)" |
533 | + id="g3279" /> |
534 | + </g> |
535 | + <path |
536 | + style="fill:#d40000;fill-opacity:1;stroke:#ffffff;stroke-width:1.70000005;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
537 | + d="m 29.78125,1.0249519 c -0.200346,-0.00693 -0.393078,0.104186 -0.5,0.3125001 l -1.375,2.65625 c -1.068903,-0.3679226 -2.237706,-0.5625 -3.46875,-0.5625 -1.366399,0 -2.652232,0.2394169 -3.8125,0.6875 l -1.40625,-2.75 C 19.076187,1.0909499 18.780186,0.99092944 18.53125,1.1187019 18.282314,1.2464745 18.169937,1.5597 18.3125,1.837452 l 1.40625,2.6875 c -2.563621,1.3037284 -4.28125,3.6451702 -4.28125,6.3125 0,0.224276 0.03887,0.43704 0.0625,0.65625 l 17.875,0 c 0.02363,-0.21921 0.0625,-0.431974 0.0625,-0.65625 0,-2.7740229 -1.857873,-5.1997008 -4.59375,-6.46875 l 1.3125,-2.5625 c 0.142563,-0.277752 0.06144,-0.6222276 -0.1875,-0.7500001 -0.06223,-0.031943 -0.120718,-0.028941 -0.1875,-0.03125 z m -16.875,10.7500001 c -1.101761,0 -2,0.898239 -2,2 l 0,8.40625 c 0,1.101761 0.898239,2 2,2 1.101761,0 1.96875,-0.898239 1.96875,-2 l 0,-8.40625 c 0,-1.101761 -0.866989,-2 -1.96875,-2 z m 22.9375,0.15625 c -1.101761,0 -2,0.866989 -2,1.96875 l 0,8.4375 c 0,1.101761 0.898239,2 2,2 1.101761,0 2,-0.898239 2,-2 l 0,-8.4375 c 0,-1.101761 -0.898239,-1.96875 -2,-1.96875 z m -20.21875,0.1875 0,1.15625 0,0.34375 0,1.4375 0,6.25 0,3.75 c 0,1.19785 0.9584,2.15625 2.15625,2.15625 l 1.4375,0 0,4.625 c 0,0.943048 0.744452,1.6875 1.6875,1.6875 l 0.59375,0 c 0.943048,0 1.71875,-0.744452 1.71875,-1.6875 l 0,-4.625 2.5625,0 0,4.59375 c 0,0.943048 0.775702,1.71875 1.71875,1.71875 l 0.59375,0 c 0.943048,0 1.71875,-0.775702 1.71875,-1.71875 l 0,-4.59375 1.1875,0 c 1.19785,0 2.1875,-0.9584 2.1875,-2.15625 l 0,-3.75 0,-6.25 0,-1.78125 0,-1.15625 -17.5625,0 z" |
538 | + id="rect5365-8" /> |
539 | + <g |
540 | + id="g5488" |
541 | + style="stroke:none" |
542 | + transform="translate(0,0.39995194)"> |
543 | + <path |
544 | + id="rect5365" |
545 | + d="m 15.65625,11.75 0,1.15625 0,0.34375 0,1.4375 0,6.25 0,3.75 c 0,1.19785 0.9584,2.15625 2.15625,2.15625 l 13.21875,0 c 1.19785,0 2.1875,-0.9584 2.1875,-2.15625 l 0,-3.75 0,-6.25 0,-1.78125 0,-1.15625 -17.5625,0 z" |
546 | + style="fill:#97c024;fill-opacity:1;stroke:none" /> |
547 | + <rect |
548 | + rx="1.7022525" |
549 | + y="23.661636" |
550 | + x="19.224466" |
551 | + height="9.5017471" |
552 | + width="4.0090432" |
553 | + id="rect5370" |
554 | + style="fill:#97c024;fill-opacity:1;stroke:none" /> |
555 | + <rect |
556 | + rx="1.7022525" |
557 | + y="23.645853" |
558 | + x="25.80624" |
559 | + height="9.5017471" |
560 | + width="4.0090432" |
561 | + id="rect5370-3" |
562 | + style="fill:#97c024;fill-opacity:1;stroke:none" /> |
563 | + <rect |
564 | + rx="1.9887384" |
565 | + y="11.413537" |
566 | + x="10.922275" |
567 | + height="12.405936" |
568 | + width="3.9774768" |
569 | + id="rect5394" |
570 | + style="fill:#97c024;fill-opacity:1;stroke:none" /> |
571 | + <rect |
572 | + rx="1.9887384" |
573 | + y="11.55559" |
574 | + x="33.871677" |
575 | + height="12.405936" |
576 | + width="3.9774768" |
577 | + id="rect5394-2" |
578 | + style="fill:#97c024;fill-opacity:1;stroke:none" /> |
579 | + <g |
580 | + transform="translate(-0.20025,0)" |
581 | + id="g5481" |
582 | + style="stroke:none"> |
583 | + <path |
584 | + style="fill:#97c024;fill-opacity:1;stroke:none" |
585 | + d="m 24.65625,3.0625 c -4.968725,0 -9,3.3092317 -9,7.40625 0,0.224276 0.03887,0.43704 0.0625,0.65625 l 17.875,0 c 0.02363,-0.21921 0.0625,-0.431974 0.0625,-0.65625 0,-4.0970183 -4.031275,-7.40625 -9,-7.40625 z" |
586 | + id="path5418" /> |
587 | + <path |
588 | + sodipodi:type="arc" |
589 | + style="fill:#ffffff;fill-opacity:1;stroke:none" |
590 | + id="path5449" |
591 | + sodipodi:cx="21.37104" |
592 | + sodipodi:cy="8.3357286" |
593 | + sodipodi:rx="0.78918165" |
594 | + sodipodi:ry="0.77339804" |
595 | + d="m 22.160222,8.3357286 c 0,0.427136 -0.353329,0.7733981 -0.789182,0.7733981 -0.435853,0 -0.789181,-0.3462621 -0.789181,-0.7733981 0,-0.4271359 0.353328,-0.773398 0.789181,-0.773398 0.435853,0 0.789182,0.3462621 0.789182,0.773398 z" |
596 | + transform="matrix(1.0212245,0,0,1.0212245,-1.4154165,-1.4231952)" /> |
597 | + <path |
598 | + sodipodi:type="arc" |
599 | + style="fill:#ffffff;fill-opacity:1;stroke:none" |
600 | + id="path5449-6" |
601 | + sodipodi:cx="21.37104" |
602 | + sodipodi:cy="8.3357286" |
603 | + sodipodi:rx="0.78918165" |
604 | + sodipodi:ry="0.77339804" |
605 | + d="m 22.160222,8.3357286 c 0,0.427136 -0.353329,0.7733981 -0.789182,0.7733981 -0.435853,0 -0.789181,-0.3462621 -0.789181,-0.7733981 0,-0.4271359 0.353328,-0.773398 0.789181,-0.773398 0.435853,0 0.789182,0.3462621 0.789182,0.773398 z" |
606 | + transform="matrix(1.0212245,0,0,1.0212245,6.7121839,-1.4238284)" /> |
607 | + <rect |
608 | + style="fill:#97c024;fill-opacity:1;stroke:none" |
609 | + id="rect5423" |
610 | + width="1.0101534" |
611 | + height="5.0507627" |
612 | + x="15.824705" |
613 | + y="9.2116003" |
614 | + rx="0.50507671" |
615 | + transform="matrix(0.88965349,-0.45663625,0.45663625,0.88965349,0,0)" |
616 | + ry="0.56354231" /> |
617 | + <rect |
618 | + style="fill:#97c024;fill-opacity:1;stroke:none" |
619 | + id="rect5423-6" |
620 | + width="1.0101534" |
621 | + height="5.0507627" |
622 | + x="-27.690969" |
623 | + y="-13.159358" |
624 | + rx="0.50507671" |
625 | + transform="matrix(-0.88965349,-0.45663625,-0.45663625,0.88965349,0,0)" |
626 | + ry="0.56354231" /> |
627 | + </g> |
628 | + </g> |
629 | + <g |
630 | + style="display:inline" |
631 | + id="g1574" |
632 | + transform="matrix(0.7113809,-0.1906141,0.1906141,0.7113809,19.866431,-7.0127809)" |
633 | + inkscape:r_cx="true" |
634 | + inkscape:r_cy="true"> |
635 | + <path |
636 | + transform="translate(-29.75546,19)" |
637 | + sodipodi:nodetypes="cccccc" |
638 | + id="path2960" |
639 | + d="m 17.34116,32.5 5.625,-5.625 20.093749,-9.75 c 3.25,-1.25 5.1875,3.375 2.3125,5 L 25.34116,31.5 l -8,1 z" |
640 | + style="fill:#cb9022;fill-opacity:1;fill-rule:evenodd;stroke:#5c410c;stroke-width:0.93443578;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
641 | + inkscape:r_cx="true" |
642 | + inkscape:r_cy="true" /> |
643 | + <path |
644 | + transform="translate(-29.75546,19)" |
645 | + style="fill:url(#linearGradient4272);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
646 | + d="m 38.330708,20 c 0,0 1.4375,0.09375 2,1.34375 0.579493,1.287761 0,2.65625 0,2.65625 l 5.03125,-2.46875 c 0,0 1.452032,-0.881367 0.65625,-2.84375 -0.784912,-1.935577 -2.6875,-1.15625 -2.6875,-1.15625 l -5,2.46875 z" |
647 | + id="path2964" |
648 | + sodipodi:nodetypes="czcczcc" |
649 | + inkscape:r_cx="true" |
650 | + inkscape:r_cy="true" /> |
651 | + <path |
652 | + transform="translate(-29.75546,19)" |
653 | + sodipodi:nodetypes="czcczcc" |
654 | + id="path2962" |
655 | + d="m 38.330708,20 c 0,0 1.4375,0.09375 2,1.34375 0.579493,1.287761 0,2.65625 0,2.65625 l 2,-1 c 0,0 0.827032,-1.318867 0.21875,-2.6875 C 41.924458,18.90625 40.330708,19 40.330708,19 l -2,1 z" |
656 | + style="fill:url(#linearGradient4274);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
657 | + inkscape:r_cx="true" |
658 | + inkscape:r_cy="true" /> |
659 | + <path |
660 | + transform="translate(-29.75546,19)" |
661 | + sodipodi:nodetypes="cccc" |
662 | + id="path2982" |
663 | + d="m 18.768208,31.78125 4.5,-4.5 c 1.5,0.8125 2.28125,2.15625 1.875,3.71875 l -6.375,0.78125 z" |
664 | + style="fill:url(#radialGradient4276);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
665 | + inkscape:r_cx="true" |
666 | + inkscape:r_cy="true" /> |
667 | + <path |
668 | + transform="translate(-29.75546,19)" |
669 | + sodipodi:nodetypes="cccc" |
670 | + id="path2992" |
671 | + d="m 20.111958,30.375 -1.625,1.59375 2.34375,-0.3125 c 0.21875,-0.71875 -0.1875,-1.0625 -0.71875,-1.28125 z" |
672 | + style="fill:url(#linearGradient4278);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
673 | + inkscape:r_cx="true" |
674 | + inkscape:r_cy="true" /> |
675 | + <path |
676 | + transform="translate(-29.75546,19)" |
677 | + sodipodi:nodetypes="ccccc" |
678 | + id="path3002" |
679 | + d="m 23.268208,27.25 1.5625,1.25 15.38734,-7.31867 C 39.773616,20.325286 38.976281,20.096733 38.314669,20.019068 L 23.268208,27.25 z" |
680 | + style="fill:#ffffff;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
681 | + inkscape:r_cx="true" |
682 | + inkscape:r_cy="true" /> |
683 | + <path |
684 | + transform="translate(-29.75546,19)" |
685 | + sodipodi:nodetypes="ccccc" |
686 | + id="path3004" |
687 | + d="m 25.143208,31.0625 0.1875,-0.75 15.23109,-7.1296 c 0,0 -0.11016,0.613627 -0.215879,0.74935 L 25.143208,31.0625 z" |
688 | + style="fill:#000000;fill-opacity:0.36363639;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" |
689 | + inkscape:r_cx="true" |
690 | + inkscape:r_cy="true" /> |
691 | + </g> |
692 | + </g> |
693 | +</svg> |
694 | |
695 | === modified file 'default.properties' |
696 | --- default.properties 2010-01-25 05:01:42 +0000 |
697 | +++ default.properties 2010-10-03 12:21:44 +0000 |
698 | @@ -10,5 +10,5 @@ |
699 | # Indicates whether an apk should be generated for each density. |
700 | split.density=false |
701 | # Project target. |
702 | -target=android-3 |
703 | +target=android-4 |
704 | apk-configurations= |
705 | |
706 | === added directory 'lib' |
707 | === added file 'lib/signpost-commonshttp4-1.2.1.1.jar' |
708 | Binary files lib/signpost-commonshttp4-1.2.1.1.jar 1970-01-01 00:00:00 +0000 and lib/signpost-commonshttp4-1.2.1.1.jar 2010-10-03 12:21:44 +0000 differ |
709 | === added file 'lib/signpost-core-1.2.1.1.jar' |
710 | Binary files lib/signpost-core-1.2.1.1.jar 1970-01-01 00:00:00 +0000 and lib/signpost-core-1.2.1.1.jar 2010-10-03 12:21:44 +0000 differ |
711 | === added directory 'res/anim' |
712 | === added file 'res/anim/pulse.xml' |
713 | --- res/anim/pulse.xml 1970-01-01 00:00:00 +0000 |
714 | +++ res/anim/pulse.xml 2010-10-03 12:21:44 +0000 |
715 | @@ -0,0 +1,10 @@ |
716 | +<?xml version="1.0" encoding="utf-8"?> |
717 | + |
718 | +<alpha xmlns:android="http://schemas.android.com/apk/res/android" |
719 | + android:interpolator="@android:anim/accelerate_interpolator" |
720 | + android:fromAlpha="0.0" |
721 | + android:toAlpha="1.0" |
722 | + android:duration="500" |
723 | + android:repeatMode="reverse" |
724 | + android:repeatCount="-1" |
725 | + /> |
726 | \ No newline at end of file |
727 | |
728 | === added directory 'res/drawable-hdpi' |
729 | === added file 'res/drawable-hdpi/icon_actionbar_dot.png' |
730 | Binary files res/drawable-hdpi/icon_actionbar_dot.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/icon_actionbar_dot.png 2010-10-03 12:21:44 +0000 differ |
731 | === added file 'res/drawable-hdpi/icon_actionbar_sync.png' |
732 | Binary files res/drawable-hdpi/icon_actionbar_sync.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/icon_actionbar_sync.png 2010-10-03 12:21:44 +0000 differ |
733 | === added file 'res/drawable-hdpi/icon_actionbar_sync_background.png' |
734 | Binary files res/drawable-hdpi/icon_actionbar_sync_background.png 1970-01-01 00:00:00 +0000 and res/drawable-hdpi/icon_actionbar_sync_background.png 2010-10-03 12:21:44 +0000 differ |
735 | === added directory 'res/drawable-mdpi' |
736 | === added file 'res/drawable-mdpi/icon_actionbar_dot.png' |
737 | Binary files res/drawable-mdpi/icon_actionbar_dot.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/icon_actionbar_dot.png 2010-10-03 12:21:44 +0000 differ |
738 | === added file 'res/drawable-mdpi/icon_actionbar_sync.png' |
739 | Binary files res/drawable-mdpi/icon_actionbar_sync.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/icon_actionbar_sync.png 2010-10-03 12:21:44 +0000 differ |
740 | === added file 'res/drawable-mdpi/icon_actionbar_sync_background.png' |
741 | Binary files res/drawable-mdpi/icon_actionbar_sync_background.png 1970-01-01 00:00:00 +0000 and res/drawable-mdpi/icon_actionbar_sync_background.png 2010-10-03 12:21:44 +0000 differ |
742 | === modified file 'res/drawable/icon.png' |
743 | Binary files res/drawable/icon.png 2009-04-03 03:19:35 +0000 and res/drawable/icon.png 2010-10-03 12:21:44 +0000 differ |
744 | === added file 'res/drawable/icon_actionbar_dot.png' |
745 | Binary files res/drawable/icon_actionbar_dot.png 1970-01-01 00:00:00 +0000 and res/drawable/icon_actionbar_dot.png 2010-10-03 12:21:44 +0000 differ |
746 | === added file 'res/drawable/icon_actionbar_sync.png' |
747 | Binary files res/drawable/icon_actionbar_sync.png 1970-01-01 00:00:00 +0000 and res/drawable/icon_actionbar_sync.png 2010-10-03 12:21:44 +0000 differ |
748 | === added file 'res/drawable/icon_actionbar_sync_background.png' |
749 | Binary files res/drawable/icon_actionbar_sync_background.png 1970-01-01 00:00:00 +0000 and res/drawable/icon_actionbar_sync_background.png 2010-10-03 12:21:44 +0000 differ |
750 | === removed file 'res/drawable/icon_sync.png' |
751 | Binary files res/drawable/icon_sync.png 2009-10-03 15:29:03 +0000 and res/drawable/icon_sync.png 1970-01-01 00:00:00 +0000 differ |
752 | === added file 'res/drawable/syncbutton_background.xml' |
753 | --- res/drawable/syncbutton_background.xml 1970-01-01 00:00:00 +0000 |
754 | +++ res/drawable/syncbutton_background.xml 2010-10-03 12:21:44 +0000 |
755 | @@ -0,0 +1,16 @@ |
756 | +<?xml version="1.0" encoding="utf-8"?> |
757 | +<selector |
758 | + xmlns:android="http://schemas.android.com/apk/res/android"> |
759 | + <item |
760 | + android:state_focused="true" |
761 | + android:state_pressed="false" |
762 | + android:drawable="@drawable/syncbutton_background_focus" /> |
763 | + <item |
764 | + android:state_focused="true" |
765 | + android:state_pressed="true" |
766 | + android:drawable="@drawable/syncbutton_background_pressed" /> |
767 | + <item |
768 | + android:state_focused="false" |
769 | + android:state_pressed="true" |
770 | + android:drawable="@drawable/syncbutton_background_pressed" /> |
771 | +</selector> |
772 | \ No newline at end of file |
773 | |
774 | === added file 'res/drawable/syncbutton_background_focus.xml' |
775 | --- res/drawable/syncbutton_background_focus.xml 1970-01-01 00:00:00 +0000 |
776 | +++ res/drawable/syncbutton_background_focus.xml 2010-10-03 12:21:44 +0000 |
777 | @@ -0,0 +1,4 @@ |
778 | +<?xml version="1.0" encoding="utf-8"?> |
779 | +<shape xmlns:android="http://schemas.android.com/apk/res/android"> |
780 | + <solid android:color="#ED6400"/> |
781 | +</shape> |
782 | \ No newline at end of file |
783 | |
784 | === added file 'res/drawable/syncbutton_background_pressed.xml' |
785 | --- res/drawable/syncbutton_background_pressed.xml 1970-01-01 00:00:00 +0000 |
786 | +++ res/drawable/syncbutton_background_pressed.xml 2010-10-03 12:21:44 +0000 |
787 | @@ -0,0 +1,4 @@ |
788 | +<?xml version="1.0" encoding="utf-8"?> |
789 | +<shape xmlns:android="http://schemas.android.com/apk/res/android"> |
790 | + <solid android:color="#EA9F00"/> |
791 | +</shape> |
792 | \ No newline at end of file |
793 | |
794 | === added file 'res/layout/actionbar.xml' |
795 | --- res/layout/actionbar.xml 1970-01-01 00:00:00 +0000 |
796 | +++ res/layout/actionbar.xml 2010-10-03 12:21:44 +0000 |
797 | @@ -0,0 +1,84 @@ |
798 | +<!-- |
799 | + Tomdroid |
800 | + Tomboy on Android |
801 | + http://www.launchpad.net/tomdroid |
802 | + |
803 | + Copyright 2010 Rodja Trappe <mail@rodja.net> |
804 | + |
805 | + This file is part of Tomdroid. |
806 | + |
807 | + Tomdroid is free software: you can redistribute it and/or modify |
808 | + it under the terms of the GNU General Public License as published by |
809 | + the Free Software Foundation, either version 3 of the License, or |
810 | + (at your option) any later version. |
811 | + |
812 | + Tomdroid is distributed in the hope that it will be useful, |
813 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
814 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
815 | + GNU General Public License for more details. |
816 | + |
817 | + You should have received a copy of the GNU General Public License |
818 | + along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
819 | +--> |
820 | +<org.tomdroid.ui.Actionbar |
821 | + xmlns:android="http://schemas.android.com/apk/res/android" |
822 | + android:id="@+id/dhistory_row" |
823 | + android:layout_width="fill_parent" |
824 | + android:layout_height="40dip" |
825 | + android:background="#ddd" |
826 | + android:gravity="center_horizontal" |
827 | + android:orientation="horizontal"> |
828 | + <ImageView |
829 | + android:id="@+id/action_icon" |
830 | + android:src="@drawable/icon" |
831 | + android:layout_height="wrap_content" |
832 | + android:layout_width="wrap_content" |
833 | + android:scaleType="fitStart" |
834 | + android:padding="4dip" |
835 | + /> |
836 | + <TextView |
837 | + android:id="@+id/title" |
838 | + android:text="Tomdroid" |
839 | + android:layout_marginLeft="42dip" |
840 | + android:layout_height="wrap_content" |
841 | + android:layout_width="wrap_content" |
842 | + android:textSize="18dip" |
843 | + android:textStyle="bold" |
844 | + android:textColor="#FF555555" |
845 | + android:singleLine="true" |
846 | + android:ellipsize="marquee" |
847 | + android:fadingEdge="horizontal" |
848 | + android:fadingEdgeLength="5mm" |
849 | + android:paddingTop="10dip" |
850 | + android:paddingRight="30dip" |
851 | + /> |
852 | + <ImageView |
853 | + android:id="@+id/sync" |
854 | + android:src="@drawable/icon_actionbar_sync_background" |
855 | + android:background="@drawable/syncbutton_background" |
856 | + android:layout_alignParentRight="true" |
857 | + android:layout_width="wrap_content" |
858 | + android:layout_height="fill_parent" |
859 | + android:scaleType="center" |
860 | + android:clickable="true" |
861 | + android:focusable="true" |
862 | + /> |
863 | + <ImageView |
864 | + android:id="@+id/syncIcon" |
865 | + android:src="@drawable/icon_actionbar_sync" |
866 | + android:background="#00000000" |
867 | + android:layout_alignParentRight="true" |
868 | + android:layout_width="wrap_content" |
869 | + android:layout_height="fill_parent" |
870 | + android:scaleType="center" |
871 | + /> |
872 | + <ImageView |
873 | + android:id="@+id/sync_dot" |
874 | + android:src="@drawable/icon_actionbar_dot" |
875 | + android:layout_alignParentRight="true" |
876 | + android:layout_width="wrap_content" |
877 | + android:layout_height="fill_parent" |
878 | + android:scaleType="center" |
879 | + android:visibility="invisible" |
880 | + /> |
881 | +</org.tomdroid.ui.Actionbar> |
882 | \ No newline at end of file |
883 | |
884 | === modified file 'res/layout/main.xml' |
885 | --- res/layout/main.xml 2009-09-29 04:42:34 +0000 |
886 | +++ res/layout/main.xml 2010-10-03 12:21:44 +0000 |
887 | @@ -22,17 +22,23 @@ |
888 | along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
889 | --> |
890 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
891 | - android:layout_width="wrap_content" |
892 | - android:layout_height="wrap_content" |
893 | + android:layout_width="fill_parent" |
894 | + android:layout_height="fill_parent" |
895 | + android:orientation="vertical" |
896 | > |
897 | + |
898 | + <include android:id="@+id/actionbar" layout="@layout/actionbar" /> |
899 | |
900 | - <ListView android:id="@+id/android:list" |
901 | + <ListView android:id="@android:id/android:list" |
902 | android:layout_width="fill_parent" |
903 | android:layout_height="fill_parent" |
904 | + android:divider="#00000000" |
905 | + android:dividerHeight="0px" |
906 | + android:cacheColorHint="#ffdddddd" |
907 | /> |
908 | <TextView android:id="@+id/list_empty" |
909 | android:layout_width="wrap_content" |
910 | android:layout_height="wrap_content" |
911 | android:text="@string/strListEmptyNoNotes" |
912 | /> |
913 | -</LinearLayout> |
914 | +</LinearLayout> |
915 | \ No newline at end of file |
916 | |
917 | === modified file 'res/layout/main_list_item.xml' |
918 | --- res/layout/main_list_item.xml 2009-06-23 02:51:17 +0000 |
919 | +++ res/layout/main_list_item.xml 2010-10-03 12:21:44 +0000 |
920 | @@ -21,9 +21,28 @@ |
921 | You should have received a copy of the GNU General Public License |
922 | along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
923 | --> |
924 | -<TextView android:id="@+id/note_title" xmlns:android="http://schemas.android.com/apk/res/android" |
925 | - android:layout_width="fill_parent" |
926 | - android:layout_height="fill_parent" |
927 | - android:textSize="24dp" |
928 | - android:padding="10dip" |
929 | - /> |
930 | +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
931 | + android:orientation="vertical" |
932 | + android:layout_width="fill_parent" |
933 | + android:layout_height="wrap_content" > |
934 | + <TextView android:id="@+id/note_title" xmlns:android="http://schemas.android.com/apk/res/android" |
935 | + android:layout_width="fill_parent" |
936 | + android:layout_height="fill_parent" |
937 | + android:textStyle="bold" |
938 | + android:textColor="#FF555555" |
939 | + android:textSize="18dp" |
940 | + android:paddingTop="5dip" |
941 | + android:paddingLeft="5dip" |
942 | + android:paddingRight="5dip" |
943 | + /> |
944 | + <TextView android:id="@+id/note_date" xmlns:android="http://schemas.android.com/apk/res/android" |
945 | + android:layout_width="fill_parent" |
946 | + android:layout_height="fill_parent" |
947 | + android:textColor="#FF555555" |
948 | + android:textSize="14dp" |
949 | + android:paddingTop="2dip" |
950 | + android:paddingLeft="5dip" |
951 | + android:paddingRight="5dip" |
952 | + android:paddingBottom="5dip" |
953 | + /> |
954 | +</LinearLayout> |
955 | \ No newline at end of file |
956 | |
957 | === modified file 'res/layout/note_view.xml' |
958 | --- res/layout/note_view.xml 2009-06-17 11:02:51 +0000 |
959 | +++ res/layout/note_view.xml 2010-10-03 12:21:44 +0000 |
960 | @@ -21,22 +21,40 @@ |
961 | You should have received a copy of the GNU General Public License |
962 | along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
963 | --> |
964 | - |
965 | +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
966 | + android:layout_width="fill_parent" |
967 | + android:layout_height="fill_parent" |
968 | + android:orientation="vertical" |
969 | + > |
970 | +<include android:id="@+id/actionbar" layout="@layout/actionbar" /> |
971 | <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" |
972 | android:id="@+id/textScroller" |
973 | android:layout_width="fill_parent" |
974 | android:layout_height="fill_parent" |
975 | - > |
976 | - |
977 | - <TextView |
978 | - xmlns:android="http://schemas.android.com/apk/res/android" |
979 | - android:id="@+id/content" |
980 | - android:layout_width="wrap_content" |
981 | - android:layout_height="wrap_content" |
982 | - android:singleLine="false" |
983 | - android:text="@string/strWait" |
984 | - android:padding="10dip" |
985 | - android:textColor="#ffb8bcb8" |
986 | - /> |
987 | - |
988 | + android:background="#ffffffff" |
989 | + > |
990 | + <LinearLayout |
991 | + android:id="@+id/LinearLayout01" |
992 | + android:orientation="vertical" |
993 | + android:layout_width="fill_parent" |
994 | + android:layout_height="fill_parent"> |
995 | + |
996 | + <!-- <TextView |
997 | + android:id="@+id/title" |
998 | + android:layout_width="fill_parent" |
999 | + android:layout_height="wrap_content" |
1000 | + android:padding="10dip" |
1001 | + android:textStyle="bold" />--> |
1002 | + |
1003 | + <TextView |
1004 | + xmlns:android="http://schemas.android.com/apk/res/android" |
1005 | + android:id="@+id/content" |
1006 | + android:layout_width="wrap_content" |
1007 | + android:layout_height="wrap_content" |
1008 | + android:singleLine="false" |
1009 | + android:text="@string/strWait" |
1010 | + android:padding="10dip" |
1011 | + android:textColor="#ffb8bcb8" /> |
1012 | + </LinearLayout> |
1013 | </ScrollView> |
1014 | +</LinearLayout> |
1015 | \ No newline at end of file |
1016 | |
1017 | === modified file 'res/menu/main.xml' |
1018 | --- res/menu/main.xml 2010-01-31 22:30:28 +0000 |
1019 | +++ res/menu/main.xml 2010-10-03 12:21:44 +0000 |
1020 | @@ -23,17 +23,15 @@ |
1021 | --> |
1022 | <menu xmlns:android="http://schemas.android.com/apk/res/android"> |
1023 | |
1024 | - <item |
1025 | - android:icon="@drawable/icon_sync" |
1026 | - android:title="@string/menuSyncWithSD" |
1027 | - android:id="@+id/menuSyncWithSD" |
1028 | - /> |
1029 | - |
1030 | - |
1031 | <item |
1032 | android:icon="@drawable/icon_about" |
1033 | android:title="@string/menuAbout" |
1034 | android:id="@+id/menuAbout" |
1035 | /> |
1036 | - |
1037 | + |
1038 | + |
1039 | + <item |
1040 | + android:icon="@android:drawable/ic_menu_preferences" |
1041 | + android:title="@string/menuPrefs" |
1042 | + android:id="@+id/menuPrefs"/> |
1043 | </menu> |
1044 | |
1045 | === added file 'res/values/arrays.xml' |
1046 | --- res/values/arrays.xml 1970-01-01 00:00:00 +0000 |
1047 | +++ res/values/arrays.xml 2010-10-03 12:21:44 +0000 |
1048 | @@ -0,0 +1,11 @@ |
1049 | +<?xml version="1.0" encoding="utf-8"?> |
1050 | +<resources> |
1051 | +<array name="sortOrderArray"> |
1052 | + <item>sort_date</item> |
1053 | + <item>sort_title</item> |
1054 | +</array> |
1055 | +<array name="sortOrderValues"> |
1056 | + <item>Date Modified</item> |
1057 | + <item>Note Title</item> |
1058 | +</array> |
1059 | +</resources> |
1060 | |
1061 | === modified file 'res/values/strings.xml' |
1062 | --- res/values/strings.xml 2010-01-31 21:54:19 +0000 |
1063 | +++ res/values/strings.xml 2010-10-03 12:21:44 +0000 |
1064 | @@ -33,7 +33,8 @@ |
1065 | the tomdroid/ directory on your sdcard then press \"Menu\" and \"Sync with SD Card\". |
1066 | </string> |
1067 | |
1068 | - <string name="menuSyncWithSD">Sync with SD Card</string> |
1069 | + <string name="menuSync">Sync</string> |
1070 | + <string name="menuPrefs">Settings</string> |
1071 | <string name="menuAbout">About</string> |
1072 | <string name="strWelcome"> |
1073 | Welcome to Tomdroid. |
1074 | @@ -59,5 +60,15 @@ |
1075 | |
1076 | <!-- note-view.xml --> |
1077 | <string name="strWait">Please wait while note loads...</string> |
1078 | - |
1079 | + |
1080 | + <string name="prefSync">Synchronization</string> |
1081 | + |
1082 | + <string name="prefSyncService">Service</string> |
1083 | + <string name="prefSyncServer">Server</string> |
1084 | + <string name="prefAuthenticate">Authenticate</string> |
1085 | + |
1086 | + <string name="prefSyncConnectionFailed">The connection to the server has failed, please check that the address you entered is correct.</string> |
1087 | + <string name="prefServerEmpty">The server address changed but the new value is empty</string> |
1088 | + |
1089 | + |
1090 | </resources> |
1091 | |
1092 | === added directory 'res/xml' |
1093 | === added file 'res/xml/preferences.xml' |
1094 | --- res/xml/preferences.xml 1970-01-01 00:00:00 +0000 |
1095 | +++ res/xml/preferences.xml 2010-10-03 12:21:44 +0000 |
1096 | @@ -0,0 +1,18 @@ |
1097 | +<?xml version="1.0" encoding="utf-8"?> |
1098 | +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
1099 | + |
1100 | + <PreferenceCategory android:title="@string/prefSync"> |
1101 | + |
1102 | + <ListPreference android:title="@string/prefSyncService" |
1103 | + android:dialogTitle="Choose the sync service to use" |
1104 | + android:key="sync_service" |
1105 | + android:defaultValue="tomboy-web"/> |
1106 | + |
1107 | + <EditTextPreference android:key="sync_server" |
1108 | + android:title="@string/prefSyncServer" |
1109 | + android:positiveButtonText="@string/prefAuthenticate" |
1110 | + android:shouldDisableView="true"/> |
1111 | + |
1112 | + </PreferenceCategory> |
1113 | + |
1114 | +</PreferenceScreen> |
1115 | \ No newline at end of file |
1116 | |
1117 | === modified file 'src/org/tomdroid/Note.java' |
1118 | --- src/org/tomdroid/Note.java 2010-02-18 03:58:09 +0000 |
1119 | +++ src/org/tomdroid/Note.java 2010-10-03 12:21:44 +0000 |
1120 | @@ -4,6 +4,7 @@ |
1121 | * http://www.launchpad.net/tomdroid |
1122 | * |
1123 | * Copyright 2008, 2009 Olivier Bilodeau <olivier@bottomlesspit.org> |
1124 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1125 | * |
1126 | * This file is part of Tomdroid. |
1127 | * |
1128 | @@ -26,7 +27,10 @@ |
1129 | import java.util.regex.Matcher; |
1130 | import java.util.regex.Pattern; |
1131 | |
1132 | +import org.json.JSONObject; |
1133 | +import org.json.JSONArray; |
1134 | import org.tomdroid.util.NoteContentBuilder; |
1135 | +import org.tomdroid.util.XmlUtils; |
1136 | |
1137 | import android.os.Handler; |
1138 | import android.text.SpannableStringBuilder; |
1139 | @@ -43,6 +47,7 @@ |
1140 | public static final String MODIFIED_DATE = "modified_date"; |
1141 | public static final String URL = "url"; |
1142 | public static final String FILE = "file"; |
1143 | + public static final String TAGS = "tags"; |
1144 | public static final String NOTE_CONTENT = "content"; |
1145 | |
1146 | // Logging info |
1147 | @@ -52,9 +57,9 @@ |
1148 | // TODO this is a weird yellow that was usable for the android emulator, I must confirm this for real usage |
1149 | public static final int NOTE_HIGHLIGHT_COLOR = 0xFFFFFF77; |
1150 | public static final String NOTE_MONOSPACE_TYPEFACE = "monospace"; |
1151 | - public static final float NOTE_SIZE_SMALL_FACTOR = 0.8f; |
1152 | - public static final float NOTE_SIZE_LARGE_FACTOR = 1.3f; |
1153 | - public static final float NOTE_SIZE_HUGE_FACTOR = 1.6f; |
1154 | + public static final float NOTE_SIZE_SMALL_FACTOR = 1.0f; |
1155 | + public static final float NOTE_SIZE_LARGE_FACTOR = 1.5f; |
1156 | + public static final float NOTE_SIZE_HUGE_FACTOR = 1.8f; |
1157 | |
1158 | // Members |
1159 | private SpannableStringBuilder noteContent; |
1160 | @@ -62,6 +67,7 @@ |
1161 | private String url; |
1162 | private String fileName; |
1163 | private String title; |
1164 | + private String tags; |
1165 | private Time lastChangeDate; |
1166 | private int dbId; |
1167 | private UUID guid; |
1168 | @@ -73,8 +79,32 @@ |
1169 | ".+" + // matches what we are getting rid of |
1170 | "([-\\+]\\d{2}:\\d{2})"); // matches timezone (-xx:xx or +xx:xx) |
1171 | |
1172 | - public Note() {} |
1173 | - |
1174 | + public Note() { |
1175 | + tags = new String(); |
1176 | + } |
1177 | + |
1178 | + public Note(JSONObject json) { |
1179 | + |
1180 | + // These methods return an empty string if the key is not found |
1181 | + setTitle(XmlUtils.unescape(json.optString("title"))); |
1182 | + setGuid(json.optString("guid")); |
1183 | + setLastChangeDate(json.optString("last-change-date")); |
1184 | + setXmlContent(json.optString("note-content")); |
1185 | + JSONArray jtags = json.optJSONArray("tags"); |
1186 | + String tag; |
1187 | + tags = new String(); |
1188 | + if (jtags != null) { |
1189 | + for (int i = 0; i < jtags.length(); i++ ) { |
1190 | + tag = jtags.optString(i); |
1191 | + tags += tag + ","; |
1192 | + } |
1193 | + } |
1194 | + } |
1195 | + |
1196 | + public String getTags() { |
1197 | + return tags; |
1198 | + } |
1199 | + |
1200 | public String getUrl() { |
1201 | return url; |
1202 | } |
1203 | @@ -138,7 +168,7 @@ |
1204 | public void setGuid(String guid) { |
1205 | this.guid = UUID.fromString(guid); |
1206 | } |
1207 | - |
1208 | + |
1209 | // TODO: should this handler passed around evolve into an observer pattern? |
1210 | public SpannableStringBuilder getNoteContent(Handler handler) { |
1211 | |
1212 | |
1213 | === modified file 'src/org/tomdroid/NoteManager.java' |
1214 | --- src/org/tomdroid/NoteManager.java 2010-01-25 05:01:42 +0000 |
1215 | +++ src/org/tomdroid/NoteManager.java 2010-10-03 12:21:44 +0000 |
1216 | @@ -23,12 +23,15 @@ |
1217 | package org.tomdroid; |
1218 | |
1219 | import org.tomdroid.ui.Tomdroid; |
1220 | +import org.tomdroid.util.NoteListCursorAdapter; |
1221 | +import org.tomdroid.util.Preferences; |
1222 | |
1223 | import android.app.Activity; |
1224 | import android.content.ContentResolver; |
1225 | import android.content.ContentValues; |
1226 | import android.database.Cursor; |
1227 | import android.net.Uri; |
1228 | +import android.preference.ListPreference; |
1229 | import android.util.Log; |
1230 | import android.widget.ListAdapter; |
1231 | import android.widget.SimpleCursorAdapter; |
1232 | @@ -36,8 +39,9 @@ |
1233 | public class NoteManager { |
1234 | |
1235 | public static final String[] FULL_PROJECTION = { Note.ID, Note.TITLE, Note.FILE, Note.NOTE_CONTENT, Note.MODIFIED_DATE }; |
1236 | - public static final String[] LIST_PROJECTION = { Note.ID, Note.TITLE }; |
1237 | + public static final String[] LIST_PROJECTION = { Note.ID, Note.TITLE, Note.MODIFIED_DATE }; |
1238 | public static final String[] TITLE_PROJECTION = { Note.TITLE }; |
1239 | + public static final String[] GUID_PROJECTION = { Note.ID, Note.GUID }; |
1240 | public static final String[] ID_PROJECTION = { Note.ID }; |
1241 | public static final String[] EMPTY_PROJECTION = {}; |
1242 | |
1243 | @@ -95,6 +99,7 @@ |
1244 | // Notice that we store the date in UTC because sqlite doesn't handle RFC3339 timezone information |
1245 | values.put(Note.MODIFIED_DATE, note.getLastChangeDate().format3339(false)); |
1246 | values.put(Note.NOTE_CONTENT, note.getXmlContent()); |
1247 | + values.put(Note.TAGS, note.getTags()); |
1248 | |
1249 | if (managedCursor.getCount() == 0) { |
1250 | |
1251 | @@ -113,18 +118,42 @@ |
1252 | } |
1253 | } |
1254 | |
1255 | + public static boolean deleteNote(Activity activity, int id) |
1256 | + { |
1257 | + Uri uri = Uri.parse(Tomdroid.CONTENT_URI+"/"+id); |
1258 | + |
1259 | + ContentResolver cr = activity.getContentResolver(); |
1260 | + int result = cr.delete(uri, null, null); |
1261 | + |
1262 | + if(result > 0) |
1263 | + return true; |
1264 | + else |
1265 | + return false; |
1266 | + } |
1267 | + |
1268 | + public static Cursor getAllNotes(Activity activity, Boolean includeNotebookTemplates) { |
1269 | + // get a cursor representing all notes from the NoteProvider |
1270 | + Uri notes = Tomdroid.CONTENT_URI; |
1271 | + String where = null; |
1272 | + String orderBy; |
1273 | + if (!includeNotebookTemplates) { |
1274 | + where = Note.TAGS + " NOT LIKE '%" + "system:template" + "%'"; |
1275 | + } |
1276 | + orderBy = Note.MODIFIED_DATE + " DESC"; |
1277 | + return activity.managedQuery(notes, LIST_PROJECTION, where, null, orderBy); |
1278 | + } |
1279 | + |
1280 | + |
1281 | public static ListAdapter getListAdapter(Activity activity) { |
1282 | - |
1283 | - // get a cursor representing all notes from the NoteProvider |
1284 | - Uri notes = Tomdroid.CONTENT_URI; |
1285 | - Cursor notesCursor = activity.managedQuery(notes, LIST_PROJECTION, null, null, null); |
1286 | + |
1287 | + Cursor notesCursor = getAllNotes(activity, false); |
1288 | |
1289 | // set up an adapter binding the TITLE field of the cursor to the list item |
1290 | - String[] from = new String[] { Note.TITLE }; |
1291 | - int[] to = new int[] { R.id.note_title }; |
1292 | - return new SimpleCursorAdapter(activity, R.layout.main_list_item, notesCursor, from, to); |
1293 | + String[] from = new String[] { Note.TITLE, Note.MODIFIED_DATE }; |
1294 | + int[] to = new int[] { R.id.note_title, R.id.note_date }; |
1295 | + return new NoteListCursorAdapter(activity, R.layout.main_list_item, notesCursor, from, to); |
1296 | } |
1297 | - |
1298 | + |
1299 | // gets the titles of the notes present in the db, used in ViewNote.buildLinkifyPattern() |
1300 | public static Cursor getTitles(Activity activity) { |
1301 | |
1302 | @@ -132,6 +161,13 @@ |
1303 | return activity.managedQuery(Tomdroid.CONTENT_URI, TITLE_PROJECTION, null, null, null); |
1304 | } |
1305 | |
1306 | + // gets the ids of the notes present in the db, used in SyncService.deleteNotes() |
1307 | + public static Cursor getGuids(Activity activity) { |
1308 | + |
1309 | + // get a cursor containing the notes guids |
1310 | + return activity.managedQuery(Tomdroid.CONTENT_URI, GUID_PROJECTION, null, null, null); |
1311 | + } |
1312 | + |
1313 | public static int getNoteId(Activity activity, String title) { |
1314 | |
1315 | int id = 0; |
1316 | |
1317 | === modified file 'src/org/tomdroid/NoteProvider.java' |
1318 | --- src/org/tomdroid/NoteProvider.java 2010-01-25 05:01:42 +0000 |
1319 | +++ src/org/tomdroid/NoteProvider.java 2010-10-03 12:21:44 +0000 |
1320 | @@ -4,6 +4,7 @@ |
1321 | * http://www.launchpad.net/tomdroid |
1322 | * |
1323 | * Copyright 2009 Olivier Bilodeau <olivier@bottomlesspit.org> |
1324 | + * Copyright 2009 Benoit Garret <benoit.garret_launchpad@gadz.org> |
1325 | * |
1326 | * This file is part of Tomdroid. |
1327 | * |
1328 | @@ -68,7 +69,7 @@ |
1329 | // -- |
1330 | private static final String DATABASE_NAME = "tomdroid-notes.db"; |
1331 | private static final String DB_TABLE_NOTES = "notes"; |
1332 | - private static final int DB_VERSION = 2; |
1333 | + private static final int DB_VERSION = 3; |
1334 | private static final String DEFAULT_SORT_ORDER = Note.MODIFIED_DATE + " DESC"; |
1335 | |
1336 | private static HashMap<String, String> notesProjectionMap; |
1337 | @@ -99,7 +100,8 @@ |
1338 | + Note.TITLE + " TEXT," |
1339 | + Note.FILE + " TEXT," |
1340 | + Note.NOTE_CONTENT + " TEXT," |
1341 | - + Note.MODIFIED_DATE + " STRING" |
1342 | + + Note.MODIFIED_DATE + " STRING," |
1343 | + + Note.TAGS + " STRING" |
1344 | + ");"); |
1345 | } |
1346 | |
1347 | @@ -296,6 +298,7 @@ |
1348 | notesProjectionMap.put(Note.TITLE, Note.TITLE); |
1349 | notesProjectionMap.put(Note.FILE, Note.FILE); |
1350 | notesProjectionMap.put(Note.NOTE_CONTENT, Note.NOTE_CONTENT); |
1351 | + notesProjectionMap.put(Note.TAGS, Note.TAGS); |
1352 | notesProjectionMap.put(Note.MODIFIED_DATE, Note.MODIFIED_DATE); |
1353 | } |
1354 | } |
1355 | |
1356 | === added directory 'src/org/tomdroid/sync' |
1357 | === added file 'src/org/tomdroid/sync/ServiceAuth.java' |
1358 | --- src/org/tomdroid/sync/ServiceAuth.java 1970-01-01 00:00:00 +0000 |
1359 | +++ src/org/tomdroid/sync/ServiceAuth.java 2010-10-03 12:21:44 +0000 |
1360 | @@ -0,0 +1,33 @@ |
1361 | +/* |
1362 | + * Tomdroid |
1363 | + * Tomboy on Android |
1364 | + * http://www.launchpad.net/tomdroid |
1365 | + * |
1366 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1367 | + * |
1368 | + * This file is part of Tomdroid. |
1369 | + * |
1370 | + * Tomdroid is free software: you can redistribute it and/or modify |
1371 | + * it under the terms of the GNU General Public License as published by |
1372 | + * the Free Software Foundation, either version 3 of the License, or |
1373 | + * (at your option) any later version. |
1374 | + * |
1375 | + * Tomdroid is distributed in the hope that it will be useful, |
1376 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1377 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1378 | + * GNU General Public License for more details. |
1379 | + * |
1380 | + * You should have received a copy of the GNU General Public License |
1381 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1382 | + */ |
1383 | +package org.tomdroid.sync; |
1384 | + |
1385 | +import android.net.Uri; |
1386 | +import android.os.Handler; |
1387 | + |
1388 | +public interface ServiceAuth { |
1389 | + |
1390 | + public boolean isConfigured(); |
1391 | + public void getAuthUri(final String server, Handler handler); |
1392 | + public void remoteAuthComplete(Uri uri, Handler handler); |
1393 | +} |
1394 | |
1395 | === added file 'src/org/tomdroid/sync/SyncManager.java' |
1396 | --- src/org/tomdroid/sync/SyncManager.java 1970-01-01 00:00:00 +0000 |
1397 | +++ src/org/tomdroid/sync/SyncManager.java 2010-10-03 12:21:44 +0000 |
1398 | @@ -0,0 +1,106 @@ |
1399 | +/* |
1400 | + * Tomdroid |
1401 | + * Tomboy on Android |
1402 | + * http://www.launchpad.net/tomdroid |
1403 | + * |
1404 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1405 | + * |
1406 | + * This file is part of Tomdroid. |
1407 | + * |
1408 | + * Tomdroid is free software: you can redistribute it and/or modify |
1409 | + * it under the terms of the GNU General Public License as published by |
1410 | + * the Free Software Foundation, either version 3 of the License, or |
1411 | + * (at your option) any later version. |
1412 | + * |
1413 | + * Tomdroid is distributed in the hope that it will be useful, |
1414 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1415 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1416 | + * GNU General Public License for more details. |
1417 | + * |
1418 | + * You should have received a copy of the GNU General Public License |
1419 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1420 | + */ |
1421 | +package org.tomdroid.sync; |
1422 | + |
1423 | +import java.io.FileNotFoundException; |
1424 | +import java.util.ArrayList; |
1425 | + |
1426 | +import org.tomdroid.sync.sd.SdCardSyncService; |
1427 | +import org.tomdroid.sync.web.SnowySyncService; |
1428 | +import org.tomdroid.util.Preferences; |
1429 | + |
1430 | +import android.app.Activity; |
1431 | +import android.os.Handler; |
1432 | +import android.util.Log; |
1433 | + |
1434 | +public class SyncManager { |
1435 | + |
1436 | + private static final String TAG = "SyncManager"; |
1437 | + |
1438 | + private ArrayList<SyncService> services = new ArrayList<SyncService>(); |
1439 | + |
1440 | + public SyncManager() { |
1441 | + createServices(); |
1442 | + } |
1443 | + |
1444 | + public ArrayList<SyncService> getServices() { |
1445 | + return services; |
1446 | + } |
1447 | + |
1448 | + public SyncService getService(String name) { |
1449 | + |
1450 | + for (int i = 0; i < services.size(); i++) { |
1451 | + SyncService service = services.get(i); |
1452 | + if (name.equals(service.getName())) |
1453 | + return service; |
1454 | + } |
1455 | + |
1456 | + return null; |
1457 | + } |
1458 | + |
1459 | + public void startSynchronization() { |
1460 | + |
1461 | + SyncService service = getCurrentService(); |
1462 | + service.startSynchronization(); |
1463 | + } |
1464 | + |
1465 | + public SyncService getCurrentService() { |
1466 | + String serviceName = Preferences.getString(Preferences.Key.SYNC_SERVICE); |
1467 | + return getService(serviceName); |
1468 | + } |
1469 | + |
1470 | + private static SyncManager instance = null; |
1471 | + private static Activity activity; |
1472 | + private static Handler handler; |
1473 | + |
1474 | + public static SyncManager getInstance() { |
1475 | + |
1476 | + if (instance == null) |
1477 | + instance = new SyncManager(); |
1478 | + |
1479 | + return instance; |
1480 | + } |
1481 | + |
1482 | + public static void setActivity(Activity a) { |
1483 | + activity = a; |
1484 | + getInstance().createServices(); |
1485 | + } |
1486 | + |
1487 | + public static void setHandler(Handler h) { |
1488 | + handler = h; |
1489 | + getInstance().createServices(); |
1490 | + } |
1491 | + |
1492 | + private void createServices() { |
1493 | + services.clear(); |
1494 | + |
1495 | + services.add(new SnowySyncService(activity, handler)); |
1496 | + |
1497 | + try { |
1498 | + services.add(new SdCardSyncService(activity, handler)); |
1499 | + } catch (FileNotFoundException e) { |
1500 | + // TODO Auto-generated catch block |
1501 | + e.printStackTrace(); |
1502 | + } |
1503 | + } |
1504 | +} |
1505 | |
1506 | === added file 'src/org/tomdroid/sync/SyncService.java' |
1507 | --- src/org/tomdroid/sync/SyncService.java 1970-01-01 00:00:00 +0000 |
1508 | +++ src/org/tomdroid/sync/SyncService.java 2010-10-03 12:21:44 +0000 |
1509 | @@ -0,0 +1,196 @@ |
1510 | +/* |
1511 | + * Tomdroid |
1512 | + * Tomboy on Android |
1513 | + * http://www.launchpad.net/tomdroid |
1514 | + * |
1515 | + * Copyright 2009, Olivier Bilodeau <olivier@bottomlesspit.org> |
1516 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1517 | + * Copyright 2010, Rodja Trappe <mail@rodja.net> |
1518 | + * |
1519 | + * This file is part of Tomdroid. |
1520 | + * |
1521 | + * Tomdroid is free software: you can redistribute it and/or modify |
1522 | + * it under the terms of the GNU General Public License as published by |
1523 | + * the Free Software Foundation, either version 3 of the License, or |
1524 | + * (at your option) any later version. |
1525 | + * |
1526 | + * Tomdroid is distributed in the hope that it will be useful, |
1527 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1528 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1529 | + * GNU General Public License for more details. |
1530 | + * |
1531 | + * You should have received a copy of the GNU General Public License |
1532 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1533 | + */ |
1534 | +package org.tomdroid.sync; |
1535 | + |
1536 | +import java.util.ArrayList; |
1537 | + |
1538 | +import java.util.concurrent.ExecutorService; |
1539 | +import java.util.concurrent.Executors; |
1540 | + |
1541 | +import org.tomdroid.Note; |
1542 | +import org.tomdroid.NoteManager; |
1543 | +import org.tomdroid.ui.Tomdroid; |
1544 | + |
1545 | +import android.app.Activity; |
1546 | +import android.database.Cursor; |
1547 | +import android.os.Handler; |
1548 | +import android.os.Message; |
1549 | +import android.util.Log; |
1550 | +import android.widget.Toast; |
1551 | + |
1552 | +public abstract class SyncService { |
1553 | + |
1554 | + private static final String TAG = "SyncService"; |
1555 | + |
1556 | + private Activity activity; |
1557 | + private final ExecutorService pool; |
1558 | + private final static int poolSize = 1; |
1559 | + |
1560 | + private Handler handler; |
1561 | + private int syncProgress = 100; |
1562 | + |
1563 | + // handler messages |
1564 | + public final static int PARSING_COMPLETE = 1; |
1565 | + public final static int PARSING_FAILED = 2; |
1566 | + public final static int PARSING_NO_NOTES = 3; |
1567 | + public final static int NO_INTERNET = 4; |
1568 | + public final static int SYNC_PROGRESS = 5; |
1569 | + |
1570 | + public SyncService(Activity activity, Handler handler) { |
1571 | + |
1572 | + this.activity = activity; |
1573 | + this.handler = handler; |
1574 | + pool = Executors.newFixedThreadPool(poolSize); |
1575 | + } |
1576 | + |
1577 | + public void startSynchronization() { |
1578 | + |
1579 | + if (syncProgress != 100){ |
1580 | + Toast.makeText(activity, "Sync already in prgress", Toast.LENGTH_SHORT).show(); |
1581 | + return; |
1582 | + } |
1583 | + |
1584 | + sync(); |
1585 | + } |
1586 | + |
1587 | + protected abstract void sync(); |
1588 | + public abstract boolean needsServer(); |
1589 | + public abstract boolean needsAuth(); |
1590 | + |
1591 | + /** |
1592 | + * @return An unique identifier, not visible to the user. |
1593 | + */ |
1594 | + |
1595 | + public abstract String getName(); |
1596 | + |
1597 | + /** |
1598 | + * @return An human readable name, used in the preferences to distinguish the different sync services. |
1599 | + */ |
1600 | + |
1601 | + public abstract String getDescription(); |
1602 | + |
1603 | + /** |
1604 | + * Execute code in a separate thread. |
1605 | + * Use this for blocking and/or cpu intensive operations and thus avoid blocking the UI. |
1606 | + * |
1607 | + * @param r The Runner subclass to execute |
1608 | + */ |
1609 | + |
1610 | + protected void execInThread(Runnable r) { |
1611 | + |
1612 | + pool.execute(r); |
1613 | + } |
1614 | + |
1615 | + /** |
1616 | + * Insert a note in the content provider. The identifier for the notes is the guid. |
1617 | + * |
1618 | + * @param note The note to insert. |
1619 | + */ |
1620 | + |
1621 | + protected void insertNote(Note note, boolean syncFinished) { |
1622 | + |
1623 | + NoteManager.putNote(this.activity, note); |
1624 | + |
1625 | + // if last note warn in UI that we are done |
1626 | + if (syncFinished) { |
1627 | + handler.sendEmptyMessage(PARSING_COMPLETE); |
1628 | + } |
1629 | + } |
1630 | + |
1631 | + /** |
1632 | + * Delete notes in the content provider. The guids passed identify the notes existing |
1633 | + * on the remote end (ie. that shouldn't be deleted). |
1634 | + * |
1635 | + * @param remoteGuids The notes NOT to delete. |
1636 | + */ |
1637 | + |
1638 | + protected void deleteNotes(ArrayList<String> remoteGuids) { |
1639 | + |
1640 | + Cursor localGuids = NoteManager.getGuids(this.activity); |
1641 | + |
1642 | + // cursor must not be null and must return more than 0 entry |
1643 | + if (!(localGuids == null || localGuids.getCount() == 0)) { |
1644 | + |
1645 | + String localGuid; |
1646 | + |
1647 | + localGuids.moveToFirst(); |
1648 | + |
1649 | + do { |
1650 | + localGuid = localGuids.getString(localGuids.getColumnIndexOrThrow(Note.GUID)); |
1651 | + |
1652 | + if(!remoteGuids.contains(localGuid)) { |
1653 | + int id = localGuids.getInt(localGuids.getColumnIndexOrThrow(Note.ID)); |
1654 | + NoteManager.deleteNote(this.activity, id); |
1655 | + } |
1656 | + |
1657 | + } while (localGuids.moveToNext()); |
1658 | + |
1659 | + } else { |
1660 | + |
1661 | + // TODO send an error to the user |
1662 | + if (Tomdroid.LOGGING_ENABLED) Log.d(TAG, "Cursor returned null or 0 notes"); |
1663 | + } |
1664 | + } |
1665 | + |
1666 | + /** |
1667 | + * Send a message to the main UI. |
1668 | + * |
1669 | + * @param message The message id to send, the PARSING_* or NO_INTERNET attributes can be used. |
1670 | + */ |
1671 | + |
1672 | + protected void sendMessage(int message) { |
1673 | + |
1674 | + handler.sendEmptyMessage(message); |
1675 | + } |
1676 | + |
1677 | + /** |
1678 | + * Update the synchronization progress |
1679 | + * |
1680 | + * @param progress |
1681 | + */ |
1682 | + |
1683 | + protected void setSyncProgress(int progress) { |
1684 | + synchronized (TAG) { |
1685 | + Log.v(TAG, "sync progress: " + progress); |
1686 | + Message progressMessage = new Message(); |
1687 | + progressMessage.what = SYNC_PROGRESS; |
1688 | + progressMessage.arg1 = progress; |
1689 | + progressMessage.arg2 = syncProgress; |
1690 | + |
1691 | + handler.sendMessage(progressMessage); |
1692 | + syncProgress = progress; |
1693 | + } |
1694 | + } |
1695 | + |
1696 | + protected int getSyncProgress(){ |
1697 | + synchronized (TAG) { |
1698 | + return syncProgress; |
1699 | + } |
1700 | + } |
1701 | + |
1702 | + public boolean isSyncable() { |
1703 | + return getSyncProgress() == 100; |
1704 | + } |
1705 | +} |
1706 | |
1707 | === added directory 'src/org/tomdroid/sync/sd' |
1708 | === renamed file 'src/org/tomdroid/xml/NoteHandler.java' => 'src/org/tomdroid/sync/sd/NoteHandler.java' |
1709 | --- src/org/tomdroid/xml/NoteHandler.java 2010-02-16 05:18:09 +0000 |
1710 | +++ src/org/tomdroid/sync/sd/NoteHandler.java 2010-10-03 12:21:44 +0000 |
1711 | @@ -4,6 +4,7 @@ |
1712 | * http://www.launchpad.net/tomdroid |
1713 | * |
1714 | * Copyright 2008, 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
1715 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1716 | * |
1717 | * This file is part of Tomdroid. |
1718 | * |
1719 | @@ -20,7 +21,7 @@ |
1720 | * You should have received a copy of the GNU General Public License |
1721 | * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1722 | */ |
1723 | -package org.tomdroid.xml; |
1724 | +package org.tomdroid.sync.sd; |
1725 | |
1726 | import org.tomdroid.Note; |
1727 | import org.xml.sax.Attributes; |
1728 | |
1729 | === renamed file 'src/org/tomdroid/util/AsyncNoteLoaderAndParser.java' => 'src/org/tomdroid/sync/sd/SdCardSyncService.java' |
1730 | --- src/org/tomdroid/util/AsyncNoteLoaderAndParser.java 2010-02-16 05:18:09 +0000 |
1731 | +++ src/org/tomdroid/sync/sd/SdCardSyncService.java 2010-10-03 12:21:44 +0000 |
1732 | @@ -4,6 +4,8 @@ |
1733 | * http://www.launchpad.net/tomdroid |
1734 | * |
1735 | * Copyright 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
1736 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1737 | + * Copyright 2010, Rodja Trappe <mail@rodja.net> |
1738 | * |
1739 | * This file is part of Tomdroid. |
1740 | * |
1741 | @@ -20,17 +22,16 @@ |
1742 | * You should have received a copy of the GNU General Public License |
1743 | * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1744 | */ |
1745 | -package org.tomdroid.util; |
1746 | +package org.tomdroid.sync.sd; |
1747 | |
1748 | import java.io.BufferedReader; |
1749 | import java.io.File; |
1750 | import java.io.FileInputStream; |
1751 | +import java.io.FileNotFoundException; |
1752 | import java.io.FilenameFilter; |
1753 | import java.io.IOException; |
1754 | import java.io.InputStreamReader; |
1755 | import java.io.Reader; |
1756 | -import java.util.concurrent.ExecutorService; |
1757 | -import java.util.concurrent.Executors; |
1758 | import java.util.regex.Matcher; |
1759 | import java.util.regex.Pattern; |
1760 | |
1761 | @@ -39,9 +40,8 @@ |
1762 | import javax.xml.parsers.SAXParserFactory; |
1763 | |
1764 | import org.tomdroid.Note; |
1765 | -import org.tomdroid.NoteManager; |
1766 | +import org.tomdroid.sync.SyncService; |
1767 | import org.tomdroid.ui.Tomdroid; |
1768 | -import org.tomdroid.xml.NoteHandler; |
1769 | import org.xml.sax.InputSource; |
1770 | import org.xml.sax.SAXException; |
1771 | import org.xml.sax.XMLReader; |
1772 | @@ -51,55 +51,75 @@ |
1773 | import android.util.Log; |
1774 | import android.util.TimeFormatException; |
1775 | |
1776 | -public class AsyncNoteLoaderAndParser { |
1777 | - |
1778 | - // thread pool info |
1779 | - private final ExecutorService pool; |
1780 | - private final static int poolSize = 1; |
1781 | - |
1782 | - // members |
1783 | - private Activity activity; |
1784 | +public class SdCardSyncService extends SyncService { |
1785 | + |
1786 | private File path; |
1787 | - private Handler handler; |
1788 | - |
1789 | - // handler messages |
1790 | - public final static int PARSING_COMPLETE = 1; |
1791 | - public final static int PARSING_FAILED = 2; |
1792 | - public final static int PARSING_NO_NOTES = 3; |
1793 | + private int numberOfFilesToSync = 0; |
1794 | |
1795 | // regexp for <note-content..>...</note-content> |
1796 | - private static Pattern note_content = Pattern.compile(".*(<note-content.*>.*<\\/note-content>).*", Pattern.CASE_INSENSITIVE+Pattern.DOTALL); |
1797 | + private static Pattern note_content = Pattern.compile("<note-content.*>(.*)<\\/note-content>", Pattern.CASE_INSENSITIVE+Pattern.DOTALL); |
1798 | |
1799 | // logging related |
1800 | - private final static String TAG = "AsyncNoteLoaderAndParser"; |
1801 | - |
1802 | - public AsyncNoteLoaderAndParser(Activity a, File path) { |
1803 | - this.activity = a; |
1804 | - this.path = path; |
1805 | - |
1806 | - pool = Executors.newFixedThreadPool(poolSize); |
1807 | - } |
1808 | - |
1809 | - public void readAndParseNotes(Handler hndl) { |
1810 | - handler = hndl; |
1811 | + private final static String TAG = "SdCardSyncService"; |
1812 | + |
1813 | + public SdCardSyncService(Activity activity, Handler handler) throws FileNotFoundException { |
1814 | + super(activity, handler); |
1815 | + |
1816 | + path = new File(Tomdroid.NOTES_PATH); |
1817 | + |
1818 | + if (!path.exists()) |
1819 | + path.mkdir(); |
1820 | + } |
1821 | + |
1822 | + @Override |
1823 | + public String getDescription() { |
1824 | + return "SD Card"; |
1825 | + } |
1826 | + |
1827 | + @Override |
1828 | + public String getName() { |
1829 | + return "sdcard"; |
1830 | + } |
1831 | + |
1832 | + @Override |
1833 | + public boolean needsServer() { |
1834 | + return false; |
1835 | + } |
1836 | + |
1837 | + @Override |
1838 | + public boolean needsAuth() { |
1839 | + return false; |
1840 | + } |
1841 | + |
1842 | + @Override |
1843 | + protected void sync() { |
1844 | + |
1845 | + setSyncProgress(0); |
1846 | + |
1847 | + // start loading local notes |
1848 | + if (Tomdroid.LOGGING_ENABLED) Log.v(TAG, "Loading local notes"); |
1849 | + |
1850 | File[] fileList = path.listFiles(new NotesFilter()); |
1851 | + numberOfFilesToSync = fileList.length; |
1852 | |
1853 | // If there are no notes, warn the UI through an empty message |
1854 | - if (fileList.length == 0) { |
1855 | + if (fileList == null || fileList.length == 0) { |
1856 | if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "There are no notes in "+path); |
1857 | - handler.sendEmptyMessage(PARSING_NO_NOTES); |
1858 | + sendMessage(PARSING_NO_NOTES); |
1859 | + setSyncProgress(100); |
1860 | return; |
1861 | } |
1862 | |
1863 | // every but the last note |
1864 | for(int i = 0; i < fileList.length-1; i++) { |
1865 | + // TODO better progress reporting from within the workers |
1866 | |
1867 | // give a filename to a thread and ask to parse it |
1868 | - pool.execute(new Worker(fileList[i], false)); |
1869 | + execInThread(new Worker(fileList[i], false)); |
1870 | } |
1871 | |
1872 | // last task, warn it so it'll warn UI when done |
1873 | - pool.execute(new Worker(fileList[fileList.length-1], true)); |
1874 | + execInThread(new Worker(fileList[fileList.length-1], true)); |
1875 | } |
1876 | |
1877 | /** |
1878 | @@ -145,7 +165,7 @@ |
1879 | |
1880 | // Get the XMLReader of the SAXParser we created |
1881 | XMLReader xr = sp.getXMLReader(); |
1882 | - |
1883 | + |
1884 | // Create a new ContentHandler, send it this note to fill and apply it to the XML-Reader |
1885 | NoteHandler xmlHandler = new NoteHandler(note); |
1886 | xr.setContentHandler(xmlHandler); |
1887 | @@ -157,7 +177,7 @@ |
1888 | |
1889 | if (Tomdroid.LOGGING_ENABLED) Log.d(TAG, "parsing note"); |
1890 | xr.parse(is); |
1891 | - |
1892 | + |
1893 | // TODO wrap and throw a new exception here |
1894 | } catch (ParserConfigurationException e) { |
1895 | e.printStackTrace(); |
1896 | @@ -168,7 +188,8 @@ |
1897 | } catch (TimeFormatException e) { |
1898 | e.printStackTrace(); |
1899 | if (Tomdroid.LOGGING_ENABLED) Log.e(TAG, "Problem parsing the note's date and time"); |
1900 | - handler.sendEmptyMessage(PARSING_FAILED); |
1901 | + sendMessage(PARSING_FAILED); |
1902 | + onWorkDone(); |
1903 | return; |
1904 | } |
1905 | |
1906 | @@ -202,12 +223,15 @@ |
1907 | if (Tomdroid.LOGGING_ENABLED) Log.w(TAG, "Something went wrong trying to read the note"); |
1908 | } |
1909 | |
1910 | - NoteManager.putNote(AsyncNoteLoaderAndParser.this.activity, note); |
1911 | - |
1912 | - // if last note warn in UI that we are done |
1913 | - if (isLast) { |
1914 | - handler.sendEmptyMessage(PARSING_COMPLETE); |
1915 | - } |
1916 | + insertNote(note, isLast); |
1917 | + onWorkDone(); |
1918 | + } |
1919 | + |
1920 | + private void onWorkDone(){ |
1921 | + if (isLast) |
1922 | + setSyncProgress(100); |
1923 | + else |
1924 | + setSyncProgress((int) (getSyncProgress() + 100.0 / numberOfFilesToSync)); |
1925 | } |
1926 | } |
1927 | } |
1928 | |
1929 | === added directory 'src/org/tomdroid/sync/web' |
1930 | === added file 'src/org/tomdroid/sync/web/AnonymousConnection.java' |
1931 | --- src/org/tomdroid/sync/web/AnonymousConnection.java 1970-01-01 00:00:00 +0000 |
1932 | +++ src/org/tomdroid/sync/web/AnonymousConnection.java 2010-10-03 12:21:44 +0000 |
1933 | @@ -0,0 +1,62 @@ |
1934 | +/* |
1935 | + * Tomdroid |
1936 | + * Tomboy on Android |
1937 | + * http://www.launchpad.net/tomdroid |
1938 | + * |
1939 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
1940 | + * |
1941 | + * This file is part of Tomdroid. |
1942 | + * |
1943 | + * Tomdroid is free software: you can redistribute it and/or modify |
1944 | + * it under the terms of the GNU General Public License as published by |
1945 | + * the Free Software Foundation, either version 3 of the License, or |
1946 | + * (at your option) any later version. |
1947 | + * |
1948 | + * Tomdroid is distributed in the hope that it will be useful, |
1949 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1950 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1951 | + * GNU General Public License for more details. |
1952 | + * |
1953 | + * You should have received a copy of the GNU General Public License |
1954 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
1955 | + */ |
1956 | +package org.tomdroid.sync.web; |
1957 | + |
1958 | +import java.io.UnsupportedEncodingException; |
1959 | +import java.net.UnknownHostException; |
1960 | + |
1961 | +import org.apache.http.HttpResponse; |
1962 | +import org.apache.http.client.methods.HttpGet; |
1963 | +import org.apache.http.client.methods.HttpPut; |
1964 | +import org.apache.http.entity.StringEntity; |
1965 | + |
1966 | +public class AnonymousConnection extends WebConnection { |
1967 | + |
1968 | + @Override |
1969 | + public String get(String uri) throws UnknownHostException |
1970 | + { |
1971 | + // Prepare a request object |
1972 | + HttpGet httpGet = new HttpGet(uri); |
1973 | + HttpResponse response = execute(httpGet); |
1974 | + return parseResponse(response); |
1975 | + } |
1976 | + |
1977 | + @Override |
1978 | + public String put(String uri, String data) throws UnknownHostException { |
1979 | + |
1980 | + // Prepare a request object |
1981 | + HttpPut httpPut = new HttpPut(uri); |
1982 | + |
1983 | + try { |
1984 | + // The default http content charset is ISO-8859-1, JSON requires UTF-8 |
1985 | + httpPut.setEntity(new StringEntity(data, "UTF-8")); |
1986 | + } catch (UnsupportedEncodingException e1) { |
1987 | + e1.printStackTrace(); |
1988 | + return null; |
1989 | + } |
1990 | + |
1991 | + httpPut.setHeader("Content-Type", "application/json"); |
1992 | + HttpResponse response = execute(httpPut); |
1993 | + return parseResponse(response); |
1994 | + } |
1995 | +} |
1996 | |
1997 | === added file 'src/org/tomdroid/sync/web/OAuthConnection.java' |
1998 | --- src/org/tomdroid/sync/web/OAuthConnection.java 1970-01-01 00:00:00 +0000 |
1999 | +++ src/org/tomdroid/sync/web/OAuthConnection.java 2010-10-03 12:21:44 +0000 |
2000 | @@ -0,0 +1,278 @@ |
2001 | +/* |
2002 | + * Tomdroid |
2003 | + * Tomboy on Android |
2004 | + * http://www.launchpad.net/tomdroid |
2005 | + * |
2006 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
2007 | + * |
2008 | + * This file is part of Tomdroid. |
2009 | + * |
2010 | + * Tomdroid is free software: you can redistribute it and/or modify |
2011 | + * it under the terms of the GNU General Public License as published by |
2012 | + * the Free Software Foundation, either version 3 of the License, or |
2013 | + * (at your option) any later version. |
2014 | + * |
2015 | + * Tomdroid is distributed in the hope that it will be useful, |
2016 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2017 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2018 | + * GNU General Public License for more details. |
2019 | + * |
2020 | + * You should have received a copy of the GNU General Public License |
2021 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2022 | + */ |
2023 | +package org.tomdroid.sync.web; |
2024 | + |
2025 | +import java.io.UnsupportedEncodingException; |
2026 | +import java.net.UnknownHostException; |
2027 | + |
2028 | +import oauth.signpost.OAuthConsumer; |
2029 | +import oauth.signpost.OAuthProvider; |
2030 | +import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; |
2031 | +import oauth.signpost.commonshttp.CommonsHttpOAuthProvider; |
2032 | +import oauth.signpost.exception.OAuthCommunicationException; |
2033 | +import oauth.signpost.exception.OAuthExpectationFailedException; |
2034 | +import oauth.signpost.exception.OAuthMessageSignerException; |
2035 | +import oauth.signpost.exception.OAuthNotAuthorizedException; |
2036 | + |
2037 | +import org.apache.http.HttpRequest; |
2038 | +import org.apache.http.HttpResponse; |
2039 | +import org.apache.http.client.methods.HttpGet; |
2040 | +import org.apache.http.client.methods.HttpPut; |
2041 | +import org.apache.http.entity.StringEntity; |
2042 | +import org.json.JSONException; |
2043 | +import org.json.JSONObject; |
2044 | +import org.tomdroid.ui.Tomdroid; |
2045 | +import org.tomdroid.util.Preferences; |
2046 | + |
2047 | +import android.net.Uri; |
2048 | +import android.util.Log; |
2049 | + |
2050 | +public class OAuthConnection extends WebConnection { |
2051 | + |
2052 | + private static final String TAG = "OAuthConnection"; |
2053 | + private static final String CONSUMER_KEY = "anyone"; |
2054 | + private static final String CONSUMER_SECRET = "anyone"; |
2055 | + |
2056 | + private OAuthConsumer consumer = null; |
2057 | + |
2058 | + public String accessToken = ""; |
2059 | + public String accessTokenSecret = ""; |
2060 | + public String requestToken = ""; |
2061 | + public String requestTokenSecret = ""; |
2062 | + public boolean oauth10a = false; |
2063 | + public String authorizeUrl = ""; |
2064 | + public String requestTokenUrl = ""; |
2065 | + public String accessTokenUrl = ""; |
2066 | + public String rootApi = ""; |
2067 | + public String userApi = ""; |
2068 | + |
2069 | + public OAuthConnection() { |
2070 | + |
2071 | + consumer = new CommonsHttpOAuthConsumer( |
2072 | + CONSUMER_KEY, |
2073 | + CONSUMER_SECRET); |
2074 | + } |
2075 | + |
2076 | + public boolean isAuthenticated() { |
2077 | + |
2078 | + if (accessToken.equals("") || accessTokenSecret.equals("")) |
2079 | + return false; |
2080 | + else |
2081 | + return true; |
2082 | + } |
2083 | + |
2084 | + private OAuthProvider getProvider() { |
2085 | + |
2086 | + // Use the provider bundled with signpost, the android libs are buggy |
2087 | + // See: http://code.google.com/p/oauth-signpost/issues/detail?id=20 |
2088 | + OAuthProvider provider = new CommonsHttpOAuthProvider( |
2089 | + requestTokenUrl, |
2090 | + accessTokenUrl, |
2091 | + authorizeUrl); |
2092 | + provider.setOAuth10a(oauth10a); |
2093 | + |
2094 | + return provider; |
2095 | + } |
2096 | + |
2097 | + private void sign(HttpRequest request) { |
2098 | + |
2099 | + if (isAuthenticated()) |
2100 | + consumer.setTokenWithSecret(accessToken, accessTokenSecret); |
2101 | + else |
2102 | + return; |
2103 | + |
2104 | + // TODO: figure out if we should throw exceptions |
2105 | + try { |
2106 | + consumer.sign(request); |
2107 | + } catch (OAuthMessageSignerException e1) { |
2108 | + e1.printStackTrace(); |
2109 | + } catch (OAuthExpectationFailedException e1) { |
2110 | + e1.printStackTrace(); |
2111 | + } catch (OAuthCommunicationException e) { |
2112 | + // TODO Auto-generated catch block |
2113 | + e.printStackTrace(); |
2114 | + } |
2115 | + } |
2116 | + |
2117 | + public Uri getAuthorizationUrl(String server) throws UnknownHostException { |
2118 | + |
2119 | + String url = ""; |
2120 | + |
2121 | + // this method shouldn't have been called |
2122 | + if (isAuthenticated()) |
2123 | + return null; |
2124 | + |
2125 | + rootApi = server+"/api/1.0/"; |
2126 | + |
2127 | + AnonymousConnection connection = new AnonymousConnection(); |
2128 | + String response = connection.get(rootApi); |
2129 | + |
2130 | + JSONObject jsonResponse; |
2131 | + |
2132 | + try { |
2133 | + jsonResponse = new JSONObject(response); |
2134 | + |
2135 | + accessTokenUrl = jsonResponse.getString("oauth_access_token_url"); |
2136 | + requestTokenUrl = jsonResponse.getString("oauth_request_token_url"); |
2137 | + authorizeUrl = jsonResponse.getString("oauth_authorize_url"); |
2138 | + |
2139 | + } catch (JSONException e) { |
2140 | + e.printStackTrace(); |
2141 | + return null; |
2142 | + } |
2143 | + |
2144 | + OAuthProvider provider = getProvider(); |
2145 | + |
2146 | + try { |
2147 | + // the argument is the callback used when the remote authorization is complete |
2148 | + url = provider.retrieveRequestToken(consumer, "tomdroid://sync"); |
2149 | + |
2150 | + requestToken = consumer.getToken(); |
2151 | + requestTokenSecret = consumer.getTokenSecret(); |
2152 | + oauth10a = provider.isOAuth10a(); |
2153 | + accessToken = ""; |
2154 | + accessTokenSecret = ""; |
2155 | + saveConfiguration(); |
2156 | + |
2157 | + } catch (OAuthMessageSignerException e1) { |
2158 | + e1.printStackTrace(); |
2159 | + return null; |
2160 | + } catch (OAuthNotAuthorizedException e1) { |
2161 | + e1.printStackTrace(); |
2162 | + return null; |
2163 | + } catch (OAuthExpectationFailedException e1) { |
2164 | + e1.printStackTrace(); |
2165 | + return null; |
2166 | + } catch (OAuthCommunicationException e1) { |
2167 | + e1.printStackTrace(); |
2168 | + return null; |
2169 | + } |
2170 | + |
2171 | + if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "Authorization URL : "+url); |
2172 | + |
2173 | + return Uri.parse(url); |
2174 | + } |
2175 | + |
2176 | + public boolean getAccess(String verifier) throws UnknownHostException { |
2177 | + |
2178 | + Log.i(TAG, "Verifier: "+verifier); |
2179 | + |
2180 | + // this method shouldn't have been called |
2181 | + if (isAuthenticated()) |
2182 | + return false; |
2183 | + |
2184 | + if (!requestToken.equals("") && !requestTokenSecret.equals("")) { |
2185 | + consumer.setTokenWithSecret(requestToken, requestTokenSecret); |
2186 | + if(Tomdroid.LOGGING_ENABLED) { |
2187 | + Log.d(TAG, "Added request token "+requestTokenSecret+" and request token secret "+requestTokenSecret); |
2188 | + } |
2189 | + } |
2190 | + else |
2191 | + return false; |
2192 | + |
2193 | + OAuthProvider provider = getProvider(); |
2194 | + |
2195 | + try { |
2196 | + provider.retrieveAccessToken(consumer, verifier); |
2197 | + } catch (OAuthMessageSignerException e1) { |
2198 | + e1.printStackTrace(); |
2199 | + return false; |
2200 | + } catch (OAuthNotAuthorizedException e1) { |
2201 | + e1.printStackTrace(); |
2202 | + return false; |
2203 | + } catch (OAuthExpectationFailedException e1) { |
2204 | + e1.printStackTrace(); |
2205 | + return false; |
2206 | + } catch (OAuthCommunicationException e1) { |
2207 | + e1.printStackTrace(); |
2208 | + return false; |
2209 | + } |
2210 | + |
2211 | + // access has been granted, store the access token |
2212 | + accessToken = consumer.getToken(); |
2213 | + accessTokenSecret = consumer.getTokenSecret(); |
2214 | + requestToken = ""; |
2215 | + requestTokenSecret = ""; |
2216 | + |
2217 | + try { |
2218 | + JSONObject response = new JSONObject(get(rootApi)); |
2219 | + // append a slash to the url, else the signature will fail |
2220 | + userApi = response.getJSONObject("user-ref").getString("api-ref"); |
2221 | + } catch (JSONException e) { |
2222 | + // TODO Auto-generated catch block |
2223 | + e.printStackTrace(); |
2224 | + } |
2225 | + |
2226 | + saveConfiguration(); |
2227 | + |
2228 | + if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "Got access token "+consumer.getToken()+"."); |
2229 | + |
2230 | + return true; |
2231 | + } |
2232 | + |
2233 | + @Override |
2234 | + public String get(String uri) throws java.net.UnknownHostException { |
2235 | + |
2236 | + // Prepare a request object |
2237 | + HttpGet httpGet = new HttpGet(uri); |
2238 | + sign(httpGet); |
2239 | + HttpResponse response = execute(httpGet); |
2240 | + return parseResponse(response); |
2241 | + } |
2242 | + |
2243 | + @Override |
2244 | + public String put(String uri, String data) throws UnknownHostException { |
2245 | + |
2246 | + // Prepare a request object |
2247 | + HttpPut httpPut = new HttpPut(uri); |
2248 | + |
2249 | + try { |
2250 | + // The default http content charset is ISO-8859-1, JSON requires UTF-8 |
2251 | + httpPut.setEntity(new StringEntity(data, "UTF-8")); |
2252 | + } catch (UnsupportedEncodingException e1) { |
2253 | + e1.printStackTrace(); |
2254 | + return null; |
2255 | + } |
2256 | + |
2257 | + httpPut.setHeader("Content-Type", "application/json"); |
2258 | + sign(httpPut); |
2259 | + |
2260 | + // Do not handle redirects, we need to sign the request again as the old signature will be invalid |
2261 | + HttpResponse response = execute(httpPut); |
2262 | + return parseResponse(response); |
2263 | + } |
2264 | + |
2265 | + private void saveConfiguration() { |
2266 | + |
2267 | + Preferences.putString(Preferences.Key.ACCESS_TOKEN, accessToken); |
2268 | + Preferences.putString(Preferences.Key.ACCESS_TOKEN_SECRET, accessTokenSecret); |
2269 | + Preferences.putString(Preferences.Key.ACCESS_TOKEN_URL, accessTokenUrl); |
2270 | + Preferences.putString(Preferences.Key.REQUEST_TOKEN, requestToken); |
2271 | + Preferences.putString(Preferences.Key.REQUEST_TOKEN_SECRET, requestTokenSecret); |
2272 | + Preferences.putString(Preferences.Key.REQUEST_TOKEN_URL, requestTokenUrl); |
2273 | + Preferences.putBoolean(Preferences.Key.OAUTH_10A, oauth10a); |
2274 | + Preferences.putString(Preferences.Key.AUTHORIZE_URL, authorizeUrl); |
2275 | + Preferences.putString(Preferences.Key.SYNC_SERVER_ROOT_API, rootApi); |
2276 | + Preferences.putString(Preferences.Key.SYNC_SERVER_USER_API, userApi); |
2277 | + } |
2278 | +} |
2279 | |
2280 | === added file 'src/org/tomdroid/sync/web/SnowySyncService.java' |
2281 | --- src/org/tomdroid/sync/web/SnowySyncService.java 1970-01-01 00:00:00 +0000 |
2282 | +++ src/org/tomdroid/sync/web/SnowySyncService.java 2010-10-03 12:21:44 +0000 |
2283 | @@ -0,0 +1,232 @@ |
2284 | +/* |
2285 | + * Tomdroid |
2286 | + * Tomboy on Android |
2287 | + * http://www.launchpad.net/tomdroid |
2288 | + * |
2289 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
2290 | + * |
2291 | + * This file is part of Tomdroid. |
2292 | + * |
2293 | + * Tomdroid is free software: you can redistribute it and/or modify |
2294 | + * it under the terms of the GNU General Public License as published by |
2295 | + * the Free Software Foundation, either version 3 of the License, or |
2296 | + * (at your option) any later version. |
2297 | + * |
2298 | + * Tomdroid is distributed in the hope that it will be useful, |
2299 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2300 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2301 | + * GNU General Public License for more details. |
2302 | + * |
2303 | + * You should have received a copy of the GNU General Public License |
2304 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2305 | + */ |
2306 | +package org.tomdroid.sync.web; |
2307 | + |
2308 | +import java.net.UnknownHostException; |
2309 | +import java.util.ArrayList; |
2310 | + |
2311 | +import org.json.JSONArray; |
2312 | +import org.json.JSONException; |
2313 | +import org.json.JSONObject; |
2314 | +import org.tomdroid.Note; |
2315 | +import org.tomdroid.sync.ServiceAuth; |
2316 | +import org.tomdroid.sync.SyncService; |
2317 | +import org.tomdroid.ui.Tomdroid; |
2318 | +import org.tomdroid.util.Preferences; |
2319 | + |
2320 | +import android.app.Activity; |
2321 | +import android.net.Uri; |
2322 | +import android.os.Handler; |
2323 | +import android.os.Message; |
2324 | +import android.util.Log; |
2325 | + |
2326 | +public class SnowySyncService extends SyncService implements ServiceAuth { |
2327 | + |
2328 | + private static final String TAG = "SnowySyncService"; |
2329 | + |
2330 | + public SnowySyncService(Activity activity, Handler handler) { |
2331 | + super(activity, handler); |
2332 | + } |
2333 | + |
2334 | + @Override |
2335 | + public String getDescription() { |
2336 | + return "Tomboy Web"; |
2337 | + } |
2338 | + |
2339 | + @Override |
2340 | + public String getName() { |
2341 | + return "tomboy-web"; |
2342 | + } |
2343 | + |
2344 | + public boolean isConfigured() { |
2345 | + OAuthConnection auth = getAuthConnection(); |
2346 | + return auth.isAuthenticated(); |
2347 | + } |
2348 | + |
2349 | + @Override |
2350 | + public boolean needsServer() { |
2351 | + return true; |
2352 | + } |
2353 | + |
2354 | + @Override |
2355 | + public boolean needsAuth() { |
2356 | + return true; |
2357 | + } |
2358 | + |
2359 | + public void getAuthUri(final String server, final Handler handler) { |
2360 | + |
2361 | + execInThread(new Runnable() { |
2362 | + |
2363 | + public void run() { |
2364 | + |
2365 | + // Reset the authentication credentials |
2366 | + OAuthConnection auth = new OAuthConnection(); |
2367 | + Uri authUri = null; |
2368 | + |
2369 | + try { |
2370 | + authUri = auth.getAuthorizationUrl(server); |
2371 | + |
2372 | + } catch (UnknownHostException e) { |
2373 | + if (Tomdroid.LOGGING_ENABLED) |
2374 | + Log.e(TAG, "Internet connection not available"); |
2375 | + sendMessage(NO_INTERNET); |
2376 | + } |
2377 | + |
2378 | + Message message = new Message(); |
2379 | + message.obj = authUri; |
2380 | + handler.sendMessage(message); |
2381 | + } |
2382 | + |
2383 | + }); |
2384 | + } |
2385 | + |
2386 | + public void remoteAuthComplete(final Uri uri, final Handler handler) { |
2387 | + |
2388 | + execInThread(new Runnable() { |
2389 | + |
2390 | + public void run() { |
2391 | + |
2392 | + try { |
2393 | + // TODO: might be intelligent to show something like a progress dialog |
2394 | + // else the user might try to sync before the authorization process |
2395 | + // is complete |
2396 | + OAuthConnection auth = getAuthConnection(); |
2397 | + boolean result = auth.getAccess(uri.getQueryParameter("oauth_verifier")); |
2398 | + |
2399 | + if (Tomdroid.LOGGING_ENABLED) { |
2400 | + if (result) { |
2401 | + Log.i(TAG, "The authorization process is complete."); |
2402 | + } else |
2403 | + Log.e(TAG, "Something went wrong during the authorization process."); |
2404 | + } |
2405 | + } catch (UnknownHostException e) { |
2406 | + if (Tomdroid.LOGGING_ENABLED) |
2407 | + Log.e(TAG, "Internet connection not available"); |
2408 | + sendMessage(NO_INTERNET); |
2409 | + } |
2410 | + |
2411 | + // We don't care what we send, just remove the dialog |
2412 | + handler.sendEmptyMessage(0); |
2413 | + } |
2414 | + }); |
2415 | + } |
2416 | + |
2417 | + @Override |
2418 | + public boolean isSyncable(){ |
2419 | + return super.isSyncable() && isConfigured(); |
2420 | + } |
2421 | + |
2422 | + |
2423 | + @Override |
2424 | + protected void sync() { |
2425 | + |
2426 | + // start loading snowy notes |
2427 | + setSyncProgress(0); |
2428 | + if (Tomdroid.LOGGING_ENABLED) Log.v(TAG, "Loading Snowy notes"); |
2429 | + |
2430 | + final String userRef = Preferences.getString(Preferences.Key.SYNC_SERVER_USER_API); |
2431 | + |
2432 | + execInThread(new Runnable() { |
2433 | + |
2434 | + public void run() { |
2435 | + |
2436 | + OAuthConnection auth = getAuthConnection(); |
2437 | + |
2438 | + try { |
2439 | + String rawResponse = auth.get(userRef); |
2440 | + setSyncProgress(30); |
2441 | + JSONObject response = new JSONObject(rawResponse); |
2442 | + String notesUrl = response.getJSONObject("notes-ref").getString("api-ref"); |
2443 | + |
2444 | + response = new JSONObject(auth.get(notesUrl)); |
2445 | + |
2446 | + long latestSyncRevision = (Long)Preferences.getLong(Preferences.Key.LATEST_SYNC_REVISION); |
2447 | + setSyncProgress(35); |
2448 | + |
2449 | + if (response.getLong("latest-sync-revision") < latestSyncRevision) { |
2450 | + setSyncProgress(100); |
2451 | + return; |
2452 | + } |
2453 | + |
2454 | + response = new JSONObject(auth.get(notesUrl + "?include_notes=true")); |
2455 | + JSONArray notes = response.getJSONArray("notes"); |
2456 | + setSyncProgress(60); |
2457 | + |
2458 | + // Delete the notes that are not in the database |
2459 | + ArrayList<String> remoteGuids = new ArrayList<String>(); |
2460 | + |
2461 | + for (int i = 0; i < notes.length(); i++) { |
2462 | + remoteGuids.add(notes.getJSONObject(i).getString("guid")); |
2463 | + } |
2464 | + |
2465 | + deleteNotes(remoteGuids); |
2466 | + setSyncProgress(70); |
2467 | + |
2468 | + // Insert or update the rest of the notes |
2469 | + for (int i = 0; i < notes.length() - 1; i++) { |
2470 | + |
2471 | + JSONObject jsonNote = notes.getJSONObject(i); |
2472 | + insertNote(new Note(jsonNote), false); |
2473 | + } |
2474 | + setSyncProgress(90); |
2475 | + |
2476 | + JSONObject jsonNote = notes.getJSONObject(notes.length() - 1); |
2477 | + insertNote(new Note(jsonNote), true); |
2478 | + |
2479 | + Preferences.putLong(Preferences.Key.LATEST_SYNC_REVISION, response |
2480 | + .getLong("latest-sync-revision")); |
2481 | + setSyncProgress(100); |
2482 | + |
2483 | + } catch (JSONException e1) { |
2484 | + if (Tomdroid.LOGGING_ENABLED) Log.e(TAG, "Problem parsing the server response", e1); |
2485 | + sendMessage(PARSING_FAILED); |
2486 | + setSyncProgress(100); |
2487 | + return; |
2488 | + } catch (java.net.UnknownHostException e) { |
2489 | + if (Tomdroid.LOGGING_ENABLED) Log.e(TAG, "Internet connection not available"); |
2490 | + sendMessage(NO_INTERNET); |
2491 | + setSyncProgress(100); |
2492 | + return; |
2493 | + } |
2494 | + } |
2495 | + }); |
2496 | + } |
2497 | + |
2498 | + private OAuthConnection getAuthConnection() { |
2499 | + |
2500 | + OAuthConnection auth = new OAuthConnection(); |
2501 | + |
2502 | + auth.accessToken = Preferences.getString(Preferences.Key.ACCESS_TOKEN); |
2503 | + auth.accessTokenSecret = Preferences.getString(Preferences.Key.ACCESS_TOKEN_SECRET); |
2504 | + auth.requestToken = Preferences.getString(Preferences.Key.REQUEST_TOKEN); |
2505 | + auth.requestTokenSecret = Preferences.getString(Preferences.Key.REQUEST_TOKEN_SECRET); |
2506 | + auth.oauth10a = Preferences.getBoolean(Preferences.Key.OAUTH_10A); |
2507 | + auth.authorizeUrl = Preferences.getString(Preferences.Key.AUTHORIZE_URL); |
2508 | + auth.accessTokenUrl = Preferences.getString(Preferences.Key.ACCESS_TOKEN_URL); |
2509 | + auth.requestTokenUrl = Preferences.getString(Preferences.Key.REQUEST_TOKEN_URL); |
2510 | + auth.rootApi = Preferences.getString(Preferences.Key.SYNC_SERVER_ROOT_API); |
2511 | + auth.userApi = Preferences.getString(Preferences.Key.SYNC_SERVER_USER_API); |
2512 | + |
2513 | + return auth; |
2514 | + } |
2515 | +} |
2516 | |
2517 | === added file 'src/org/tomdroid/sync/web/WebConnection.java' |
2518 | --- src/org/tomdroid/sync/web/WebConnection.java 1970-01-01 00:00:00 +0000 |
2519 | +++ src/org/tomdroid/sync/web/WebConnection.java 2010-10-03 12:21:44 +0000 |
2520 | @@ -0,0 +1,139 @@ |
2521 | +/* |
2522 | + * Tomdroid |
2523 | + * Tomboy on Android |
2524 | + * http://www.launchpad.net/tomdroid |
2525 | + * |
2526 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
2527 | + * |
2528 | + * This file is part of Tomdroid. |
2529 | + * |
2530 | + * Tomdroid is free software: you can redistribute it and/or modify |
2531 | + * it under the terms of the GNU General Public License as published by |
2532 | + * the Free Software Foundation, either version 3 of the License, or |
2533 | + * (at your option) any later version. |
2534 | + * |
2535 | + * Tomdroid is distributed in the hope that it will be useful, |
2536 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2537 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2538 | + * GNU General Public License for more details. |
2539 | + * |
2540 | + * You should have received a copy of the GNU General Public License |
2541 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2542 | + */ |
2543 | +package org.tomdroid.sync.web; |
2544 | + |
2545 | +import java.io.BufferedReader; |
2546 | +import java.io.IOException; |
2547 | +import java.io.InputStream; |
2548 | +import java.io.InputStreamReader; |
2549 | +import java.net.UnknownHostException; |
2550 | + |
2551 | +import org.apache.http.HttpEntity; |
2552 | +import org.apache.http.HttpResponse; |
2553 | +import org.apache.http.client.ClientProtocolException; |
2554 | +import org.apache.http.client.methods.HttpUriRequest; |
2555 | +import org.apache.http.impl.client.DefaultHttpClient; |
2556 | +import org.tomdroid.ui.Tomdroid; |
2557 | + |
2558 | +import android.util.Log; |
2559 | + |
2560 | +public abstract class WebConnection { |
2561 | + |
2562 | + private static final String TAG = "WebConnection"; |
2563 | + |
2564 | + public abstract String get(String uri) throws UnknownHostException; |
2565 | + public abstract String put(String uri, String data) throws UnknownHostException; |
2566 | + |
2567 | + private static String convertStreamToString(InputStream is) { |
2568 | + /* |
2569 | + * To convert the InputStream to String we use the BufferedReader.readLine() |
2570 | + * method. We iterate until the BufferedReader return null which means |
2571 | + * there's no more data to read. Each line will appended to a StringBuilder |
2572 | + * and returned as String. |
2573 | + */ |
2574 | + BufferedReader reader = new BufferedReader(new InputStreamReader(is)); |
2575 | + StringBuilder sb = new StringBuilder(); |
2576 | + |
2577 | + String line = null; |
2578 | + try { |
2579 | + while ((line = reader.readLine()) != null) { |
2580 | + sb.append(line + "\n"); |
2581 | + } |
2582 | + } catch (IOException e) { |
2583 | + e.printStackTrace(); |
2584 | + } finally { |
2585 | + try { |
2586 | + is.close(); |
2587 | + } catch (IOException e) { |
2588 | + e.printStackTrace(); |
2589 | + } |
2590 | + } |
2591 | + |
2592 | + return sb.toString(); |
2593 | + } |
2594 | + |
2595 | + protected String parseResponse(HttpResponse response) { |
2596 | + |
2597 | + if (response == null) |
2598 | + return ""; |
2599 | + |
2600 | + String result = null; |
2601 | + |
2602 | + // Examine the response status |
2603 | + if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "Response status : "+response.getStatusLine().toString()); |
2604 | + |
2605 | + // Get hold of the response entity |
2606 | + HttpEntity entity = response.getEntity(); |
2607 | + // If the response does not enclose an entity, there is no need |
2608 | + // to worry about connection release |
2609 | + |
2610 | + if (entity != null) { |
2611 | + |
2612 | + try { |
2613 | + InputStream instream; |
2614 | + |
2615 | + instream = entity.getContent(); |
2616 | + |
2617 | + result = convertStreamToString(instream); |
2618 | + |
2619 | + if (Tomdroid.LOGGING_ENABLED) Log.i(TAG, "Received : "+result); |
2620 | + |
2621 | + // Closing the input stream will trigger connection release |
2622 | + instream.close(); |
2623 | + |
2624 | + } catch (IllegalStateException e) { |
2625 | + // TODO Auto-generated catch block |
2626 | + e.printStackTrace(); |
2627 | + } catch (IOException e) { |
2628 | + // TODO Auto-generated catch block |
2629 | + e.printStackTrace(); |
2630 | + } |
2631 | + } |
2632 | + |
2633 | + return result; |
2634 | + } |
2635 | + |
2636 | + protected HttpResponse execute(HttpUriRequest request) throws UnknownHostException { |
2637 | + |
2638 | + DefaultHttpClient httpclient = new DefaultHttpClient(); |
2639 | + |
2640 | + try { |
2641 | + // Execute the request |
2642 | + HttpResponse response = httpclient.execute(request); |
2643 | + return response; |
2644 | + |
2645 | + }catch (UnknownHostException e){ |
2646 | + throw e; |
2647 | + } catch (ClientProtocolException e) { |
2648 | + e.printStackTrace(); |
2649 | + } catch (IOException e) { |
2650 | + e.printStackTrace(); |
2651 | + } catch (IllegalArgumentException e) { |
2652 | + e.printStackTrace(); |
2653 | + } catch (IllegalStateException e) { |
2654 | + e.printStackTrace(); |
2655 | + } |
2656 | + |
2657 | + return null; |
2658 | + } |
2659 | +} |
2660 | |
2661 | === added file 'src/org/tomdroid/ui/Actionbar.java' |
2662 | --- src/org/tomdroid/ui/Actionbar.java 1970-01-01 00:00:00 +0000 |
2663 | +++ src/org/tomdroid/ui/Actionbar.java 2010-10-03 12:21:44 +0000 |
2664 | @@ -0,0 +1,69 @@ |
2665 | +/* |
2666 | + * Tomdroid |
2667 | + * Tomboy on Android |
2668 | + * http://www.launchpad.net/tomdroid |
2669 | + * |
2670 | + * Copyright 2010, Rodja Trappe <mail@rodja.net> |
2671 | + * |
2672 | + * This file is part of Tomdroid. |
2673 | + * |
2674 | + * Tomdroid is free software: you can redistribute it and/or modify |
2675 | + * it under the terms of the GNU General Public License as published by |
2676 | + * the Free Software Foundation, either version 3 of the License, or |
2677 | + * (at your option) any later version. |
2678 | + * |
2679 | + * Tomdroid is distributed in the hope that it will be useful, |
2680 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2681 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2682 | + * GNU General Public License for more details. |
2683 | + * |
2684 | + * You should have received a copy of the GNU General Public License |
2685 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2686 | + */ |
2687 | +package org.tomdroid.ui; |
2688 | + |
2689 | +import org.tomdroid.R; |
2690 | +import org.tomdroid.sync.SyncManager; |
2691 | + |
2692 | +import android.content.Context; |
2693 | +import android.util.AttributeSet; |
2694 | +import android.view.View; |
2695 | +import android.widget.ImageView; |
2696 | +import android.widget.RelativeLayout; |
2697 | + |
2698 | +public class Actionbar extends RelativeLayout { |
2699 | + |
2700 | + public static final int DEFAULT_ICON_ALPHA = 200; |
2701 | + |
2702 | + public Actionbar(Context context, AttributeSet attrs) { |
2703 | + super(context, attrs); |
2704 | + } |
2705 | + |
2706 | + public Actionbar(Context context, AttributeSet attrs, int defStyle) { |
2707 | + super(context, attrs, defStyle); |
2708 | + } |
2709 | + |
2710 | + public Actionbar(Context context) { |
2711 | + super(context); |
2712 | + } |
2713 | + |
2714 | + @Override |
2715 | + public void onFinishInflate(){ |
2716 | + super.onFinishInflate(); |
2717 | + setupSyncButton(); |
2718 | + } |
2719 | + |
2720 | + private void setupSyncButton(){ |
2721 | + |
2722 | + final ImageView syncButton = (ImageView) findViewById(R.id.sync); |
2723 | + final ImageView syncIcon = (ImageView) findViewById(R.id.syncIcon); |
2724 | + syncIcon.getDrawable().setAlpha(Actionbar.DEFAULT_ICON_ALPHA); |
2725 | + syncButton.setOnClickListener(new View.OnClickListener() { |
2726 | + |
2727 | + public void onClick(View v) { |
2728 | + SyncManager.getInstance().startSynchronization(); |
2729 | + } |
2730 | + }); |
2731 | + } |
2732 | + |
2733 | +} |
2734 | |
2735 | === added file 'src/org/tomdroid/ui/PreferencesActivity.java' |
2736 | --- src/org/tomdroid/ui/PreferencesActivity.java 1970-01-01 00:00:00 +0000 |
2737 | +++ src/org/tomdroid/ui/PreferencesActivity.java 2010-10-03 12:21:44 +0000 |
2738 | @@ -0,0 +1,217 @@ |
2739 | +/* |
2740 | + * Tomdroid |
2741 | + * Tomboy on Android |
2742 | + * http://www.launchpad.net/tomdroid |
2743 | + * |
2744 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
2745 | + * |
2746 | + * This file is part of Tomdroid. |
2747 | + * |
2748 | + * Tomdroid is free software: you can redistribute it and/or modify |
2749 | + * it under the terms of the GNU General Public License as published by |
2750 | + * the Free Software Foundation, either version 3 of the License, or |
2751 | + * (at your option) any later version. |
2752 | + * |
2753 | + * Tomdroid is distributed in the hope that it will be useful, |
2754 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2755 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2756 | + * GNU General Public License for more details. |
2757 | + * |
2758 | + * You should have received a copy of the GNU General Public License |
2759 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2760 | + */ |
2761 | +package org.tomdroid.ui; |
2762 | + |
2763 | +import java.util.ArrayList; |
2764 | + |
2765 | +import org.tomdroid.R; |
2766 | +import org.tomdroid.sync.ServiceAuth; |
2767 | +import org.tomdroid.sync.SyncManager; |
2768 | +import org.tomdroid.sync.SyncService; |
2769 | +import org.tomdroid.util.Preferences; |
2770 | + |
2771 | +import android.app.AlertDialog; |
2772 | +import android.app.ProgressDialog; |
2773 | +import android.content.DialogInterface; |
2774 | +import android.content.Intent; |
2775 | +import android.content.DialogInterface.OnClickListener; |
2776 | +import android.net.Uri; |
2777 | +import android.os.Bundle; |
2778 | +import android.os.Handler; |
2779 | +import android.os.Message; |
2780 | +import android.preference.EditTextPreference; |
2781 | +import android.preference.ListPreference; |
2782 | +import android.preference.Preference; |
2783 | +import android.preference.PreferenceActivity; |
2784 | +import android.preference.Preference.OnPreferenceChangeListener; |
2785 | +import android.util.Log; |
2786 | +import android.widget.Toast; |
2787 | + |
2788 | +public class PreferencesActivity extends PreferenceActivity { |
2789 | + |
2790 | + private static final String TAG = "PreferencesActivity"; |
2791 | + |
2792 | + // TODO: put the various preferences in fields and figure out what to do on activity suspend/resume |
2793 | + private EditTextPreference syncServer = null; |
2794 | + private ListPreference syncService = null; |
2795 | + |
2796 | + @Override |
2797 | + protected void onCreate(Bundle savedInstanceState) { |
2798 | + |
2799 | + super.onCreate(savedInstanceState); |
2800 | + addPreferencesFromResource(R.xml.preferences); |
2801 | + |
2802 | + // Fill the Preferences fields |
2803 | + syncServer = (EditTextPreference)findPreference(Preferences.Key.SYNC_SERVER.getName()); |
2804 | + syncService = (ListPreference)findPreference(Preferences.Key.SYNC_SERVICE.getName()); |
2805 | + |
2806 | + // Set the default values if nothing exists |
2807 | + this.setDefaults(); |
2808 | + |
2809 | + // Fill the services combo list |
2810 | + this.fillServices(); |
2811 | + |
2812 | + // Enable or disable the server field depending on the selected sync service |
2813 | + setServer(syncService.getValue()); |
2814 | + |
2815 | + syncService.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { |
2816 | + |
2817 | + public boolean onPreferenceChange(Preference preference, Object newValue) { |
2818 | + |
2819 | + setServer((String)newValue); |
2820 | + return true; |
2821 | + } |
2822 | + }); |
2823 | + |
2824 | + // Re-authenticate if the sync server changes |
2825 | + syncServer.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { |
2826 | + |
2827 | + public boolean onPreferenceChange(Preference preference, |
2828 | + Object serverUri) { |
2829 | + |
2830 | + if (serverUri == null) { |
2831 | + Toast.makeText(PreferencesActivity.this, |
2832 | + getString(R.string.prefServerEmpty), |
2833 | + Toast.LENGTH_SHORT).show(); |
2834 | + return false; |
2835 | + } |
2836 | + |
2837 | + authenticate((String) serverUri); |
2838 | + return true; |
2839 | + } |
2840 | + |
2841 | + }); |
2842 | + |
2843 | + } |
2844 | + |
2845 | + private void authenticate(String serverUri) { |
2846 | + |
2847 | + // update the value before doing anything |
2848 | + Preferences.putString(Preferences.Key.SYNC_SERVER, serverUri); |
2849 | + |
2850 | + SyncService currentService = SyncManager.getInstance().getCurrentService(); |
2851 | + |
2852 | + if (!currentService.needsAuth()) { |
2853 | + return; |
2854 | + } |
2855 | + |
2856 | + // service needs authentication |
2857 | + Log.i(TAG, "Creating dialog"); |
2858 | + |
2859 | + final ProgressDialog authProgress = ProgressDialog.show(this, "", |
2860 | + "Authenticating. Please wait...", true, false); |
2861 | + |
2862 | + Handler handler = new Handler() { |
2863 | + |
2864 | + @Override |
2865 | + public void handleMessage(Message msg) { |
2866 | + |
2867 | + boolean wasSuccsessful = false; |
2868 | + Uri authorizationUri = (Uri) msg.obj; |
2869 | + if (authorizationUri != null) { |
2870 | + |
2871 | + Intent i = new Intent(Intent.ACTION_VIEW, authorizationUri); |
2872 | + startActivity(i); |
2873 | + wasSuccsessful = true; |
2874 | + |
2875 | + } else { |
2876 | + // Auth failed, don't update the value |
2877 | + wasSuccsessful = false; |
2878 | + } |
2879 | + |
2880 | + if (authProgress != null) |
2881 | + authProgress.dismiss(); |
2882 | + |
2883 | + if (wasSuccsessful) { |
2884 | + resetLocalDatabase(); |
2885 | + } else { |
2886 | + connectionFailed(); |
2887 | + } |
2888 | + } |
2889 | + }; |
2890 | + |
2891 | + ((ServiceAuth) currentService).getAuthUri(serverUri, handler); |
2892 | + } |
2893 | + |
2894 | + private void fillServices() |
2895 | + { |
2896 | + ArrayList<SyncService> availableServices = SyncManager.getInstance().getServices(); |
2897 | + CharSequence[] entries = new CharSequence[availableServices.size()]; |
2898 | + CharSequence[] entryValues = new CharSequence[availableServices.size()]; |
2899 | + |
2900 | + for (int i = 0; i < availableServices.size(); i++) { |
2901 | + entries[i] = availableServices.get(i).getDescription(); |
2902 | + entryValues[i] = availableServices.get(i).getName(); |
2903 | + } |
2904 | + |
2905 | + syncService.setEntries(entries); |
2906 | + syncService.setEntryValues(entryValues); |
2907 | + } |
2908 | + |
2909 | + private void setDefaults() |
2910 | + { |
2911 | + String defaultServer = (String)Preferences.Key.SYNC_SERVER.getDefault(); |
2912 | + syncServer.setDefaultValue(defaultServer); |
2913 | + if(syncServer.getText() == null) |
2914 | + syncServer.setText(defaultServer); |
2915 | + |
2916 | + String defaultService = (String)Preferences.Key.SYNC_SERVICE.getDefault(); |
2917 | + syncService.setDefaultValue(defaultService); |
2918 | + if(syncService.getValue() == null) |
2919 | + syncService.setValue(defaultService); |
2920 | + |
2921 | + } |
2922 | + |
2923 | + private void setServer(String syncServiceKey) { |
2924 | + |
2925 | + SyncService service = SyncManager.getInstance().getService(syncServiceKey); |
2926 | + |
2927 | + if (service == null) |
2928 | + return; |
2929 | + |
2930 | + if (!service.needsAuth()){ |
2931 | + resetLocalDatabase(); |
2932 | + } |
2933 | + |
2934 | + syncServer.setEnabled(service.needsServer()); |
2935 | + syncService.setSummary(service.getDescription()); |
2936 | + |
2937 | + } |
2938 | + |
2939 | + private void connectionFailed() { |
2940 | + new AlertDialog.Builder(this) |
2941 | + .setMessage(getString(R.string.prefSyncConnectionFailed)) |
2942 | + .setNeutralButton(getString(R.string.btnOk), new OnClickListener() { |
2943 | + public void onClick(DialogInterface dialog, int which) { |
2944 | + dialog.dismiss(); |
2945 | + }}) |
2946 | + .show(); |
2947 | + } |
2948 | + |
2949 | + //TODO use LocalStorage wrapper from two-way-sync branch when it get's merged |
2950 | + private void resetLocalDatabase() { |
2951 | + getContentResolver().delete(Tomdroid.CONTENT_URI, null, null); |
2952 | + Preferences.putLong(Preferences.Key.LATEST_SYNC_REVISION, 0); |
2953 | + } |
2954 | + |
2955 | +} |
2956 | |
2957 | === added file 'src/org/tomdroid/ui/SyncMessageHandler.java' |
2958 | --- src/org/tomdroid/ui/SyncMessageHandler.java 1970-01-01 00:00:00 +0000 |
2959 | +++ src/org/tomdroid/ui/SyncMessageHandler.java 2010-10-03 12:21:44 +0000 |
2960 | @@ -0,0 +1,158 @@ |
2961 | +/* |
2962 | + * Tomdroid |
2963 | + * Tomboy on Android |
2964 | + * http://www.launchpad.net/tomdroid |
2965 | + * |
2966 | + * Copyright 2010, Rodja Trappe <mail@rodja.net> |
2967 | + * |
2968 | + * This file is part of Tomdroid. |
2969 | + * |
2970 | + * Tomdroid is free software: you can redistribute it and/or modify |
2971 | + * it under the terms of the GNU General Public License as published by |
2972 | + * the Free Software Foundation, either version 3 of the License, or |
2973 | + * (at your option) any later version. |
2974 | + * |
2975 | + * Tomdroid is distributed in the hope that it will be useful, |
2976 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2977 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2978 | + * GNU General Public License for more details. |
2979 | + * |
2980 | + * You should have received a copy of the GNU General Public License |
2981 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
2982 | + */ |
2983 | +package org.tomdroid.ui; |
2984 | + |
2985 | +import org.tomdroid.R; |
2986 | +import org.tomdroid.sync.SyncManager; |
2987 | +import org.tomdroid.sync.SyncService; |
2988 | + |
2989 | +import android.app.Activity; |
2990 | +import android.app.AlertDialog; |
2991 | +import android.content.DialogInterface; |
2992 | +import android.content.DialogInterface.OnClickListener; |
2993 | +import android.os.Handler; |
2994 | +import android.os.Message; |
2995 | +import android.util.Log; |
2996 | +import android.view.View; |
2997 | +import android.view.animation.Animation; |
2998 | +import android.view.animation.AnimationUtils; |
2999 | +import android.view.animation.RotateAnimation; |
3000 | +import android.widget.ImageView; |
3001 | +import android.widget.Toast; |
3002 | + |
3003 | +public class SyncMessageHandler extends Handler { |
3004 | + |
3005 | + private static String TAG = "SycnMessageHandler"; |
3006 | + private Activity activity; |
3007 | + |
3008 | + // State variables |
3009 | + private boolean parsingErrorShown = false; |
3010 | + |
3011 | + public SyncMessageHandler(Activity activity) { |
3012 | + this.activity = activity; |
3013 | + } |
3014 | + |
3015 | + @Override |
3016 | + public void handleMessage(Message msg) { |
3017 | + |
3018 | + switch (msg.what) { |
3019 | + case SyncService.PARSING_COMPLETE: |
3020 | + // TODO put string in a translatable bundle |
3021 | + Toast.makeText( |
3022 | + activity, |
3023 | + "Synchronization with " |
3024 | + + SyncManager.getInstance().getCurrentService().getDescription() |
3025 | + + " is complete.", Toast.LENGTH_SHORT).show(); |
3026 | + break; |
3027 | + |
3028 | + case SyncService.PARSING_NO_NOTES: |
3029 | + // TODO put string in a translatable bundle |
3030 | + Toast.makeText( |
3031 | + activity, |
3032 | + "No notes found on " |
3033 | + + SyncManager.getInstance().getCurrentService().getDescription() |
3034 | + + ".", Toast.LENGTH_SHORT).show(); |
3035 | + break; |
3036 | + |
3037 | + case SyncService.PARSING_FAILED: |
3038 | + if (Tomdroid.LOGGING_ENABLED) |
3039 | + Log.w(TAG, "handler called with a parsing failed message"); |
3040 | + |
3041 | + // if we already shown a parsing error in this pass, we |
3042 | + // won't show it again |
3043 | + if (!parsingErrorShown) { |
3044 | + parsingErrorShown = true; |
3045 | + |
3046 | + // TODO put error string in a translatable resource |
3047 | + new AlertDialog.Builder(activity).setMessage( |
3048 | + "There was an error trying to parse your note collection. If " |
3049 | + + "you are able to replicate the problem, please contact us!") |
3050 | + .setTitle("Error").setNeutralButton("Ok", new OnClickListener() { |
3051 | + public void onClick(DialogInterface dialog, int which) { |
3052 | + dialog.dismiss(); |
3053 | + } |
3054 | + }).show(); |
3055 | + } |
3056 | + break; |
3057 | + |
3058 | + case SyncService.NO_INTERNET: |
3059 | + // TODO put string in a translatable bundle |
3060 | + Toast.makeText(activity, "You are not connected to the internet.", |
3061 | + Toast.LENGTH_SHORT).show(); |
3062 | + break; |
3063 | + |
3064 | + case SyncService.SYNC_PROGRESS: |
3065 | + handleSyncProgress(msg); |
3066 | + break; |
3067 | + |
3068 | + default: |
3069 | + if (Tomdroid.LOGGING_ENABLED) |
3070 | + Log.i(TAG, "handler called with an unknown message"); |
3071 | + break; |
3072 | + |
3073 | + } |
3074 | + } |
3075 | + |
3076 | + private void handleSyncProgress(Message msg) { |
3077 | + ImageView syncIcon = (ImageView) activity.findViewById(R.id.syncIcon); |
3078 | + |
3079 | + RotateAnimation rotation = new RotateAnimation(180 * msg.arg2 / 100f, |
3080 | + 180 * msg.arg1 / 100f, Animation.RELATIVE_TO_SELF, 0.5f, |
3081 | + Animation.RELATIVE_TO_SELF, 0.5f); |
3082 | + rotation.setDuration(700); |
3083 | + rotation.setFillAfter(true); |
3084 | + syncIcon.startAnimation(rotation); |
3085 | + |
3086 | + if (msg.arg1 == 0) { |
3087 | + onSynchronizationStarted(); |
3088 | + } else if (msg.arg1 == 100) { |
3089 | + onSynchronizationDone(); |
3090 | + } |
3091 | + } |
3092 | + |
3093 | + private void onSynchronizationDone() { |
3094 | + ImageView syncButton = (ImageView) activity.findViewById(R.id.sync); |
3095 | + ImageView syncIcon = (ImageView) activity.findViewById(R.id.syncIcon); |
3096 | + |
3097 | + syncButton.setClickable(true); |
3098 | + syncIcon.getDrawable().setAlpha(Actionbar.DEFAULT_ICON_ALPHA); |
3099 | + |
3100 | + View dot = activity.findViewById(R.id.sync_dot); |
3101 | + dot.setVisibility(View.INVISIBLE); |
3102 | + dot.getAnimation().setRepeatCount(0); |
3103 | + } |
3104 | + |
3105 | + private void onSynchronizationStarted() { |
3106 | + ImageView syncButton = (ImageView) activity.findViewById(R.id.sync); |
3107 | + ImageView syncIcon = (ImageView) activity.findViewById(R.id.syncIcon); |
3108 | + |
3109 | + syncButton.setClickable(false); |
3110 | + syncIcon.getDrawable().setAlpha(40); |
3111 | + |
3112 | + Animation pulse = AnimationUtils.loadAnimation(activity, R.anim.pulse); |
3113 | + View dot = activity.findViewById(R.id.sync_dot); |
3114 | + dot.setVisibility(View.VISIBLE); |
3115 | + dot.startAnimation(pulse); |
3116 | + } |
3117 | + |
3118 | +} |
3119 | |
3120 | === modified file 'src/org/tomdroid/ui/Tomdroid.java' |
3121 | --- src/org/tomdroid/ui/Tomdroid.java 2010-02-16 05:18:09 +0000 |
3122 | +++ src/org/tomdroid/ui/Tomdroid.java 2010-10-03 12:21:44 +0000 |
3123 | @@ -3,7 +3,9 @@ |
3124 | * Tomboy on Android |
3125 | * http://www.launchpad.net/tomdroid |
3126 | * |
3127 | - * Copyright 2008, 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
3128 | + * Copyright 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
3129 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
3130 | + * Copyright 2010, Rodja Trappe <mail@rodja.net> |
3131 | * |
3132 | * This file is part of Tomdroid. |
3133 | * |
3134 | @@ -22,16 +24,17 @@ |
3135 | */ |
3136 | package org.tomdroid.ui; |
3137 | |
3138 | -import java.io.File; |
3139 | -import java.io.FileNotFoundException; |
3140 | - |
3141 | import org.tomdroid.Note; |
3142 | import org.tomdroid.NoteManager; |
3143 | import org.tomdroid.R; |
3144 | -import org.tomdroid.util.AsyncNoteLoaderAndParser; |
3145 | +import org.tomdroid.sync.ServiceAuth; |
3146 | +import org.tomdroid.sync.SyncManager; |
3147 | +import org.tomdroid.sync.SyncService; |
3148 | +import org.tomdroid.util.Preferences; |
3149 | |
3150 | import android.app.AlertDialog; |
3151 | import android.app.ListActivity; |
3152 | +import android.app.ProgressDialog; |
3153 | import android.content.DialogInterface; |
3154 | import android.content.Intent; |
3155 | import android.content.DialogInterface.OnClickListener; |
3156 | @@ -39,6 +42,7 @@ |
3157 | import android.database.Cursor; |
3158 | import android.net.Uri; |
3159 | import android.os.Bundle; |
3160 | +import android.os.Environment; |
3161 | import android.os.Handler; |
3162 | import android.os.Message; |
3163 | import android.util.Log; |
3164 | @@ -49,136 +53,127 @@ |
3165 | import android.widget.ListAdapter; |
3166 | import android.widget.ListView; |
3167 | import android.widget.TextView; |
3168 | -import android.widget.Toast; |
3169 | |
3170 | public class Tomdroid extends ListActivity { |
3171 | |
3172 | // Global definition for Tomdroid |
3173 | - public static final String AUTHORITY = "org.tomdroid.notes"; |
3174 | - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes"); |
3175 | - public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.tomdroid.note"; |
3176 | - public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.tomdroid.note"; |
3177 | - public static final String PROJECT_HOMEPAGE = "http://www.launchpad.net/tomdroid/"; |
3178 | - |
3179 | + public static final String AUTHORITY = "org.tomdroid.notes"; |
3180 | + public static final Uri CONTENT_URI = Uri |
3181 | + .parse("content://" + AUTHORITY |
3182 | + + "/notes"); |
3183 | + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.tomdroid.note"; |
3184 | + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.tomdroid.note"; |
3185 | + public static final String PROJECT_HOMEPAGE = "http://www.launchpad.net/tomdroid/"; |
3186 | + |
3187 | // config parameters |
3188 | // TODO hardcoded for now |
3189 | - public static final String NOTES_PATH = "/sdcard/tomdroid/"; |
3190 | + public static final String NOTES_PATH = Environment.getExternalStorageDirectory() |
3191 | + + "/tomdroid/"; |
3192 | // Logging should be disabled for release builds |
3193 | - public static final boolean LOGGING_ENABLED = false; |
3194 | + public static final boolean LOGGING_ENABLED = false; |
3195 | + // Set this to false for release builds, the reason should be obvious |
3196 | + public static final boolean CLEAR_PREFERENCES = false; |
3197 | |
3198 | // Logging info |
3199 | - private static final String TAG = "Tomdroid"; |
3200 | - |
3201 | + private static final String TAG = "Tomdroid"; |
3202 | + |
3203 | // UI to data model glue |
3204 | - private TextView listEmptyView; |
3205 | - private ListAdapter adapter; |
3206 | - |
3207 | - // Bundle keys for saving state |
3208 | - private static final String WARNING_SHOWN = "w"; |
3209 | - |
3210 | - // State variables |
3211 | - private boolean warningShown = false; |
3212 | - private boolean parsingErrorShown = false; |
3213 | - |
3214 | - |
3215 | - /** Called when the activity is created. */ |
3216 | - @Override |
3217 | - public void onCreate(Bundle savedInstanceState) { |
3218 | - super.onCreate(savedInstanceState); |
3219 | - |
3220 | - setContentView(R.layout.main); |
3221 | - |
3222 | - // did we already show the warning and got destroyed by android's activity killer? |
3223 | - if (savedInstanceState == null || !savedInstanceState.getBoolean(WARNING_SHOWN)) { |
3224 | - |
3225 | - // Warn that this is a "will eat your babies" release |
3226 | - new AlertDialog.Builder(this) |
3227 | - .setMessage(getString(R.string.strWelcome)) |
3228 | - .setTitle("Warning") |
3229 | - .setNeutralButton("Ok", new OnClickListener() { |
3230 | - public void onClick(DialogInterface dialog, int which) { |
3231 | - warningShown = true; |
3232 | - dialog.dismiss(); |
3233 | - }}) |
3234 | - .setIcon(R.drawable.icon) |
3235 | - .show(); |
3236 | - } |
3237 | - |
3238 | - // adapter that binds the ListView UI to the notes in the note manager |
3239 | - adapter = NoteManager.getListAdapter(this); |
3240 | + private TextView listEmptyView; |
3241 | + private ListAdapter adapter; |
3242 | + |
3243 | + // UI feedback handler |
3244 | + private Handler syncMessageHandler = new SyncMessageHandler(this); |
3245 | + |
3246 | + /** Called when the activity is created. */ |
3247 | + @Override |
3248 | + public void onCreate(Bundle savedInstanceState) { |
3249 | + super.onCreate(savedInstanceState); |
3250 | + |
3251 | + setContentView(R.layout.main); |
3252 | + Preferences.init(this, CLEAR_PREFERENCES); |
3253 | + |
3254 | + // did we already show the warning and got destroyed by android's activity killer? |
3255 | + if (Preferences.getBoolean(Preferences.Key.FIRST_RUN)) { |
3256 | + |
3257 | + // Warn that this is a "will eat your babies" release |
3258 | + new AlertDialog.Builder(this).setMessage(getString(R.string.strWelcome)).setTitle( |
3259 | + "Warning").setNeutralButton("Ok", new OnClickListener() { |
3260 | + public void onClick(DialogInterface dialog, int which) { |
3261 | + Preferences.putBoolean(Preferences.Key.FIRST_RUN, false); |
3262 | + dialog.dismiss(); |
3263 | + } |
3264 | + }).setIcon(R.drawable.icon).show(); |
3265 | + } |
3266 | + |
3267 | + // adapter that binds the ListView UI to the notes in the note manager |
3268 | + adapter = NoteManager.getListAdapter(this); |
3269 | setListAdapter(adapter); |
3270 | |
3271 | - // set the view shown when the list is empty |
3272 | + // set the view shown when the list is empty |
3273 | // TODO default empty-list text is butt-ugly! |
3274 | - listEmptyView = (TextView)findViewById(R.id.list_empty); |
3275 | - getListView().setEmptyView(listEmptyView); |
3276 | - } |
3277 | + listEmptyView = (TextView) findViewById(R.id.list_empty); |
3278 | + getListView().setEmptyView(listEmptyView); |
3279 | + } |
3280 | |
3281 | @Override |
3282 | public boolean onCreateOptionsMenu(Menu menu) { |
3283 | |
3284 | // Create the menu based on what is defined in res/menu/main.xml |
3285 | - MenuInflater inflater = getMenuInflater(); |
3286 | - inflater.inflate(R.menu.main, menu); |
3287 | - return true; |
3288 | + MenuInflater inflater = getMenuInflater(); |
3289 | + inflater.inflate(R.menu.main, menu); |
3290 | + return true; |
3291 | + |
3292 | } |
3293 | |
3294 | @Override |
3295 | public boolean onOptionsItemSelected(MenuItem item) { |
3296 | - switch (item.getItemId()) { |
3297 | - case R.id.menuSyncWithSD: |
3298 | - |
3299 | - // start loading local notes |
3300 | - if (LOGGING_ENABLED) Log.v(TAG, "Loading local notes"); |
3301 | - // reset parsing error flag |
3302 | - parsingErrorShown = false; |
3303 | - |
3304 | - try { |
3305 | - File notesRoot = new File(Tomdroid.NOTES_PATH); |
3306 | - |
3307 | - if (!notesRoot.exists()) { |
3308 | - throw new FileNotFoundException("Tomdroid notes folder doesn't exist. It is configured to be at: "+Tomdroid.NOTES_PATH); |
3309 | - } |
3310 | - |
3311 | - AsyncNoteLoaderAndParser asyncLoader = new AsyncNoteLoaderAndParser(this, notesRoot); |
3312 | - asyncLoader.readAndParseNotes(handler); |
3313 | - |
3314 | - } catch (FileNotFoundException e) { |
3315 | - //TODO put strings in an external resource |
3316 | - listEmptyView.setText(R.string.strListEmptyNoNotes); |
3317 | - new AlertDialog.Builder(this) |
3318 | - .setMessage(e.getMessage()) |
3319 | - .setTitle("Error") |
3320 | - .setNeutralButton("Ok", new OnClickListener() { |
3321 | - public void onClick(DialogInterface dialog, int which) { |
3322 | - dialog.dismiss(); |
3323 | - }}) |
3324 | - .show(); |
3325 | - e.printStackTrace(); |
3326 | - } |
3327 | - |
3328 | - return true; |
3329 | - |
3330 | - case R.id.menuAbout: |
3331 | + switch (item.getItemId()) { |
3332 | + case R.id.menuAbout: |
3333 | showAboutDialog(); |
3334 | - return true; |
3335 | - } |
3336 | - |
3337 | - return super.onOptionsItemSelected(item); |
3338 | + return true; |
3339 | + |
3340 | + case R.id.menuPrefs: |
3341 | + startActivity(new Intent(this, PreferencesActivity.class)); |
3342 | + return true; |
3343 | + } |
3344 | + |
3345 | + return super.onOptionsItemSelected(item); |
3346 | } |
3347 | |
3348 | - @Override |
3349 | - protected void onSaveInstanceState(Bundle outState) { |
3350 | - super.onSaveInstanceState(outState); |
3351 | + public void onResume() { |
3352 | + super.onResume(); |
3353 | + Intent intent = this.getIntent(); |
3354 | + |
3355 | + SyncService currentService = SyncManager.getInstance().getCurrentService(); |
3356 | |
3357 | - // saving the state of the warning dialog |
3358 | - if (warningShown) { |
3359 | - outState.putBoolean(WARNING_SHOWN, true); |
3360 | + if (currentService.needsAuth() && intent != null) { |
3361 | + Uri uri = intent.getData(); |
3362 | + |
3363 | + if (uri != null && uri.getScheme().equals("tomdroid")) { |
3364 | + Log.i(TAG, "Got url : " + uri.toString()); |
3365 | + |
3366 | + final ProgressDialog dialog = ProgressDialog.show(this, "", |
3367 | + "Completing authentication. Please wait...", true, false); |
3368 | + |
3369 | + Handler handler = new Handler() { |
3370 | + |
3371 | + @Override |
3372 | + public void handleMessage(Message msg) { |
3373 | + dialog.dismiss(); |
3374 | + } |
3375 | + |
3376 | + }; |
3377 | + |
3378 | + ((ServiceAuth) currentService).remoteAuthComplete(uri, handler); |
3379 | + } |
3380 | } |
3381 | + |
3382 | + SyncManager.setActivity(this); |
3383 | + SyncManager.setHandler(this.syncMessageHandler); |
3384 | } |
3385 | |
3386 | private void showAboutDialog() { |
3387 | - |
3388 | + |
3389 | // grab version info |
3390 | String ver; |
3391 | try { |
3392 | @@ -187,90 +182,38 @@ |
3393 | e.printStackTrace(); |
3394 | ver = "Not found!"; |
3395 | } |
3396 | - |
3397 | + |
3398 | // format the string |
3399 | String aboutDialogFormat = getString(R.string.strAbout); |
3400 | - String aboutDialogStr = String.format(aboutDialogFormat, |
3401 | - getString(R.string.app_desc), // App description |
3402 | - getString(R.string.author), // Author name |
3403 | - ver // Version |
3404 | + String aboutDialogStr = String.format(aboutDialogFormat, getString(R.string.app_desc), // App description |
3405 | + getString(R.string.author), // Author name |
3406 | + ver // Version |
3407 | ); |
3408 | - |
3409 | + |
3410 | // build and show the dialog |
3411 | - new AlertDialog.Builder(this) |
3412 | - .setMessage(aboutDialogStr) |
3413 | - .setTitle("About Tomdroid") |
3414 | - .setIcon(R.drawable.icon) |
3415 | - .setNegativeButton("Project page", new OnClickListener() { |
3416 | - public void onClick(DialogInterface dialog, int which) { |
3417 | - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Tomdroid.PROJECT_HOMEPAGE))); |
3418 | - dialog.dismiss(); |
3419 | - }}) |
3420 | - .setPositiveButton("Ok", new OnClickListener() { |
3421 | - public void onClick(DialogInterface dialog, int which) { |
3422 | - dialog.dismiss(); |
3423 | - }}) |
3424 | - .show(); |
3425 | + new AlertDialog.Builder(this).setMessage(aboutDialogStr).setTitle("About Tomdroid") |
3426 | + .setIcon(R.drawable.icon).setNegativeButton("Project page", new OnClickListener() { |
3427 | + public void onClick(DialogInterface dialog, int which) { |
3428 | + startActivity(new Intent(Intent.ACTION_VIEW, Uri |
3429 | + .parse(Tomdroid.PROJECT_HOMEPAGE))); |
3430 | + dialog.dismiss(); |
3431 | + } |
3432 | + }).setPositiveButton("Ok", new OnClickListener() { |
3433 | + public void onClick(DialogInterface dialog, int which) { |
3434 | + dialog.dismiss(); |
3435 | + } |
3436 | + }).show(); |
3437 | } |
3438 | |
3439 | @Override |
3440 | protected void onListItemClick(ListView l, View v, int position, long id) { |
3441 | - |
3442 | - Cursor item = (Cursor)adapter.getItem(position); |
3443 | + |
3444 | + Cursor item = (Cursor) adapter.getItem(position); |
3445 | int noteId = item.getInt(item.getColumnIndexOrThrow(Note.ID)); |
3446 | - |
3447 | - Uri intentUri = Uri.parse(Tomdroid.CONTENT_URI+"/"+noteId); |
3448 | + |
3449 | + Uri intentUri = Uri.parse(Tomdroid.CONTENT_URI + "/" + noteId); |
3450 | Intent i = new Intent(Intent.ACTION_VIEW, intentUri, this, ViewNote.class); |
3451 | startActivity(i); |
3452 | } |
3453 | - |
3454 | - private Handler handler = new Handler() { |
3455 | - |
3456 | - @Override |
3457 | - public void handleMessage(Message msg) { |
3458 | - |
3459 | - switch(msg.what) { |
3460 | - case AsyncNoteLoaderAndParser.PARSING_COMPLETE: |
3461 | - // TODO put string in a translatable bundle |
3462 | - Toast.makeText(getApplicationContext(), |
3463 | - "Synchronization with SD Card is complete.", |
3464 | - Toast.LENGTH_SHORT) |
3465 | - .show(); |
3466 | - break; |
3467 | - |
3468 | - case AsyncNoteLoaderAndParser.PARSING_NO_NOTES: |
3469 | - // TODO put string in a translatable bundle |
3470 | - Toast.makeText(getApplicationContext(), |
3471 | - "There are no files in tomdroid/ on the sdcard.", |
3472 | - Toast.LENGTH_SHORT) |
3473 | - .show(); |
3474 | - break; |
3475 | - |
3476 | - case AsyncNoteLoaderAndParser.PARSING_FAILED: |
3477 | - if (Tomdroid.LOGGING_ENABLED) Log.w(TAG,"handler called with a parsing failed message"); |
3478 | - |
3479 | - // if we already shown a parsing error in this pass, we won't show it again |
3480 | - if (!parsingErrorShown) { |
3481 | - parsingErrorShown = true; |
3482 | - |
3483 | - // TODO put error string in a translatable resource |
3484 | - new AlertDialog.Builder(Tomdroid.this) |
3485 | - .setMessage("There was an error trying to parse your note collection. If " + |
3486 | - "you are able to replicate the problem, please contact us!") |
3487 | - .setTitle("Error") |
3488 | - .setNeutralButton("Ok", new OnClickListener() { |
3489 | - public void onClick(DialogInterface dialog, int which) { |
3490 | - dialog.dismiss(); |
3491 | - }}) |
3492 | - .show(); |
3493 | - } |
3494 | - break; |
3495 | - |
3496 | - default: |
3497 | - if (Tomdroid.LOGGING_ENABLED) Log.i(TAG,"handler called with an unknown message"); |
3498 | - break; |
3499 | - |
3500 | - } |
3501 | - } |
3502 | - }; |
3503 | + |
3504 | } |
3505 | |
3506 | === modified file 'src/org/tomdroid/ui/ViewNote.java' |
3507 | --- src/org/tomdroid/ui/ViewNote.java 2010-02-06 14:57:07 +0000 |
3508 | +++ src/org/tomdroid/ui/ViewNote.java 2010-10-03 12:21:44 +0000 |
3509 | @@ -4,6 +4,7 @@ |
3510 | * http://www.launchpad.net/tomdroid |
3511 | * |
3512 | * Copyright 2008, 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
3513 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
3514 | * |
3515 | * This file is part of Tomdroid. |
3516 | * |
3517 | @@ -28,6 +29,7 @@ |
3518 | import org.tomdroid.Note; |
3519 | import org.tomdroid.NoteManager; |
3520 | import org.tomdroid.R; |
3521 | +import org.tomdroid.sync.SyncManager; |
3522 | import org.tomdroid.util.LinkifyPhone; |
3523 | import org.tomdroid.util.NoteContentBuilder; |
3524 | |
3525 | @@ -37,6 +39,7 @@ |
3526 | import android.content.Intent; |
3527 | import android.content.DialogInterface.OnClickListener; |
3528 | import android.database.Cursor; |
3529 | +import android.graphics.Color; |
3530 | import android.net.Uri; |
3531 | import android.os.Bundle; |
3532 | import android.os.Handler; |
3533 | @@ -52,6 +55,7 @@ |
3534 | public class ViewNote extends Activity { |
3535 | |
3536 | // UI elements |
3537 | + private TextView title; |
3538 | private TextView content; |
3539 | |
3540 | // Model objects |
3541 | @@ -61,6 +65,9 @@ |
3542 | // Logging info |
3543 | private static final String TAG = "ViewNote"; |
3544 | |
3545 | + // UI feedback handler |
3546 | + private Handler syncMessageHandler = new SyncMessageHandler(this); |
3547 | + |
3548 | // TODO extract methods in here |
3549 | @Override |
3550 | protected void onCreate(Bundle savedInstanceState) { |
3551 | @@ -68,6 +75,14 @@ |
3552 | |
3553 | setContentView(R.layout.note_view); |
3554 | content = (TextView) findViewById(R.id.content); |
3555 | + content.setBackgroundColor(0xffffffff); |
3556 | + content.setTextColor(Color.DKGRAY); |
3557 | + content.setTextSize(18.0f); |
3558 | + title = (TextView) findViewById(R.id.title); |
3559 | + title.setBackgroundColor(0xffdddddd); |
3560 | + title.setTextColor(Color.DKGRAY); |
3561 | + title.setTextSize(18.0f); |
3562 | + |
3563 | final Intent intent = getIntent(); |
3564 | Uri uri = intent.getData(); |
3565 | |
3566 | @@ -84,7 +99,9 @@ |
3567 | |
3568 | if(note != null) { |
3569 | |
3570 | - noteContent = note.getNoteContent(handler); |
3571 | + noteContent = note.getNoteContent(noteContentHandler); |
3572 | + |
3573 | + //Log.i(TAG, "THE NOTE IS: " + note.getXmlContent().toString()); |
3574 | |
3575 | } else { |
3576 | |
3577 | @@ -120,6 +137,13 @@ |
3578 | } |
3579 | } |
3580 | |
3581 | + @Override |
3582 | + public void onResume(){ |
3583 | + super.onResume(); |
3584 | + SyncManager.setActivity(this); |
3585 | + SyncManager.setHandler(this.syncMessageHandler); |
3586 | + } |
3587 | + |
3588 | // TODO add a menu that switches the view to an EditText instead of TextView |
3589 | // this will need some other quit mechanism as onKeyDown though.. (but the back key might do it) |
3590 | |
3591 | @@ -132,9 +156,9 @@ |
3592 | |
3593 | return true; |
3594 | } |
3595 | - |
3596 | + |
3597 | private void showNote() { |
3598 | - setTitle(note.getTitle()); |
3599 | + //setTitle(note.getTitle()); |
3600 | |
3601 | // get rid of the title that is doubled in the note's content |
3602 | // using quote to escape potential regexp chars in pattern |
3603 | @@ -147,6 +171,7 @@ |
3604 | |
3605 | // show the note (spannable makes the TextView able to output styled text) |
3606 | content.setText(noteContent, TextView.BufferType.SPANNABLE); |
3607 | + title.setText((CharSequence) note.getTitle()); |
3608 | |
3609 | // add links to stuff that is understood by Android except phone numbers because it's too aggressive |
3610 | // TODO this is SLOWWWW!!!! |
3611 | @@ -165,7 +190,14 @@ |
3612 | noteTitleTransformFilter); |
3613 | } |
3614 | |
3615 | - private Handler handler = new Handler() { |
3616 | + public void setTitle(CharSequence title){ |
3617 | + super.setTitle(title); |
3618 | + // temporary setting title of actionbar until we have a better idea |
3619 | + TextView titleView = (TextView) findViewById(R.id.title); |
3620 | + titleView.setText(title); |
3621 | + } |
3622 | + |
3623 | + private Handler noteContentHandler = new Handler() { |
3624 | |
3625 | @Override |
3626 | public void handleMessage(Message msg) { |
3627 | |
3628 | === modified file 'src/org/tomdroid/util/NoteContentBuilder.java' |
3629 | --- src/org/tomdroid/util/NoteContentBuilder.java 2010-01-23 04:43:26 +0000 |
3630 | +++ src/org/tomdroid/util/NoteContentBuilder.java 2010-10-03 12:21:44 +0000 |
3631 | @@ -62,7 +62,8 @@ |
3632 | |
3633 | public NoteContentBuilder setInputSource(String nc) { |
3634 | |
3635 | - noteContentIs = new InputSource(new StringReader(nc)); |
3636 | + String noteContent = "<note-content>"+nc+"</note-content>"; |
3637 | + noteContentIs = new InputSource(new StringReader(noteContent)); |
3638 | return this; |
3639 | } |
3640 | |
3641 | |
3642 | === added file 'src/org/tomdroid/util/NoteListCursorAdapter.java' |
3643 | --- src/org/tomdroid/util/NoteListCursorAdapter.java 1970-01-01 00:00:00 +0000 |
3644 | +++ src/org/tomdroid/util/NoteListCursorAdapter.java 2010-10-03 12:21:44 +0000 |
3645 | @@ -0,0 +1,113 @@ |
3646 | +package org.tomdroid.util; |
3647 | + |
3648 | +import java.text.DateFormat; |
3649 | +import java.util.Date; |
3650 | + |
3651 | +import android.text.format.DateUtils; |
3652 | +import android.text.format.Time; |
3653 | +import org.tomdroid.Note; |
3654 | +import org.tomdroid.R; |
3655 | +import org.tomdroid.ui.Tomdroid; |
3656 | + |
3657 | +import android.content.Context; |
3658 | +import android.database.Cursor; |
3659 | +import android.graphics.Color; |
3660 | +import android.view.LayoutInflater; |
3661 | +import android.view.View; |
3662 | +import android.view.ViewGroup; |
3663 | +import android.widget.Filterable; |
3664 | +import android.widget.SimpleCursorAdapter; |
3665 | +import android.widget.TextView; |
3666 | + |
3667 | +/* Provides a custom ListView layout for Note List */ |
3668 | + |
3669 | +public class NoteListCursorAdapter extends SimpleCursorAdapter { |
3670 | + |
3671 | + private Context context; |
3672 | + |
3673 | + private int layout; |
3674 | + private int[] colors = new int[] { 0xFFFFFFFF, 0xFFEEEEEE }; |
3675 | + |
3676 | + private DateFormat localeDateFormat; |
3677 | + private DateFormat localeTimeFormat; |
3678 | + |
3679 | + public NoteListCursorAdapter (Context context, int layout, Cursor c, String[] from, int[] to) { |
3680 | + super(context, layout, c, from, to); |
3681 | + this.context = context; |
3682 | + this.layout = layout; |
3683 | + localeDateFormat = DateFormat.getDateInstance(DateFormat.SHORT); |
3684 | + localeTimeFormat = DateFormat.getTimeInstance(DateFormat.SHORT); |
3685 | + } |
3686 | + |
3687 | + |
3688 | + @Override |
3689 | + public View newView(Context context, Cursor cursor, ViewGroup parent) { |
3690 | + |
3691 | + Cursor c = getCursor(); |
3692 | + |
3693 | + final LayoutInflater inflater = LayoutInflater.from(context); |
3694 | + View v = inflater.inflate(layout, parent, false); |
3695 | + |
3696 | + populateFields(v, c); |
3697 | + |
3698 | + return v; |
3699 | + } |
3700 | + |
3701 | + @Override |
3702 | + public void bindView(View v, Context context, Cursor c) { |
3703 | + |
3704 | + populateFields(v, c); |
3705 | + } |
3706 | + |
3707 | + @Override |
3708 | + public View getView(int position, View convertView, ViewGroup parent) { |
3709 | + View view = super.getView(position, convertView, parent); |
3710 | + int colorPos = position % colors.length; |
3711 | + view.setBackgroundColor(colors[colorPos]); |
3712 | + //view.setTextColor(Color.DKGRAY); |
3713 | + return view; |
3714 | + } |
3715 | + |
3716 | + private void populateFields(View v, Cursor c){ |
3717 | + |
3718 | + int nameCol = c.getColumnIndex(Note.TITLE); |
3719 | + int modifiedCol = c.getColumnIndex(Note.MODIFIED_DATE); |
3720 | + |
3721 | + String title = c.getString(nameCol); |
3722 | + |
3723 | + //Format last modified dates to be similar to desktop Tomboy |
3724 | + //TODO this is messy - must be a better way than having 3 separate date types |
3725 | + Time lastModified = new Time(); |
3726 | + lastModified.parse3339(c.getString(modifiedCol)); |
3727 | + Long lastModifiedMillis = lastModified.toMillis(false); |
3728 | + Date lastModifiedDate = new Date(lastModifiedMillis); |
3729 | + |
3730 | + String strModified = "Modified: "; |
3731 | + //TODO this is very inefficient |
3732 | + if (DateUtils.isToday(lastModifiedMillis)){ |
3733 | + strModified += "Today, " + localeTimeFormat.format(lastModifiedDate); |
3734 | + } else { |
3735 | + // Add a day to the last modified date - if the date is now today, it means the note was edited yesterday |
3736 | + Time yesterdayTest = lastModified; |
3737 | + yesterdayTest.monthDay += 1; |
3738 | + if (DateUtils.isToday(yesterdayTest.toMillis(false))){ |
3739 | + strModified += "Yesterday, " + localeTimeFormat.format(lastModifiedDate); |
3740 | + } else { |
3741 | + strModified += localeDateFormat.format(lastModifiedDate) + ", " + localeTimeFormat.format(lastModifiedDate); |
3742 | + } |
3743 | + } |
3744 | + |
3745 | + /** |
3746 | + * Next set the name of the entry. |
3747 | + */ |
3748 | + TextView note_title = (TextView) v.findViewById(R.id.note_title); |
3749 | + if (note_title != null) { |
3750 | + note_title.setText(title); |
3751 | + } |
3752 | + TextView note_modified = (TextView) v.findViewById(R.id.note_date); |
3753 | + if (note_modified != null) { |
3754 | + note_modified.setText(strModified); |
3755 | + } |
3756 | + } |
3757 | + |
3758 | +} |
3759 | |
3760 | === added file 'src/org/tomdroid/util/Preferences.java' |
3761 | --- src/org/tomdroid/util/Preferences.java 1970-01-01 00:00:00 +0000 |
3762 | +++ src/org/tomdroid/util/Preferences.java 2010-10-03 12:21:44 +0000 |
3763 | @@ -0,0 +1,112 @@ |
3764 | +/* |
3765 | + * Tomdroid |
3766 | + * Tomboy on Android |
3767 | + * http://www.launchpad.net/tomdroid |
3768 | + * |
3769 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
3770 | + * |
3771 | + * This file is part of Tomdroid. |
3772 | + * |
3773 | + * Tomdroid is free software: you can redistribute it and/or modify |
3774 | + * it under the terms of the GNU General Public License as published by |
3775 | + * the Free Software Foundation, either version 3 of the License, or |
3776 | + * (at your option) any later version. |
3777 | + * |
3778 | + * Tomdroid is distributed in the hope that it will be useful, |
3779 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3780 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3781 | + * GNU General Public License for more details. |
3782 | + * |
3783 | + * You should have received a copy of the GNU General Public License |
3784 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
3785 | + */ |
3786 | +package org.tomdroid.util; |
3787 | + |
3788 | +import android.content.Context; |
3789 | +import android.content.SharedPreferences; |
3790 | +import android.preference.PreferenceManager; |
3791 | + |
3792 | +public class Preferences { |
3793 | + |
3794 | + public enum Key { |
3795 | + SYNC_SERVICE ("sync_service", "sdcard"), |
3796 | + SYNC_SERVER_ROOT_API ("sync_server_root_api", ""), |
3797 | + SYNC_SERVER_USER_API ("sync_server_user_api", ""), |
3798 | + SYNC_SERVER ("sync_server", "https://one.ubuntu.com/notes"), |
3799 | + ACCESS_TOKEN ("access_token", ""), |
3800 | + ACCESS_TOKEN_SECRET ("access_token_secret", ""), |
3801 | + REQUEST_TOKEN ("request_token", ""), |
3802 | + REQUEST_TOKEN_SECRET ("request_token_secret", ""), |
3803 | + OAUTH_10A ("oauth_10a", false), |
3804 | + AUTHORIZE_URL ("authorize_url", ""), |
3805 | + ACCESS_TOKEN_URL ("access_token_url", ""), |
3806 | + REQUEST_TOKEN_URL ("request_token_url", ""), |
3807 | + LATEST_SYNC_REVISION ("latest_sync_revision", 0L), |
3808 | + SORT_ORDER ("sort_order", "sort_date"), |
3809 | + FIRST_RUN ("first_run", true); |
3810 | + |
3811 | + private String name = ""; |
3812 | + private Object defaultValue = ""; |
3813 | + |
3814 | + Key(String name, Object defaultValue) { |
3815 | + this.name = name; |
3816 | + this.defaultValue = defaultValue; |
3817 | + } |
3818 | + |
3819 | + public String getName() { |
3820 | + return name; |
3821 | + } |
3822 | + |
3823 | + public Object getDefault() { |
3824 | + return defaultValue; |
3825 | + } |
3826 | + } |
3827 | + |
3828 | + private static SharedPreferences client = null; |
3829 | + private static SharedPreferences.Editor editor = null; |
3830 | + |
3831 | + public static void init(Context context, boolean clean) { |
3832 | + |
3833 | + client = PreferenceManager.getDefaultSharedPreferences(context); |
3834 | + editor = client.edit(); |
3835 | + |
3836 | + if (clean) |
3837 | + editor.clear().commit(); |
3838 | + } |
3839 | + |
3840 | + public static String getString(Key key) { |
3841 | + |
3842 | + return client.getString(key.getName(), (String) key.getDefault()); |
3843 | + } |
3844 | + |
3845 | + public static void putString(Key key, String value) { |
3846 | + |
3847 | + if (value == null) |
3848 | + editor.putString(key.getName(), (String)key.getDefault()); |
3849 | + else |
3850 | + editor.putString(key.getName(), value); |
3851 | + editor.commit(); |
3852 | + } |
3853 | + |
3854 | + public static long getLong(Key key) { |
3855 | + |
3856 | + return client.getLong(key.getName(), (Long)key.getDefault()); |
3857 | + } |
3858 | + |
3859 | + public static void putLong(Key key, long value) { |
3860 | + |
3861 | + editor.putLong(key.getName(), value); |
3862 | + editor.commit(); |
3863 | + } |
3864 | + |
3865 | + public static boolean getBoolean(Key key) { |
3866 | + |
3867 | + return client.getBoolean(key.getName(), (Boolean)key.getDefault()); |
3868 | + } |
3869 | + |
3870 | + public static void putBoolean(Key key, boolean value) { |
3871 | + |
3872 | + editor.putBoolean(key.getName(), value); |
3873 | + editor.commit(); |
3874 | + } |
3875 | +} |
3876 | |
3877 | === added file 'src/org/tomdroid/util/XmlUtils.java' |
3878 | --- src/org/tomdroid/util/XmlUtils.java 1970-01-01 00:00:00 +0000 |
3879 | +++ src/org/tomdroid/util/XmlUtils.java 2010-10-03 12:21:44 +0000 |
3880 | @@ -0,0 +1,58 @@ |
3881 | +/* |
3882 | + * Tomdroid |
3883 | + * Tomboy on Android |
3884 | + * http://www.launchpad.net/tomdroid |
3885 | + * |
3886 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
3887 | + * |
3888 | + * This file is part of Tomdroid. |
3889 | + * |
3890 | + * Tomdroid is free software: you can redistribute it and/or modify |
3891 | + * it under the terms of the GNU General Public License as published by |
3892 | + * the Free Software Foundation, either version 3 of the License, or |
3893 | + * (at your option) any later version. |
3894 | + * |
3895 | + * Tomdroid is distributed in the hope that it will be useful, |
3896 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3897 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3898 | + * GNU General Public License for more details. |
3899 | + * |
3900 | + * You should have received a copy of the GNU General Public License |
3901 | + * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>. |
3902 | + */ |
3903 | +package org.tomdroid.util; |
3904 | + |
3905 | +public class XmlUtils { |
3906 | + |
3907 | + /** |
3908 | + * Useful to replace the characters forbidden in xml by their escaped counterparts |
3909 | + * Ex: & -> &amp; |
3910 | + * |
3911 | + * @param input the string to escape |
3912 | + * @return the escaped string |
3913 | + */ |
3914 | + public static String escape(String input) { |
3915 | + return input |
3916 | + .replace("&", "&") |
3917 | + .replace("<", "<") |
3918 | + .replace(">", ">") |
3919 | + .replace("\"", """) |
3920 | + .replace("\'", "'"); |
3921 | + } |
3922 | + |
3923 | + /** |
3924 | + * Useful to replace the escaped characters their unescaped counterparts |
3925 | + * Ex: &amp; -> & |
3926 | + * |
3927 | + * @param input the string to unescape |
3928 | + * @return the unescaped string |
3929 | + */ |
3930 | + public static String unescape(String input) { |
3931 | + return input |
3932 | + .replace("&", "&") |
3933 | + .replace("<", "<") |
3934 | + .replace(">", ">") |
3935 | + .replace(""", "\"") |
3936 | + .replace("'", "\'"); |
3937 | + } |
3938 | +} |
3939 | |
3940 | === modified file 'src/org/tomdroid/xml/NoteContentHandler.java' |
3941 | --- src/org/tomdroid/xml/NoteContentHandler.java 2010-02-01 05:11:47 +0000 |
3942 | +++ src/org/tomdroid/xml/NoteContentHandler.java 2010-10-03 12:21:44 +0000 |
3943 | @@ -4,6 +4,7 @@ |
3944 | * http://www.launchpad.net/tomdroid |
3945 | * |
3946 | * Copyright 2008, 2009, 2010 Olivier Bilodeau <olivier@bottomlesspit.org> |
3947 | + * Copyright 2009, Benoit Garret <benoit.garret_launchpad@gadz.org> |
3948 | * |
3949 | * This file is part of Tomdroid. |
3950 | * |
3951 | |
3952 | === added directory 'tests' |
3953 | === added directory 'tests/org' |
3954 | === added directory 'tests/org/tomdroid' |
3955 | === added file 'tests/org/tomdroid/NoteManagerTest.java' |
3956 | --- tests/org/tomdroid/NoteManagerTest.java 1970-01-01 00:00:00 +0000 |
3957 | +++ tests/org/tomdroid/NoteManagerTest.java 2010-10-03 12:21:44 +0000 |
3958 | @@ -0,0 +1,74 @@ |
3959 | +package org.tomdroid; |
3960 | + |
3961 | +import org.json.JSONObject; |
3962 | +import org.tomdroid.Note; |
3963 | +import org.tomdroid.NoteManager; |
3964 | +import org.tomdroid.ui.Tomdroid; |
3965 | +import org.tomdroid.util.Preferences; |
3966 | + |
3967 | +import android.app.Activity; |
3968 | +import android.content.Intent; |
3969 | +import android.database.Cursor; |
3970 | +import android.test.ActivityUnitTestCase; |
3971 | + |
3972 | +public class NoteManagerTest extends ActivityUnitTestCase<Tomdroid> { |
3973 | + |
3974 | + public NoteManagerTest() { |
3975 | + super(Tomdroid.class); |
3976 | + } |
3977 | + |
3978 | + public void testGetAllNotes() throws Exception { |
3979 | + Activity activity = getActivity(); |
3980 | + putNotes(activity); |
3981 | + Cursor cursor; |
3982 | + // Get all notes excluding the notebook template ones. |
3983 | + cursor = NoteManager.getAllNotes(activity, false); |
3984 | + assertEquals(1, cursor.getCount()); |
3985 | + |
3986 | + // Get all notes, including notebook templates this time. |
3987 | + cursor = NoteManager.getAllNotes(activity, true); |
3988 | + assertEquals(2, cursor.getCount()); |
3989 | + } |
3990 | + |
3991 | + private void putNotes(Activity a) throws Exception { |
3992 | + // Add a regular note to the content manager. |
3993 | + JSONObject note = new JSONObject( |
3994 | + "{'title': 'foo', 'note-content': 'bar', " + |
3995 | + "'guid': '002e91a2-2e34-4e2d-bf88-21def49a7704', " + |
3996 | + "'last-change-date': '2009-04-19T21:29:23.2197340-07:00', " + |
3997 | + "'tags': ['tag1', 'tag2']}"); |
3998 | + Note n = new Note(note); |
3999 | + NoteManager.putNote(a, n); |
4000 | + |
4001 | + // Add a notebook template to the content manager. |
4002 | + JSONObject template = new JSONObject( |
4003 | + "{'title': 'foo', 'note-content': 'bar', " + |
4004 | + "'guid': '992e91a2-2e34-4e2d-bf88-21def49a7712', " + |
4005 | + "'last-change-date': '2009-04-19T21:29:23.2197340-07:00', " + |
4006 | + "'tags': ['system:template', 'tag2']}"); |
4007 | + Note t = new Note(template); |
4008 | + NoteManager.putNote(a, t); |
4009 | + } |
4010 | + |
4011 | + @Override |
4012 | + public void setUp() throws Exception { |
4013 | + super.setUp(); |
4014 | + // XXX: For some reason this will raise an |
4015 | + // "Unable to add window -- token null is not for an application" |
4016 | + // error when you run the test after wiping user data from the emulator. |
4017 | + // The error is actually raised when we try to display the AlertDialog that |
4018 | + // is shown the first time the user runs tomdroid. |
4019 | + startActivity(new Intent(), null, null); |
4020 | + // XXX: Soon we'll be able to replace the two lines below with LocalStorage.resetDatabase(). |
4021 | + getActivity().getContentResolver().delete(Tomdroid.CONTENT_URI, null, null); |
4022 | + Preferences.putLong(Preferences.Key.LATEST_SYNC_REVISION, 0); |
4023 | + } |
4024 | + |
4025 | + @Override |
4026 | + public void tearDown() throws Exception { |
4027 | + // XXX: Soon we'll be able to replace the two lines below with LocalStorage.resetDatabase(). |
4028 | + getActivity().getContentResolver().delete(Tomdroid.CONTENT_URI, null, null); |
4029 | + Preferences.putLong(Preferences.Key.LATEST_SYNC_REVISION, 0); |
4030 | + super.tearDown(); |
4031 | + } |
4032 | +} |
4033 | |
4034 | === added file 'tests/org/tomdroid/NoteTest.java' |
4035 | --- tests/org/tomdroid/NoteTest.java 1970-01-01 00:00:00 +0000 |
4036 | +++ tests/org/tomdroid/NoteTest.java 2010-10-03 12:21:44 +0000 |
4037 | @@ -0,0 +1,35 @@ |
4038 | +package org.tomdroid; |
4039 | + |
4040 | +import junit.framework.Assert; |
4041 | +import junit.framework.TestCase; |
4042 | + |
4043 | +import org.tomdroid.Note; |
4044 | +import org.json.JSONException; |
4045 | +import org.json.JSONObject; |
4046 | + |
4047 | + |
4048 | +public class NoteTest extends TestCase { |
4049 | + |
4050 | + public void testConstructorForNoteWithTags() throws JSONException { |
4051 | + JSONObject json = new JSONObject( |
4052 | + "{'title': 'foo', 'note-content': 'bar', " + |
4053 | + "'guid': '002e91a2-2e34-4e2d-bf88-21def49a7705', " + |
4054 | + "'last-change-date': '2009-04-19T21:29:23.2197340-07:00', " + |
4055 | + "'tags': ['tag1', 'tag2']}"); |
4056 | + Note n = new Note(json); |
4057 | + Assert.assertEquals("foo", n.getTitle()); |
4058 | + Assert.assertEquals("002e91a2-2e34-4e2d-bf88-21def49a7705", n.getGuid().toString()); |
4059 | + Assert.assertEquals("bar", n.getXmlContent()); |
4060 | + Assert.assertEquals("tag1,tag2,", n.getTags()); |
4061 | + } |
4062 | + |
4063 | + public void testConstructorForNoteWithNoTags() throws JSONException { |
4064 | + JSONObject json = new JSONObject( |
4065 | + "{'title': 'foo', 'note-content': 'bar', " + |
4066 | + "'guid': '002e91a2-2e34-4e2d-bf88-21def49a7705', " + |
4067 | + "'last-change-date': '2009-04-19T21:29:23.2197340-07:00'}"); |
4068 | + Note n = new Note(json); |
4069 | + Assert.assertEquals("foo", n.getTitle()); |
4070 | + Assert.assertEquals("", n.getTags()); |
4071 | + } |
4072 | +} |
First, I only glanced quickly at your work but I'm very excited to see your work!
Second, sorry if anything here was already mentionned elsewhere but I haven't replied..
Third, all of this is a matter of discussion. Given the right arguments I will change my mind.
1) order of things
I'm a bit confused with the merge hiearchy here..
Is this based on web-sync meaning we need to merge web-sync first or does this integrates web-sync so merging this will result in a web-sync + sync-ui integration?
2) commons-codec
What is commons-codec used for? Was there no built-in alternative already available? I'm trying to avoid adding a 64k jar into the tomdroid package here.
3) signpost
Not sure what you did with signpost.. haven't looked but can't you use a released jar (with a version we can track bugs against, etc.) instead of having a git checkout of their stuff? Did you need to modify their upstream code? If you can't proceed with released code, can you get rid of the git metadata (signpost/.git/) and identify in a README.tomdroid what revision/repo is this code from and what custom changes you needed done. Also, I would like the eclipse metadata removed.
4) file headers
Some new files are missing the usual project header. Be careful to assign copyright to the right person who created the work. If you are willing to give me the copyright feel free to do so. In any case you will be attributed for your work elsewhere.
Start looking at these please. Once dealt with I'll checkout the branch and play with it.
Thanks!