Fixed some warnings, pulled out repeat completion listener into it's own

class, now handling "repeat after complete date", and cloning task.

Needs a unit test of course (of course!)
pull/14/head
Tim Su 14 years ago
parent a3ce02e073
commit 21ea97ed34

@ -207,6 +207,12 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver android:name="com.todoroo.astrid.repeats.RepeatTaskCompleteListener">
<intent-filter>
<action android:name="com.todoroo.astrid.TASK_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<!-- notes -->
<receiver android:name="com.todoroo.astrid.notes.NoteDetailExposer">

@ -31,7 +31,7 @@ public abstract class DBObject<T extends DBObject<?>> implements Cloneable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DBObject dbObject = (DBObject) o;
DBObject<?> dbObject = (DBObject<?>) o;
if (alias != null ? !alias.equals(dbObject.alias) : dbObject.alias != null) return false;
if (expression != null ? !expression.equals(dbObject.expression) : dbObject.expression != null) return false;

@ -415,7 +415,7 @@ public abstract class UserTask<Params, Progress, Result> {
}
protected static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked"})
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void handleMessage(Message msg) {
UserTaskResult result = (UserTaskResult) msg.obj;

@ -38,11 +38,18 @@ import com.todoroo.astrid.model.Task;
*/
public class RepeatControlSet implements TaskEditControlSet {
// --- spinner constants
private static final int INTERVAL_DAYS = 0;
private static final int INTERVAL_WEEKS = 1;
private static final int INTERVAL_MONTHS = 2;
private static final int INTERVAL_YEARS = 3;
private static final int TYPE_DUE_DATE = 0;
private static final int TYPE_COMPLETION_DATE = 1;
// --- instance variables
private final Activity activity;
private final CheckBox enabled;
private final Button value;
@ -52,6 +59,8 @@ public class RepeatControlSet implements TaskEditControlSet {
private final LinearLayout daysOfWeekContainer;
private final CompoundButton[] daysOfWeek = new CompoundButton[7];
// --- implementation
public RepeatControlSet(final Activity activity, ViewGroup parent) {
this.activity = activity;
LayoutInflater.from(activity).inflate(R.layout.repeat_control, parent, true);
@ -143,6 +152,7 @@ public class RepeatControlSet implements TaskEditControlSet {
public void readFromTask(Task task) {
String recurrence = task.getValue(Task.RECURRENCE);
// read recurrence rule
if(recurrence.length() > 0) {
try {
RRule rrule = new RRule(recurrence);
@ -174,9 +184,14 @@ public class RepeatControlSet implements TaskEditControlSet {
recurrence = ""; //$NON-NLS-1$
}
}
enabled.setChecked(recurrence.length() > 0);
repeatContainer.setVisibility(enabled.isChecked() ? View.VISIBLE : View.GONE);
// read flag
if(task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION))
type.setSelection(TYPE_COMPLETION_DATE);
else
type.setSelection(TYPE_DUE_DATE);
}
@ -210,5 +225,16 @@ public class RepeatControlSet implements TaskEditControlSet {
result = rrule.toIcal();
}
task.setValue(Task.RECURRENCE, result);
switch(type.getSelectedItemPosition()) {
case TYPE_DUE_DATE:
task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, false);
break;
case TYPE_COMPLETION_DATE:
task.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, true);
}
if(task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION))
type.setSelection(1);
}
}

