Merge lp://staging/~pjv/tomdroid/fix-tomdroid-Android-lifecycle into lp://staging/~tomdroid-maintainers/tomdroid/main

Proposed by pjv
Status: Rejected
Rejected by: Benoit Garret
Proposed branch: lp://staging/~pjv/tomdroid/fix-tomdroid-Android-lifecycle
Merge into: lp://staging/~tomdroid-maintainers/tomdroid/main
Diff against target: None lines
To merge this branch: bzr merge lp://staging/~pjv/tomdroid/fix-tomdroid-Android-lifecycle
Reviewer Review Type Date Requested Status
Benoit Garret Disapprove
Olivier Bilodeau Needs Information
Review via email: mp+7982@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
pjv (pjv) wrote :

- remove 'close' menu item as it is not necessary with Andro...
- remove 'close' menu item as it is not necessary with Android
- substitute OI About as about dialog
- use a Service to fill the ContentProvider (does not remove notes yet!) and let Android fill the list from the ContentProvider itself.

Revision history for this message
Olivier Bilodeau (plaxx) wrote :

Sorry for the long delay. I just merged Benoit's storage-redesign branch and it took me way longer than it should have.

My comments on your branch:
A lot of different things here that should not be related in one branch.

- The close item was dealt with.
- I'm not convinced with OI About.. I mean you have to install an app to get an about dialog..? Why isn't OI About a LGPL jar file instead of a full and seperate APK?
- What's the advantage of using a Service vs the sqlite db and provider?

If you don't reply and just don't want to hear about tomdroid anymore I would understand. I've been terribly slow.

review: Needs Information
Revision history for this message
pjv (pjv) wrote :

I don't have much time right now. Tomdroid's code changed a lot, you should not merge anything this old.

> - I'm not convinced with OI About.. I mean you have to install an app to get
> an about dialog..? Why isn't OI About a LGPL jar file instead of a full and
> seperate APK?
Phone memory is not abundant. One app like that can take detailed information about authors, open source license, etc, and handle/show it well (the reuse principle). Besides, what's a quick one-time install from the market? Gnome/gtk also has a universal about box.

> - What's the advantage of using a Service vs the sqlite db and provider?
The service was for searching the notes on the fs, right? If so then it was not vs. the db or provider but vs the class that searched the notes (on Tomdroid startup?). Services are dedicated to running in the background, and can be run seperately from the program. For instance, on insert of another sd card, or on bootup.

Shall I get back to you on this?

Revision history for this message
Benoit Garret (benoit.garret) wrote :

Can I close this merge request? It's nearly been a year and I'm guessing it would be quicker to create a new branch on top of the current main.

Revision history for this message
Benoit Garret (benoit.garret) wrote :

Age of the merge request and one big patch means it's basically unmergeable. I'm closing this.

review: Disapprove
Revision history for this message
pjv (pjv) wrote :

What a waste ;-) but yeah it has become unmergeable. The ContentProvider idea still seems like a good idea to me. Not sure what Tomdroid is using now. OI About also is still in use.

Revision history for this message
Benoit Garret (benoit.garret) wrote :

We're plugging the NoteProvider through a subclass of SimpleCursorAdapter, basically what you did with a little bit of sugar on top.

I'm with Olivier on the about dialog, a full app to handle a dumb dialog seems overkill to me.

