From c092436f4f694c97f0ac689ac8c2306c8dc07702 Mon Sep 17 00:00:00 2001 From: Tim Su Date: Mon, 16 Aug 2010 14:29:13 -0700 Subject: [PATCH 1/6] Fix for AST-242 - task editing cancelled when rotate on edit new task, AST-211 - new tag box doesn't always appear, AST-262 - tag drop down selector --- .../com/todoroo/astrid/tags/TagService.java | 11 +- .../todoroo/astrid/tags/TagsControlSet.java | 119 ++++++++++++++---- astrid/res/layout/task_edit_activity.xml | 4 + astrid/res/values/strings-tags.xml | 3 + .../astrid/activity/TaskEditActivity.java | 67 +++++----- .../src/com/todoroo/astrid/dao/TaskDao.java | 2 +- .../todoroo/astrid/widget/TasksWidget.java | 4 +- 7 files changed, 143 insertions(+), 67 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java index 24e912ff1..62509f576 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java @@ -2,9 +2,9 @@ package com.todoroo.astrid.tags; import java.util.LinkedHashSet; -import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.data.Property.CountProperty; 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.sql.Criterion; @@ -71,6 +71,11 @@ public final class TagService { public String tag; int count; + public Tag(String tag, int count) { + this.tag = tag; + this.count = count; + } + @Override public String toString() { return tag; @@ -114,9 +119,7 @@ public final class TagService { Tag[] array = new Tag[cursor.getCount()]; for (int i = 0; i < array.length; i++) { cursor.moveToNext(); - array[i] = new Tag(); - array[i].tag = cursor.get(TAG); - array[i].count = cursor.get(COUNT); + array[i] = new Tag(cursor.get(TAG), cursor.get(COUNT)); } return array; } finally { diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java index 4154e6e83..b24c0960a 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java @@ -1,16 +1,25 @@ package com.todoroo.astrid.tags; +import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashSet; import android.app.Activity; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; +import android.view.inputmethod.EditorInfo; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; import android.widget.ImageButton; import android.widget.LinearLayout; +import android.widget.Spinner; import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; import com.timsu.astrid.R; import com.todoroo.andlib.data.AbstractModel; @@ -32,6 +41,7 @@ public final class TagsControlSet implements TaskEditControlSet { // --- instance variables + private final Spinner tagSpinner; private final TagService tagService = TagService.getInstance(); private final Tag[] allTags; private String[] loadedTags; @@ -42,6 +52,36 @@ public final class TagsControlSet implements TaskEditControlSet { allTags = tagService.getGroupedTags(TagService.GROUPED_TAGS_BY_SIZE, Criterion.all); this.activity = activity; this.tagsContainer = (LinearLayout) activity.findViewById(tagsContainer); + this.tagSpinner = (Spinner) activity.findViewById(R.id.tags_dropdown); + + if(allTags.length == 0) { + tagSpinner.setVisibility(View.GONE); + } else { + ArrayList dropDownList = new ArrayList(Arrays.asList(allTags)); + dropDownList.add(0, new Tag(activity.getString(R.string.TEA_tag_dropdown), 0)); + ArrayAdapter tagAdapter = new ArrayAdapter(activity, + android.R.layout.simple_spinner_item, + dropDownList); + tagAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + tagSpinner.setAdapter(tagAdapter); + tagSpinner.setSelection(0); + + tagSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView arg0, View arg1, + int position, long arg3) { + if(position == 0 || position > allTags.length) + return; + addTag(allTags[position - 1].tag, true); + tagSpinner.setSelection(0); + } + + @Override + public void onNothingSelected(AdapterView arg0) { + // nothing! + } + }); + } } @Override @@ -55,16 +95,14 @@ public final class TagsControlSet implements TaskEditControlSet { for(int i = 0; i < loadedTags.length; i++) { cursor.moveToNext(); String tag = cursor.get(TagService.TAG); - addTag(tag); + addTag(tag, true); loadedTags[i] = tag; } } finally { cursor.close(); } } - - if(tagsContainer.getChildCount() == 0) - addTag(""); //$NON-NLS-1$ + addTag("", false); //$NON-NLS-1$ } @Override @@ -96,10 +134,25 @@ public final class TagsControlSet implements TaskEditControlSet { } /** Adds a tag to the tag field */ - boolean addTag(String tagName) { + boolean addTag(String tagName, boolean reuse) { LayoutInflater inflater = activity.getLayoutInflater(); - final View tagItem = inflater.inflate(R.layout.tag_edit_row, null); - tagsContainer.addView(tagItem); + + // check if already exists + TextView lastText = null; + for(int i = 0; i < tagsContainer.getChildCount(); i++) { + View view = tagsContainer.getChildAt(i); + lastText = (TextView) view.findViewById(R.id.text1); + if(lastText.getText().equals(tagName)) + return false; + } + + final View tagItem; + if(reuse && lastText != null && lastText.getText().length() == 0) { + tagItem = (View) lastText.getParent(); + } else { + tagItem = inflater.inflate(R.layout.tag_edit_row, null); + tagsContainer.addView(tagItem); + } final AutoCompleteTextView textView = (AutoCompleteTextView)tagItem. findViewById(R.id.text1); @@ -109,36 +162,46 @@ public final class TagsControlSet implements TaskEditControlSet { android.R.layout.simple_dropdown_item_1line, allTags); textView.setAdapter(tagsAdapter); - textView.setOnClickListener(new OnClickListener() { + textView.addTextChangedListener(new TextWatcher() { @Override - public void onClick(View arg0) { - View lastItem = tagsContainer.getChildAt(tagsContainer.getChildCount()-1); - TextView lastText = (TextView) lastItem.findViewById(R.id.text1); - if(lastText.getText().length() != 0) { - addTag(""); //$NON-NLS-1$ - } + public void afterTextChanged(Editable s) { + // + } + @Override + public void beforeTextChanged(CharSequence s, int start, int count, + int after) { + // + } + @Override + public void onTextChanged(CharSequence s, int start, int before, + int count) { + if(count > 0 && tagsContainer.getChildAt(tagsContainer.getChildCount()-1) == + tagItem) + addTag("", false); //$NON-NLS-1$ } }); - /*textView.setOnEditorActionListener(new OnEditorActionListener() { + textView.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView arg0, int actionId, KeyEvent arg2) { if(actionId != EditorInfo.IME_NULL) return false; - View lastItem = tagsContainer.getChildAt(tagsContainer.getChildCount()-1); - TextView lastText = (TextView) lastItem.findViewById(R.id.text1); - if(lastText.getText().length() != 0) { - addTag(""); //$NON-NLS-1$ + if(getLastTextView().getText().length() != 0) { + addTag("", false); //$NON-NLS-1$ } return true; } - });*/ + }); ImageButton reminderRemoveButton; reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1); reminderRemoveButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - if(tagsContainer.getChildCount() > 0) + TextView lastView = getLastTextView(); + if(lastView == textView && textView.getText().length() == 0) + return; + + if(tagsContainer.getChildCount() > 1) tagsContainer.removeView(tagItem); else textView.setText(""); //$NON-NLS-1$ @@ -147,4 +210,16 @@ public final class TagsControlSet implements TaskEditControlSet { return true; } + + /** + * Get tags container last text view. might be null + * @return + */ + private TextView getLastTextView() { + if(tagsContainer.getChildCount() == 0) + return null; + View lastItem = tagsContainer.getChildAt(tagsContainer.getChildCount()-1); + TextView lastText = (TextView) lastItem.findViewById(R.id.text1); + return lastText; + } } \ No newline at end of file diff --git a/astrid/res/layout/task_edit_activity.xml b/astrid/res/layout/task_edit_activity.xml index e6fdb48b2..5691e1d23 100644 --- a/astrid/res/layout/task_edit_activity.xml +++ b/astrid/res/layout/task_edit_activity.xml @@ -65,6 +65,10 @@ + diff --git a/astrid/res/values/strings-tags.xml b/astrid/res/values/strings-tags.xml index 86ed091ae..e33705159 100644 --- a/astrid/res/values/strings-tags.xml +++ b/astrid/res/values/strings-tags.xml @@ -11,6 +11,9 @@ Tag Name + + + Select a tag diff --git a/astrid/src/com/todoroo/astrid/activity/TaskEditActivity.java b/astrid/src/com/todoroo/astrid/activity/TaskEditActivity.java index 2bc380038..c4b6c4422 100644 --- a/astrid/src/com/todoroo/astrid/activity/TaskEditActivity.java +++ b/astrid/src/com/todoroo/astrid/activity/TaskEditActivity.java @@ -27,15 +27,15 @@ import java.util.List; import android.app.AlertDialog; import android.app.DatePickerDialog; -import android.app.TabActivity; import android.app.DatePickerDialog.OnDateSetListener; +import android.app.TabActivity; import android.content.BroadcastReceiver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; +import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.content.IntentFilter; -import android.content.DialogInterface.OnCancelListener; import android.content.res.Resources; import android.os.Bundle; import android.text.format.DateUtils; @@ -45,6 +45,7 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; @@ -59,7 +60,6 @@ import android.widget.TabHost; import android.widget.TimePicker; import android.widget.Toast; import android.widget.ToggleButton; -import android.widget.AdapterView.OnItemSelectedListener; import com.flurry.android.FlurryAgent; import com.timsu.astrid.R; @@ -155,6 +155,9 @@ public final class TaskEditActivity extends TabActivity { // --- other instance variables + /** true if editing started with a new task */ + boolean isNewTask = false; + /** task model */ private Task model = null; @@ -251,25 +254,10 @@ public final class TaskEditActivity extends TabActivity { }); } - // read data - populateFields(); - - // request add-on controls - Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_REQUEST_EDIT_CONTROLS); - broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, model.getId()); - sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); - // set up listeners setUpListeners(); } - /** - * @return true if task is newly created - */ - private boolean isNewTask() { - return model == null ? true : model.getValue(Task.TITLE).length() == 0; - } - /** Set up button listeners */ private void setUpListeners() { final View.OnClickListener mSaveListener = new View.OnClickListener() { @@ -324,9 +312,13 @@ public final class TaskEditActivity extends TabActivity { values = AndroidUtilities.contentValuesFromSerializedString(valuesAsString); model = TaskListActivity.createWithValues(values, null, taskService, metadataService); } - if(model.getValue(Task.TITLE).length() == 0) + + if(model.getValue(Task.TITLE).length() == 0) { FlurryAgent.onEvent("create-task"); - FlurryAgent.onEvent("edit-task"); + isNewTask = true; + } else { + FlurryAgent.onEvent("edit-task"); + } if(model == null) { exceptionService.reportError("task-edit-no-task", @@ -341,7 +333,7 @@ public final class TaskEditActivity extends TabActivity { Resources r = getResources(); loadItem(getIntent()); - if(isNewTask()) + if(isNewTask) setTitle(R.string.TEA_view_titleNew); else setTitle(r.getString(R.string.TEA_view_title, model.getValue(Task.TITLE))); @@ -352,14 +344,6 @@ public final class TaskEditActivity extends TabActivity { /** Save task model from values in UI components */ private void save() { - // abandon editing in this case - if(title.getText().length() == 0) { - if(isNewTask()) - taskService.delete(model); - discardButtonClick(); - return; - } - for(TaskEditControlSet controlSet : controls) controlSet.writeToModel(model); @@ -367,6 +351,18 @@ public final class TaskEditActivity extends TabActivity { showSaveToast(); } + @Override + public void finish() { + super.finish(); + + // abandon editing in this case + if(title.getText().length() == 0 && isNewTask) { + taskService.delete(model); + showCancelToast(); + setResult(RESULT_CANCELED); + } + } + /* ====================================================================== * ================================================ edit control handling * ====================================================================== */ @@ -416,7 +412,7 @@ public final class TaskEditActivity extends TabActivity { */ private void showSaveToast() { // if we have no title, or nothing's changed, don't show toast - if(isNewTask()) + if(isNewTask) return; int stringResource; @@ -445,7 +441,7 @@ public final class TaskEditActivity extends TabActivity { // abandon editing in this case if(title.getText().length() == 0) { - if(isNewTask()) + if(isNewTask) taskService.delete(model); } @@ -540,6 +536,7 @@ public final class TaskEditActivity extends TabActivity { super.onResume(); registerReceiver(controlReceiver, new IntentFilter(AstridApiConstants.BROADCAST_SEND_EDIT_CONTROLS)); + populateFields(); } @Override @@ -552,14 +549,6 @@ public final class TaskEditActivity extends TabActivity { protected void onStop() { super.onStop(); FlurryAgent.onEndSession(this); - - // don't save if user accidentally created a new task - if(title.getText().length() == 0) { - if(model.isSaved()) - taskService.delete(model); - showCancelToast(); - return; - } } /* ====================================================================== diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index debbf747a..613ec1658 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -223,7 +223,7 @@ public class TaskDao extends GenericDao { * @param skipHooks whether this save occurs as part of a sync */ private void afterSave(Task task, ContentValues values) { - if(values.containsKey(Task.COMPLETION_DATE.name) && task.isCompleted()) + if(values != null && values.containsKey(Task.COMPLETION_DATE.name) && task.isCompleted()) afterComplete(task, values); else ReminderService.getInstance().scheduleAlarm(task); diff --git a/astrid/src/com/todoroo/astrid/widget/TasksWidget.java b/astrid/src/com/todoroo/astrid/widget/TasksWidget.java index 576f1fb65..c89a41bd8 100644 --- a/astrid/src/com/todoroo/astrid/widget/TasksWidget.java +++ b/astrid/src/com/todoroo/astrid/widget/TasksWidget.java @@ -98,7 +98,9 @@ public class TasksWidget extends AppWidgetProvider { TasksWidget.class); AppWidgetManager manager = AppWidgetManager.getInstance(this); - int extrasId = intent.getIntExtra(EXTRA_WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + int extrasId = AppWidgetManager.INVALID_APPWIDGET_ID; + if(intent != null) + extrasId = intent.getIntExtra(EXTRA_WIDGET_ID, extrasId); if(extrasId == AppWidgetManager.INVALID_APPWIDGET_ID) { for(int id : manager.getAppWidgetIds(thisWidget)) { RemoteViews updateViews = buildUpdate(this, id); From e31cc413724d90dddf1f8e1b07ce9b0e15a8894a Mon Sep 17 00:00:00 2001 From: Tim Su Date: Mon, 16 Aug 2010 14:51:55 -0700 Subject: [PATCH 2/6] Fix for AST-260 - overdue alarms during quiet hours get no vibrate --- .../com/todoroo/astrid/reminders/Notifications.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java index 18ee80574..b0d82d878 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java @@ -246,8 +246,9 @@ public class Notifications extends BroadcastReceiver { } } - // quiet hours + periodic = no vibrate - if(quietHours && (type == ReminderService.TYPE_RANDOM)) { + // quiet hours && ! due date or snooze = no vibrate + if(quietHours && !(type == ReminderService.TYPE_DUE || + type == ReminderService.TYPE_SNOOZE)) { notification.vibrate = null; } else { if (Preferences.getBoolean(R.string.p_rmd_vibrate, true) From dffd0d1e1127c410cae997ee629f4612945bf1e1 Mon Sep 17 00:00:00 2001 From: Tim Su Date: Mon, 16 Aug 2010 15:01:14 -0700 Subject: [PATCH 3/6] Fix for AST-170 - clear notifications when complete tasks --- .../todoroo/astrid/reminders/Notifications.java | 17 +++++++++++++++++ astrid/src/com/todoroo/astrid/dao/TaskDao.java | 3 +++ 2 files changed, 20 insertions(+) diff --git a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java index b0d82d878..8a25b7c35 100644 --- a/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java +++ b/astrid/plugin-src/com/todoroo/astrid/reminders/Notifications.java @@ -265,6 +265,23 @@ public class Notifications extends BroadcastReceiver { notificationManager.notify(notificationId, notification); } + /** + * Schedules alarms for a single task + * + * @param shouldPerformPropertyCheck + * whether to check if task has requisite properties + */ + public static void cancelNotifications(long taskId) { + if(notificationManager == null) + synchronized(Notifications.class) { + if(notificationManager == null) + notificationManager = new AndroidNotificationManager( + ContextManager.getContext()); + } + + notificationManager.cancel((int)taskId); + } + // --- notification manager public static void setNotificationManager( diff --git a/astrid/src/com/todoroo/astrid/dao/TaskDao.java b/astrid/src/com/todoroo/astrid/dao/TaskDao.java index 613ec1658..5ef9e3c65 100644 --- a/astrid/src/com/todoroo/astrid/dao/TaskDao.java +++ b/astrid/src/com/todoroo/astrid/dao/TaskDao.java @@ -21,6 +21,7 @@ import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.model.Task; import com.todoroo.astrid.provider.Astrid2TaskProvider; +import com.todoroo.astrid.reminders.Notifications; import com.todoroo.astrid.reminders.ReminderService; import com.todoroo.astrid.utility.Preferences; import com.todoroo.astrid.widget.TasksWidget; @@ -245,6 +246,8 @@ public class TaskDao extends GenericDao { Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_COMPLETED); broadcastIntent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); context.sendOrderedBroadcast(broadcastIntent, null); + + Notifications.cancelNotifications(task.getId()); } } From 5cc2e0d041ba1b8b0696c02024bb92fc37ea819b Mon Sep 17 00:00:00 2001 From: Tim Su Date: Mon, 16 Aug 2010 15:02:03 -0700 Subject: [PATCH 4/6] Fix for AST-147 - show filter sizes --- .../todoroo/astrid/adapter/FilterAdapter.java | 71 +++++++++++++++++++ .../todoroo/astrid/service/TaskService.java | 14 +++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/astrid/src/com/todoroo/astrid/adapter/FilterAdapter.java b/astrid/src/com/todoroo/astrid/adapter/FilterAdapter.java index d92dc375a..7f8d60833 100644 --- a/astrid/src/com/todoroo/astrid/adapter/FilterAdapter.java +++ b/astrid/src/com/todoroo/astrid/adapter/FilterAdapter.java @@ -4,6 +4,7 @@ package com.todoroo.astrid.adapter; import java.util.ArrayList; +import java.util.concurrent.LinkedBlockingQueue; import android.app.Activity; import android.content.BroadcastReceiver; @@ -23,11 +24,15 @@ import android.widget.ImageView; import android.widget.TextView; import com.timsu.astrid.R; +import com.todoroo.andlib.data.Property.CountProperty; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.service.DependencyInjectionService; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.api.Filter; import com.todoroo.astrid.api.FilterCategory; import com.todoroo.astrid.api.FilterListHeader; import com.todoroo.astrid.api.FilterListItem; +import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.utility.Preferences; public class FilterAdapter extends BaseExpandableListAdapter { @@ -40,18 +45,45 @@ public class FilterAdapter extends BaseExpandableListAdapter { // --- instance variables + @Autowired + private TaskService taskService; + + /** parent activity */ protected final Activity activity; + + /** owner listview */ protected final ExpandableListView listView; + + /** list of filters */ private final ArrayList items; + + /** display metrics for scaling icons */ private final DisplayMetrics metrics = new DisplayMetrics(); + + /** receiver for new filters */ private final FilterReceiver filterReceiver = new FilterReceiver(); + + /** row layout to inflate */ private final int layout; + + /** layout inflater */ private final LayoutInflater inflater; + + /** whether to skip Filters that launch intents instead of being real filters */ private final boolean skipIntentFilters; + /** queue for loading list sizes */ + private final LinkedBlockingQueue filterQueue = new LinkedBlockingQueue(); + + /** thread for loading list sizes */ + private Thread filterSizeLoadingThread = null; + public FilterAdapter(Activity activity, ExpandableListView listView, int rowLayout, boolean skipIntentFilters) { super(); + + DependencyInjectionService.getInstance().inject(this); + this.activity = activity; this.items = new ArrayList(); this.listView = listView; @@ -64,6 +96,35 @@ public class FilterAdapter extends BaseExpandableListAdapter { activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); listView.setGroupIndicator( activity.getResources().getDrawable(R.drawable.expander_group)); + + startFilterSizeLoadingThread(); + } + + private void startFilterSizeLoadingThread() { + filterSizeLoadingThread = new Thread() { + @Override + public void run() { + CountProperty cp = new CountProperty(); + while(true) { + try { + Filter filter = filterQueue.take(); + int size = taskService.countTasks(filter, cp); + filter.listingTitle = filter.listingTitle + (" (" + //$NON-NLS-1$ + size + ")"); //$NON-NLS-1$ + activity.runOnUiThread(new Runnable() { + public void run() { + notifyDataSetInvalidated(); + } + }); + } catch (InterruptedException e) { + break; + } catch (Exception e) { + Log.e("astrid-filter-adapter", "Error loading filter size", e); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + } + }; + filterSizeLoadingThread.start(); } public boolean hasStableIds() { @@ -72,6 +133,14 @@ public class FilterAdapter extends BaseExpandableListAdapter { public void add(FilterListItem item) { items.add(item); + + // load sizes + if(item instanceof Filter) { + filterQueue.offer((Filter) item); + } else if(item instanceof FilterCategory) { + for(Filter filter : ((FilterCategory)item).children) + filterQueue.offer(filter); + } } public void clear() { @@ -300,6 +369,8 @@ public class FilterAdapter extends BaseExpandableListAdapter { */ public void unregisterRecevier() { activity.unregisterReceiver(filterReceiver); + if(filterSizeLoadingThread != null) + filterSizeLoadingThread.interrupt(); } /** diff --git a/astrid/src/com/todoroo/astrid/service/TaskService.java b/astrid/src/com/todoroo/astrid/service/TaskService.java index bd73e95a7..926514236 100644 --- a/astrid/src/com/todoroo/astrid/service/TaskService.java +++ b/astrid/src/com/todoroo/astrid/service/TaskService.java @@ -1,6 +1,7 @@ package com.todoroo.astrid.service; import com.todoroo.andlib.data.Property; +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; @@ -9,10 +10,11 @@ import com.todoroo.andlib.sql.Functions; 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.api.PermaSql; import com.todoroo.astrid.dao.MetadataDao; -import com.todoroo.astrid.dao.TaskDao; 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; @@ -231,6 +233,16 @@ public class TaskService { } } + public int countTasks(Filter filter, CountProperty countProperty) { + TodorooCursor cursor = query(Query.select(countProperty).withQueryTemplate(filter.sqlQuery)); + try { + cursor.moveToFirst(); + return cursor.getInt(0); + } finally { + cursor.close(); + } + } + } From 992eb9f746fbe1ce98389075c288740db3a6ea35 Mon Sep 17 00:00:00 2001 From: Tim Su Date: Mon, 16 Aug 2010 15:04:16 -0700 Subject: [PATCH 5/6] Bump! 3.2.0 --- astrid/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astrid/AndroidManifest.xml b/astrid/AndroidManifest.xml index ad27b7629..ebdf7be29 100644 --- a/astrid/AndroidManifest.xml +++ b/astrid/AndroidManifest.xml @@ -1,7 +1,7 @@ + android:versionName="3.2.0" android:versionCode="147"> From 85ca151b01e450f6c1e813b26be2a2e29d9efce7 Mon Sep 17 00:00:00 2001 From: Arne Jans Date: Mon, 16 Aug 2010 05:29:33 +0800 Subject: [PATCH 6/6] TaskEditPage: responsibleSpinner gets updated by selecting another dashboard. And its more robust now, if selecting another dashboard, it tries to identify the responsible amongst the associated users and sets it. And if you select the nosync-dashboard, it doesnt get NPEs anymore. Also fixed an invalid whitespace in strings-producteev.xml --- .../producteev/ProducteevControlSet.java | 96 ++++++++++++++----- astrid/res/values/strings-producteev.xml | 4 +- 2 files changed, 74 insertions(+), 26 deletions(-) diff --git a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java index 5c8389499..7b2a6c451 100644 --- a/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java +++ b/astrid/plugin-src/com/todoroo/astrid/producteev/ProducteevControlSet.java @@ -7,9 +7,11 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; +import android.widget.AdapterView.OnItemSelectedListener; import com.timsu.astrid.R; import com.todoroo.andlib.service.Autowired; @@ -55,7 +57,70 @@ public class ProducteevControlSet implements TaskEditControlSet { view = LayoutInflater.from(activity).inflate(R.layout.producteev_control, parent, true); this.responsibleSelector = (Spinner) activity.findViewById(R.id.producteev_TEA_task_assign); + TextView emptyView = new TextView(activity); + emptyView.setText(activity.getText(R.string.producteev_no_dashboard)); + responsibleSelector.setEmptyView(emptyView); + this.dashboardSelector = (Spinner) activity.findViewById(R.id.producteev_TEA_dashboard_assign); + this.dashboardSelector.setOnItemSelectedListener(new OnItemSelectedListener() { + + @Override + public void onItemSelected(AdapterView parent, View view, + int position, long id) { + Spinner dashSelector = (Spinner) parent; + ProducteevDashboard dashboard = (ProducteevDashboard) dashSelector.getSelectedItem(); + refreshResponsibleSpinner(dashboard.getUsers()); + } + + @Override + public void onNothingSelected(AdapterView parent) { + responsibleSelector.setAdapter(null); + responsibleSelector.setEnabled(false); + view.findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(View.GONE); + } + }); + } + + /** + * Refresh the content of the responsibleSelector with the given userlist. + * + * @param users the new userlist to show in the responsibleSelector + */ + private void refreshResponsibleSpinner(ArrayList users) { + Metadata metadata = ProducteevDataService.getInstance().getTaskMetadata(myTask.getId()); + Long responsibleId = metadata.getValue(ProducteevTask.RESPONSIBLE_ID); + refreshResponsibleSpinner(users, responsibleId); + } + + /** + * Refresh the content of the responsibleSelector with the given userlist. + * + * @param users the new userlist to show in the responsibleSelector + * @param responsibleId the id of the responsible user to set in the spinner + */ + private void refreshResponsibleSpinner(ArrayList users, Long responsibleId) { + // Fill the responsible-spinner and set the current responsible + this.users = (users == null ? new ArrayList() : users); + + ArrayAdapter usersAdapter = new ArrayAdapter(activity, + android.R.layout.simple_spinner_item, this.users); + usersAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + responsibleSelector.setAdapter(usersAdapter); + if (users == null) + view.findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(View.GONE); + else + view.findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(View.VISIBLE); + + + int responsibleSpinnerIndex = 0; + + for (int i = 0; i < this.users.size() ; i++) { + if (this.users.get(i).getId() == responsibleId) { + responsibleSpinnerIndex=i; + break; + } + } + responsibleSelector.setSelection(responsibleSpinnerIndex); } @Override @@ -71,50 +136,33 @@ public class ProducteevControlSet implements TaskEditControlSet { StoreObject[] dashboardsData = ProducteevDataService.getInstance().getDashboards(); dashboards = new ArrayList(dashboardsData.length); ProducteevDashboard ownerDashboard = null; - int dashboardSpinnerIndex = 0; + int dashboardSpinnerIndex = -1; //dashboard to not sync as first spinner-entry - dashboards.add(new ProducteevDashboard(ProducteevUtilities.DASHBOARD_NO_SYNC, activity.getString(R.string.producteev_no_dashboard),null)); - for (int i=1;i dashAdapter = new ArrayAdapter(activity, android.R.layout.simple_spinner_item, dashboards); dashAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); dashboardSelector.setAdapter(dashAdapter); - dashboardSelector.setSelection(dashboardSpinnerIndex); + dashboardSelector.setSelection(dashboardSpinnerIndex+1); if (ownerDashboard == null || ownerDashboard.getId() == ProducteevUtilities.DASHBOARD_NO_SYNC) { responsibleSelector.setEnabled(false); - TextView emptyView = new TextView(activity); - emptyView.setText(activity.getText(R.string.producteev_no_dashboard)); - responsibleSelector.setEmptyView(emptyView); + responsibleSelector.setAdapter(null); view.findViewById(R.id.producteev_TEA_task_assign_label).setVisibility(View.GONE); return; } - // Fill the responsible-spinner and set the current responsible - users = ownerDashboard.getUsers(); - long responsibleId = metadata.getValue(ProducteevTask.RESPONSIBLE_ID); - int userSpinnerIndex = 0; - - for (ProducteevUser user : users) { - if (user.getId() == responsibleId) { - break; - } - userSpinnerIndex++; - } - ArrayAdapter usersAdapter = new ArrayAdapter(activity, - android.R.layout.simple_spinner_item, users); - usersAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - responsibleSelector.setAdapter(usersAdapter); - responsibleSelector.setSelection(userSpinnerIndex); + refreshResponsibleSpinner(ownerDashboard.getUsers()); } @Override diff --git a/astrid/res/values/strings-producteev.xml b/astrid/res/values/strings-producteev.xml index 6b368884e..8e68070c0 100644 --- a/astrid/res/values/strings-producteev.xml +++ b/astrid/res/values/strings-producteev.xml @@ -1,9 +1,9 @@ - - + + Producteev