@ -0,0 +1,99 @@
package com.todoroo.astrid.repeats;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.google.ical.iter.RecurrenceIterator;
import com.google.ical.iter.RecurrenceIteratorFactory;
import com.google.ical.values.DateTimeValueImpl;
import com.google.ical.values.DateValue;
import com.google.ical.values.DateValueImpl;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.service.TaskService;
public class RepeatTaskCompleteListener extends BroadcastReceiver {
@Autowired
private TaskService taskService;
@Autowired
private ExceptionService exceptionService;
@Override
public void onReceive(Context context, Intent intent) {
long taskId = intent.getLongExtra(AstridApiConstants.EXTRAS_TASK_ID, -1);
if(taskId == -1)
return;
DependencyInjectionService.getInstance().inject(this);
Task task = taskService.fetchById(taskId, Task.ID, Task.RECURRENCE,
Task.DUE_DATE, Task.FLAGS);
if(task == null)
return;
String recurrence = task.getValue(Task.RECURRENCE);
if(recurrence.length() > 0) {
Date date = new Date();
DateValue today = new DateValueImpl(date.getYear() + 1900,
date.getMonth() + 1, date.getDate());
DateValue repeatFrom;
if(task.hasDueDate() && !task.getFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION)) {
date = new Date(task.getValue(Task.DUE_DATE));
repeatFrom = new DateTimeValueImpl(date.getYear() + 1900,
date.getMonth() + 1, date.getDate(),
date.getHours(), date.getMinutes(), date.getSeconds());
} else {
repeatFrom = today;
}
// invoke the recurrence iterator
try {
RecurrenceIterator iterator = RecurrenceIteratorFactory.createRecurrenceIterator(recurrence,
repeatFrom, TimeZone.getDefault());
if(repeatFrom.compareTo(today) < 0)
repeatFrom = today;
// go to the latest value and advance one more
iterator.advanceTo(repeatFrom);
if(!iterator.hasNext())
return;
DateValue nextDate = iterator.next();
if(nextDate.equals(repeatFrom)) {
if(!iterator.hasNext())
return;
nextDate = iterator.next();
}
long newDueDate;
if(nextDate instanceof DateTimeValueImpl) {
DateTimeValueImpl newDateTime = (DateTimeValueImpl)nextDate;
newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
new Date(newDateTime.year() - 1900, newDateTime.month() - 1,
newDateTime.day(), newDateTime.hour(),
newDateTime.minute(), newDateTime.second()).getTime());
} else {
newDueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
new Date(nextDate.year() - 1900, nextDate.month() - 1,
nextDate.day()).getTime());
}
Task newTask = taskService.clone(task);
task.setValue(Task.DUE_DATE, newDueDate);
taskService.save(newTask, false);
} catch (ParseException e) {
exceptionService.reportError("recurrence-rule: " + recurrence, e); //$NON-NLS-1$
}
}
}
}

@ -78,8 +78,8 @@ public class TagFilterExposer extends BroadcastReceiver {
FilterListHeader tagsHeader = new FilterListHeader(TagsPlugin.IDENTIFIER,
context.getString(R.string.tag_FEx_header));
Filter untagged = new Filter(TagsPlugin.IDENTIFIER,
"Untagged",
"Untagged",
r.getString(R.string.tag_FEx_untagged),
r.getString(R.string.tag_FEx_untagged),
tagService.untaggedTemplate(),
null);
untagged.listingIcon = ((BitmapDrawable)r.getDrawable(R.drawable.filter_untagged)).getBitmap();

@ -0,0 +1,127 @@
package com.todoroo.astrid.tags;
import java.util.ArrayList;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.astrid.activity.TaskEditActivity.TaskEditControlSet;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.tags.TagService.Tag;
/**
* Control set to manage adding and removing tags
*
* @author Tim Su <tim@todoroo.com>
*
*/
public final class TagsControlSet implements TaskEditControlSet {
// --- constants
/** Number of tags a task can have */
static final int MAX_TAGS = 5;
// --- instance variables
private final TagService tagService = new TagService();
private final Tag[] allTags;
private final LinearLayout tagsContainer;
private final Activity activity;
public TagsControlSet(Activity activity, int tagsContainer) {
allTags = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE);
this.activity = activity;
this.tagsContainer = (LinearLayout) activity.findViewById(tagsContainer);
}
@SuppressWarnings("nls")
@Override
public void readFromTask(Task task) {
// tags (only configure if not already set)
if(tagsContainer.getChildCount() == 0) {
TodorooCursor<Metadata> cursor = tagService.getTags(task.getId());
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
addTag(cursor.get(Metadata.VALUE));
} finally {
cursor.close();
}
addTag("");
}
}
@Override
public void writeToModel(Task task) {
ArrayList<String> tags = new ArrayList<String>();
for(int i = 0; i < tagsContainer.getChildCount(); i++) {
TextView tagName = (TextView)tagsContainer.getChildAt(i).findViewById(R.id.text1);
if(tagName.getText().length() == 0)
continue;
tags.add(tagName.getText().toString());
}
tagService.synchronizeTags(task.getId(), tags);
}
/** Adds a tag to the tag field */
boolean addTag(String tagName) {
if (tagsContainer.getChildCount() >= MAX_TAGS) {
return false;
}
LayoutInflater inflater = activity.getLayoutInflater();
final View tagItem = inflater.inflate(R.layout.tag_edit_row, null);
tagsContainer.addView(tagItem);
AutoCompleteTextView textView = (AutoCompleteTextView)tagItem.
findViewById(R.id.text1);
textView.setText(tagName);
ArrayAdapter<Tag> tagsAdapter =
new ArrayAdapter<Tag>(activity,
android.R.layout.simple_dropdown_item_1line, allTags);
textView.setAdapter(tagsAdapter);
textView.addTextChangedListener(new TextWatcher() {
@SuppressWarnings("nls")
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(start == 0 && tagsContainer.getChildAt(
tagsContainer.getChildCount()-1) == tagItem) {
addTag("");
}
}
public void afterTextChanged(Editable s) {
//
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
//
}
});
ImageButton reminderRemoveButton;
reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1);
reminderRemoveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tagsContainer.removeView(tagItem);
}
});
return true;
}
}

