Merge from koxx3/astrid-provider

------------------------------------------------------------
Use --include-merges or -n0 to see merged revisions.
pull/14/head
Tim Su 16 years ago
parent f1796694d1
commit a48ebe5d9c

@ -15,11 +15,19 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- For Tasks provider -->
<permission android:name="com.timsu.astrid.permission.READ_TASKS"
android:permissionGroup="android.permission-group.MESSAGES"
android:protectionLevel="normal"
android:label="@string/read_tasks_permission"
android:description="@string/read_tasks_permission"/>
<uses-permission android:name="com.timsu.astrid.permission.READ_TASKS"/>
<uses-sdk android:minSdkVersion="3" <uses-sdk android:minSdkVersion="3"
android:targetSdkVersion="4" /> android:targetSdkVersion="4" />
<supports-screens /> <supports-screens />
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="false">
<!-- ======================== Activities ========================= --> <!-- ======================== Activities ========================= -->
@ -43,6 +51,13 @@
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/task" />
</intent-filter>
</activity> </activity>
<!-- Activity that views tags --> <!-- Activity that views tags -->
@ -105,6 +120,17 @@
<service android:name=".appwidget.AstridAppWidgetProvider$UpdateService"></service> <service android:name=".appwidget.AstridAppWidgetProvider$UpdateService"></service>
<!-- ======================== Providers ========================== -->
<provider
android:name=".provider.TasksProvider"
android:authorities="com.timsu.astrid.tasksprovider"
android:multiprocess="true"
android:grantUriPermissions="true"
android:readPermission="com.timsu.astrid.permission.READ_TASKS"
/>
</application> </application>
</manifest> </manifest>

@ -465,4 +465,7 @@ Astrid is the highly-acclaimed open-source task list that is simple enough to no
<!-- Widget text when loading tasks --> <!-- Widget text when loading tasks -->
<string name="widget_loading">Loading...</string> <string name="widget_loading">Loading...</string>
<!-- Permissions -->
<string name="read_tasks_permission">Read Astrid tasks</string>
</resources> </resources>