I believe what really killed this merge was the fact that you put everything in one commit, preventing us from merging the parts of the work that everyone agreed upon. That, and less work for the maintainer means a greater chance of inclusion (after all, we're as lazy as the next developer ;-) ).

Unmerged revisions

141. By pjv

- remove 'close' menu item as it is not necessary with Android
- substitute OI About as about dialog
- use a Service to fill the ContentProvider (does not remove notes yet!) and let Android fill the list from the ContentProvider itself.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.classpath'
2--- .classpath 2009-06-21 15:58:01 +0000
3+++ .classpath 2009-06-27 21:04:05 +0000
4@@ -4,5 +4,6 @@
5 <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
6 <classpathentry kind="lib" path="lib/joda-time/joda-time-1.6.jar"/>
7 <classpathentry kind="src" path="gen"/>
8+ <classpathentry combineaccessrules="false" kind="src" path="/OI About"/>
9 <classpathentry kind="output" path="bin"/>
10 </classpath>
11
12=== modified file '.project'
13--- .project 2008-11-19 07:01:14 +0000
14+++ .project 2009-06-27 21:04:05 +0000
15@@ -1,6 +1,6 @@
16 <?xml version="1.0" encoding="UTF-8"?>
17 <projectDescription>
18- <name>tomdroid</name>
19+ <name>tomdroid-fix-Android-lifecycle</name>
20 <comment></comment>
21 <projects>
22 </projects>
23
24=== modified file 'AndroidManifest.xml'
25--- AndroidManifest.xml 2009-06-24 19:50:22 +0000
26+++ AndroidManifest.xml 2009-06-27 21:04:05 +0000
27@@ -6,7 +6,27 @@
28 <uses-sdk android:minSdkVersion="1" />
29
30 <application android:icon="@drawable/icon" android:label="@string/app_name">
31-
32+ <meta-data android:name="org.openintents.metadata.COMMENTS"
33+ android:value="@string/about_comments" />
34+ <meta-data android:name="org.openintents.metadata.COPYRIGHT"
35+ android:value="@string/about_copyright" />
36+ <meta-data android:name="org.openintents.metadata.AUTHORS"
37+ android:resource="@array/about_authors" />
38+ <meta-data android:name="org.openintents.metadata.DOCUMENTERS"
39+ android:resource="@array/about_documenters" />
40+ <meta-data android:name="org.openintents.metadata.TRANSLATORS"
41+ android:resource="@string/about_translators" />
42+ <meta-data android:name="org.openintents.metadata.ARTISTS"
43+ android:resource="@array/about_artists" />
44+ <meta-data android:name="org.openintents.metadata.WEBSITE_LABEL"
45+ android:value="@string/about_website_label" />
46+ <meta-data android:name="org.openintents.metadata.WEBSITE_URL"
47+ android:value="@string/about_website_url" />
48+ <meta-data android:name="org.openintents.metadata.EMAIL"
49+ android:value="@string/about_email" />
50+ <meta-data android:name="org.openintents.metadata.LICENSE"
51+ android:resource="@raw/license_short" />
52+
53 <activity android:label="@string/app_name"
54 android:name=".ui.Tomdroid"
55 android:launchMode="singleTop"
56@@ -31,6 +51,8 @@
57 <provider android:name="NoteProvider"
58 android:authorities="org.tomdroid.notes"
59 />
60+
61+ <service android:name="NoteCollectingService"></service>
62 </application>
63 <uses-permission android:name="android.permission.INTERNET" />
64 </manifest>
65\ No newline at end of file
66
67=== modified file 'res/layout/main_list_item.xml'
68--- res/layout/main_list_item.xml 2009-06-23 02:51:17 +0000
69+++ res/layout/main_list_item.xml 2009-06-27 21:04:05 +0000
70@@ -21,9 +21,10 @@
71 You should have received a copy of the GNU General Public License
72 along with Tomdroid. If not, see <http://www.gnu.org/licenses/>.
73 -->
74-<TextView android:id="@+id/note_title" xmlns:android="http://schemas.android.com/apk/res/android"
75+<TextView android:id="@android:id/text1" xmlns:android="http://schemas.android.com/apk/res/android"
76 android:layout_width="fill_parent"
77- android:layout_height="fill_parent"
78- android:textSize="24dp"
79- android:padding="10dip"
80- />
81+ android:layout_height="wrap_content"
82+ android:minHeight="?android:attr/listPreferredItemHeight"
83+ android:textAppearance="?android:attr/textAppearanceLarge"
84+ android:gravity="center_vertical"
85+ android:paddingLeft="5dip"/>
86
87=== modified file 'res/menu/main.xml'
88--- res/menu/main.xml 2009-04-06 01:07:32 +0000
89+++ res/menu/main.xml 2009-06-27 21:04:05 +0000
90@@ -28,11 +28,11 @@
91 android:title="@string/menuLoadWebNote"
92 android:id="@+id/menuLoadWebNote"
93 />
94- <item
95+ <!-- <item
96 android:icon="@drawable/icon_close"
97 android:title="@string/menuClose"
98 android:id="@+id/menuClose"
99- />
100+ /> -->
101 <item
102 android:icon="@drawable/icon_about"
103 android:title="@string/menuAbout"
104
105=== added directory 'res/raw'
106=== added file 'res/raw/license_short'
107--- res/raw/license_short 1970-01-01 00:00:00 +0000
108+++ res/raw/license_short 2009-06-27 21:04:05 +0000
109@@ -0,0 +1,12 @@
110+Tomdroid is free software: you can redistribute it and/or modify
111+it under the terms of the GNU General Public License as published by
112+the Free Software Foundation, either version 3 of the License, or
113+(at your option) any later version.
114+
115+Tomdroid is distributed in the hope that it will be useful,
116+but WITHOUT ANY WARRANTY; without even the implied warranty of
117+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
118+GNU General Public License for more details.
119+
120+You should have received a copy of the GNU General Public License
121+along with Tomdroid. If not, see <http://www.gnu.org/licenses/>.
122\ No newline at end of file
123
124=== added file 'res/values/arrays.xml'
125--- res/values/arrays.xml 1970-01-01 00:00:00 +0000
126+++ res/values/arrays.xml 2009-06-27 21:04:05 +0000
127@@ -0,0 +1,21 @@
128+<?xml version="1.0" encoding="utf-8"?>
129+<resources>
130+ <string-array name="about_authors">
131+ <item>Olivier Bilodeau olivier@bottomlesspit.org</item>
132+ <item>pjv https://launchpad.net/~pjv</item>
133+ <item>This app reuses several system / typical components.</item>
134+ </string-array>
135+
136+ <string-array name="about_documenters">
137+ <item>Olivier Bilodeau olivier@bottomlesspit.org</item>
138+ <item>pjv https://launchpad.net/~pjv</item>
139+ </string-array>
140+
141+ <string-array name="about_translators">
142+ <item>Olivier Bilodeau olivier@bottomlesspit.org</item>
143+ </string-array>
144+
145+ <string-array name="about_artists">
146+ <item>Olivier Bilodeau olivier@bottomlesspit.org</item>
147+ </string-array>
148+</resources>
149\ No newline at end of file
150
151=== modified file 'res/values/strings.xml'
152--- res/values/strings.xml 2009-06-21 22:50:37 +0000
153+++ res/values/strings.xml 2009-06-27 21:04:05 +0000
154@@ -23,9 +23,7 @@
155 -->
156 <resources>
157 <string name="app_name">Tomdroid</string>
158- <string name="app_desc">Tomboy compatible wikiwiki note-taking application that can\'t take notes yet.</string>
159- <string name="author">Olivier Bilodeau</string>
160-
161+
162 <!-- main.xml -->
163 <string name="strListEmptyWaiting">Please wait while the notes load..</string>
164 <string name="strListEmptyNoNotes">
165@@ -46,12 +44,20 @@
166 \n\nIf you would like to contribute, help at all levels would be appreciated.
167 Hop on board on launchpad.net/tomdroid and contact us!\n
168 </string>
169- <string name="strAbout">
170- %1$s
171- \n\nAuthor: %2$s
172- \nVersion: %3$s
173- \nLicensed under the GPLv3
174- </string>
175+
176+ <!-- About -->
177+
178+ <string name="about_comments">Tomboy compatible wikiwiki note-taking application that can\'t take notes yet.</string>
179+ <string name="about_copyright">Copyright © 2009 Olivier Bilodeau</string><!-- Add your name here, separated with comma's, if you helped out -->
180+ <string name="about_website_label">Project page</string>
181+ <string name="about_website_url">http://www.launchpad.net/tomdroid/</string>
182+ <string name="about_email">olivier@bottomlesspit.org</string>
183+ <string name="about_feedback">tomdroid-dev@lists.launchpad.net</string>
184+ <string name="about_translators">translator-credits</string>
185+ <string name="about_backup">To view information about this app you need to install OI About. See http://www.openintents.org/ or the Market.</string>
186+ <string name="link_about_dialog">market://search?q=pname:org.openintents.about</string>
187+ <string name="market_backup">You do not seem to have the Android Market app installed. Ignoring.</string>
188+
189
190 <!-- load_web_note_dialog.xml -->
191 <string name="strLoadFromWebTitle">Note from the Web</string>
192
193=== modified file 'src/org/tomdroid/Note.java'
194--- src/org/tomdroid/Note.java 2009-06-21 20:25:16 +0000
195+++ src/org/tomdroid/Note.java 2009-06-27 21:04:05 +0000
196@@ -25,6 +25,7 @@
197 import org.joda.time.DateTime;
198 import org.joda.time.format.DateTimeFormatter;
199 import org.joda.time.format.ISODateTimeFormat;
200+import org.tomdroid.ui.Tomdroid;
201
202 import android.text.Spannable;
203 import android.text.SpannableStringBuilder;
204@@ -45,7 +46,7 @@
205 public static final String[] PROJECTION = { Note.ID, Note.TITLE, Note.FILE, Note.MODIFIED_DATE };
206
207 // Logging info
208- private static final String TAG = "Note";
209+ private static final String TAG = Tomdroid.TAG;//"Note";
210
211 // Notes constants
212 // TODO this is a weird yellow that was usable for the android emulator, I must confirm this for real usage
213
214=== added file 'src/org/tomdroid/NoteCollectingService.java'
215--- src/org/tomdroid/NoteCollectingService.java 1970-01-01 00:00:00 +0000
216+++ src/org/tomdroid/NoteCollectingService.java 2009-06-27 21:04:05 +0000
217@@ -0,0 +1,183 @@
218+package org.tomdroid;
219+
220+import java.io.BufferedReader;
221+import java.io.File;
222+import java.io.FileInputStream;
223+import java.io.FileNotFoundException;
224+import java.io.FilenameFilter;
225+import java.io.IOException;
226+import java.io.InputStreamReader;
227+
228+import javax.xml.parsers.ParserConfigurationException;
229+import javax.xml.parsers.SAXParser;
230+import javax.xml.parsers.SAXParserFactory;
231+
232+import org.tomdroid.ui.Tomdroid;
233+import org.tomdroid.xml.NoteHandler;
234+import org.xml.sax.InputSource;
235+import org.xml.sax.SAXException;
236+import org.xml.sax.XMLReader;
237+
238+import android.app.Service;
239+import android.content.ContentValues;
240+import android.content.Intent;
241+import android.database.Cursor;
242+import android.net.Uri;
243+import android.os.IBinder;
244+import android.util.Log;
245+
246+public class NoteCollectingService extends Service {
247+ private File notesRoot;
248+
249+ // domain elements
250+ private NoteCollection noteCollection;
251+
252+ // Logging info
253+ private static final String TAG = Tomdroid.TAG;//"NoteCollectingService";
254+
255+ /* (non-Javadoc)
256+ * @see android.app.Service#onStart(android.content.Intent, int)
257+ */
258+ @Override
259+ public void onStart(Intent intent, int startId) {
260+ // TODO Auto-generated method stub
261+ super.onStart(intent, startId);
262+
263+ noteCollection = NoteCollection.getInstance();
264+ notesRoot = new File(Tomdroid.NOTES_PATH);
265+ try {
266+ if (!notesRoot.exists()) {
267+ throw new FileNotFoundException("Tomdroid notes folder doesn't exist. It is configured to be at: "+Tomdroid.NOTES_PATH);
268+ }//TODO: FNFE not catched anymore
269+ } catch (FileNotFoundException e) {
270+ e.printStackTrace();
271+ }
272+ new Thread(new Runnable() {
273+ public void run() {
274+ readAndParseNotes();
275+ stopSelf();
276+ }
277+ }).start();
278+ }
279+
280+
281+ public void readAndParseNotes() {
282+ File[] fileList = notesRoot.listFiles(new NotesFilter());
283+
284+ // If there are no notes, warn the UI through an empty message
285+ if (fileList.length == 0) {
286+ //TODO: also remove notes from ContentProvider
287+ }
288+
289+ for (File file : fileList) {
290+
291+ // give a filename to a thread and ask to parse it when nothing's left to do its over
292+ parseFile(file);
293+ }
294+ }
295+
296+ /**
297+ * Simple filename filter that grabs files ending with .note
298+ * TODO move into its own static class in a util package
299+ */
300+ class NotesFilter implements FilenameFilter {
301+ public boolean accept(File dir, String name) {
302+ return (name.endsWith(".note"));
303+ }
304+ }
305+
306+
307+ public void parseFile(File file) {
308+ Note note = new Note();
309+
310+ note.setFileName(file.getAbsolutePath());
311+
312+ try {
313+ // Parsing
314+ // XML
315+ // Get a SAXParser from the SAXPArserFactory
316+ SAXParserFactory spf = SAXParserFactory.newInstance();
317+ SAXParser sp = spf.newSAXParser();
318+
319+ // Get the XMLReader of the SAXParser we created
320+ XMLReader xr = sp.getXMLReader();
321+
322+ // Create a new ContentHandler, send it this note to fill and apply it to the XML-Reader
323+ NoteHandler xmlHandler = new NoteHandler(note);
324+ xr.setContentHandler(xmlHandler);
325+
326+
327+ // Create the proper input source based on if its a local note or a web note
328+ FileInputStream fin = new FileInputStream(file);
329+ BufferedReader in = new BufferedReader(new InputStreamReader(fin), 8192);
330+ InputSource is = new InputSource(in);
331+
332+ if (Tomdroid.LOGGING_ENABLED) Log.v(TAG, "parsing note");
333+ xr.parse(is);
334+
335+ // TODO wrap and throw a new exception here
336+ } catch (ParserConfigurationException e) {
337+ e.printStackTrace();
338+ } catch (SAXException e) {
339+ e.printStackTrace();
340+ } catch (IOException e) {
341+ e.printStackTrace();
342+ }
343+
344+ synchronized (noteCollection) {
345+ noteCollection.addNote(note);
346+ }
347+
348+ // notify UI that we are done here and send result
349+ updateNoteListWith(note.getTitle());
350+ }
351+
352+ private void updateNoteListWith(String noteTitle) {
353+
354+ // get the note instance we will work with that instead from now on
355+ Note note = NoteCollection.getInstance().findNoteFromTitle(noteTitle);
356+
357+ // verify if the note is already in the content provider
358+
359+ // TODO I could see a problem where someone delete a note and recreate one with the same title.
360+ // It would been seen as not new although it is (it will have a new filename)
361+ // TODO make the query prettier (use querybuilder)
362+ Uri notes = Tomdroid.CONTENT_URI;
363+ String[] whereArgs = new String[1];
364+ whereArgs[0] = noteTitle;
365+ Cursor managedCursor = getContentResolver().query( notes,
366+ NoteProvider.PROJECTION,
367+ Note.TITLE + "= ?",
368+ whereArgs,
369+ Note.TITLE + " ASC");
370+ if (managedCursor.getCount() == 0) {
371+
372+ // This note is not in the database yet we need to insert it
373+ if (Tomdroid.LOGGING_ENABLED) Log.v(TAG,"A new note has been detected (not yet in db)");
374+
375+ // This add the note to the content Provider
376+ // TODO PoC code that should be removed in next iteration's refactoring (no notecollection, everything should come from the provider I guess?)
377+ ContentValues values = new ContentValues();
378+ values.put(Note.TITLE, note.getTitle());
379+ values.put(Note.FILE, note.getFileName());
380+ Uri uri = getContentResolver().insert(Tomdroid.CONTENT_URI, values);
381+ // now that we inserted the note put its ID in the note itself
382+ note.setDbId(Integer.parseInt(uri.getLastPathSegment()));
383+
384+ if (Tomdroid.LOGGING_ENABLED) Log.v(TAG,"Note inserted in content provider. ID: "+uri+" TITLE:"+noteTitle+" ID:"+note.getDbId());
385+ } else {
386+
387+ // find out the note's id and put it in the note
388+ if (managedCursor.moveToFirst()) {
389+ int idColumn = managedCursor.getColumnIndex(Note.ID);
390+ note.setDbId(managedCursor.getInt(idColumn));
391+ }
392+ }
393+ }
394+
395+
396+ @Override
397+ public IBinder onBind(Intent intent) {
398+ throw new RuntimeException("onBind not supported for NoteCollectingService");
399+ }
400+}
401
402=== modified file 'src/org/tomdroid/NoteCollection.java'
403--- src/org/tomdroid/NoteCollection.java 2009-06-21 22:20:10 +0000
404+++ src/org/tomdroid/NoteCollection.java 2009-06-27 21:04:05 +0000
405@@ -22,17 +22,13 @@
406 */
407 package org.tomdroid;
408
409-import java.io.File;
410-import java.io.FileNotFoundException;
411 import java.util.ArrayList;
412 import java.util.Iterator;
413 import java.util.List;
414 import java.util.regex.Pattern;
415
416 import org.tomdroid.ui.Tomdroid;
417-import org.tomdroid.util.AsyncNoteLoaderAndParser;
418
419-import android.os.Handler;
420 import android.util.Log;
421
422 // TODO Transform the NoteCollection into a Provider (see .../android-sdk-linux_x86-1.0_r1/docs/devel/data/contentproviders.html#creatingacontentprovider)
423@@ -44,7 +40,7 @@
424 private List<Note> notes = new ArrayList<Note>();
425
426 // Logging info
427- private static final String TAG = "NoteCollection";
428+ private static final String TAG = Tomdroid.TAG;//"NoteCollection";
429
430 public List<Note> getNotes() {
431 return notes;
432@@ -76,6 +72,18 @@
433 return null;
434 }
435
436+ public synchronized Note findNoteFromDbId(long id) {
437+ if (Tomdroid.LOGGING_ENABLED) Log.d(TAG,"searching for note with db id: "+id);
438+ Iterator<Note> i = notes.iterator();
439+ while(i.hasNext()) {
440+ Note curNote = i.next();
441+ if (curNote.getDbId()==id) {
442+ return curNote;
443+ }
444+ }
445+ return null;
446+ }
447+
448 // TODO there is most likely a better way to do this
449 public Note findNoteFromFilename(String filename) {
450 if (Tomdroid.LOGGING_ENABLED) Log.d(TAG,"searching for note with filename: "+filename);
451@@ -88,18 +96,6 @@
452 }
453 return null;
454 }
455-
456- // TODO also throw a empty exception that we will catch in tomdroid and display the empty notelist msg
457- public void loadNotes(Handler hndl) throws FileNotFoundException {
458- File notesRoot = new File(Tomdroid.NOTES_PATH);
459-
460- if (!notesRoot.exists()) {
461- throw new FileNotFoundException("Tomdroid notes folder doesn't exist. It is configured to be at: "+Tomdroid.NOTES_PATH);
462- }
463-
464- AsyncNoteLoaderAndParser asyncLoader = new AsyncNoteLoaderAndParser(notesRoot, this, hndl);
465- asyncLoader.readAndParseNotes();
466- }
467
468 /**
469 * Builds a regular expression pattern that will match any of the note title currently in the collection.
470
471=== modified file 'src/org/tomdroid/NoteProvider.java'
472--- src/org/tomdroid/NoteProvider.java 2009-04-06 22:30:41 +0000
473+++ src/org/tomdroid/NoteProvider.java 2009-06-27 21:04:05 +0000
474@@ -67,20 +67,25 @@
475 // --
476 private static final String DATABASE_NAME = "tomdroid-notes.db";
477 private static final String DB_TABLE_NOTES = "notes";
478- private static final int DB_VERSION = 1;
479+ private static final int DB_VERSION = 2;
480 // TODO once properly implemented, sort by: KEY_MODIFIED_DATE + " DESC"
481- private static final String DEFAULT_SORT_ORDER = Note.ID;
482+ public static final String DEFAULT_SORT_ORDER = Note.ID;
483
484 private static HashMap<String, String> notesProjectionMap;
485
486 private static final int NOTES = 1;
487 private static final int NOTE_ID = 2;
488 private static final int NOTE_TITLE = 3;
489+
490+ public static final String[] PROJECTION = new String[] {
491+ Note.ID,
492+ Note.TITLE,
493+ };
494
495 private static final UriMatcher uriMatcher;
496
497 // Logging info
498- private static final String TAG = "NoteProvider";
499+ private static final String TAG = Tomdroid.TAG;//"NoteProvider";
500
501 /**
502 * This class helps open, create, and upgrade the database file.
503
504=== modified file 'src/org/tomdroid/ui/Tomdroid.java'
505--- src/org/tomdroid/ui/Tomdroid.java 2009-06-24 19:50:22 +0000
506+++ src/org/tomdroid/ui/Tomdroid.java 2009-06-27 21:04:05 +0000
507@@ -22,24 +22,24 @@
508 */
509 package org.tomdroid.ui;
510
511-import java.io.FileNotFoundException;
512+import java.io.File;
513
514+import org.openintents.intents.AboutIntents;
515 import org.tomdroid.Note;
516+import org.tomdroid.NoteCollectingService;
517 import org.tomdroid.NoteCollection;
518+import org.tomdroid.NoteProvider;
519 import org.tomdroid.R;
520
521 import android.app.AlertDialog;
522 import android.app.ListActivity;
523-import android.content.ContentValues;
524+import android.content.ActivityNotFoundException;
525 import android.content.DialogInterface;
526 import android.content.Intent;
527 import android.content.DialogInterface.OnClickListener;
528-import android.content.pm.PackageManager.NameNotFoundException;
529 import android.database.Cursor;
530 import android.net.Uri;
531 import android.os.Bundle;
532-import android.os.Handler;
533-import android.os.Message;
534 import android.util.Log;
535 import android.view.Menu;
536 import android.view.MenuInflater;
537@@ -47,7 +47,9 @@
538 import android.view.View;
539 import android.widget.ArrayAdapter;
540 import android.widget.ListView;
541+import android.widget.SimpleCursorAdapter;
542 import android.widget.TextView;
543+import android.widget.Toast;
544
545 public class Tomdroid extends ListActivity {
546
547@@ -56,16 +58,15 @@
548 public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/notes");
549 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.tomdroid.note";
550 public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.tomdroid.note";
551- public static final String PROJECT_HOMEPAGE = "http://www.launchpad.net/tomdroid/";
552-
553+
554 // config parameters
555 // TODO hardcoded for now
556 public static final String NOTES_PATH = "/sdcard/tomdroid/";
557 // Logging should be disabled for release builds
558- public static final boolean LOGGING_ENABLED = false;
559+ public static final boolean LOGGING_ENABLED = true;
560
561 // Logging info
562- private static final String TAG = "Tomdroid";
563+ public static final String TAG = "Tomdroid";
564
565 // data keys
566 public static final String RESULT_URL_TO_LOAD = "urlToLoad";
567@@ -78,7 +79,6 @@
568 private NoteCollection localNotes;
569
570 // UI to data model glue
571- private ArrayAdapter<String> notesListAdapter;
572 private TextView listEmptyView;
573
574 // Bundle keys for saving state
575@@ -111,9 +111,23 @@
576 .show();
577 }
578
579- // listAdapter that binds the UI to the notes names
580- notesListAdapter = new ArrayAdapter<String>(this, R.layout.main_list_item);
581- setListAdapter(notesListAdapter);
582+ // If no data was given in the intent (because we were started
583+ // as a MAIN activity), then use our default content provider.
584+ Intent intent = getIntent();
585+ if (intent.getData() == null) {
586+ intent.setData(CONTENT_URI);
587+ }
588+
589+
590+ // Perform a managed query. The Activity will handle closing and requerying the cursor
591+ // when needed.
592+ Cursor cursor = managedQuery(getIntent().getData(), NoteProvider.PROJECTION, null, null,
593+ NoteProvider.DEFAULT_SORT_ORDER);
594+
595+ // Used to map notes entries from the database to views
596+ SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.main_list_item, cursor,
597+ new String[] { Note.TITLE }, new int[] { android.R.id.text1 });
598+ setListAdapter(adapter);
599
600 // set the view shown when the list is empty
601 listEmptyView = (TextView)findViewById(R.id.list_empty);
602@@ -121,24 +135,19 @@
603
604 // start loading local notes
605 if (LOGGING_ENABLED) Log.v(TAG, "Loading local notes");
606-
607+ File notesRoot = new File(Tomdroid.NOTES_PATH);
608+ if (!notesRoot.exists()) {
609+ new AlertDialog.Builder(this)
610+ .setMessage("Tomdroid notes folder doesn't exist. It is configured to be at: "+Tomdroid.NOTES_PATH)
611+ .setTitle("Error")
612+ .setNeutralButton("Ok", new OnClickListener() {
613+ public void onClick(DialogInterface dialog, int which) {
614+ dialog.dismiss();
615+ }})
616+ .show();
617+ }
618+ startService(new Intent(this, NoteCollectingService.class));
619 localNotes = NoteCollection.getInstance();
620- try {
621- localNotes.loadNotes(handler);
622- } catch (FileNotFoundException e) {
623- //TODO put strings in ressource
624- listEmptyView.setText(R.string.strListEmptyNoNotes);
625- new AlertDialog.Builder(this)
626- .setMessage(e.getMessage())
627- .setTitle("Error")
628- .setNeutralButton("Ok", new OnClickListener() {
629- public void onClick(DialogInterface dialog, int which) {
630- dialog.dismiss();
631- }})
632- .show();
633- e.printStackTrace();
634- }
635-
636 }
637
638 @Override
639@@ -156,12 +165,12 @@
640 case R.id.menuLoadWebNote:
641 showLoadWebNoteDialog();
642 return true;
643-
644+/*
645 case R.id.menuClose:
646 // closing everything then closing itself
647 finishActivity(ACTIVITY_VIEW);
648 finish();
649- return true;
650+ return true;*/
651
652 case R.id.menuAbout:
653 showAboutDialog();
654@@ -180,41 +189,29 @@
655 outState.putBoolean(WARNING_SHOWN, true);
656 }
657 }
658-
659- private void showAboutDialog() {
660+
661+ /**
662+ * Show an about dialog for this application.
663+ */
664+ protected void showAboutDialog() {
665+ Intent intent = new Intent(AboutIntents.ACTION_SHOW_ABOUT_DIALOG);
666
667- // grab version info
668- String ver;
669- try {
670- ver = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
671- } catch (NameNotFoundException e) {
672- e.printStackTrace();
673- ver = "Not found!";
674+ // Start about activity. Needs to be "forResult" with requestCode>=0
675+ // so that the package name is passed properly.
676+ //
677+ // The details are obtained from the Manifest through
678+ // default tags and metadata.
679+ try{
680+ startActivityForResult(intent, 0);
681+ }catch(ActivityNotFoundException e){
682+ try{
683+ //FlurryAgent.onError("LCA:showAboutDialog1", getString(R.string.about_backup), "Toast");
684+ startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.link_about_dialog))));
685+ }catch(ActivityNotFoundException e2){
686+ //FlurryAgent.onError("LCA:showAboutDialog2", getString(R.string.about_backup), "Toast");
687+ Toast.makeText(this, getString(R.string.market_backup), Toast.LENGTH_LONG).show();
688+ }
689 }
690-
691- // format the string
692- String aboutDialogFormat = getString(R.string.strAbout);
693- String aboutDialogStr = String.format(aboutDialogFormat,
694- getString(R.string.app_desc), // App description
695- getString(R.string.author), // Author name
696- ver // Version
697- );
698-
699- // build and show the dialog
700- new AlertDialog.Builder(this)
701- .setMessage(aboutDialogStr)
702- .setTitle("About Tomdroid")
703- .setIcon(R.drawable.icon)
704- .setNegativeButton("Project page", new OnClickListener() {
705- public void onClick(DialogInterface dialog, int which) {
706- startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Tomdroid.PROJECT_HOMEPAGE)));
707- dialog.dismiss();
708- }})
709- .setPositiveButton("Ok", new OnClickListener() {
710- public void onClick(DialogInterface dialog, int which) {
711- dialog.dismiss();
712- }})
713- .show();
714 }
715
716 @Override
717@@ -229,31 +226,12 @@
718 }
719 }
720 }
721-
722- private Handler handler = new Handler() {
723-
724- @Override
725- public void handleMessage(Message msg) {
726-
727- // thread is done fetching a note and parsing went well
728- if (msg.what == Note.NOTE_RECEIVED_AND_VALID) {
729-
730- // update the note list with this newly parsed note
731- updateNoteListWith(msg.getData().getString(Note.TITLE));
732-
733- } else if (msg.what == Note.NO_NOTES) {
734-
735- // if there are no notes, say so in the list_empty message
736- listEmptyView.setText(R.string.strListEmptyNoNotes);
737- }
738- }
739- };
740
741 @Override
742 protected void onListItemClick(ListView l, View v, int position, long id) {
743
744 // get the clicked note
745- Note n = localNotes.findNoteFromTitle(notesListAdapter.getItem(position));
746+ Note n = localNotes.findNoteFromDbId(id);
747
748 Intent i = new Intent(Tomdroid.this, ViewNote.class);
749 i.putExtra(Note.FILE, n.getFileName());
750@@ -273,54 +251,4 @@
751 i.putExtra(Note.URL, url);
752 startActivity(i);
753 }
754-
755- private void updateNoteListWith(String noteTitle) {
756-
757- // add note to the note list
758- notesListAdapter.add(noteTitle);
759-
760- // get the note instance we will work with that instead from now on
761- Note note = localNotes.findNoteFromTitle(noteTitle);
762-
763- // verify if the note is already in the content provider
764- String[] projection = new String[] {
765- Note.ID,
766- Note.TITLE,
767- };
768-
769- // TODO I could see a problem where someone delete a note and recreate one with the same title.
770- // It would been seen as not new although it is (it will have a new filename)
771- // TODO make the query prettier (use querybuilder)
772- Uri notes = Tomdroid.CONTENT_URI;
773- String[] whereArgs = new String[1];
774- whereArgs[0] = noteTitle;
775- Cursor managedCursor = managedQuery( notes,
776- projection,
777- Note.TITLE + "= ?",
778- whereArgs,
779- Note.TITLE + " ASC");
780- if (managedCursor.getCount() == 0) {
781-
782- // This note is not in the database yet we need to insert it
783- if (LOGGING_ENABLED) Log.v(TAG,"A new note has been detected (not yet in db)");
784-
785- // This add the note to the content Provider
786- // TODO PoC code that should be removed in next iteration's refactoring (no notecollection, everything should come from the provider I guess?)
787- ContentValues values = new ContentValues();
788- values.put(Note.TITLE, note.getTitle());
789- values.put(Note.FILE, note.getFileName());
790- Uri uri = getContentResolver().insert(CONTENT_URI, values);
791- // now that we inserted the note put its ID in the note itself
792- note.setDbId(Integer.parseInt(uri.getLastPathSegment()));
793-
794- if (LOGGING_ENABLED) Log.v(TAG,"Note inserted in content provider. ID: "+uri+" TITLE:"+noteTitle+" ID:"+note.getDbId());
795- } else {
796-
797- // find out the note's id and put it in the note
798- if (managedCursor.moveToFirst()) {
799- int idColumn = managedCursor.getColumnIndex(Note.ID);
800- note.setDbId(managedCursor.getInt(idColumn));
801- }
802- }
803- }
804 }
805
806=== modified file 'src/org/tomdroid/ui/ViewNote.java'
807--- src/org/tomdroid/ui/ViewNote.java 2009-06-21 20:25:16 +0000
808+++ src/org/tomdroid/ui/ViewNote.java 2009-06-27 21:04:05 +0000
809@@ -60,7 +60,7 @@
810 private Note note;
811
812 // Logging info
813- private static final String TAG = "ViewNote";
814+ private static final String TAG = Tomdroid.TAG;//"ViewNote";
815
816 // TODO extract methods in here
817 @Override
818
819=== removed file 'src/org/tomdroid/util/AsyncNoteLoaderAndParser.java'
820--- src/org/tomdroid/util/AsyncNoteLoaderAndParser.java 2009-06-21 21:28:14 +0000
821+++ src/org/tomdroid/util/AsyncNoteLoaderAndParser.java 1970-01-01 00:00:00 +0000
822@@ -1,163 +0,0 @@
823-/*
824- * Tomdroid
825- * Tomboy on Android
826- * http://www.launchpad.net/tomdroid
827- *
828- * Copyright 2009 Olivier Bilodeau <olivier@bottomlesspit.org>
829- *
830- * This file is part of Tomdroid.
831- *
832- * Tomdroid is free software: you can redistribute it and/or modify
833- * it under the terms of the GNU General Public License as published by
834- * the Free Software Foundation, either version 3 of the License, or
835- * (at your option) any later version.
836- *
837- * Tomdroid is distributed in the hope that it will be useful,
838- * but WITHOUT ANY WARRANTY; without even the implied warranty of
839- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
840- * GNU General Public License for more details.
841- *
842- * You should have received a copy of the GNU General Public License
843- * along with Tomdroid. If not, see <http://www.gnu.org/licenses/>.
844- */
845-package org.tomdroid.util;
846-
847-import java.io.BufferedReader;
848-import java.io.File;
849-import java.io.FileInputStream;
850-import java.io.FilenameFilter;
851-import java.io.IOException;
852-import java.io.InputStreamReader;
853-import java.util.concurrent.ExecutorService;
854-import java.util.concurrent.Executors;
855-
856-import javax.xml.parsers.ParserConfigurationException;
857-import javax.xml.parsers.SAXParser;
858-import javax.xml.parsers.SAXParserFactory;
859-
860-import org.tomdroid.Note;
861-import org.tomdroid.NoteCollection;
862-import org.tomdroid.ui.Tomdroid;
863-import org.tomdroid.xml.NoteHandler;
864-import org.xml.sax.InputSource;
865-import org.xml.sax.SAXException;
866-import org.xml.sax.XMLReader;
867-
868-import android.os.Bundle;
869-import android.os.Handler;
870-import android.os.Message;
871-import android.util.Log;
872-
873-public class AsyncNoteLoaderAndParser {
874- private final ExecutorService pool;
875- private final static int poolSize = 1;
876- private File path;
877- private NoteCollection noteCollection;
878- private Handler parentHandler;
879-
880- // logging related
881- private final static String TAG = "AsyncNoteLoaderAndParser";
882-
883- public AsyncNoteLoaderAndParser(File path, NoteCollection nc, Handler hndl) {
884- this.path = path;
885- pool = Executors.newFixedThreadPool(poolSize);
886- noteCollection = nc;
887- parentHandler = hndl;
888- }
889-
890- public void readAndParseNotes() {
891- File[] fileList = path.listFiles(new NotesFilter());
892-
893- // If there are no notes, warn the UI through an empty message
894- if (fileList.length == 0) {
895- parentHandler.sendEmptyMessage(Note.NO_NOTES);
896- }
897-
898- for (File file : fileList) {
899-
900- // give a filename to a thread and ask to parse it when nothing's left to do its over
901- pool.execute(new Worker(file));
902- }
903- }
904-
905- /**
906- * Simple filename filter that grabs files ending with .note
907- * TODO move into its own static class in a util package
908- */
909- class NotesFilter implements FilenameFilter {
910- public boolean accept(File dir, String name) {
911- return (name.endsWith(".note"));
912- }
913- }
914-
915- /**
916- * The worker spawns a new note, parse the file its being given by the executor and add it to the NoteCollection
917- */
918- class Worker implements Runnable {
919-
920- // the note to be loaded and parsed
921- private Note note = new Note();
922- private File file;
923-
924- public Worker(File f) {
925- file = f;
926- }
927-
928- public void run() {
929-
930- note.setFileName(file.getAbsolutePath());
931-
932- try {
933- // Parsing
934- // XML
935- // Get a SAXParser from the SAXPArserFactory
936- SAXParserFactory spf = SAXParserFactory.newInstance();
937- SAXParser sp = spf.newSAXParser();
938-
939- // Get the XMLReader of the SAXParser we created
940- XMLReader xr = sp.getXMLReader();
941-
942- // Create a new ContentHandler, send it this note to fill and apply it to the XML-Reader
943- NoteHandler xmlHandler = new NoteHandler(note);
944- xr.setContentHandler(xmlHandler);
945-
946-
947- // Create the proper input source based on if its a local note or a web note
948- FileInputStream fin = new FileInputStream(file);
949- BufferedReader in = new BufferedReader(new InputStreamReader(fin), 8192);
950- InputSource is = new InputSource(in);
951-
952- if (Tomdroid.LOGGING_ENABLED) Log.v(TAG, "parsing note");
953- xr.parse(is);
954-
955- // TODO wrap and throw a new exception here
956- } catch (ParserConfigurationException e) {
957- e.printStackTrace();
958- } catch (SAXException e) {
959- e.printStackTrace();
960- } catch (IOException e) {
961- e.printStackTrace();
962- }
963-
964- synchronized (noteCollection) {
965- noteCollection.addNote(note);
966- }
967-
968- // notify UI that we are done here and send result
969- warnHandler();
970- }
971-
972- private void warnHandler() {
973-
974- // notify the main UI that we are done here (sending an ok along with the note's title)
975- Message msg = Message.obtain();
976- Bundle bundle = new Bundle();
977- bundle.putString(Note.TITLE, note.getTitle());
978- msg.setData(bundle);
979- msg.what = Note.NOTE_RECEIVED_AND_VALID;
980-
981- parentHandler.sendMessage(msg);
982- }
983-
984- }
985-}
986
987=== modified file 'src/org/tomdroid/util/NoteBuilder.java'
988--- src/org/tomdroid/util/NoteBuilder.java 2009-06-21 20:25:16 +0000
989+++ src/org/tomdroid/util/NoteBuilder.java 2009-06-27 21:04:05 +0000
990@@ -60,7 +60,7 @@
991 // the object being built
992 private Note note = new Note();
993
994- private final String TAG = "NoteBuilder";
995+ private final String TAG = Tomdroid.TAG;//"NoteBuilder";
996
997 // thread related
998 private Thread runner;

Subscribers

People subscribed via source and target branches