@ -24,7 +24,7 @@
minimizing the annoyance.
-->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ==================================================== task values == -->

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<color name="task_list_overdue">#FFFB6666</color>
<color name="task_list_normal">#FFFFFFFF</color>
<color name="task_list_done">#ff777777</color>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ======================== AndroidManifest ========================== -->
@ -298,12 +298,6 @@ to the plugin creator for fastest service.
<!-- Repeat label when repeats are not set -->
<string name="TEA_repeat_value_unset">No Repeat Set</string>
<!-- Tags label -->
<string name="TEA_tags_label">Tags:</string>
<!-- Tags hint -->
<string name="TEA_tag_hint">Tag Name</string>
<!-- dialog boxes -->
<string name="TEA_repeat_picker_title">Repeat Every (0 to disable)</string>
<string name="TEA_repeat_help_dialog_title">Help: Astrid Repeats</string>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Resources for built-in filter plug-in -->

@ -19,7 +19,7 @@
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- General String Constants -->
<skip />

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Resources for built-in reminders plug-in -->

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Resources for built-in repeat plug-in -->

@ -1,24 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Resources for built-in tag plug-in -->
<string name="tag_EOE_button">Add Tags</string>
<string name="tag_EOE_button_w_tags">Tags: %s</string>
<string name="tag_TLA_detail">Tags: %s</string>
<string name="tag_FEx_header">Tags</string>
<string name="tag_FEx_by_size">By Size</string>
<string name="tag_FEx_alpha">Alphabetical</string>
<!-- $T => tag, $C => count -->
<string name="tag_FEx_tag_w_size">$T ($C)</string>
<!-- %s => tag name -->
<string name="tag_FEx_name">Tagged \'%s\'</string>
<!-- =============================================== Task Edit Controls == -->
<!-- Tags label -->
<string name="TEA_tags_label">Tags:</string>
<!-- Tags hint -->
<string name="TEA_tag_hint">Tag Name</string>
<!-- ===================================================== Task Details == -->
<string name="tag_TLA_detail">Tags: %s</string>
<string name="tag_TEA_hint">Type In a Tag</string>
<string name="tag_TEA_title">Edit Tags</string>
<!-- ========================================================== Filters == -->
<string name="tag_FEx_header">Tags</string>
<string name="tag_FEx_by_size">By Size</string>
<string name="tag_FEx_alpha">Alphabetical</string>
<string name="tag_FEx_untagged">Untagged</string>
<!-- $T => tag, $C => count -->
<string name="tag_FEx_tag_w_size">$T ($C)</string>
<!-- %s => tag name -->
<string name="tag_FEx_name">Tagged \'%s\'</string>
</resources>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- See the file "LICENSE" for the full license governing this code. -->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- ============================ General ============================= -->

