got widget working. and fixed some bugs with it...

pull/14/head
Tim Su 14 years ago
parent 9df24b5fff
commit 734face4c2

@ -119,7 +119,7 @@
</intent-filter>
</receiver>
<receiver android:name=".appwidget.AstridAppWidgetProvider" >
<receiver android:name="com.todoroo.astrid.widget.TasksWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
@ -129,7 +129,7 @@
<!-- ======================================================== Services = -->
<service android:name=".appwidget.AstridAppWidgetProvider$UpdateService"></service>
<service android:name="com.todoroo.astrid.widget.TasksWidget$UpdateService"></service>
<service android:name=".sync.SynchronizationService" />
<service android:name=".utilities.BackupService"/>

@ -5,7 +5,9 @@
*/
package com.todoroo.andlib.data;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
@ -150,7 +152,7 @@ abstract public class AbstractDatabase {
/**
* @return sql database. opens database if not yet open
*/
public final SQLiteDatabase getDatabase() {
private synchronized final SQLiteDatabase getDatabase() {
// open database if requested
if(database == null)
openForWriting();
@ -165,6 +167,36 @@ abstract public class AbstractDatabase {
return "DB:" + getName();
}
// --- database wrapper
/*
* @see android.database.sqlite.SQLiteDatabase#rawQuery(String sql, String[] selectionArgs)
*/
public synchronized Cursor rawQuery(String sql, String[] selectionArgs) {
return getDatabase().rawQuery(sql, selectionArgs);
}
/*
* @see android.database.sqlite.SQLiteDatabase#insert(String table, String nullColumnHack, ContentValues values)
*/
public synchronized long insert(String table, String nullColumnHack, ContentValues values) {
return getDatabase().insert(table, nullColumnHack, values);
}
/*
* @see android.database.sqlite.SQLiteDatabase#delete(String table, String whereClause, String[] whereArgs)
*/
public synchronized int delete(String table, String whereClause, String[] whereArgs) {
return getDatabase().delete(table, whereClause, whereArgs);
}
/*
* @see android.database.sqlite.SQLiteDatabase#update(String table, ContentValues values, String whereClause, String[] whereArgs)
*/
public synchronized int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
return getDatabase().update(table, values, whereClause, whereArgs);
}
// --- helper classes
/**

@ -62,7 +62,7 @@ public class GenericDao<TYPE extends AbstractModel> {
*/
public TodorooCursor<TYPE> query(Query query) {
query.from(table);
Cursor cursor = database.getDatabase().rawQuery(query.toString(), null);
Cursor cursor = database.rawQuery(query.toString(), null);
return new TodorooCursor<TYPE>(cursor, query.getFields());
}
@ -110,7 +110,7 @@ public class GenericDao<TYPE extends AbstractModel> {
* @return true if delete was successful
*/
public boolean delete(long id) {
return database.getDatabase().delete(table.name,
return database.delete(table.name,
AbstractModel.ID_PROPERTY.eq(id).toString(), null) > 0;
}
@ -121,7 +121,7 @@ public class GenericDao<TYPE extends AbstractModel> {
* @return # of deleted items
*/
public int deleteWhere(Criterion where) {
return database.getDatabase().delete(table.name,
return database.delete(table.name,
where.toString(), null);
}
@ -155,7 +155,7 @@ public class GenericDao<TYPE extends AbstractModel> {
* @return returns true on success.
*/
public boolean createNew(TYPE item) {
long newRow = database.getDatabase().insert(table.name,
long newRow = database.insert(table.name,
AbstractModel.ID_PROPERTY.name, item.getMergedValues());
item.setId(newRow);
return newRow >= 0;
@ -175,7 +175,7 @@ public class GenericDao<TYPE extends AbstractModel> {
ContentValues values = item.getSetValues();
if(values.size() == 0) // nothing changed
return true;
return database.getDatabase().update(table.name, values,
return database.update(table.name, values,
AbstractModel.ID_PROPERTY.eq(item.getId()).toString(), null) > 0;
}

@ -38,12 +38,10 @@ public class ReminderPreferences extends TodorooPreferences {
if(index <= 0) {
preference.setSummary(r.getString(R.string.rmd_EPr_quiet_hours_desc_none));
endPreference.setEnabled(false);
endPreference.setSummary(r.getString(R.string.rmd_EPr_quiet_hours_desc_none));
} else {
String setting = r.getStringArray(R.array.EPr_quiet_hours_start)[index];
preference.setSummary(r.getString(R.string.rmd_EPr_quiet_hours_start_desc, setting));
endPreference.setEnabled(true);
updatePreferences(endPreference, Preferences.getStringValue(endPreference.getKey()));
}
} else if(r.getString(R.string.p_rmd_quietEnd).equals(preference.getKey())) {
int index = AndroidUtilities.indexOf(r.getStringArray(R.array.EPr_quiet_hours_end_values), (String)value);
@ -63,9 +61,9 @@ public class ReminderPreferences extends TodorooPreferences {
preference.setSummary(r.getString(R.string.rmd_EPr_defaultRemind_desc, setting));
}
} else if(r.getString(R.string.p_rmd_ringtone).equals(preference.getKey())) {
if(value == null || "content://settings/system/notification_sound".equals(value))
if(value == null || "content://settings/system/notification_sound".equals(value)) //$NON-NLS-1$
preference.setSummary(r.getString(R.string.rmd_EPr_ringtone_desc_default));
else if("".equals(value))
else if("".equals(value)) //$NON-NLS-1$
preference.setSummary(r.getString(R.string.rmd_EPr_ringtone_desc_silent));
else
preference.setSummary(r.getString(R.string.rmd_EPr_ringtone_desc_custom));

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -62,7 +62,7 @@
<!-- Quiet Hours Start Description (%s => time set) -->
<string name="rmd_EPr_quiet_hours_start_desc">No notifications will appear after %s</string>
<!-- Quiet Hours Start/End Description (disabled) -->
<string name="rmd_EPr_quiet_hours_desc_none">Please set both start and end times</string>
<string name="rmd_EPr_quiet_hours_desc_none">Quiet hours is disabled</string>
<!-- Quiet Hours End Title -->
<string name="rmd_EPr_quiet_hours_end_title">Quiet Hours End</string>

@ -36,7 +36,6 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
import com.timsu.astrid.appwidget.AstridAppWidgetProvider.UpdateService;
import com.timsu.astrid.data.AbstractController;
import com.timsu.astrid.data.alerts.AlertController;
import com.timsu.astrid.data.sync.SyncDataController;
@ -45,6 +44,7 @@ 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.SynchronizerListener;
import com.todoroo.astrid.widget.TasksWidget.UpdateService;
/**
* Controller for task-related operations

@ -18,15 +18,15 @@ import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.FrameLayout;
import android.widget.Toast;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import com.flurry.android.FlurryAgent;
import com.timsu.astrid.R;
@ -136,9 +136,9 @@ public class FilterListActivity extends ExpandableListActivity {
R.string.FLA_menu_search);
item.setIcon(android.R.drawable.ic_menu_search);
item = menu.add(Menu.NONE, MENU_HELP_ID, Menu.NONE,
/*item = menu.add(Menu.NONE, MENU_HELP_ID, Menu.NONE,
R.string.FLA_menu_help);
item.setIcon(android.R.drawable.ic_menu_help);
item.setIcon(android.R.drawable.ic_menu_help);*/
return true;
}

@ -27,9 +27,9 @@ import java.util.List;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TabActivity;
import android.app.TimePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.ContentValues;
import android.content.DialogInterface;
@ -44,7 +44,6 @@ 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.AutoCompleteTextView;
import android.widget.Button;
@ -60,21 +59,22 @@ import android.widget.TextView;
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;
import com.timsu.astrid.data.enums.RepeatInterval;
import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo;
import com.timsu.astrid.data.task.TaskModelForEdit;
import com.timsu.astrid.data.task.AbstractTaskModel.RepeatInfo;
import com.timsu.astrid.utilities.AstridUtilities;
import com.timsu.astrid.widget.NumberPicker;
import com.timsu.astrid.widget.NumberPickerDialog;
import com.timsu.astrid.widget.NumberPickerDialog.OnNumberPickedListener;
import com.timsu.astrid.widget.TimeDurationControlSet;
import com.timsu.astrid.widget.NumberPickerDialog.OnNumberPickedListener;
import com.timsu.astrid.widget.TimeDurationControlSet.TimeDurationType;
import com.todoroo.andlib.data.TodorooCursor;
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;
@ -236,7 +236,7 @@ public final class TaskEditActivity extends TabActivity {
* @return true if task is newly created
*/
private boolean isNewTask() {
return model.getValue(Task.TITLE).length() == 0;
return model == null ? true : model.getValue(Task.TITLE).length() == 0;
}
/** Set up button listeners */
@ -297,14 +297,9 @@ public final class TaskEditActivity extends TabActivity {
@SuppressWarnings("nls")
protected void loadItem(Intent intent) {
long idParam = intent.getLongExtra(ID_TOKEN, -1L);
if(idParam == -1) {
exceptionService.reportError("task-edit-no-token", null);
finish();
return;
}
database.openForReading();
if(idParam == Task.NO_ID) {
if(idParam == -1L) {
model = new Task();
taskService.save(model, false);
} else {

@ -44,11 +44,8 @@ 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.sql.Functions;
import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.QueryTemplate;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.DialogUtilities;
import com.todoroo.andlib.utility.Pair;
import com.todoroo.astrid.adapter.TaskAdapter;
@ -199,17 +196,17 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
MenuItem item;
item = menu.add(Menu.NONE, MENU_ADDONS_ID, Menu.NONE,
/*item = menu.add(Menu.NONE, MENU_ADDONS_ID, Menu.NONE,
R.string.TLA_menu_addons);
item.setIcon(android.R.drawable.ic_menu_set_as);
item.setIcon(android.R.drawable.ic_menu_set_as);*/
item = menu.add(Menu.NONE, MENU_SETTINGS_ID, Menu.NONE,
R.string.TLA_menu_settings);
item.setIcon(android.R.drawable.ic_menu_preferences);
item = menu.add(Menu.NONE, MENU_HELP_ID, Menu.NONE,
/*item = menu.add(Menu.NONE, MENU_HELP_ID, Menu.NONE,
R.string.TLA_menu_help);
item.setIcon(android.R.drawable.ic_menu_help);
item.setIcon(android.R.drawable.ic_menu_help);*/
// ask about plug-ins
Intent queryIntent = new Intent(AstridApiConstants.ACTION_TASK_LIST_MENU);
@ -479,15 +476,12 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
protected void setUpTaskList() {
// use default ordering if none specified
if(!filter.sqlQuery.toUpperCase().contains("ORDER BY")) {
filter.sqlQuery += " ORDER BY " + Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0),
DateUtilities.now() + DateUtilities.ONE_WEEK,
Task.DUE_DATE) + " + 200000000 * " +
Task.IMPORTANCE + " + " + Task.COMPLETION_DATE);
filter.sqlQuery += " ORDER BY " + TaskService.defaultTaskOrder();
}
// perform query
TodorooCursor<Task> currentCursor = taskService.fetchFiltered(
TaskAdapter.PROPERTIES, filter);
filter, TaskAdapter.PROPERTIES);
startManagingCursor(currentCursor);
// set up list adapters
@ -523,8 +517,7 @@ public class TaskListActivity extends ListActivity implements OnScrollListener {
else
filter.sqlQuery = filter.sqlQuery.replace("WHERE ", "WHERE " +
TaskCriteria.byId(withCustomId) + " OR ");
currentCursor = taskService.fetchFiltered(
TaskAdapter.PROPERTIES, filter);
currentCursor = taskService.fetchFiltered(filter, TaskAdapter.PROPERTIES);
startManagingCursor(currentCursor);
taskAdapter.changeCursor(currentCursor);

@ -65,7 +65,7 @@ public class MetadataDao extends GenericDao<Metadata> {
public TodorooCursor<Metadata> fetchDangling(Property<?>[] properties) {
Query sql = Query.select(properties).from(Metadata.TABLE).join(Join.left(Task.TABLE,
Metadata.TASK.eq(Task.ID))).where(Task.TITLE.isNull());
Cursor cursor = database.getDatabase().rawQuery(sql.toString(), null);
Cursor cursor = database.rawQuery(sql.toString(), null);
return new TodorooCursor<Metadata>(cursor, properties);
}

@ -14,7 +14,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import com.timsu.astrid.R;
import com.timsu.astrid.appwidget.AstridAppWidgetProvider.UpdateService;
import com.timsu.astrid.sync.SynchronizationService;
import com.timsu.astrid.utilities.BackupService;
import com.todoroo.andlib.service.Autowired;
@ -26,6 +25,7 @@ import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.reminders.ReminderService;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.utility.Preferences;
import com.todoroo.astrid.widget.TasksWidget.UpdateService;
/**
* Service which handles jobs that need to be run when Astrid starts up.

@ -4,6 +4,8 @@ import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
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;
@ -103,12 +105,31 @@ public class TaskService {
}
}
public TodorooCursor<Task> fetchFiltered(Property<?>[] properties,
Filter filter) {
/**
* Fetch tasks for the given filter
* @param properties
* @param filter
* @return
*/
public TodorooCursor<Task> fetchFiltered(Filter filter, Property<?>... properties) {
if(filter == null || filter.sqlQuery == null)
return taskDao.query(Query.select(properties));
else
return taskDao.query(Query.select(properties).withQueryTemplate(filter.sqlQuery));
}
/**
* Return the default task ordering
* @return
*/
@SuppressWarnings("nls")
public static Order defaultTaskOrder() {
return Order.asc(Functions.caseStatement(Task.DUE_DATE.eq(0),
DateUtilities.now() + DateUtilities.ONE_WEEK,
Task.DUE_DATE) + " + 200000000 * " +
Task.IMPORTANCE + " + " + Task.COMPLETION_DATE);
}
}

@ -31,5 +31,5 @@ public final class Constants {
/**
* Whether to turn on debugging logging and UI
*/
public static final boolean DEBUG = true;
public static final boolean DEBUG = false;
}

@ -1,6 +1,4 @@
package com.timsu.astrid.appwidget;
import java.util.ArrayList;
package com.todoroo.astrid.widget;
import android.app.PendingIntent;
import android.app.Service;
@ -11,24 +9,29 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import com.timsu.astrid.R;
import com.timsu.astrid.data.task.TaskController;
import com.timsu.astrid.data.task.TaskModelForWidget;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.activity.TaskEditActivity;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.core.CoreFilterExposer;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.model.Task;
import com.todoroo.astrid.service.AstridDependencyInjector;
import com.todoroo.astrid.service.TaskService;
public class AstridAppWidgetProvider extends AppWidgetProvider {
public class TasksWidget extends AppWidgetProvider {
static {
AstridDependencyInjector.initialize();
}
private final static String TAG = "AstridAppWidgetProvider";
public final static int[] TEXT_IDS = { R.id.task_1, R.id.task_2,
R.id.task_3, R.id.task_4, R.id.task_5 };
public final static int[] SEPARATOR_IDS = { R.id.separator_1,
@ -39,7 +42,6 @@ public class AstridAppWidgetProvider extends AppWidgetProvider {
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
Log.e(TAG, "onUpdate()");
// Start in service to prevent Application Not Responding timeout
context.startService(new Intent(context, UpdateService.class));
@ -47,15 +49,20 @@ public class AstridAppWidgetProvider extends AppWidgetProvider {
public static class UpdateService extends Service {
@Autowired
Database database;
@Autowired
TaskService taskService;
@Override
public void onStart(Intent intent, int startId) {
Log.e("UpdateService", "onStart()");
DependencyInjectionService.getInstance().inject(this);
RemoteViews updateViews = buildUpdate(this);
ComponentName thisWidget = new ComponentName(this,
AstridAppWidgetProvider.class);
TasksWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(thisWidget, updateViews);
}
@ -65,7 +72,8 @@ public class AstridAppWidgetProvider extends AppWidgetProvider {
return null;
}
public static RemoteViews buildUpdate(Context context) {
@SuppressWarnings("nls")
public RemoteViews buildUpdate(Context context) {
RemoteViews views = null;
views = new RemoteViews(context.getPackageName(),
@ -75,43 +83,42 @@ public class AstridAppWidgetProvider extends AppWidgetProvider {
int[] separatorIDs = SEPARATOR_IDS;
int numberOfTasks = 5;
TaskController taskController = new TaskController(context);
taskController.open();
ArrayList<TaskModelForWidget> taskList = taskController
.getTasksForWidget(Integer.toString(numberOfTasks));
taskController.close();
Intent listIntent = new Intent(context, TaskListActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
listIntent, 0);
views.setOnClickPendingIntent(R.id.taskbody, pendingIntent);
for (int i = 0; i < textIDs.length; i++) {
TaskModelForWidget taskModel = (i < taskList.size()) ?
taskList.get(i) : null;
String textContent = "";
int textColor = Color.WHITE;
if (taskModel != null) {
textContent = taskModel.getName();
// tweak color if overdue
if((taskModel.getPreferredDueDate() != null && taskModel.getPreferredDueDate().getTime() < System.currentTimeMillis()) ||
(taskModel.getDefiniteDueDate() != null && taskModel.getDefiniteDueDate().getTime() < System.currentTimeMillis()))
Filter inboxFilter = CoreFilterExposer.buildInboxFilter(getResources());
inboxFilter.sqlQuery += " LIMIT " + numberOfTasks;
TodorooCursor<Task> cursor = null;
try {
database.openForWriting();
cursor = taskService.fetchFiltered(inboxFilter, Task.TITLE, Task.DUE_DATE);
Task task = new Task();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.moveToPosition(i);
task.readFromCursor(cursor);
String textContent = "";
int textColor = Color.WHITE;
textContent = task.getValue(Task.TITLE);
if(task.hasDueDate() && task.getValue(Task.DUE_DATE) < DateUtilities.now())
textColor = context.getResources().getColor(R.color.task_list_overdue);
}
if (i < separatorIDs.length) {
if (i < taskList.size() - 1 && taskList.get(i + 1) != null) {
views.setViewVisibility(separatorIDs[i], View.VISIBLE);
} else {
views.setViewVisibility(separatorIDs[i],
View.INVISIBLE);
}
if(i > 0)
views.setViewVisibility(separatorIDs[i-1], View.VISIBLE);
views.setTextViewText(textIDs[i], textContent);
views.setTextColor(textIDs[i], textColor);
}
views.setTextViewText(textIDs[i], textContent);
views.setTextColor(textIDs[i], textColor);
for(int i = cursor.getCount() - 1; i < separatorIDs.length; i++)
views.setViewVisibility(separatorIDs[i], View.INVISIBLE);
} catch (Exception e) {
// can happen if database is not ready
} finally {
if(cursor != null)
cursor.close();
}
Intent editIntent = new Intent(context, TaskEditActivity.class);

@ -1,30 +0,0 @@
package com.todoroo.astrid.dao;
import android.database.sqlite.SQLiteDatabase;
import com.todoroo.astrid.test.DatabaseTestCase;
public class BasicDatabaseTests extends DatabaseTestCase {
/**
* Test that it's possible to open the database multiple times, to no effect
*/
public void testOpenMultipleTimes() {
SQLiteDatabase sqlDatabase = database.getDatabase();
database.openForReading();
assertEquals(sqlDatabase, database.getDatabase());
database.openForWriting();
assertEquals(sqlDatabase, database.getDatabase());
database.openForReading();
assertEquals(sqlDatabase, database.getDatabase());
}
public void testCloseAndReopen() {
SQLiteDatabase sqlDatabase = database.getDatabase();
database.close();
database.openForReading();
assertNotSame(sqlDatabase, database.getDatabase());
}
}
Loading…
Cancel
Save