diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6f29f736..b57ef31d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -175,6 +175,7 @@
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e0e93276..ff0f565b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -159,6 +159,10 @@
Synchronize with calendar
Choose calendar MobileOrg will use
Calendar name
+ Assimilate calendar entries not inserted by MobileOrg and add them to capture file. EXPERIMENTAL!
+ Assimilate calendar entries
+ Delete entries that have been assimilated from the calendar
+ Delete on assimilation
Clear phone calendar
Are you sure you want to clear the phones\' calendar?
Add reminders for scheduled items to calendar
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index b4a872eb..37d9b82f 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -120,6 +120,18 @@
android:key="calendarHabits"
android:summary="@string/preference_calendar_show_habits_summary"
android:title="@string/preference_calendar_show_habits" />
+
+
0;
+ String date = OrgNodeDate.getDate(this.dtStart, this.dtEnd, isAllDay);
+ String formatedDate = OrgNodeTimeDate.formatDate(
+ OrgNodeTimeDate.TYPE.Timestamp, date);
+
+ String payload = formatedDate + "\n" + this.description;
+
+ if (TextUtils.isEmpty(this.location) == false)
+ payload += "\n:LOCATION: " + this.location;
+
+ node.setPayload(payload);
+ return node;
+ }
+}
diff --git a/src/com/matburt/mobileorg/OrgData/OrgFileParser.java b/src/com/matburt/mobileorg/OrgData/OrgFileParser.java
index 70cf9808..b03617ee 100644
--- a/src/com/matburt/mobileorg/OrgData/OrgFileParser.java
+++ b/src/com/matburt/mobileorg/OrgData/OrgFileParser.java
@@ -11,7 +11,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.text.TextUtils;
-import android.util.Log;
import android.util.Pair;
import com.matburt.mobileorg.OrgData.OrgContract.OrgData;
@@ -223,11 +222,8 @@ public static HashMap getFilesFromIndex(String filecontents) {
Pattern indexOrgFilePattern = Pattern.compile(fileMatchPattern);
Matcher indexOrgFileMatcher = indexOrgFilePattern.matcher(filecontents);
HashMap allOrgFiles = new HashMap();
-
- Log.d("MobileOrg", filecontents);
-
+
while (indexOrgFileMatcher.find()) {
- Log.d("MobileOrg", "Key: " + indexOrgFileMatcher.group(1) + ":" + indexOrgFileMatcher.group(2));
allOrgFiles.put(indexOrgFileMatcher.group(1), indexOrgFileMatcher.group(2));
}
diff --git a/src/com/matburt/mobileorg/OrgData/OrgNodeDate.java b/src/com/matburt/mobileorg/OrgData/OrgNodeDate.java
index d2c2cd35..a4337a7d 100644
--- a/src/com/matburt/mobileorg/OrgData/OrgNodeDate.java
+++ b/src/com/matburt/mobileorg/OrgData/OrgNodeDate.java
@@ -3,6 +3,7 @@
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
+import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -16,6 +17,7 @@ public class OrgNodeDate {
public long endTime = 0;
public int allDay = 0;
public String type = "";
+ private String title = "";
private static final SimpleDateFormat dateTimeformatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private static final SimpleDateFormat dateformatter = new SimpleDateFormat("yyyy-MM-dd");
@@ -73,6 +75,28 @@ private static long getDayInUTC(long time) {
return cal.getTimeInMillis();
}
+ public static String getDate(long dtStart, long dtEnd, boolean allDay) {
+ String date;
+
+ if (allDay)
+ date = dateformatter.format(new Date(dtStart));
+ else
+ date = dateTimeformatter.format(new Date(dtStart));
+
+ if (dtEnd > 0 && dtStart != dtEnd) {
+ long timeDiff = dtEnd - dtStart;
+
+ if(timeDiff <= DateUtils.DAY_IN_MILLIS) {
+ SimpleDateFormat timeformatter = new SimpleDateFormat("HH:mm");
+ String endTime = timeformatter.format(new Date(dtEnd));
+
+ date += "-" + endTime;
+ }
+ }
+
+ return date;
+ }
+
/**
* Whether an event is in the past. True if event ended 24 hours ago or
* sometime in the future.
@@ -80,4 +104,12 @@ private static long getDayInUTC(long time) {
public boolean isInPast() {
return System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS >= endTime;
}
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getTitle() {
+ return this.type + this.title;
+ }
}
diff --git a/src/com/matburt/mobileorg/OrgData/OrgNodePayload.java b/src/com/matburt/mobileorg/OrgData/OrgNodePayload.java
index bd26219e..1ebeb334 100644
--- a/src/com/matburt/mobileorg/OrgData/OrgNodePayload.java
+++ b/src/com/matburt/mobileorg/OrgData/OrgNodePayload.java
@@ -216,24 +216,27 @@ public String getProperty(String property) {
}
- public ArrayList getDates() {
+ public ArrayList getDates(String title) {
ArrayList result = new ArrayList();
try {
OrgNodeDate scheduledEntry = new OrgNodeDate(getScheduled());
scheduledEntry.type = "SC: ";
+ scheduledEntry.setTitle(title);
result.add(scheduledEntry);
} catch (IllegalArgumentException e) {}
try {
OrgNodeDate deadlineEntry = new OrgNodeDate(getDeadline());
deadlineEntry.type = "DL: ";
+ deadlineEntry.setTitle(title);
result.add(deadlineEntry);
} catch (IllegalArgumentException e) {}
try {
OrgNodeDate timestampEntry = new OrgNodeDate(getTimestamp());
timestampEntry.type = "";
+ timestampEntry.setTitle(title);
result.add(timestampEntry);
} catch (IllegalArgumentException e) {}
diff --git a/src/com/matburt/mobileorg/Services/CalendarComptabilityWrappers.java b/src/com/matburt/mobileorg/Services/CalendarComptabilityWrappers.java
new file mode 100644
index 00000000..55d02af3
--- /dev/null
+++ b/src/com/matburt/mobileorg/Services/CalendarComptabilityWrappers.java
@@ -0,0 +1,155 @@
+package com.matburt.mobileorg.Services;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.CalendarContract.CalendarAlerts;
+import android.provider.CalendarContract.Calendars;
+import android.provider.CalendarContract.Events;
+import android.provider.CalendarContract.Reminders;
+
+public class CalendarComptabilityWrappers {
+
+ public intEvents events = new intEvents();
+ public intCalendars calendars = new intCalendars();
+ public intReminders reminders = new intReminders();
+ public intCalendarAlerts calendarAlerts = new intCalendarAlerts();
+ private Context context;
+
+ public String[] eventsProjection;
+
+ public CalendarComptabilityWrappers(Context context) {
+ this.context = context;
+ initCalendar();
+
+ this.eventsProjection = new String[] { events.CALENDAR_ID,
+ events.DTSTART, events.DTEND, events.DESCRIPTION, events.TITLE,
+ events.EVENT_LOCATION, events._ID, events.ALL_DAY };
+ }
+
+ public class intEvents {
+ public Uri CONTENT_URI;
+ public String CALENDAR_ID = "calendar_id";
+ public String TITLE = "title";
+ public String DESCRIPTION = "description";
+ public String EVENT_LOCATION = "eventLocation";
+ public String ALL_DAY = "allDay";
+ public String DTSTART = "dtstart";
+ public String DTEND = "dtend";
+ public String HAS_ALARM = "hasAlarm";
+ public String ORGANIZER = "organizer";
+ public String EVENT_TIMEZONE = "eventTimezone";
+ public String _ID = "_id";
+ };
+
+ public class intCalendars {
+ public Uri CONTENT_URI;
+ public String _ID = "_id";
+ public String CALENDAR_DISPLAY_NAME = "displayName";
+ public String ACCOUNT_NAME = "accountName";
+ public String VISIBLE = "selected";
+ };
+
+ public class intReminders {
+ public Uri CONTENT_URI;
+ public String MINUTES = "minutes";
+ public String EVENT_ID = "event_id";
+ public String METHOD = "method";
+ public int METHOD_ALERT = 1;
+ };
+
+ public class intCalendarAlerts {
+ public Uri CONTENT_URI;
+ public String EVENT_ID = "event_id";
+ public String BEGIN = "begin";
+ public String END = "end";
+ public String ALERT_TIME = "alarmTime";
+ public String MINUTES = "minutes";
+ public String STATE = "state";
+ public int STATE_SCHEDULED = 0;
+ };
+
+ /**
+ * Hack to support phones with Android <3.0
+ */
+ @SuppressLint("NewApi")
+ private void initCalendar() {
+ try {
+ calendars.CONTENT_URI = Calendars.CONTENT_URI;
+ calendars._ID = Calendars._ID;
+ calendars.ACCOUNT_NAME = Calendars.ACCOUNT_NAME;
+ calendars.CALENDAR_DISPLAY_NAME = Calendars.CALENDAR_DISPLAY_NAME;
+ calendars.VISIBLE = Calendars.VISIBLE;
+
+ events.CONTENT_URI = Events.CONTENT_URI;
+ events.CALENDAR_ID = Events.CALENDAR_ID;
+ events.TITLE = Events.TITLE;
+ events.DESCRIPTION = Events.DESCRIPTION;
+ events.EVENT_LOCATION = Events.EVENT_LOCATION;
+ events.ORGANIZER = Events.ORGANIZER;
+ events.ALL_DAY = Events.ALL_DAY;
+ events.DTEND = Events.DTEND;
+ events.DTSTART = Events.DTSTART;
+ events.HAS_ALARM = Events.HAS_ALARM;
+ events.EVENT_TIMEZONE = Events.EVENT_TIMEZONE;
+ events._ID = Events._ID;
+
+ reminders.CONTENT_URI = Reminders.CONTENT_URI;
+ reminders.MINUTES = Reminders.MINUTES;
+ reminders.EVENT_ID = Reminders.EVENT_ID;
+ reminders.METHOD_ALERT = Reminders.METHOD_ALERT;
+ reminders.METHOD = Reminders.METHOD;
+
+ calendarAlerts.CONTENT_URI = CalendarAlerts.CONTENT_URI;
+ calendarAlerts.STATE_SCHEDULED = CalendarAlerts.STATE_SCHEDULED;
+ calendarAlerts.EVENT_ID = CalendarAlerts.EVENT_ID;
+ calendarAlerts.BEGIN = CalendarAlerts.BEGIN;
+ calendarAlerts.END = CalendarAlerts.END;
+ calendarAlerts.ALERT_TIME = CalendarAlerts.ALARM_TIME;
+ calendarAlerts.STATE = CalendarAlerts.STATE;
+ calendarAlerts.MINUTES = CalendarAlerts.MINUTES;
+ } catch (NoClassDefFoundError e) {
+ // The classes referenced above are not available on pre 4.0 phones.
+ setupBaseUris();
+ }
+ }
+
+ private void setupBaseUris() {
+ String baseUri = getCalendarUriBase();
+
+ calendars.CONTENT_URI = Uri.parse(baseUri + "/calendars");
+ events.CONTENT_URI = Uri.parse(baseUri + "/events");
+ reminders.CONTENT_URI = Uri.parse(baseUri + "/reminders");
+ calendarAlerts.CONTENT_URI = Uri.parse(baseUri + "/calendar_alerts");
+ }
+
+ /**
+ * Hack to get the proper calendar uri for pre 4.0 phones.
+ */
+ public String getCalendarUriBase() {
+ String calendarUriBase = null;
+ Uri calendars = Uri.parse("content://com.android.calendar/calendars");
+ Cursor managedCursor = null;
+ try {
+ managedCursor = context.getContentResolver().query(calendars, null, null, null, null);
+ } catch (Exception e) {
+ }
+ if (managedCursor != null) {
+ calendarUriBase = "content://com.android.calendar";
+ managedCursor.close();
+ } else {
+ calendars = Uri.parse("content://calendar/calendars");
+ try {
+ managedCursor = context.getContentResolver().query(calendars, null, null, null, null);
+ } catch (Exception e) {
+ }
+ if (managedCursor != null) {
+ calendarUriBase = "content://calendar";
+ managedCursor.close();
+ }
+ }
+
+ return calendarUriBase;
+ }
+}
diff --git a/src/com/matburt/mobileorg/Services/CalendarSyncService.java b/src/com/matburt/mobileorg/Services/CalendarSyncService.java
index 176727ba..280e57aa 100644
--- a/src/com/matburt/mobileorg/Services/CalendarSyncService.java
+++ b/src/com/matburt/mobileorg/Services/CalendarSyncService.java
@@ -3,419 +3,271 @@
import java.util.ArrayList;
import java.util.HashSet;
-import android.annotation.SuppressLint;
+import android.app.Service;
import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
-import android.database.SQLException;
-import android.net.Uri;
+import android.os.IBinder;
import android.preference.PreferenceManager;
-import android.provider.CalendarContract.CalendarAlerts;
-import android.provider.CalendarContract.Calendars;
-import android.provider.CalendarContract.Events;
-import android.provider.CalendarContract.Reminders;
-import android.text.format.Time;
+import android.util.Log;
-import com.matburt.mobileorg.R;
+import com.matburt.mobileorg.OrgData.CalendarEntriesParser;
+import com.matburt.mobileorg.OrgData.CalendarEntry;
import com.matburt.mobileorg.OrgData.OrgFile;
import com.matburt.mobileorg.OrgData.OrgNode;
import com.matburt.mobileorg.OrgData.OrgNodeDate;
import com.matburt.mobileorg.OrgData.OrgProviderUtils;
+import com.matburt.mobileorg.util.MultiMap;
import com.matburt.mobileorg.util.OrgFileNotFoundException;
import com.matburt.mobileorg.util.OrgNodeNotFoundException;
+import com.matburt.mobileorg.util.OrgUtils;
-public class CalendarSyncService {
- private final static String CALENDAR_ORGANIZER = "MobileOrg";
-
- private intCalendars intCalendars = new intCalendars();
- private intEvents intEvents = new intEvents();
- private intReminders intReminders = new intReminders();
- private intCalendarAlerts intCalendarAlerts = new intCalendarAlerts();
+public class CalendarSyncService extends Service implements
+ SharedPreferences.OnSharedPreferenceChangeListener {
+ public final static String CLEARDB = "clearDB";
+ public final static String PULL = "pull";
+ public final static String PUSH = "push";
+ public final static String FILELIST = "filelist";
private Context context;
private SharedPreferences sharedPreferences;
-
private ContentResolver resolver;
- private String calendarName = "";
- private int calendarId = -1;
- private Integer reminderTime = 0;
- private boolean reminderEnabled = false;
+ private CalendarWrapper calendarWrapper;
+
private boolean showDone = false;
private boolean showPast = true;
private boolean showHabits = false;
+ private boolean pullEnabled = false;
+ private boolean pullDelete = false;
+
private HashSet activeTodos = new HashSet();
private HashSet allTodos = new HashSet();
-
- public CalendarSyncService(ContentResolver resolver, Context context) {
- this.resolver = resolver;
- this.context = context;
- this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
- initCalendar();
- refreshPreferences();
- }
-
- private void refreshPreferences() {
- this.reminderEnabled = sharedPreferences.getBoolean(
- "calendarReminder", false);
-
- if(reminderEnabled) {
- String intervalString = sharedPreferences.getString("calendarReminderInterval", "0");
- if(intervalString == null)
- throw new IllegalArgumentException("Invalid calendar reminder interval");
- this.reminderTime = Integer.valueOf(intervalString);
- }
-
- this.showDone = sharedPreferences.getBoolean("calendarShowDone", true);
- this.showPast = sharedPreferences.getBoolean("calendarShowPast", true);
- this.showHabits = sharedPreferences.getBoolean("calendarHabits", true);
- this.calendarName = PreferenceManager
- .getDefaultSharedPreferences(context).getString("calendarName",
- "");
- this.calendarId = getCalendarID(calendarName);
- this.activeTodos = new HashSet(OrgProviderUtils.getActiveTodos(resolver));
- this.allTodos = new HashSet(OrgProviderUtils.getTodos(resolver));
- }
-
- public void syncFiles() {
- refreshPreferences();
- this.deleteAllEntries(context);
-
- ArrayList files = OrgProviderUtils.getFilenames(resolver);
- files.remove(OrgFile.AGENDA_FILE);
- for(String filename: files)
- insertFileEntries(filename);
- }
-
- public void syncFile(String filename) throws IllegalArgumentException {
- refreshPreferences();
- deleteFileEntries(filename, context);
- insertFileEntries(filename);
- }
-
- public int deleteAllEntries(Context context) {
- refreshPreferences();
- return context.getContentResolver()
- .delete(intEvents.CONTENT_URI, intEvents.DESCRIPTION + " LIKE ?",
- new String[] { CALENDAR_ORGANIZER + "%" });
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
}
- public int deleteFileEntries(String filename, Context context) {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ this.resolver = getContentResolver();
+ this.context = getBaseContext();
+ this.sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ this.sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ this.calendarWrapper = new CalendarWrapper(context);
refreshPreferences();
- return context.getContentResolver().delete(intEvents.CONTENT_URI,
- intEvents.DESCRIPTION + " LIKE ?",
- new String[] { CALENDAR_ORGANIZER + ":" + filename + "%" });
}
-
- public CharSequence[] getCalendars(Context context) {
- CharSequence[] result = new CharSequence[1];
- result[0] = context.getString(R.string.error_setting_no_calendar);
-
- try {
- Cursor cursor = context.getContentResolver().query(
- intCalendars.CONTENT_URI,
- new String[] { intCalendars._ID,
- intCalendars.CALENDAR_DISPLAY_NAME }, null, null,
- null);
- if(cursor == null)
- return result;
-
- if (cursor.getCount() == 0) {
- cursor.close();
- return result;
- }
+ @Override
+ public void onDestroy() {
+ this.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
+ super.onDestroy();
+ }
- if (cursor.moveToFirst()) {
- result = new CharSequence[cursor.getCount()];
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ refreshPreferences();
+ final String[] fileList = intent.getStringArrayExtra(FILELIST);
+ final boolean clearDB = intent.getBooleanExtra(CLEARDB, false);
+ final boolean pull = intent.getBooleanExtra(PULL, false);
+ final boolean push = intent.getBooleanExtra(PUSH, false);
+
+ new Thread() {
+ public void run() {
+ if (clearDB) {
+ if (fileList != null)
+ calendarWrapper.deleteFileEntries(fileList);
+ else
+ calendarWrapper.deleteEntries();
+ }
- for (int i = 0; i < cursor.getCount(); i++) {
- result[i] = cursor.getString(1);
- cursor.moveToNext();
+ if (push) {
+ if (fileList != null)
+ syncFiles(fileList);
+ else
+ syncFiles();
+
+ if (pullEnabled)
+ assimilateCalendar();
+ }
+
+ if (pull) {
+ assimilateCalendar();
}
}
- cursor.close();
- } catch (SQLException e) {}
+ }.start();
- return result;
+ return 0;
}
-
-
- public void insertNode(long node_id) {
- OrgNode node;
- try {
- node = new OrgNode(node_id, resolver);
- } catch (OrgNodeNotFoundException e) {
- return;
- }
- try {
- insertNode(node, node.getOrgFile(resolver).filename);
- } catch (OrgFileNotFoundException e) {
- insertNode(node, "");
+ private void syncFiles() {
+ ArrayList files = OrgProviderUtils.getFilenames(resolver);
+ files.remove(OrgFile.AGENDA_FILE);
+ for (String filename : files)
+ syncFile(filename);
+ }
+
+ private void syncFiles(String[] files) {
+ for (String filename : files) {
+ if (filename.equals(OrgFile.AGENDA_FILE) == false) {
+ syncFile(filename);
+ }
}
}
-
- private void insertFileEntries(String filename) throws IllegalArgumentException {
- Cursor scheduled;
-
+
+
+ private int inserted = 0;
+ private int deleted = 0;
+ private int unchanged = 0;
+
+ private void syncFile(String filename) {
+ inserted = 0;
+ deleted = 0;
+ unchanged = 0;
+
+ Cursor scheduledQuery;
try {
- scheduled = OrgProviderUtils.getFileSchedule(filename, this.showHabits,
- resolver);
+ scheduledQuery = OrgProviderUtils.getFileSchedule(filename,
+ this.showHabits, resolver);
} catch (OrgFileNotFoundException e) {
return;
}
- while (scheduled.isAfterLast() == false) {
+ MultiMap entries = getCalendarEntries(filename);
+
+ while (scheduledQuery.isAfterLast() == false) {
try {
- OrgNode node = new OrgNode(scheduled);
- insertNode(node, filename);
+ OrgNode node = new OrgNode(scheduledQuery);
+ syncNode(node, entries, filename);
} catch (OrgNodeNotFoundException e) {}
- scheduled.moveToNext();
+ scheduledQuery.moveToNext();
}
+ scheduledQuery.close();
- scheduled.close();
+ removeCalendarEntries(entries);
+
+ Log.d("MobileOrg", "Calendar (" + filename + ") Inserted: " + inserted
+ + " and deleted: " + deleted + " unchanged: " + unchanged);
}
-
- private void insertNode(OrgNode node, String filename)
- throws IllegalArgumentException {
- boolean isActive = true;
-
- if(allTodos.contains(node.todo))
- isActive = this.activeTodos.contains(node.todo);
-
- String cleanedName = node.getCleanedName();
-
- for (OrgNodeDate date : node.getOrgNodePayload().getDates()) {
- insertEntry(cleanedName, isActive, node.getCleanedPayload(),
- Long.toString(node.id), date, filename,
- node.getOrgNodePayload().getProperty("LOCATION"));
+
+ private void syncNode(OrgNode node, MultiMap entries,
+ String filename) {
+ for (OrgNodeDate date : node.getOrgNodePayload().getDates(
+ node.getCleanedName())) {
+ if (shouldInsertEntry(node.todo, date))
+ tryToInsertNode(entries, date, filename, node);
}
}
- // TODO Speed up using bulkInserts
- private String insertEntry(String name, boolean isTodoActive, String payload,
- String orgID, OrgNodeDate date, String filename, String location) throws IllegalArgumentException {
-
- if (this.showDone == false && isTodoActive == false)
- return null;
-
- if(this.calendarId == -1)
- throw new IllegalArgumentException("Couldn't find selected calendar: " + calendarName);
-
- if(this.showPast == false && date.isInPast())
- return null;
+ private void tryToInsertNode(MultiMap entries,
+ OrgNodeDate date, String filename, OrgNode node) {
+ CalendarEntry insertedEntry = entries.findValue(date.beginTime, date);
- ContentValues values = new ContentValues();
- values.put(intEvents.CALENDAR_ID, this.calendarId);
- values.put(intEvents.TITLE, date.type + name);
- values.put(intEvents.DESCRIPTION, CALENDAR_ORGANIZER + ":" + filename + "\n" + payload);
- values.put(intEvents.EVENT_LOCATION, location);
-
- // Sync with google will overwrite organizer :(
- //values.put(intEvents.ORGANIZER, embeddedNodeMetadata);
-
- values.put(intEvents.DTSTART, date.beginTime);
- values.put(intEvents.DTEND, date.endTime);
- values.put(intEvents.ALL_DAY, date.allDay);
- values.put(intEvents.HAS_ALARM, 0);
- values.put(intEvents.EVENT_TIMEZONE, Time.getCurrentTimezone());
-
- Uri uri = context.getContentResolver().insert(
- intEvents.CONTENT_URI, values);
- String nodeID = uri.getLastPathSegment();
+ if (insertedEntry != null) {
+ entries.remove(date.beginTime, insertedEntry);
+ unchanged++;
+ } else {
+ calendarWrapper.insertEntry(date, node.getCleanedPayload(), filename, node
+ .getOrgNodePayload().getProperty("LOCATION"));
+ inserted++;
+ }
+ }
+
+ private boolean shouldInsertEntry(String todo, OrgNodeDate date) {
+ boolean isTodoActive = true;
+ if (allTodos.contains(todo))
+ isTodoActive = this.activeTodos.contains(todo);
- if (date.allDay == 0 && this.reminderEnabled)
- addReminder(nodeID, date.beginTime, date.endTime);
+ if (this.showDone == false && isTodoActive == false)
+ return false;
- return nodeID;
- }
- private void addReminder(String eventID, long beginTime, long endTime) {
- if(beginTime < System.currentTimeMillis())
- return;
-
- ContentValues reminderValues = new ContentValues();
- reminderValues.put(intReminders.MINUTES, this.reminderTime);
- reminderValues.put(intReminders.EVENT_ID, eventID);
- reminderValues.put(intReminders.METHOD, intReminders.METHOD_ALERT);
- context.getContentResolver().insert(intReminders.CONTENT_URI, reminderValues);
+ if (this.showPast == false && date.isInPast())
+ return false;
- ContentValues alertvalues = new ContentValues();
- alertvalues.put(intCalendarAlerts.EVENT_ID, eventID );
- alertvalues.put(intCalendarAlerts.BEGIN, beginTime );
- alertvalues.put(intCalendarAlerts.END, endTime );
- alertvalues.put(intCalendarAlerts.ALERT_TIME, this.reminderTime );
- alertvalues.put(intCalendarAlerts.STATE, intCalendarAlerts.STATE_SCHEDULED);
- alertvalues.put(intCalendarAlerts.MINUTES, this.reminderTime );
- context.getContentResolver().insert(intCalendarAlerts.CONTENT_URI,
- alertvalues);
-
- ContentValues eventValues = new ContentValues();
- eventValues.put(intEvents.HAS_ALARM, 1);
- context.getContentResolver().update(
- ContentUris.withAppendedId(intEvents.CONTENT_URI,
- Long.valueOf(eventID)), eventValues, null, null);
+ return true;
}
- private int getCalendarID(String calendarName) {
- Cursor cursor = context.getContentResolver().query(
- intCalendars.CONTENT_URI,
- new String[] { intCalendars._ID,
- intCalendars.CALENDAR_DISPLAY_NAME }, null,
- null, null);
- if (cursor != null && cursor.moveToFirst()) {
- for (int i = 0; i < cursor.getCount(); i++) {
- int calId = cursor.getInt(0);
- String calName = cursor.getString(1);
-
- if (calName.equals(calendarName)) {
- cursor.close();
- return calId;
- }
- cursor.moveToNext();
- }
- cursor.close();
+ private MultiMap getCalendarEntries(String filename) {
+ refreshPreferences();
+
+ Cursor query = calendarWrapper.getCalendarCursor(filename);
+
+ MultiMap map = new MultiMap();
+ CalendarEntriesParser entriesParser = new CalendarEntriesParser(calendarWrapper.calendar.events,
+ query);
+
+ while (query.isAfterLast() == false) {
+ CalendarEntry entry = entriesParser.getEntryFromCursor(query);
+ map.put(entry.dtStart, entry);
+
+ query.moveToNext();
}
- return -1;
+
+ return map;
}
- @SuppressWarnings("unused")
- private int deleteEntry(String nodeCalendarID) {
- return context.getContentResolver().delete(
- ContentUris.withAppendedId(intEvents.CONTENT_URI,
- Long.valueOf(nodeCalendarID)), null, null);
+ private void removeCalendarEntries(MultiMap entries) {
+ for (Long entryKey : entries.keySet()) {
+ for (CalendarEntry entry : entries.get(entryKey)) {
+ calendarWrapper.deleteEntry(entry);
+ deleted++;
+ }
+ }
}
-/*** Compatibility with Android 4.0 *****/
- private class intEvents {
- public Uri CONTENT_URI;
- public String CALENDAR_ID = "calendar_id";
- public String TITLE = "title";
- public String DESCRIPTION = "description";
- public String EVENT_LOCATION = "eventLocation";
- public String ALL_DAY = "allDay";
- public String DTSTART = "dtstart";
- public String DTEND = "dtend";
- public String HAS_ALARM = "hasAlarm";
- @SuppressWarnings("unused")
- public String ORGANIZER = "organizer";
- public String EVENT_TIMEZONE = "eventTimezone";
- };
-
- private class intCalendars {
- public Uri CONTENT_URI;
- public String _ID = "_id";
- public String CALENDAR_DISPLAY_NAME = "displayName";
- @SuppressWarnings("unused")
- public String ACCOUNT_NAME = "accountName";
- @SuppressWarnings("unused")
- public String VISIBLE = "selected";
- };
-
- private class intReminders {
- public Uri CONTENT_URI;
- public String MINUTES = "minutes";
- public String EVENT_ID = "event_id";
- public String METHOD = "method";
- public int METHOD_ALERT = 1;
- };
-
- private class intCalendarAlerts {
- public Uri CONTENT_URI;
- public String EVENT_ID = "event_id";
- public String BEGIN = "begin";
- public String END = "end";
- public String ALERT_TIME = "alarmTime";
- public String MINUTES = "minutes";
- public String STATE = "state";
- public int STATE_SCHEDULED = 0;
- };
-
- /**
- * Hack to support phones with Android <3.0
- */
- @SuppressLint("NewApi")
- private void initCalendar() {
- try {
- intCalendars.CONTENT_URI = Calendars.CONTENT_URI;
- intCalendars._ID = Calendars._ID;
- intCalendars.ACCOUNT_NAME = Calendars.ACCOUNT_NAME;
- intCalendars.CALENDAR_DISPLAY_NAME = Calendars.CALENDAR_DISPLAY_NAME;
- intCalendars.VISIBLE = Calendars.VISIBLE;
-
- intEvents.CONTENT_URI = Events.CONTENT_URI;
- intEvents.CALENDAR_ID = Events.CALENDAR_ID;
- intEvents.TITLE = Events.TITLE;
- intEvents.DESCRIPTION = Events.DESCRIPTION;
- intEvents.EVENT_LOCATION = Events.EVENT_LOCATION;
- intEvents.ORGANIZER = Events.ORGANIZER;
- intEvents.ALL_DAY = Events.ALL_DAY;
- intEvents.DTEND = Events.DTEND;
- intEvents.DTSTART = Events.DTSTART;
- intEvents.HAS_ALARM = Events.HAS_ALARM;
- intEvents.EVENT_TIMEZONE = Events.EVENT_TIMEZONE;
-
- intReminders.CONTENT_URI = Reminders.CONTENT_URI;
- intReminders.MINUTES = Reminders.MINUTES;
- intReminders.EVENT_ID = Reminders.EVENT_ID;
- intReminders.METHOD_ALERT = Reminders.METHOD_ALERT;
- intReminders.METHOD = Reminders.METHOD;
-
- intCalendarAlerts.CONTENT_URI = CalendarAlerts.CONTENT_URI;
- intCalendarAlerts.STATE_SCHEDULED = CalendarAlerts.STATE_SCHEDULED;
- intCalendarAlerts.EVENT_ID = CalendarAlerts.EVENT_ID;
- intCalendarAlerts.BEGIN = CalendarAlerts.BEGIN;
- intCalendarAlerts.END = CalendarAlerts.END;
- intCalendarAlerts.ALERT_TIME = CalendarAlerts.ALARM_TIME;
- intCalendarAlerts.STATE = CalendarAlerts.STATE;
- intCalendarAlerts.MINUTES = CalendarAlerts.MINUTES;
- } catch (NoClassDefFoundError e) {
- // The classes referenced above are not available on pre 4.0 phones.
- setupBaseUris();
+ private void assimilateCalendar() {
+ Cursor query = calendarWrapper.getUnassimilatedCalendarCursor();
+
+ CalendarEntriesParser entriesParser = new CalendarEntriesParser(
+ calendarWrapper.calendar.events, query);
+
+ while(query.isAfterLast() == false) {
+ CalendarEntry entry = entriesParser.getEntryFromCursor(query);
+ OrgNode node = entry.convertToOrgNode();
+
+ OrgFile captureFile = OrgProviderUtils
+ .getOrCreateCaptureFile(getContentResolver());
+ node.fileId = captureFile.id;
+ node.parentId = captureFile.nodeId;
+ node.level = 1;
+
+ node.write(getContentResolver());
+
+ if (this.pullDelete)
+ calendarWrapper.deleteEntry(entry);
+
+ query.moveToNext();
}
- }
-
- private void setupBaseUris() {
- String baseUri = getCalendarUriBase();
- intCalendars.CONTENT_URI = Uri.parse(baseUri + "/calendars");
- intEvents.CONTENT_URI = Uri.parse(baseUri + "/events");
- intReminders.CONTENT_URI = Uri.parse(baseUri + "/reminders");
- intCalendarAlerts.CONTENT_URI = Uri.parse(baseUri + "/calendar_alerts");
+ query.close();
+ OrgUtils.announceSyncDone(this);
}
-
- /**
- * Hack to get the proper calendar uri for pre 4.0 phones.
- */
- private String getCalendarUriBase() {
- String calendarUriBase = null;
- Uri calendars = Uri.parse("content://com.android.calendar/calendars");
- Cursor managedCursor = null;
- try {
- managedCursor = context.getContentResolver().query(calendars, null, null, null, null);
- } catch (Exception e) {
- }
- if (managedCursor != null) {
- calendarUriBase = "content://com.android.calendar";
- managedCursor.close();
- } else {
- calendars = Uri.parse("content://calendar/calendars");
- try {
- managedCursor = context.getContentResolver().query(calendars, null, null, null, null);
- } catch (Exception e) {
- }
- if (managedCursor != null) {
- calendarUriBase = "content://calendar";
- managedCursor.close();
- }
+
+
+ private void refreshPreferences() {
+ this.pullEnabled = sharedPreferences.getBoolean("calendarPull", false);
+ this.pullDelete = sharedPreferences.getBoolean("calendarPullDelete", false);
+ this.showDone = sharedPreferences.getBoolean("calendarShowDone", true);
+ this.showPast = sharedPreferences.getBoolean("calendarShowPast", true);
+ this.showHabits = sharedPreferences.getBoolean("calendarHabits", true);
+ this.activeTodos = new HashSet(
+ OrgProviderUtils.getActiveTodos(resolver));
+ this.allTodos = new HashSet(OrgProviderUtils.getTodos(resolver));
+ this.calendarWrapper.refreshPreferences();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.startsWith("calendar")) {
+ syncFiles();
}
-
- return calendarUriBase;
}
}
diff --git a/src/com/matburt/mobileorg/Services/CalendarWrapper.java b/src/com/matburt/mobileorg/Services/CalendarWrapper.java
new file mode 100644
index 00000000..f11ec4e1
--- /dev/null
+++ b/src/com/matburt/mobileorg/Services/CalendarWrapper.java
@@ -0,0 +1,228 @@
+package com.matburt.mobileorg.Services;
+
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.net.Uri;
+import android.preference.PreferenceManager;
+import android.text.format.Time;
+
+import com.matburt.mobileorg.R;
+import com.matburt.mobileorg.OrgData.CalendarEntry;
+import com.matburt.mobileorg.OrgData.OrgNodeDate;
+
+public class CalendarWrapper {
+
+ private final static String CALENDAR_ORGANIZER = "MobileOrg";
+
+ private Context context;
+ private SharedPreferences sharedPreferences;
+
+ public CalendarComptabilityWrappers calendar;
+
+ private String calendarName = "";
+ private int calendarId = -1;
+ private Integer reminderTime = 0;
+ private boolean reminderEnabled = false;
+
+ public CalendarWrapper(Context context) {
+ this.context = context;
+ this.sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ this.calendar = new CalendarComptabilityWrappers(context);
+
+ }
+
+ public int deleteEntries() {
+ refreshPreferences();
+ return context.getContentResolver().delete(calendar.events.CONTENT_URI,
+ calendar.events.DESCRIPTION + " LIKE ?",
+ new String[] { CALENDAR_ORGANIZER + "%" });
+ }
+
+ public void deleteFileEntries(String[] files) {
+ for (String file : files) {
+ deleteFileEntries(file);
+ }
+ }
+
+ public int deleteFileEntries(String filename) {
+ refreshPreferences();
+ return context.getContentResolver().delete(calendar.events.CONTENT_URI,
+ calendar.events.DESCRIPTION + " LIKE ?",
+ new String[] { CALENDAR_ORGANIZER + ":" + filename + "%" });
+ }
+
+ public String insertEntry(OrgNodeDate date, String payload,
+ String filename, String location) throws IllegalArgumentException {
+
+ if (this.calendarId == -1)
+ throw new IllegalArgumentException(
+ "Couldn't find selected calendar: " + calendarName);
+
+ ContentValues values = new ContentValues();
+ values.put(calendar.events.CALENDAR_ID, this.calendarId);
+ values.put(calendar.events.TITLE, date.getTitle());
+ values.put(calendar.events.DESCRIPTION, CALENDAR_ORGANIZER + ":"
+ + filename + "\n" + payload);
+ values.put(calendar.events.EVENT_LOCATION, location);
+
+ // Sync with google will overwrite organizer :(
+ // values.put(intEvents.ORGANIZER, embeddedNodeMetadata);
+
+ values.put(calendar.events.DTSTART, date.beginTime);
+ values.put(calendar.events.DTEND, date.endTime);
+ values.put(calendar.events.ALL_DAY, date.allDay);
+ values.put(calendar.events.HAS_ALARM, 0);
+ values.put(calendar.events.EVENT_TIMEZONE, Time.getCurrentTimezone());
+
+ Uri uri = context.getContentResolver().insert(
+ calendar.events.CONTENT_URI, values);
+ String nodeID = uri.getLastPathSegment();
+
+ if (date.allDay == 0 && this.reminderEnabled)
+ addReminder(nodeID, date.beginTime, date.endTime);
+
+ return nodeID;
+ }
+
+
+ private void addReminder(String eventID, long beginTime, long endTime) {
+ if (beginTime < System.currentTimeMillis())
+ return;
+
+ ContentValues reminderValues = new ContentValues();
+ reminderValues.put(calendar.reminders.MINUTES, this.reminderTime);
+ reminderValues.put(calendar.reminders.EVENT_ID, eventID);
+ reminderValues.put(calendar.reminders.METHOD,
+ calendar.reminders.METHOD_ALERT);
+ context.getContentResolver().insert(calendar.reminders.CONTENT_URI,
+ reminderValues);
+
+ ContentValues alertvalues = new ContentValues();
+ alertvalues.put(calendar.calendarAlerts.EVENT_ID, eventID);
+ alertvalues.put(calendar.calendarAlerts.BEGIN, beginTime);
+ alertvalues.put(calendar.calendarAlerts.END, endTime);
+ alertvalues.put(calendar.calendarAlerts.ALERT_TIME, this.reminderTime);
+ alertvalues.put(calendar.calendarAlerts.STATE,
+ calendar.calendarAlerts.STATE_SCHEDULED);
+ alertvalues.put(calendar.calendarAlerts.MINUTES, this.reminderTime);
+ context.getContentResolver().insert(
+ calendar.calendarAlerts.CONTENT_URI, alertvalues);
+
+ ContentValues eventValues = new ContentValues();
+ eventValues.put(calendar.events.HAS_ALARM, 1);
+ context.getContentResolver().update(
+ ContentUris.withAppendedId(calendar.events.CONTENT_URI,
+ Long.valueOf(eventID)), eventValues, null, null);
+ }
+
+
+ public int deleteEntry(CalendarEntry entry) {
+ return context.getContentResolver().delete(
+ ContentUris.withAppendedId(calendar.events.CONTENT_URI,
+ entry.id), null, null);
+ }
+
+ public int getCalendarID(String calendarName) {
+ Cursor cursor = context.getContentResolver().query(
+ calendar.calendars.CONTENT_URI,
+ new String[] { calendar.calendars._ID,
+ calendar.calendars.CALENDAR_DISPLAY_NAME }, null, null,
+ null);
+ if (cursor != null && cursor.moveToFirst()) {
+ for (int i = 0; i < cursor.getCount(); i++) {
+ int calId = cursor.getInt(0);
+ String calName = cursor.getString(1);
+
+ if (calName.equals(calendarName)) {
+ cursor.close();
+ return calId;
+ }
+ cursor.moveToNext();
+ }
+ cursor.close();
+ }
+ return -1;
+ }
+
+ public Cursor getUnassimilatedCalendarCursor() {
+ Cursor query = context.getContentResolver().query(
+ calendar.events.CONTENT_URI,
+ calendar.eventsProjection,
+ calendar.events.CALENDAR_ID + "=? AND "
+ + calendar.events.DESCRIPTION + " NOT LIKE ?",
+ new String[] { Integer.toString(this.calendarId),
+ CALENDAR_ORGANIZER + "%" }, null);
+ query.moveToFirst();
+
+ return query;
+ }
+
+ public Cursor getCalendarCursor(String filename) {
+ Cursor query = context.getContentResolver().query(
+ calendar.events.CONTENT_URI, calendar.eventsProjection,
+ calendar.events.DESCRIPTION + " LIKE ?",
+ new String[] { CALENDAR_ORGANIZER + ":" + filename + "%" },
+ null);
+ query.moveToFirst();
+
+ return query;
+ }
+
+ public static CharSequence[] getCalendars(Context context) {
+ CharSequence[] result = new CharSequence[1];
+ result[0] = context.getString(R.string.error_setting_no_calendar);
+
+ try {
+ CalendarComptabilityWrappers calendar = new CalendarComptabilityWrappers(
+ context);
+ Cursor cursor = context.getContentResolver().query(
+ calendar.calendars.CONTENT_URI,
+ new String[] { calendar.calendars._ID,
+ calendar.calendars.CALENDAR_DISPLAY_NAME }, null,
+ null, null);
+ if (cursor == null)
+ return result;
+
+ if (cursor.getCount() == 0) {
+ cursor.close();
+ return result;
+ }
+
+ if (cursor.moveToFirst()) {
+ result = new CharSequence[cursor.getCount()];
+
+ for (int i = 0; i < cursor.getCount(); i++) {
+ result[i] = cursor.getString(1);
+ cursor.moveToNext();
+ }
+ }
+ cursor.close();
+ } catch (SQLException e) {
+ }
+
+ return result;
+ }
+
+ public void refreshPreferences() {
+ this.reminderEnabled = sharedPreferences.getBoolean("calendarReminder",
+ false);
+
+ if (reminderEnabled) {
+ String intervalString = sharedPreferences.getString(
+ "calendarReminderInterval", "0");
+ if (intervalString == null)
+ throw new IllegalArgumentException(
+ "Invalid calendar reminder interval");
+ this.reminderTime = Integer.valueOf(intervalString);
+ }
+
+ this.calendarName = PreferenceManager.getDefaultSharedPreferences(
+ context).getString("calendarName", "");
+ this.calendarId = getCalendarID(calendarName);
+ }
+}
diff --git a/src/com/matburt/mobileorg/Services/MobileOrgStartupIntentReceiver.java b/src/com/matburt/mobileorg/Services/MobileOrgStartupIntentReceiver.java
index 887770d7..8246dfa9 100644
--- a/src/com/matburt/mobileorg/Services/MobileOrgStartupIntentReceiver.java
+++ b/src/com/matburt/mobileorg/Services/MobileOrgStartupIntentReceiver.java
@@ -21,5 +21,9 @@ public void onReceive(Context context, Intent intent) {
if (this.shouldStartService(context)) {
SyncService.startAlarm(context);
}
+
+ Intent calIntent = new Intent(context, CalendarSyncService.class);
+ calIntent.putExtra(CalendarSyncService.FILELIST, new String[] {});
+ context.startService(calIntent);
}
}
\ No newline at end of file
diff --git a/src/com/matburt/mobileorg/Services/SyncService.java b/src/com/matburt/mobileorg/Services/SyncService.java
index 07cdd35a..5d3b674a 100644
--- a/src/com/matburt/mobileorg/Services/SyncService.java
+++ b/src/com/matburt/mobileorg/Services/SyncService.java
@@ -1,5 +1,7 @@
package com.matburt.mobileorg.Services;
+import java.util.ArrayList;
+
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
@@ -50,6 +52,8 @@ public void onCreate() {
@Override
public void onDestroy() {
unsetAlarm();
+ this.appSettings.unregisterOnSharedPreferenceChangeListener(this);
+ super.onDestroy();
}
public static void stopAlarm(Context context) {
@@ -113,11 +117,14 @@ private void runSynchronizer() {
Thread syncThread = new Thread() {
public void run() {
- synchronizer.runSynchronizer(parser);
-
+ ArrayList changedFiles = synchronizer.runSynchronizer(parser);
+ String[] files = changedFiles.toArray(new String[changedFiles.size()]);
+
if(calendarEnabled) {
- CalendarSyncService cal = new CalendarSyncService(getContentResolver(), getBaseContext());
- cal.syncFiles();
+ Intent calIntent = new Intent(getBaseContext(), CalendarSyncService.class);
+ calIntent.putExtra(CalendarSyncService.PUSH, true);
+ calIntent.putExtra(CalendarSyncService.FILELIST, files);
+ getBaseContext().startService(calIntent);
}
synchronizer.close();
db.close();
diff --git a/src/com/matburt/mobileorg/Settings/DirectoryBrowser.java b/src/com/matburt/mobileorg/Settings/DirectoryBrowser.java
index e1f43204..01117a1f 100644
--- a/src/com/matburt/mobileorg/Settings/DirectoryBrowser.java
+++ b/src/com/matburt/mobileorg/Settings/DirectoryBrowser.java
@@ -7,18 +7,12 @@
import android.content.Context;
import android.util.Log;
-import com.matburt.mobileorg.R;
-import com.matburt.mobileorg.Synchronizers.UbuntuOneSynchronizer;
-
import com.dropbox.client2.DropboxAPI;
-import com.dropbox.client2.android.AndroidAuthSession;
-import com.dropbox.client2.android.AuthActivity;
-import com.dropbox.client2.session.AccessTokenPair;
-import com.dropbox.client2.session.AppKeyPair;
-import com.dropbox.client2.session.Session.AccessType;
-import com.dropbox.client2.session.TokenPair;
import com.dropbox.client2.DropboxAPI.Entry;
+import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
+import com.matburt.mobileorg.R;
+import com.matburt.mobileorg.Synchronizers.UbuntuOneSynchronizer;
public interface DirectoryBrowser {
diff --git a/src/com/matburt/mobileorg/Settings/SettingsActivity.java b/src/com/matburt/mobileorg/Settings/SettingsActivity.java
index 2e24cc24..6b399373 100644
--- a/src/com/matburt/mobileorg/Settings/SettingsActivity.java
+++ b/src/com/matburt/mobileorg/Settings/SettingsActivity.java
@@ -14,12 +14,12 @@
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceManager;
-import android.util.Log;
import com.actionbarsherlock.app.SherlockPreferenceActivity;
import com.matburt.mobileorg.R;
import com.matburt.mobileorg.OrgData.OrgProviderUtils;
import com.matburt.mobileorg.Services.CalendarSyncService;
+import com.matburt.mobileorg.Services.CalendarWrapper;
import com.matburt.mobileorg.Settings.Synchronizers.SDCardSettingsActivity;
import com.matburt.mobileorg.Settings.Synchronizers.ScpSettingsActivity;
import com.matburt.mobileorg.Settings.Synchronizers.UbuntuOneSettingsActivity;
@@ -37,7 +37,6 @@ public class SettingsActivity extends SherlockPreferenceActivity implements
public static final String KEY_CALENDAR_NAME = "calendarName";
public static final String KEY_CALENDAR_REMINDER_INTERVAL = "calendarReminderInterval";
public static final String KEY_DO_AUTO_SYNC = "doAutoSync";
- private boolean updateCalendar = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -76,18 +75,6 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onPause() {
- if (this.updateCalendar) {
- this.updateCalendar = false;
-
- if (isCalendarEnabled()) {
- Log.d("MobileOrg", "onPause(): syncFiles");
- getCalendarSyncService().syncFiles();
- } else {
- Log.d("MobileOrg", "onPause(): deleteAllEntries");
- getCalendarSyncService().deleteAllEntries(
- getApplicationContext());
- }
- }
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
@@ -100,10 +87,6 @@ public void onResume() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
- if(key.startsWith("calendar")) {
- Log.d("MobileOrg", "Set to update calendar");
- this.updateCalendar = true;
- }
// Set up the initial values following the Settings design guidelines for Ice Cream Sandwich
// Settings should show their current value instead of a description
setPreferenceSummary(sharedPreferences, key);
@@ -137,10 +120,10 @@ public void onClick(DialogInterface dialog,
OrgProviderUtils
.clearDB(getContentResolver());
OrgUtils.announceSyncDone(getApplicationContext());
- if (isCalendarEnabled())
- getCalendarSyncService()
- .deleteAllEntries(
- getApplicationContext());
+
+ Intent clearCalDBIntent = new Intent(getBaseContext(), CalendarSyncService.class);
+ clearCalDBIntent.putExtra(CalendarSyncService.CLEARDB, true);
+ startService(clearCalDBIntent);
}
}).setNegativeButton(R.string.no, null).show();
@@ -148,10 +131,6 @@ public void onClick(DialogInterface dialog,
}
};
- private CalendarSyncService getCalendarSyncService() {
- return new CalendarSyncService(getContentResolver(), this);
- }
-
private boolean isCalendarEnabled() {
return getPreferenceManager().getSharedPreferences().getBoolean(
"calendarEnabled", false);
@@ -160,7 +139,7 @@ private boolean isCalendarEnabled() {
private void populateCalendarNames() {
ListPreference calendarName = (ListPreference) findPreference("calendarName");
- CharSequence[] calendars = getCalendarSyncService().getCalendars(
+ CharSequence[] calendars = CalendarWrapper.getCalendars(
getApplicationContext());
calendarName.setEntries(calendars);
diff --git a/src/com/matburt/mobileorg/Settings/WizardActivity.java b/src/com/matburt/mobileorg/Settings/WizardActivity.java
index 207ca2ad..51e067c1 100644
--- a/src/com/matburt/mobileorg/Settings/WizardActivity.java
+++ b/src/com/matburt/mobileorg/Settings/WizardActivity.java
@@ -32,6 +32,13 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.dropbox.client2.DropboxAPI;
+import com.dropbox.client2.DropboxAPI.Account;
+import com.dropbox.client2.android.AndroidAuthSession;
+import com.dropbox.client2.exception.DropboxException;
+import com.dropbox.client2.session.AccessTokenPair;
+import com.dropbox.client2.session.AppKeyPair;
+import com.dropbox.client2.session.Session.AccessType;
import com.matburt.mobileorg.R;
import com.matburt.mobileorg.Synchronizers.SSHSynchronizer;
import com.matburt.mobileorg.Synchronizers.UbuntuOneSynchronizer;
@@ -39,23 +46,6 @@
import com.matburt.mobileorg.Views.PageFlipView;
import com.matburt.mobileorg.util.OrgUtils;
-import com.dropbox.client2.DropboxAPI;
-import com.dropbox.client2.android.AndroidAuthSession;
-import com.dropbox.client2.android.AuthActivity;
-import com.dropbox.client2.session.AccessTokenPair;
-import com.dropbox.client2.session.AppKeyPair;
-import com.dropbox.client2.session.Session.AccessType;
-import com.dropbox.client2.session.TokenPair;
-import com.dropbox.client2.exception.DropboxException;
-import com.dropbox.client2.exception.DropboxFileSizeException;
-import com.dropbox.client2.exception.DropboxIOException;
-import com.dropbox.client2.exception.DropboxParseException;
-import com.dropbox.client2.exception.DropboxPartialFileException;
-import com.dropbox.client2.exception.DropboxServerException;
-import com.dropbox.client2.exception.DropboxUnlinkedException;
-import com.dropbox.client2.DropboxAPI.Entry;
-import com.dropbox.client2.DropboxAPI.Account;
-
public class WizardActivity extends Activity {
private final class UIHandler extends Handler
diff --git a/src/com/matburt/mobileorg/Synchronizers/DropboxSynchronizer.java b/src/com/matburt/mobileorg/Synchronizers/DropboxSynchronizer.java
index 22f60d61..b4532522 100644
--- a/src/com/matburt/mobileorg/Synchronizers/DropboxSynchronizer.java
+++ b/src/com/matburt/mobileorg/Synchronizers/DropboxSynchronizer.java
@@ -3,38 +3,27 @@
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.io.FileInputStream;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.Handler;
import android.preference.PreferenceManager;
-import android.widget.Toast;
import android.util.Log;
-import android.view.View;
-import android.os.Handler;
-
-import com.matburt.mobileorg.R;
-import com.matburt.mobileorg.util.FileUtils;
+import android.widget.Toast;
import com.dropbox.client2.DropboxAPI;
+import com.dropbox.client2.DropboxAPI.DropboxInputStream;
import com.dropbox.client2.android.AndroidAuthSession;
-import com.dropbox.client2.android.AuthActivity;
+import com.dropbox.client2.exception.DropboxException;
+import com.dropbox.client2.exception.DropboxUnlinkedException;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;
import com.dropbox.client2.session.Session.AccessType;
-import com.dropbox.client2.session.TokenPair;
-import com.dropbox.client2.DropboxAPI.DropboxInputStream;
-import com.dropbox.client2.DropboxAPI.Entry;
-
-import com.dropbox.client2.exception.DropboxException;
-import com.dropbox.client2.exception.DropboxFileSizeException;
-import com.dropbox.client2.exception.DropboxIOException;
-import com.dropbox.client2.exception.DropboxParseException;
-import com.dropbox.client2.exception.DropboxPartialFileException;
-import com.dropbox.client2.exception.DropboxServerException;
-import com.dropbox.client2.exception.DropboxUnlinkedException;
+import com.matburt.mobileorg.R;
+import com.matburt.mobileorg.util.FileUtils;
public class DropboxSynchronizer implements SynchronizerInterface {
diff --git a/src/com/matburt/mobileorg/Synchronizers/Synchronizer.java b/src/com/matburt/mobileorg/Synchronizers/Synchronizer.java
index 62f501ff..0defabe8 100644
--- a/src/com/matburt/mobileorg/Synchronizers/Synchronizer.java
+++ b/src/com/matburt/mobileorg/Synchronizers/Synchronizer.java
@@ -62,20 +62,25 @@ public boolean isEnabled() {
return true;
}
- public void runSynchronizer(OrgFileParser parser) {
+ /**
+ * @return List of files that where changed.
+ */
+ public ArrayList runSynchronizer(OrgFileParser parser) {
if (!syncher.isConfigured()) {
notify.errorNotification("Sync not configured");
- return;
+ return new ArrayList();
}
try {
announceStartSync();
- pull(parser);
+ ArrayList changedFiles = pull(parser);
pushCaptures();
announceSyncDone();
+ return changedFiles;
} catch (Exception e) {
showErrorNotification(e);
OrgUtils.announceSyncDone(context);
+ return new ArrayList();
}
}
@@ -120,13 +125,14 @@ public void pushCaptures() throws IOException,
* This method will download index.org and checksums.dat from the remote
* host. Using those files, it determines the other files that need updating
* and downloads them.
+ * @return
*/
- public void pull(OrgFileParser parser) throws SSLHandshakeException, CertificateException, IOException {
+ public ArrayList pull(OrgFileParser parser) throws SSLHandshakeException, CertificateException, IOException {
HashMap remoteChecksums = getAndParseChecksumFile();
ArrayList changedFiles = getFilesThatChangedRemotely(remoteChecksums);
if(changedFiles.size() == 0)
- return;
+ return changedFiles;
changedFiles.remove(INDEX_FILE);
announceProgressDownload(INDEX_FILE, 0, changedFiles.size() + 2);
@@ -136,6 +142,8 @@ public void pull(OrgFileParser parser) throws SSLHandshakeException, Certificate
pull(parser, changedFiles, filenameMap, remoteChecksums);
announceProgressDownload("", changedFiles.size() + 1, changedFiles.size() + 2);
+
+ return changedFiles;
}
private void pull(OrgFileParser parser, ArrayList filesToGet,
diff --git a/src/com/matburt/mobileorg/util/MultiMap.java b/src/com/matburt/mobileorg/util/MultiMap.java
new file mode 100644
index 00000000..8c287127
--- /dev/null
+++ b/src/com/matburt/mobileorg/util/MultiMap.java
@@ -0,0 +1,51 @@
+package com.matburt.mobileorg.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+
+public class MultiMap {
+
+ private HashMap> entryMap = new HashMap>();
+
+ public void put(Long key, T value) {
+ ArrayList valueList = entryMap.get(key);
+
+ if(valueList == null) {
+ valueList = new ArrayList();
+ entryMap.put(key, valueList);
+ }
+
+ valueList.add(value);
+ }
+
+ public ArrayList get(Long key) {
+ return entryMap.get(key);
+ }
+
+ public void remove(long key, T value) {
+ ArrayList valueList = entryMap.get(key);
+
+ if(valueList != null) {
+ valueList.remove(value);
+ }
+ }
+
+ public Set keySet() {
+ return entryMap.keySet();
+ }
+
+ public T findValue(long key, Object object) throws IllegalArgumentException {
+ ArrayList matches = entryMap.get(key);
+
+ if (matches == null)
+ return null;
+
+ for (T match : matches) {
+ if (match.equals(object))
+ return match;
+ }
+
+ return null;
+ }
+}
diff --git a/tests/src/com/matburt/mobileorg/test/OrgData/OrgNodeDateTest.java b/tests/src/com/matburt/mobileorg/test/OrgData/OrgNodeDateTest.java
new file mode 100644
index 00000000..f83ffee5
--- /dev/null
+++ b/tests/src/com/matburt/mobileorg/test/OrgData/OrgNodeDateTest.java
@@ -0,0 +1,51 @@
+package com.matburt.mobileorg.test.OrgData;
+
+import java.util.Calendar;
+
+import com.matburt.mobileorg.OrgData.OrgNodeDate;
+
+import android.test.AndroidTestCase;
+
+public class OrgNodeDateTest extends AndroidTestCase {
+
+ private static final String dateString = "2000-11-24";
+ private static final String timeBeginString = "13:15";
+ private static final String timeEndString = "15:15";
+ private Calendar getDefaultCalendar() {
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 2000);
+ cal.set(Calendar.MONTH, 10);
+ cal.set(Calendar.DAY_OF_MONTH, 24);
+ cal.set(Calendar.HOUR_OF_DAY, 13);
+ cal.set(Calendar.MINUTE, 15);
+ return cal;
+ }
+
+ public void testGetDateDate() {
+ final long timeInMillis = getDefaultCalendar().getTimeInMillis();
+
+ String date = OrgNodeDate.getDate(timeInMillis, 0, true);
+
+ assertEquals(dateString, date);
+ }
+
+ public void testGetDateDateTime() {
+ final long timeInMillis = getDefaultCalendar().getTimeInMillis();
+
+ String date = OrgNodeDate.getDate(timeInMillis, timeInMillis, false);
+
+ assertEquals(dateString + " " + timeBeginString, date);
+ }
+
+ public void testGetDateTimeSpan() {
+ Calendar cal = getDefaultCalendar();
+ final long startTimeInMillis = cal.getTimeInMillis();
+ cal.set(Calendar.HOUR_OF_DAY, 15);
+ final long endTimeInMillis = cal.getTimeInMillis();
+
+ String date = OrgNodeDate.getDate(startTimeInMillis, endTimeInMillis, false);
+
+ assertEquals(dateString + " " + timeBeginString + "-" + timeEndString, date);
+ }
+
+}
diff --git a/tests/src/com/matburt/mobileorg/test/Synchronizers/CalendarSyncServiceTest.java b/tests/src/com/matburt/mobileorg/test/Synchronizers/CalendarSyncServiceTest.java
index b2459ce8..af9b05a1 100644
--- a/tests/src/com/matburt/mobileorg/test/Synchronizers/CalendarSyncServiceTest.java
+++ b/tests/src/com/matburt/mobileorg/test/Synchronizers/CalendarSyncServiceTest.java
@@ -12,7 +12,7 @@ public class CalendarSyncServiceTest extends AndroidTestCase {
public void testOrgNodePayloadGetDates() {
OrgNode node = new OrgNode();
node.setPayload("<2012-09-13 Thu>");
- ArrayList dates = node.getOrgNodePayload().getDates();
+ ArrayList dates = node.getOrgNodePayload().getDates(node.getCleanedName());
assertEquals(1, dates.size());
}