@ -19,7 +19,7 @@
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-->
<resources>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="Alert" parent="android:Theme.Dialog">
<item name="android:windowBackground">@null</item>

@ -39,8 +39,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@ -49,7 +47,6 @@ import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
@ -60,7 +57,6 @@ import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.Spinner;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.ToggleButton;
@ -73,20 +69,17 @@ import com.timsu.astrid.widget.TimeDurationControlSet;
import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType;
import com.todoroo.andlib.data.Property.IntegerProperty;
import com.todoroo.andlib.data.Property.StringProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.repeats.RepeatControlSet;
import com.todoroo.astrid.service.StartupService;
import com.todoroo.astrid.service.TaskService;
import com.todoroo.astrid.tags.TagService;
import com.todoroo.astrid.tags.TagService.Tag;
import com.todoroo.astrid.tags.TagsControlSet;
import com.todoroo.astrid.utility.Constants;
/**
@ -123,11 +116,6 @@ public final class TaskEditActivity extends TabActivity {
public static final int RESULT_CODE_DISCARDED = RESULT_FIRST_USER + 1;
public static final int RESULT_CODE_DELETED = RESULT_FIRST_USER + 2;
// --- other constants
/** Number of tags a task can have */
private static final int MAX_TAGS = 5;
// --- services
@Autowired
@ -217,7 +205,7 @@ public final class TaskEditActivity extends TabActivity {
R.id.reminder_overdue, R.id.reminder_alarm));
controls.add( new RandomReminderControlSet(R.id.reminder_random,
R.id.reminder_random_interval));
controls.add(new TagsControlSet(R.id.tags_container));
controls.add(new TagsControlSet(this, R.id.tags_container));
controls.add(new CalendarControlSet(R.id.add_to_calendar, R.id.view_calendar_event));
controls.add(new TimeDurationTaskEditControlSet(Task.ESTIMATED_SECONDS,
@ -1151,103 +1139,6 @@ public final class TaskEditActivity extends TabActivity {
}
}
/**
* Control set to manage adding and removing tags
*
* @author Tim Su <tim@todoroo.com>
*
*/
private class TagsControlSet implements TaskEditControlSet {
private final TagService tagService = new TagService();
private final Tag[] allTags;
private final LinearLayout tagsContainer;
public TagsControlSet(int tagsContainer) {
allTags = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE);
this.tagsContainer = (LinearLayout) findViewById(tagsContainer);
}
@SuppressWarnings("nls")
@Override
public void readFromTask(Task task) {
// tags (only configure if not already set)
if(tagsContainer.getChildCount() == 0) {
TodorooCursor<Metadata> cursor = tagService.getTags(task.getId());
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext())
addTag(cursor.get(Metadata.VALUE));
} finally {
cursor.close();
}
addTag("");
}
}
@Override
public void writeToModel(Task task) {
ArrayList<String> tags = new ArrayList<String>();
for(int i = 0; i < tagsContainer.getChildCount(); i++) {
TextView tagName = (TextView)tagsContainer.getChildAt(i).findViewById(R.id.text1);
if(tagName.getText().length() == 0)
continue;
tags.add(tagName.getText().toString());
}
tagService.synchronizeTags(task.getId(), tags);
}
/** Adds a tag to the tag field */
boolean addTag(String tagName) {
if (tagsContainer.getChildCount() >= MAX_TAGS) {
return false;
}
LayoutInflater inflater = getLayoutInflater();
final View tagItem = inflater.inflate(R.layout.tag_edit_row, null);
tagsContainer.addView(tagItem);
AutoCompleteTextView textView = (AutoCompleteTextView)tagItem.
findViewById(R.id.text1);
textView.setText(tagName);
ArrayAdapter<Tag> tagsAdapter =
new ArrayAdapter<Tag>(TaskEditActivity.this,
android.R.layout.simple_dropdown_item_1line, allTags);
textView.setAdapter(tagsAdapter);
textView.addTextChangedListener(new TextWatcher() {
@SuppressWarnings("nls")
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(start == 0 && tagsContainer.getChildAt(
tagsContainer.getChildCount()-1) == tagItem) {
addTag("");
}
}
public void afterTextChanged(Editable s) {
//
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
//
}
});
ImageButton reminderRemoveButton;
reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1);
reminderRemoveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tagsContainer.removeView(tagItem);
}
});
return true;
}
}
/**
* Calendar Control Set
* @author Tim Su <tim@todoroo.com>
@ -1258,7 +1149,10 @@ public final class TaskEditActivity extends TabActivity {
/** If task has no estimated time, how early to set a task in calendar */
private static final int DEFAULT_CAL_TIME = 3600;
@SuppressWarnings("unused")
private final CheckBox addToCalendar;
@SuppressWarnings("unused")
private final Button viewCalendarEvent;
public CalendarControlSet(int addToCalendar,
@ -1275,7 +1169,7 @@ public final class TaskEditActivity extends TabActivity {
* @param estimatedSeconds estimated duration or null
* @param values
*/
@SuppressWarnings("nls")
@SuppressWarnings({ "nls", "unused" })
public void createCalendarStartEndTimes(Date preferred, Date definite,
Integer estimatedSeconds, ContentValues values) {
FlurryAgent.onEvent("create-calendar-event");
@ -1296,6 +1190,7 @@ public final class TaskEditActivity extends TabActivity {
values.put("dtend", deadlineDate);
}
@SuppressWarnings("unused")
protected void onPause() {
// create calendar event
/*if(addToCalendar.isChecked() && model.getCalendarUri() == null) {
@ -1345,10 +1240,12 @@ public final class TaskEditActivity extends TabActivity {
@Override
public void readFromTask(Task task) {
//
}
@Override
public void writeToModel(Task task) {
//
}
}

@ -17,7 +17,7 @@ import com.todoroo.astrid.model.Task;
*
*/
@SuppressWarnings("nls")
public final class Database extends AbstractDatabase {
public class Database extends AbstractDatabase {
// --- constants

@ -5,19 +5,10 @@
*/
package com.todoroo.astrid.dao;
import java.text.ParseException;
import java.util.Date;
import java.util.TimeZone;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import com.google.ical.iter.RecurrenceIterator;
import com.google.ical.iter.RecurrenceIteratorFactory;
import com.google.ical.values.DateTimeValueImpl;
import com.google.ical.values.DateValue;
import com.google.ical.values.DateValueImpl;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.GenericDao;
import com.todoroo.andlib.service.Autowired;
@ -286,56 +277,7 @@ public class TaskDao extends GenericDao<Task> {
* @param duringSync
*/
private void afterComplete(Task task, ContentValues values, boolean duringSync) {
task = fetch(task.getId(), Task.ID, Task.RECURRENCE, Task.DUE_DATE);
if(task == null)
return;
String recurrence = task.getValue(Task.RECURRENCE);
if(recurrence.length() > 0) {
Date date = new Date();
DateValue today = new DateValueImpl(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
DateValue dateValue;
if(task.hasDueDate() && task.hasDueTime()) {
date = new Date(task.getValue(Task.DUE_DATE));
dateValue = new DateTimeValueImpl(date.getYear() + 1900,
date.getMonth() + 1, date.getDate(),
date.getHours(), date.getMinutes(), date.getSeconds());
} else if(task.hasDueDate()) {
date = new Date(task.getValue(Task.DUE_DATE));
dateValue = new DateValueImpl(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
} else {
dateValue = today;
}
try {
RecurrenceIterator iterator = RecurrenceIteratorFactory.createRecurrenceIterator(recurrence,
dateValue, TimeZone.getDefault());
if(dateValue.compareTo(today) < 0)
dateValue = today;
iterator.advanceTo(dateValue);
iterator.next();
if(iterator.hasNext()) {
long dueDate;
DateValue newDate = iterator.next();
if(newDate instanceof DateTimeValueImpl) {
DateTimeValueImpl newDateTime = (DateTimeValueImpl)newDate;
dueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY_TIME,
new Date(newDateTime.year() - 1900, newDateTime.month() - 1,
newDateTime.day(), newDateTime.hour(),
newDateTime.minute(), newDateTime.second()).getTime());
} else {
dueDate = task.createDueDate(Task.URGENCY_SPECIFIC_DAY,
new Date(newDate.year() - 1900, newDate.month() - 1,
newDate.day()).getTime());
}
task.setValue(Task.DUE_DATE, dueDate);
task.setValue(Task.COMPLETION_DATE, 0L);
persist(task);
}
} catch (ParseException e) {
exceptionService.reportError("recurrence-rule: " + recurrence, e); //$NON-NLS-1$
}
}
/*Cursor cursor = fetchTaskCursor(task.getTaskIdentifier(),
TaskModelForHandlers.FIELD_LIST);

@ -116,6 +116,9 @@ public final class Task extends AbstractModel {
// --- flags
/** whether repeat occurs relative to completion date instead of due date */
public static final int FLAG_REPEAT_AFTER_COMPLETION = 1 << 1;
// --- notification flags
/** whether to send a reminder at deadline */
@ -243,6 +246,19 @@ public final class Task extends AbstractModel {
return (getValue(property) & flag) > 0;
}
/**
* Sets the state of the given flag on the given property
* @param property
* @param flag
* @param value
*/
public void setFlag(IntegerProperty property, int flag, boolean value) {
if(value)
setValue(property, getValue(property) | flag);
else
setValue(property, getValue(property) & ~flag);
}
// --- due and hide until date management
/** urgency array index -> significance */

@ -1,10 +1,8 @@
package com.todoroo.astrid.service;
import android.util.Log;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.sql.Criterion;

@ -9,8 +9,11 @@ import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
/**
@ -24,6 +27,9 @@ public class TaskService {
@Autowired
private TaskDao taskDao;
@Autowired
private MetadataDao metadataDao;
public TaskService() {
DependencyInjectionService.getInstance().inject(this);
}
@ -50,7 +56,6 @@ public class TaskService {
item.setValue(Task.COMPLETION_DATE, DateUtilities.now());
else
item.setValue(Task.COMPLETION_DATE, 0L);
taskDao.save(item, false);
}
@ -66,6 +71,33 @@ public class TaskService {
return taskDao.save(item, isDuringSync);
}
/**
* Clone the given task and all its metadata
*
* @param the old task
* @return the new task
*/
public Task clone(Task task) {
Task newTask = fetchById(task.getId(), Task.PROPERTIES);
newTask.clearValue(Task.ID);
taskDao.createNew(newTask);
TodorooCursor<Metadata> cursor = metadataDao.query(
Query.select(Metadata.PROPERTIES).where(MetadataCriteria.byTask(task.getId())));
try {
Metadata metadata = new Metadata();
long newId = newTask.getId();
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
metadata.readFromCursor(cursor);
metadata.setValue(Metadata.TASK, newId);
metadata.clearValue(Metadata.ID);
metadataDao.createNew(metadata);
}
} finally {
cursor.close();
}
return newTask;
}
/**
* Delete the given task. Instead of deleting from the database, we set
* the deleted flag.

@ -56,14 +56,14 @@ public class DatabaseTestCase extends TodorooTestCase {
public static class TestDatabase extends Database {
@Override
protected String getName() {
public String getName() {
return "databasetest";
}
}
public static class TestAlarmsDatabase extends AlarmDatabase {
@Override
protected String getName() {
public String getName() {
return "alarmstest";
}
}

Loading…
Cancel
Save