@ -88,8 +88,8 @@ import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType;
/** /**
* This activity is responsible for creating new tasks and editing existing * This activity is responsible for creating new tasks and editing existing
* ones. It saves a task when it is paused (screen rotated, back button * ones. It saves a task when it is paused (screen rotated, back button pressed)
* pressed) as long as the task has a title. * as long as the task has a title.
* *
* @author timsu * @author timsu
* *
@ -159,6 +159,15 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Intent intent = getIntent();
long taskId = 0;
try {
taskId = intent.getExtras().getLong("id");
} catch (Exception e) {
e.printStackTrace();
}
// Log.d("astrid", "id = " + taskId);
tagController = new TagController(this); tagController = new TagController(this);
tagController.open(); tagController.open();
alertController = new AlertController(this); alertController = new AlertController(this);
@ -168,21 +177,14 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
tabHost.setPadding(0, 4, 0, 0); tabHost.setPadding(0, 4, 0, 0);
Resources r = getResources(); Resources r = getResources();
LayoutInflater.from(this).inflate(R.layout.task_edit, LayoutInflater.from(this).inflate(R.layout.task_edit, tabHost.getTabContentView(), true);
tabHost.getTabContentView(), true);
tabHost.addTab(tabHost.newTabSpec(TAB_BASIC).setIndicator(r.getString(R.string.taskEdit_tab_basic),
tabHost.addTab(tabHost.newTabSpec(TAB_BASIC) r.getDrawable(R.drawable.ic_dialog_info_c)).setContent(R.id.tab_basic));
.setIndicator(r.getString(R.string.taskEdit_tab_basic), tabHost.addTab(tabHost.newTabSpec(TAB_DATES).setIndicator(r.getString(R.string.taskEdit_tab_dates),
r.getDrawable(R.drawable.ic_dialog_info_c)) r.getDrawable(R.drawable.ic_dialog_time_c)).setContent(R.id.tab_dates));
.setContent(R.id.tab_basic)); tabHost.addTab(tabHost.newTabSpec(TAB_ALERTS).setIndicator(r.getString(R.string.taskEdit_tab_alerts),
tabHost.addTab(tabHost.newTabSpec(TAB_DATES) r.getDrawable(R.drawable.ic_dialog_alert_c)).setContent(R.id.tab_notification));
.setIndicator(r.getString(R.string.taskEdit_tab_dates),
r.getDrawable(R.drawable.ic_dialog_time_c))
.setContent(R.id.tab_dates));
tabHost.addTab(tabHost.newTabSpec(TAB_ALERTS)
.setIndicator(r.getString(R.string.taskEdit_tab_alerts),
r.getDrawable(R.drawable.ic_dialog_alert_c))
.setContent(R.id.tab_notification));
setUpUIComponents(); setUpUIComponents();
setUpListeners(); setUpListeners();
@ -199,9 +201,11 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
return controller.createNewTaskForEdit(); return controller.createNewTaskForEdit();
} }
/* ====================================================================== /*
* ======================================================================
* =============================================== model reading / saving * =============================================== model reading / saving
* ====================================================================== */ * ======================================================================
*/
/** Populate UI component values from the model */ /** Populate UI component values from the model */
private void populateFields() { private void populateFields() {
@ -221,10 +225,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
} }
if (model.getName().length() > 0) if (model.getName().length() > 0)
setTitle(new StringBuilder(). setTitle(new StringBuilder().append(r.getString(R.string.taskEdit_titlePrefix)).append(" ").append(
append(r.getString(R.string.taskEdit_titlePrefix)). model.getName()));
append(" ").
append(model.getName()));
estimatedDuration.setTimeDuration(model.getEstimatedSeconds()); estimatedDuration.setTimeDuration(model.getEstimatedSeconds());
elapsedDuration.setTimeDuration(model.getElapsedSeconds()); elapsedDuration.setTimeDuration(model.getElapsedSeconds());
importance.setImportance(model.getImportance()); importance.setImportance(model.getImportance());
@ -248,8 +250,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
if (model.getTaskIdentifier() != null) { if (model.getTaskIdentifier() != null) {
taskTags = tagController.getTaskTags(model.getTaskIdentifier()); taskTags = tagController.getTaskTags(model.getTaskIdentifier());
if (taskTags.size() > 0) { if (taskTags.size() > 0) {
Map<TagIdentifier, TagModelForView> tagsMap = Map<TagIdentifier, TagModelForView> tagsMap = new HashMap<TagIdentifier, TagModelForView>();
new HashMap<TagIdentifier, TagModelForView>();
for (TagModelForView tag : tags) for (TagModelForView tag : tags)
tagsMap.put(tag.getTagIdentifier(), tag); tagsMap.put(tag.getTagIdentifier(), tag);
for (TagIdentifier id : taskTags) { for (TagIdentifier id : taskTags) {
@ -334,8 +335,11 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
/** /**
* Displays a Toast reporting that the selected task has been saved and is * Displays a Toast reporting that the selected task has been saved and is
* due in 'x' amount of time, to 2 time-units of precision (e.g. Days + Hours). * due in 'x' amount of time, to 2 time-units of precision (e.g. Days +
* @param dueDate the Date when the task is due * Hours).
*
* @param dueDate
* the Date when the task is due
*/ */
private void showSaveToast(Date dueDate) { private void showSaveToast(Date dueDate) {
int stringResource; int stringResource;
@ -343,20 +347,19 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
int timeInSeconds = (int) ((dueDate.getTime() - System.currentTimeMillis()) / 1000L); int timeInSeconds = (int) ((dueDate.getTime() - System.currentTimeMillis()) / 1000L);
if (timeInSeconds < 0) { if (timeInSeconds < 0) {
timeInSeconds *= -1; // DateUtilities.getDurationString() requires positive integer timeInSeconds *= -1; // DateUtilities.getDurationString() requires
// positive integer
stringResource = R.string.taskEdit_onTaskSave_Overdue; stringResource = R.string.taskEdit_onTaskSave_Overdue;
} else { } else {
stringResource = R.string.taskEdit_onTaskSave_Due; stringResource = R.string.taskEdit_onTaskSave_Due;
} }
String formattedDate = DateUtilities.getDurationString(getResources(), timeInSeconds, 2); String formattedDate = DateUtilities.getDurationString(getResources(), timeInSeconds, 2);
Toast.makeText(this, Toast.makeText(this, getResources().getString(stringResource, formattedDate), Toast.LENGTH_SHORT).show();
getResources().getString(stringResource, formattedDate),
Toast.LENGTH_SHORT).show();
} }
/** /**
* Displays a Toast reporting that the selected task has been saved. * Displays a Toast reporting that the selected task has been saved. Use
* Use this version when no due Date has been set. * this version when no due Date has been set.
*/ */
private void showSaveToast() { private void showSaveToast() {
Toast.makeText(this, R.string.taskEdit_onTaskSave_notDue, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.taskEdit_onTaskSave_notDue, Toast.LENGTH_SHORT).show();
@ -410,53 +413,48 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
alertController.removeAlerts(model.getTaskIdentifier()); alertController.removeAlerts(model.getTaskIdentifier());
for (int i = 0; i < alertsContainer.getChildCount(); i++) { for (int i = 0; i < alertsContainer.getChildCount(); i++) {
DateControlSet dateControlSet = (DateControlSet)alertsContainer. DateControlSet dateControlSet = (DateControlSet) alertsContainer.getChildAt(i).getTag();
getChildAt(i).getTag();
Date date = dateControlSet.getDate(); Date date = dateControlSet.getDate();
alertController.addAlert(model.getTaskIdentifier(), date); alertController.addAlert(model.getTaskIdentifier(), date);
} }
} }
/* ====================================================================== /*
* ======================================================================
* ==================================================== UI initialization * ==================================================== UI initialization
* ====================================================================== */ * ======================================================================
*/
/** Initialize UI components */ /** Initialize UI components */
private void setUpUIComponents() { private void setUpUIComponents() {
Resources r = getResources(); Resources r = getResources();
setTitle(new StringBuilder() setTitle(new StringBuilder().append(r.getString(R.string.taskEdit_titleGeneric)));
.append(r.getString(R.string.taskEdit_titleGeneric)));
// populate instance variables // populate instance variables
name = (EditText) findViewById(R.id.name); name = (EditText) findViewById(R.id.name);
importance = new ImportanceControlSet(R.id.importance_container); importance = new ImportanceControlSet(R.id.importance_container);
tagsContainer = (LinearLayout) findViewById(R.id.tags_container); tagsContainer = (LinearLayout) findViewById(R.id.tags_container);
estimatedDuration = new TimeDurationControlSet(this, estimatedDuration = new TimeDurationControlSet(this, R.id.estimatedDuration, 0, R.string.hour_minutes_dialog,
R.id.estimatedDuration, 0, R.string.hour_minutes_dialog,
TimeDurationType.HOURS_MINUTES); TimeDurationType.HOURS_MINUTES);
elapsedDuration = new TimeDurationControlSet(this, R.id.elapsedDuration, elapsedDuration = new TimeDurationControlSet(this, R.id.elapsedDuration, 0, R.string.hour_minutes_dialog,
0, R.string.hour_minutes_dialog,
TimeDurationType.HOURS_MINUTES); TimeDurationType.HOURS_MINUTES);
notification = new TimeDurationControlSet(this, R.id.notification, notification = new TimeDurationControlSet(this, R.id.notification, R.string.notification_prefix,
R.string.notification_prefix, R.string.notification_dialog, R.string.notification_dialog, TimeDurationType.DAYS_HOURS);
TimeDurationType.DAYS_HOURS); definiteDueDate = new DateWithNullControlSet(this, R.id.definiteDueDate_notnull, R.id.definiteDueDate_date,
definiteDueDate = new DateWithNullControlSet(this, R.id.definiteDueDate_notnull, R.id.definiteDueDate_time);
R.id.definiteDueDate_date, R.id.definiteDueDate_time); preferredDueDate = new DateWithNullControlSet(this, R.id.preferredDueDate_notnull, R.id.preferredDueDate_date,
preferredDueDate = new DateWithNullControlSet(this, R.id.preferredDueDate_notnull, R.id.preferredDueDate_time);
R.id.preferredDueDate_date, R.id.preferredDueDate_time); hiddenUntil = new DateWithNullControlSet(this, R.id.hiddenUntil_notnull, R.id.hiddenUntil_date,
hiddenUntil = new DateWithNullControlSet(this, R.id.hiddenUntil_notnull, R.id.hiddenUntil_time);
R.id.hiddenUntil_date, R.id.hiddenUntil_time);
notes = (EditText) findViewById(R.id.notes); notes = (EditText) findViewById(R.id.notes);
flags = new NotifyFlagControlSet(R.id.flag_before, flags = new NotifyFlagControlSet(R.id.flag_before, R.id.flag_during, R.id.flag_after, R.id.flag_nonstop);
R.id.flag_during, R.id.flag_after, R.id.flag_nonstop);
alertsContainer = (LinearLayout) findViewById(R.id.alert_container); alertsContainer = (LinearLayout) findViewById(R.id.alert_container);
repeatInterval = (Spinner) findViewById(R.id.repeat_interval); repeatInterval = (Spinner) findViewById(R.id.repeat_interval);
repeatValue = (Button) findViewById(R.id.repeat_value); repeatValue = (Button) findViewById(R.id.repeat_value);
addToCalendar = (CheckBox) findViewById(R.id.add_to_calendar); addToCalendar = (CheckBox) findViewById(R.id.add_to_calendar);
// individual ui component initialization // individual ui component initialization
ArrayAdapter<String> repeatAdapter = new ArrayAdapter<String>( ArrayAdapter<String> repeatAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,
this, android.R.layout.simple_spinner_item,
RepeatInterval.getLabels(getResources())); RepeatInterval.getLabels(getResources()));
repeatAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); repeatAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
repeatInterval.setAdapter(repeatAdapter); repeatInterval.setAdapter(repeatAdapter);
@ -521,9 +519,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
private RepeatInfo getRepeatValue() { private RepeatInfo getRepeatValue() {
if (repeatValue.getTag().equals(0)) if (repeatValue.getTag().equals(0))
return null; return null;
return new RepeatInfo(RepeatInterval.values() return new RepeatInfo(RepeatInterval.values()[repeatInterval.getSelectedItemPosition()], (Integer) repeatValue
[repeatInterval.getSelectedItemPosition()], .getTag());
(Integer)repeatValue.getTag());
} }
/** Adds an alert to the alert field */ /** Adds an alert to the alert field */
@ -535,9 +532,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
final View alertItem = inflater.inflate(R.layout.edit_alert_item, null); final View alertItem = inflater.inflate(R.layout.edit_alert_item, null);
alertsContainer.addView(alertItem); alertsContainer.addView(alertItem);
DateControlSet dcs = new DateControlSet(this, DateControlSet dcs = new DateControlSet(this, (Button) alertItem.findViewById(R.id.date), (Button) alertItem
(Button)alertItem.findViewById(R.id.date), .findViewById(R.id.time));
(Button)alertItem.findViewById(R.id.time));
dcs.setDate(alert); dcs.setDate(alert);
alertItem.setTag(dcs); alertItem.setTag(dcs);
@ -562,18 +558,14 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
final View tagItem = inflater.inflate(R.layout.edit_tag_item, null); final View tagItem = inflater.inflate(R.layout.edit_tag_item, null);
tagsContainer.addView(tagItem); tagsContainer.addView(tagItem);
AutoCompleteTextView textView = (AutoCompleteTextView)tagItem. AutoCompleteTextView textView = (AutoCompleteTextView) tagItem.findViewById(R.id.text1);
findViewById(R.id.text1);
textView.setText(tagName); textView.setText(tagName);
ArrayAdapter<TagModelForView> tagsAdapter = ArrayAdapter<TagModelForView> tagsAdapter = new ArrayAdapter<TagModelForView>(this,
new ArrayAdapter<TagModelForView>(this,
android.R.layout.simple_dropdown_item_1line, tags); android.R.layout.simple_dropdown_item_1line, tags);
textView.setAdapter(tagsAdapter); textView.setAdapter(tagsAdapter);
textView.addTextChangedListener(new TextWatcher() { textView.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before, public void onTextChanged(CharSequence s, int start, int before, int count) {
int count) { if (start == 0 && tagsContainer.getChildAt(tagsContainer.getChildCount() - 1) == tagItem) {
if(start == 0 && tagsContainer.getChildAt(
tagsContainer.getChildCount()-1) == tagItem) {
addTag(""); addTag("");
} }
} }
@ -582,8 +574,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
// //
} }
public void beforeTextChanged(CharSequence s, int start, int count, public void beforeTextChanged(CharSequence s, int start, int count, int after) {
int after) {
// //
} }
}); });
@ -599,9 +590,11 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
return true; return true;
} }
/* ====================================================================== /*
* ======================================================================
* ======================================================= event handlers * ======================================================= event handlers
* ====================================================================== */ * ======================================================================
*/
@Override @Override
public void onWindowFocusChanged(boolean hasFocus) { public void onWindowFocusChanged(boolean hasFocus) {
@ -624,11 +617,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
} }
private void deleteButtonClick() { private void deleteButtonClick() {
new AlertDialog.Builder(this) new AlertDialog.Builder(this).setTitle(R.string.delete_title).setMessage(R.string.delete_this_task_title)
.setTitle(R.string.delete_title) .setIcon(android.R.drawable.ic_dialog_alert).setPositiveButton(android.R.string.ok,
.setMessage(R.string.delete_this_task_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
// tell the task list to update itself // tell the task list to update itself
@ -639,9 +629,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
setResult(Constants.RESULT_GO_HOME); setResult(Constants.RESULT_GO_HOME);
finish(); finish();
} }
}) }).setNegativeButton(android.R.string.cancel, null).show();
.setNegativeButton(android.R.string.cancel, null)
.show();
} }
private void repeatValueClick() { private void repeatValueClick() {
@ -661,8 +649,7 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
public void onNumberPicked(NumberPicker view, int number) { public void onNumberPicked(NumberPicker view, int number) {
setRepeatValue(number); setRepeatValue(number);
} }
}, getResources().getString(R.string.repeat_picker_title), }, getResources().getString(R.string.repeat_picker_title), dialogValue, 1, 0, 31).show();
dialogValue, 1, 0, 31).show();
} }
}; };
@ -671,24 +658,18 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
return; return;
} }
new AlertDialog.Builder(this) new AlertDialog.Builder(this).setTitle(R.string.repeat_help_dialog_title).setMessage(
.setTitle(R.string.repeat_help_dialog_title) R.string.repeat_help_dialog).setIcon(android.R.drawable.ic_dialog_info).setPositiveButton(
.setMessage(R.string.repeat_help_dialog) android.R.string.ok, new DialogInterface.OnClickListener() {
.setIcon(android.R.drawable.ic_dialog_info)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
openDialogRunnable.run(); openDialogRunnable.run();
} }
}) }).setNeutralButton(R.string.repeat_help_hide, new DialogInterface.OnClickListener() {
.setNeutralButton(R.string.repeat_help_hide,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
Preferences.setShowRepeatHelp(TaskEdit.this, false); Preferences.setShowRepeatHelp(TaskEdit.this, false);
openDialogRunnable.run(); openDialogRunnable.run();
} }
}) }).show();
.show();
} }
@Override @Override
@ -737,20 +718,23 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
// save the tag name token for when we rotate the screen // save the tag name token for when we rotate the screen
Bundle extras = getIntent().getExtras(); Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey(TAG_NAME_TOKEN)) if (extras != null && extras.containsKey(TAG_NAME_TOKEN))
outState.putString(TAG_NAME_TOKEN, outState.putString(TAG_NAME_TOKEN, extras.getString(TAG_NAME_TOKEN));
extras.getString(TAG_NAME_TOKEN));
} }
/** Take the values from the model and set the calendar start and end times /**
* Take the values from the model and set the calendar start and end times
* based on these. Sets keys 'dtstart' and 'dtend'. * based on these. Sets keys 'dtstart' and 'dtend'.
* *
* @param preferred preferred due date or null * @param preferred
* @param definite definite due date or null * preferred due date or null
* @param estimatedSeconds estimated duration or null * @param definite
* definite due date or null
* @param estimatedSeconds
* estimated duration or null
* @param values * @param values
*/ */
public static void createCalendarStartEndTimes(Date preferred, Date definite, public static void createCalendarStartEndTimes(Date preferred, Date definite, Integer estimatedSeconds,
Integer estimatedSeconds, ContentValues values) { ContentValues values) {
FlurryAgent.onEvent("create-calendar-event"); FlurryAgent.onEvent("create-calendar-event");
Long deadlineDate = null; Long deadlineDate = null;
@ -784,9 +768,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
values.put("transparency", 0); values.put("transparency", 0);
values.put("visibility", 0); values.put("visibility", 0);
createCalendarStartEndTimes(model.getPreferredDueDate(), createCalendarStartEndTimes(model.getPreferredDueDate(), model.getDefiniteDueDate(), model
model.getDefiniteDueDate(), model.getEstimatedSeconds(), .getEstimatedSeconds(), values);
values);
Uri result = cr.insert(uri, values); Uri result = cr.insert(uri, values);
if (result != null) if (result != null)
@ -803,9 +786,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
Intent intent = new Intent(Intent.ACTION_EDIT, result); Intent intent = new Intent(Intent.ACTION_EDIT, result);
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
createCalendarStartEndTimes(model.getPreferredDueDate(), createCalendarStartEndTimes(model.getPreferredDueDate(), model.getDefiniteDueDate(), model
model.getDefiniteDueDate(), model.getEstimatedSeconds(), .getEstimatedSeconds(), values);
values);
intent.putExtra("beginTime", values.getAsLong("dtstart")); intent.putExtra("beginTime", values.getAsLong("dtstart"));
intent.putExtra("endTime", values.getAsLong("dtend")); intent.putExtra("endTime", values.getAsLong("dtend"));
@ -829,16 +811,17 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
alertController.close(); alertController.close();
} }
/* ====================================================================== /*
* ======================================================================
* ========================================== UI component helper classes * ========================================== UI component helper classes
* ====================================================================== */ * ======================================================================
*/
/** Control set dealing with notification flags */ /** Control set dealing with notification flags */
public class NotifyFlagControlSet { public class NotifyFlagControlSet {
private CheckBox before, during, after, nonstop; private CheckBox before, during, after, nonstop;
public NotifyFlagControlSet(int beforeId, int duringId, public NotifyFlagControlSet(int beforeId, int duringId, int afterId, int nonstopId) {
int afterId, int nonstopId) {
before = (CheckBox) findViewById(beforeId); before = (CheckBox) findViewById(beforeId);
during = (CheckBox) findViewById(duringId); during = (CheckBox) findViewById(duringId);
after = (CheckBox) findViewById(afterId); after = (CheckBox) findViewById(afterId);
@ -846,14 +829,10 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
} }
public void setValue(int flags) { public void setValue(int flags) {
before.setChecked((flags & before.setChecked((flags & TaskModelForEdit.NOTIFY_BEFORE_DEADLINE) > 0);
TaskModelForEdit.NOTIFY_BEFORE_DEADLINE) > 0); during.setChecked((flags & TaskModelForEdit.NOTIFY_AT_DEADLINE) > 0);
during.setChecked((flags & after.setChecked((flags & TaskModelForEdit.NOTIFY_AFTER_DEADLINE) > 0);
TaskModelForEdit.NOTIFY_AT_DEADLINE) > 0); nonstop.setChecked((flags & TaskModelForEdit.NOTIFY_NONSTOP) > 0);
after.setChecked((flags &
TaskModelForEdit.NOTIFY_AFTER_DEADLINE) > 0);
nonstop.setChecked((flags &
TaskModelForEdit.NOTIFY_NONSTOP) > 0);
} }
public int getValue() { public int getValue() {
@ -880,8 +859,8 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
for (Importance i : Importance.values()) { for (Importance i : Importance.values()) {
final ToggleButton button = new ToggleButton(TaskEdit.this); final ToggleButton button = new ToggleButton(TaskEdit.this);
button.setLayoutParams(new LinearLayout.LayoutParams( button.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT, 1)); LayoutParams.WRAP_CONTENT, 1));
button.setTextColor(r.getColor(i.getColorResource())); button.setTextColor(r.getColor(i.getColorResource()));
button.setTextOff(r.getString(i.getLabelResource())); button.setTextOff(r.getString(i.getLabelResource()));
button.setTextOn(r.getString(i.getLabelResource())); button.setTextOn(r.getString(i.getLabelResource()));
@ -930,15 +909,12 @@ public class TaskEdit extends TaskModificationTabbedActivity<TaskModelForEdit> {
Cursor tasks = controller.getActiveTaskListCursor(); Cursor tasks = controller.getActiveTaskListCursor();
startManagingCursor(tasks); startManagingCursor(tasks);
SimpleCursorAdapter tasksAdapter = new SimpleCursorAdapter(TaskEdit.this, SimpleCursorAdapter tasksAdapter = new SimpleCursorAdapter(TaskEdit.this,
android.R.layout.simple_list_item_1, tasks, android.R.layout.simple_list_item_1, tasks, new String[] { TaskModelForList.getNameField() },
new String[] { TaskModelForList.getNameField() },
new int[] { android.R.id.text1 }); new int[] { android.R.id.text1 });
taskBox.setAdapter(tasksAdapter); taskBox.setAdapter(tasksAdapter);
activatedCheckBox.setOnCheckedChangeListener( activatedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
taskBox.setEnabled(isChecked); taskBox.setEnabled(isChecked);
} }
}); });

