Import GingerCal 1.0 source
This commit is contained in:
commit
01f49852ab
116 files changed
+5079
No files matched your search
@@ -0,0 +1,193 @@
|
||||
package org.gingercal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import org.gingercal.Model.Cal;
|
||||
import org.gingercal.Model.Ev;
|
||||
|
||||
/** Local cache so the agenda works offline and the phone doesn't refetch on every launch. */
|
||||
public class Db extends SQLiteOpenHelper implements Model.Store {
|
||||
private static Db instance;
|
||||
|
||||
public static synchronized Db get(Context c) {
|
||||
if (instance == null) instance = new Db(c.getApplicationContext());
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Db(Context c) {
|
||||
super(c, "gingercal.db", null, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE cals (href TEXT PRIMARY KEY, name TEXT, color INTEGER, enabled INTEGER,"
|
||||
+ " writable INTEGER, ctag TEXT, synced INTEGER)");
|
||||
db.execSQL("CREATE TABLE events (_id INTEGER PRIMARY KEY AUTOINCREMENT, cal TEXT, href TEXT, etag TEXT,"
|
||||
+ " uid TEXT, title TEXT, location TEXT, descr TEXT, dtstart INTEGER, dtend INTEGER,"
|
||||
+ " allday INTEGER, recurring INTEGER)");
|
||||
db.execSQL("CREATE INDEX ev_start ON events(dtstart)");
|
||||
db.execSQL("CREATE INDEX ev_cal ON events(cal)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int from, int to) {
|
||||
db.execSQL("DROP TABLE IF EXISTS events");
|
||||
db.execSQL("DROP TABLE IF EXISTS cals");
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------ calendars
|
||||
|
||||
public synchronized Map<String, Cal> calendars() {
|
||||
Map<String, Cal> m = new LinkedHashMap<String, Cal>();
|
||||
Cursor c = getReadableDatabase().rawQuery(
|
||||
"SELECT href, name, color, enabled, writable, ctag, synced FROM cals ORDER BY name", null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
Cal x = new Cal();
|
||||
x.href = c.getString(0);
|
||||
x.name = c.getString(1);
|
||||
x.color = c.getInt(2);
|
||||
x.enabled = c.getInt(3) != 0;
|
||||
x.writable = c.getInt(4) != 0;
|
||||
x.ctag = c.getString(5);
|
||||
x.synced = c.getLong(6);
|
||||
m.put(x.href, x);
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public List<Cal> calendarList() {
|
||||
return new ArrayList<Cal>(calendars().values());
|
||||
}
|
||||
|
||||
public synchronized void saveCalendar(Cal c) {
|
||||
getWritableDatabase().execSQL("INSERT OR REPLACE INTO cals (href, name, color, enabled, writable, ctag, synced)"
|
||||
+ " VALUES (?,?,?,?,?,?,?)", new Object[] {c.href, c.name, Integer.valueOf(c.color),
|
||||
Integer.valueOf(c.enabled ? 1 : 0), Integer.valueOf(c.writable ? 1 : 0), c.ctag, Long.valueOf(c.synced)});
|
||||
}
|
||||
|
||||
public synchronized void setEnabled(String href, boolean on) {
|
||||
// reset ctag/synced so the next sync refetches it
|
||||
getWritableDatabase().execSQL("UPDATE cals SET enabled=?, ctag='', synced=0 WHERE href=?",
|
||||
new Object[] {Integer.valueOf(on ? 1 : 0), href});
|
||||
if (!on) getWritableDatabase().execSQL("DELETE FROM events WHERE cal=?", new Object[] {href});
|
||||
}
|
||||
|
||||
public synchronized void deleteCalendar(String href) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.execSQL("DELETE FROM events WHERE cal=?", new Object[] {href});
|
||||
db.execSQL("DELETE FROM cals WHERE href=?", new Object[] {href});
|
||||
}
|
||||
|
||||
public synchronized void forgetSyncState() {
|
||||
getWritableDatabase().execSQL("UPDATE cals SET ctag='', synced=0");
|
||||
}
|
||||
|
||||
public synchronized void clearAll() {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.execSQL("DELETE FROM events");
|
||||
db.execSQL("DELETE FROM cals");
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------- events
|
||||
|
||||
public synchronized void replaceEvents(String cal, List<Ev> evs) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.beginTransaction();
|
||||
try {
|
||||
db.execSQL("DELETE FROM events WHERE cal=?", new Object[] {cal});
|
||||
for (Ev e : evs) {
|
||||
db.execSQL("INSERT INTO events (cal, href, etag, uid, title, location, descr, dtstart, dtend, allday,"
|
||||
+ " recurring) VALUES (?,?,?,?,?,?,?,?,?,?,?)", new Object[] {cal, e.href, e.etag, e.uid,
|
||||
e.title, e.location, e.descr, Long.valueOf(e.start), Long.valueOf(e.end),
|
||||
Integer.valueOf(e.allDay ? 1 : 0), Integer.valueOf(e.recurring ? 1 : 0)});
|
||||
}
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
static final String EV_COLS = "e._id, e.cal, e.href, e.etag, e.uid, e.title, e.location, e.descr, e.dtstart,"
|
||||
+ " e.dtend, e.allday, e.recurring, c.color, c.writable";
|
||||
|
||||
static Ev read(Cursor c) {
|
||||
Ev e = new Ev();
|
||||
e.id = c.getLong(0);
|
||||
e.cal = c.getString(1);
|
||||
e.href = c.getString(2);
|
||||
e.etag = c.getString(3);
|
||||
e.uid = c.getString(4);
|
||||
e.title = c.getString(5);
|
||||
e.location = c.getString(6);
|
||||
e.descr = c.getString(7);
|
||||
e.start = c.getLong(8);
|
||||
e.end = c.getLong(9);
|
||||
e.allDay = c.getInt(10) != 0;
|
||||
e.recurring = c.getInt(11) != 0;
|
||||
e.color = c.getInt(12);
|
||||
e.writable = c.getInt(13) != 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
List<Ev> query(String where, String[] args) {
|
||||
List<Ev> out = new ArrayList<Ev>();
|
||||
Cursor c = getReadableDatabase().rawQuery("SELECT " + EV_COLS + " FROM events e JOIN cals c ON c.href = e.cal"
|
||||
+ " WHERE c.enabled = 1 AND (" + where + ") ORDER BY e.dtstart, e.allday DESC, e.title", args);
|
||||
try {
|
||||
while (c.moveToNext()) out.add(read(c));
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Everything still running or starting after `from`. */
|
||||
public synchronized List<Ev> agenda(long from, long to) {
|
||||
return query("e.dtend > ? AND e.dtstart < ? OR (e.dtstart = e.dtend AND e.dtstart >= ? AND e.dtstart < ?)",
|
||||
new String[] {String.valueOf(from), String.valueOf(to), String.valueOf(from), String.valueOf(to)});
|
||||
}
|
||||
|
||||
public synchronized Ev event(long id) {
|
||||
List<Ev> l = query("e._id = ?", new String[] {String.valueOf(id)});
|
||||
return l.isEmpty() ? null : l.get(0);
|
||||
}
|
||||
|
||||
/** Timed events starting in (after, until]. */
|
||||
public synchronized List<Ev> startingBetween(long after, long until) {
|
||||
return query("e.allday = 0 AND e.dtstart > ? AND e.dtstart <= ?",
|
||||
new String[] {String.valueOf(after), String.valueOf(until)});
|
||||
}
|
||||
|
||||
public synchronized long nextStartAfter(long after) {
|
||||
Cursor c = getReadableDatabase().rawQuery("SELECT MIN(e.dtstart) FROM events e JOIN cals c ON c.href = e.cal"
|
||||
+ " WHERE c.enabled = 1 AND e.allday = 0 AND e.dtstart > ?", new String[] {String.valueOf(after)});
|
||||
try {
|
||||
if (c.moveToNext() && !c.isNull(0)) return c.getLong(0);
|
||||
return -1;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int count() {
|
||||
Cursor c = getReadableDatabase().rawQuery("SELECT COUNT(*) FROM events", null);
|
||||
try {
|
||||
return c.moveToNext() ? c.getInt(0) : 0;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user