@ -44,6 +44,7 @@ import com.timsu.astrid.data.alerts.AlertController;
import com.timsu.astrid.data.sync.SyncDataController; import com.timsu.astrid.data.sync.SyncDataController;
import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo; import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo;
import com.timsu.astrid.data.task.AbstractTaskModel.TaskModelDatabaseHelper; import com.timsu.astrid.data.task.AbstractTaskModel.TaskModelDatabaseHelper;
import com.timsu.astrid.provider.TasksProvider;
import com.timsu.astrid.sync.Synchronizer; import com.timsu.astrid.sync.Synchronizer;
import com.timsu.astrid.sync.Synchronizer.SynchronizerListener; import com.timsu.astrid.sync.Synchronizer.SynchronizerListener;
import com.timsu.astrid.utilities.Notifications; import com.timsu.astrid.utilities.Notifications;
@ -220,6 +221,10 @@ public class TaskController extends AbstractController {
throw new UnsupportedOperationException("Cannot delete uncreated task!"); throw new UnsupportedOperationException("Cannot delete uncreated task!");
long id = taskId.getId(); long id = taskId.getId();
cleanupTask(taskId, false); cleanupTask(taskId, false);
// notify modification
TasksProvider.notifyDatabaseModification();
return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0; return database.delete(TASK_TABLE_NAME, KEY_ROWID + "=" + id, null) > 0;
} }
@ -264,6 +269,9 @@ public class TaskController extends AbstractController {
context.startService(intent); context.startService(intent);
} }
// notify modification
TasksProvider.notifyDatabaseModification();
return saveSucessful; return saveSucessful;
} }
@ -531,6 +539,28 @@ public class TaskController extends AbstractController {
} }
} }
public ArrayList<TaskModelForProvider> getTasksForProvider(String limit) {
Cursor cursor = database.query(TASK_TABLE_NAME, TaskModelForWidget.FIELD_LIST,
AbstractTaskModel.PROGRESS_PERCENTAGE + " < " +
AbstractTaskModel.COMPLETE_PERCENTAGE + " AND (" +
AbstractTaskModel.HIDDEN_UNTIL + " ISNULL OR " + AbstractTaskModel.HIDDEN_UNTIL + " < " +
System.currentTimeMillis() + ")", null, null, null,
AbstractTaskModel.IMPORTANCE + " * " + (5 * 24 * 3600 * 1000L) +
" + CASE WHEN MAX(pdd, ddd) = 0 THEN " +
(System.currentTimeMillis() + (7 * 24 * 3600 * 1000L)) +
" ELSE (CASE WHEN pdd = 0 THEN ddd ELSE pdd END) END ASC", limit);
try {
ArrayList<TaskModelForProvider> list = new ArrayList<TaskModelForProvider>();
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
list.add(new TaskModelForProvider(cursor));
return list;
} finally {
cursor.close();
}
}
// --- boilerplate // --- boilerplate
/** /**

@ -0,0 +1,73 @@
/*
* ASTRID: Android's Simple Task Recording Dashboard
*
* Copyright (c) 2009 Francois DESLANDES
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.timsu.astrid.data.task;
import java.util.Date;
import android.database.Cursor;
import com.timsu.astrid.data.AbstractController;
import com.timsu.astrid.data.enums.Importance;
/** Fields that you would want to see in the TaskView activity */
public class TaskModelForProvider extends AbstractTaskModel {
static String[] FIELD_LIST = new String[] {
AbstractController.KEY_ROWID,
NAME,
IMPORTANCE,
PREFERRED_DUE_DATE,
DEFINITE_DUE_DATE,
"COALESCE(" + PREFERRED_DUE_DATE + ", 0) as pdd",
"COALESCE(" + DEFINITE_DUE_DATE + ", 0) as ddd"
};
// --- constructors
public TaskModelForProvider(Cursor cursor) {
super(cursor);
prefetchData(FIELD_LIST);
}
// --- getters
@Override
public String getName() {
return super.getName();
}
@Override
public Importance getImportance() {
return super.getImportance();
}
@Override
public Date getPreferredDueDate() {
return super.getPreferredDueDate();
}
@Override
public Date getDefiniteDueDate() {
return super.getDefiniteDueDate();
}
}

@ -0,0 +1,305 @@
package com.timsu.astrid.provider;
import java.util.ArrayList;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.util.Log;
import com.timsu.astrid.data.task.AbstractTaskModel;
import com.timsu.astrid.data.task.TaskController;
import com.timsu.astrid.data.task.TaskModelForProvider;
public class TasksProvider extends ContentProvider {
private static final String TAG = "MessageProvider";
public static final String AUTHORITY = "com.timsu.astrid.tasksprovider";
public static final Uri CONTENT_URI = Uri.parse("content://com.timsu.astrid.tasksprovider");
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
private static final int MAX_NUMBEER_OF_TASKS = 20;
private final static String IMPORTANCE_COLOR = "importance_color";
private final static String IDENTIFIER = "identifier";
static String[] TASK_FIELD_LIST = new String[] { AbstractTaskModel.NAME, IMPORTANCE_COLOR,
AbstractTaskModel.PREFERRED_DUE_DATE, AbstractTaskModel.DEFINITE_DUE_DATE, AbstractTaskModel.IMPORTANCE, IDENTIFIER };
private static final int URI_TASKS = 0;
// private static final int URI_MESSAGES = 1;
// private static final int URI_MESSAGE = 2;
// private static final int URI_FOLDERS = 3;
private static Context ctx = null;
static {
URI_MATCHER.addURI(AUTHORITY, "tasks", URI_TASKS);
// URI_MATCHER.addURI(AUTHORITY, "messages/*", URI_MESSAGES);
// URI_MATCHER.addURI(AUTHORITY, "message/*", URI_MESSAGE);
// URI_MATCHER.addURI(AUTHORITY, "folders/*", URI_FOLDERS);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d(TAG, "delete");
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// can only delete a message
// List<String> segments = null;
// String emailAccount = null;
// String msgId = null;
// String msgUId = null;
//
// segments = uri.getPathSegments();
// emailAccount = segments.get(1);
// msgId = segments.get(2);
//
//
// openOrReopenDatabase(emailAccount);
//
// // get messages uid
// Cursor cursor = null;
// try {
// cursor = getAllMessages(null, "( id = " + msgId + " )", null, null);
// if (cursor != null) {
// cursor.moveToFirst();
// msgUId = cursor.getString(cursor.getColumnIndex("uid"));
// cursor.close();
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// // get localstore parameter
// Message msg = null;
// try {
// Folder lf = LocalStore.getInstance(myAccount.getLocalStoreUri(),
// mApp, null).getFolder("INBOX");
// int msgCount = lf.getMessageCount();
// Log.d(TAG, "folder msg count = " + msgCount);
// msg = lf.getMessage(msgUId);
// } catch (MessagingException e) {
// e.printStackTrace();
// }
//
// // launch command to delete the message
// if ((myAccount != null) && (msg != null)) {
// MessagingController.getInstance(mApp).deleteMessage(myAccount,
// "INBOX", msg, null);
// }
//
// notifyDatabaseModification();
return 0;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public boolean onCreate() {
ctx = getContext();
return false;
}
public Cursor getTags() {
// TaskController taskController = new TaskController(ctx);
// taskController.ge
//
// MatrixCursor ret = new MatrixCursor(TASK_FIELD_LIST);
//
// for (int i = 0; i < taskList.size(); i++) {
// }
return null;
}
public Cursor getTasks() {
int numberOfTasks = MAX_NUMBEER_OF_TASKS;
TaskController taskController = new TaskController(ctx);
taskController.open();
ArrayList<TaskModelForProvider> taskList = taskController.getTasksForProvider(Integer.toString(numberOfTasks));
taskController.close();
MatrixCursor ret = new MatrixCursor(TASK_FIELD_LIST);
for (int i = 0; i < taskList.size(); i++) {
TaskModelForProvider taskModel = taskList.get(i);
if (taskModel != null) {
// get prefered due date time
long preferredDueDateTime = 0;
if (taskModel.getPreferredDueDate() != null)
preferredDueDateTime = taskModel.getPreferredDueDate().getTime();
// get definite due date time
long definiteDueDate = 0;
if (taskModel.getDefiniteDueDate() != null)
definiteDueDate = taskModel.getDefiniteDueDate().getTime();
Object[] values = new Object[6];
values[0] = taskModel.getName();
values[1] = ctx.getResources().getColor(taskModel.getImportance().getColorResource());
values[2] = preferredDueDateTime;
values[3] = definiteDueDate;
values[4] = taskModel.getImportance().ordinal();
values[5] = taskModel.getTaskIdentifier().getId();
ret.addRow(values);
}
}
return ret;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query");
Cursor cursor;
switch (URI_MATCHER.match(uri)) {
// case URI_MESSAGES:
// segments = uri.getPathSegments();
// emailAccount = segments.get(1);
//
// openOrReopenDatabase(emailAccount);
//
// cursor = getAllMessages(projection, selection, selectionArgs,
// sortOrder);
// break;
case URI_TASKS:
cursor = getTasks();
break;
// case URI_FOLDERS:
// segments = uri.getPathSegments();
// emailAccount = segments.get(1);
//
// openOrReopenDatabase(emailAccount);
//
// cursor = getFolders(projection, selection, selectionArgs, sortOrder);
// break;
default:
throw new IllegalStateException("Unrecognized URI:" + uri);
}
return cursor;
}
// private void openOrReopenDatabase(String emailAccount) {
//
// String dbPath = null;
//
// if ((!emailAccount.equals(mCurrentEmailAccount)) || (mDb == null)) {
//
// // look at existing accounts
// for (Account account :
// Preferences.getPreferences(getContext()).getAccounts()) {
// if (account.getEmail().equals(emailAccount)) {
// dbPath = account.getLocalStoreUri();
// }
// }
//
// if (dbPath != null) {
//
// // save this account as current account
// mCurrentEmailAccount = emailAccount;
//
// // close old database
// if (mDb != null)
// mDb.close();
//
// // open database
// String path = Uri.parse(dbPath).getPath();
// mDb = SQLiteDatabase.openDatabase(path, null,
// SQLiteDatabase.OPEN_READONLY);
// }
// }
//
// }
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d(TAG, "update");
// // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// // can only set flag to 'SEEN'
//
// List<String> segments = null;
// String emailAccount = null;
// String msgId = null;
// String msgUId = null;
//
// segments = uri.getPathSegments();
// emailAccount = segments.get(1);
// msgId = segments.get(2);
//
// openOrReopenDatabase(emailAccount);
//
// // get account parameters
// Account myAccount = null;
// for (Account account :
// Preferences.getPreferences(getContext()).getAccounts()) {
// if (emailAccount.equals(account.getEmail())) {
// myAccount = account;
// }
// }
//
// // get messages uid
// Cursor cursor = null;
// try {
// cursor = getAllMessages(null, "( id = " + msgId + " )", null, null);
// if (cursor != null) {
// cursor.moveToFirst();
// msgUId = cursor.getString(cursor.getColumnIndex("uid"));
// cursor.close();
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
//
// // launch command to delete the message
// if ((myAccount != null) && (msgUId != null)) {
// MessagingController.getInstance(mApp).markMessageRead(myAccount,
// "INBOX", msgUId, true);
// }
//
// notifyDatabaseModification();
return 0;
}
public static void notifyDatabaseModification() {
Log.d(TAG, "UPDATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
ctx.getContentResolver().notifyChange(CONTENT_URI, null);
}
}
Loading…
Cancel
Save