mirror of https://github.com/tasks/tasks
1.9 beta release:
- added tabbed interface for editor - added ability to set fixed-time notifications - fixed some crashespull/14/head
parent
8c3aaab57e
commit
b78e5aa309
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<Button android:id="@+id/date"
|
||||||
|
android:layout_weight="0.45"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<Button android:id="@+id/time"
|
||||||
|
android:layout_weight="0.45"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<ImageButton android:id="@+id/button1"
|
||||||
|
style="?android:attr/buttonStyleInset"
|
||||||
|
android:src="@android:drawable/ic_delete"
|
||||||
|
android:layout_weight="0.1"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_marginTop="2dip"
|
||||||
|
android:layout_marginRight="2dip"
|
||||||
|
android:layout_marginBottom="2dip"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* ASTRID: Android's Simple Task Recording Dashboard
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Tim Su
|
||||||
|
*
|
||||||
|
* 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.activities;
|
||||||
|
|
||||||
|
import android.app.TabActivity;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.timsu.astrid.R;
|
||||||
|
import com.timsu.astrid.data.task.AbstractTaskModel;
|
||||||
|
import com.timsu.astrid.data.task.TaskController;
|
||||||
|
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||||
|
import com.timsu.astrid.utilities.DialogUtilities;
|
||||||
|
|
||||||
|
/** Hack hack for tabbed activity. Should provide better interaction
|
||||||
|
*
|
||||||
|
* @author timsu
|
||||||
|
*/
|
||||||
|
public abstract class TaskModificationTabbedActivity<MODEL_TYPE extends
|
||||||
|
AbstractTaskModel> extends TabActivity {
|
||||||
|
protected static final String LOAD_INSTANCE_TOKEN = TaskModificationActivity.LOAD_INSTANCE_TOKEN;
|
||||||
|
protected TaskController controller;
|
||||||
|
protected MODEL_TYPE model;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
controller = new TaskController(this);
|
||||||
|
controller.open();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// check if we have a TaskIdentifier
|
||||||
|
TaskIdentifier identifier = null;
|
||||||
|
Bundle extras = getIntent().getExtras();
|
||||||
|
if(savedInstanceState != null && savedInstanceState.containsKey(LOAD_INSTANCE_TOKEN)) {
|
||||||
|
identifier = new TaskIdentifier(savedInstanceState.getLong(
|
||||||
|
LOAD_INSTANCE_TOKEN));
|
||||||
|
} else if(extras != null && extras.containsKey(LOAD_INSTANCE_TOKEN))
|
||||||
|
identifier = new TaskIdentifier(extras.getLong(
|
||||||
|
LOAD_INSTANCE_TOKEN));
|
||||||
|
|
||||||
|
model = getModel(identifier);
|
||||||
|
} catch (Exception e) {
|
||||||
|
showErrorAndFinish(R.string.error_opening, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showErrorAndFinish(int prefix, Throwable e) {
|
||||||
|
Resources r = getResources();
|
||||||
|
DialogUtilities.okDialog(this,
|
||||||
|
r.getString(prefix) + " " +
|
||||||
|
e.getLocalizedMessage(), new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected MODEL_TYPE getModel(TaskIdentifier identifier);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
if(model.getTaskIdentifier() != null)
|
||||||
|
outState.putLong(LOAD_INSTANCE_TOKEN, model.getTaskIdentifier().getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* ASTRID: Android's Simple Task Recording Dashboard
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Tim Su
|
||||||
|
*
|
||||||
|
* 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.alerts;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.timsu.astrid.data.AbstractController;
|
||||||
|
import com.timsu.astrid.data.AbstractModel;
|
||||||
|
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||||
|
|
||||||
|
|
||||||
|
/** A single tag on a task */
|
||||||
|
public class Alert extends AbstractModel {
|
||||||
|
|
||||||
|
/** Version number of this model */
|
||||||
|
static final int VERSION = 1;
|
||||||
|
|
||||||
|
// field names
|
||||||
|
|
||||||
|
static final String TASK = "task";
|
||||||
|
static final String DATE = "date";
|
||||||
|
|
||||||
|
/** Default values container */
|
||||||
|
private static final ContentValues defaultValues = new ContentValues();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentValues getDefaultValues() {
|
||||||
|
return defaultValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String[] FIELD_LIST = new String[] {
|
||||||
|
AbstractController.KEY_ROWID,
|
||||||
|
TASK,
|
||||||
|
DATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- database helper
|
||||||
|
|
||||||
|
/** Database Helper manages creating new tables and updating old ones */
|
||||||
|
static class AlertDatabaseHelper extends SQLiteOpenHelper {
|
||||||
|
String tableName;
|
||||||
|
|
||||||
|
AlertDatabaseHelper(Context context, String databaseName, String tableName) {
|
||||||
|
super(context, databaseName, null, VERSION);
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
String sql = new StringBuilder().
|
||||||
|
append("CREATE TABLE ").append(tableName).append(" (").
|
||||||
|
append(AbstractController.KEY_ROWID).append(" integer primary key autoincrement, ").
|
||||||
|
append(TASK).append(" integer not null,").
|
||||||
|
append(DATE).append(" integer not null,").
|
||||||
|
append("unique (").append(TASK).append(",").append(DATE).append(")").
|
||||||
|
append(");").toString();
|
||||||
|
db.execSQL(sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
Log.w(getClass().getSimpleName(), "Upgrading database from version " +
|
||||||
|
oldVersion + " to " + newVersion + ".");
|
||||||
|
|
||||||
|
switch(oldVersion) {
|
||||||
|
default:
|
||||||
|
// we don't know how to handle it... do the unfortunate thing
|
||||||
|
Log.e(getClass().getSimpleName(), "Unsupported migration, table dropped!");
|
||||||
|
db.execSQL("DROP TABLE IF EXISTS " + tableName);
|
||||||
|
onCreate(db);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- constructor pass-through
|
||||||
|
|
||||||
|
Alert(TaskIdentifier task, Date date) {
|
||||||
|
super();
|
||||||
|
setTask(task);
|
||||||
|
setDate(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Alert(Cursor cursor) {
|
||||||
|
super(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- getters and setters: expose them as you see fit
|
||||||
|
|
||||||
|
public boolean isNew() {
|
||||||
|
return getCursor() == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskIdentifier getTask() {
|
||||||
|
return new TaskIdentifier(retrieveInteger(TASK));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDate() {
|
||||||
|
return new Date(retrieveLong(DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTask(TaskIdentifier task) {
|
||||||
|
setValues.put(TASK, task.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDate(Date date) {
|
||||||
|
setValues.put(DATE, date.getTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* ASTRID: Android's Simple Task Recording Dashboard
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Tim Su
|
||||||
|
*
|
||||||
|
* 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.alerts;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.SQLException;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
|
||||||
|
import com.timsu.astrid.data.AbstractController;
|
||||||
|
import com.timsu.astrid.data.alerts.Alert.AlertDatabaseHelper;
|
||||||
|
import com.timsu.astrid.data.task.TaskIdentifier;
|
||||||
|
|
||||||
|
/** Controller for Tag-related operations */
|
||||||
|
public class AlertController extends AbstractController {
|
||||||
|
|
||||||
|
private SQLiteDatabase alertDatabase;
|
||||||
|
|
||||||
|
/** Get a cursor to tag identifiers */
|
||||||
|
public Cursor getTaskAlertsCursor(TaskIdentifier taskId) throws SQLException {
|
||||||
|
Cursor cursor = alertDatabase.query(ALERT_TABLE_NAME,
|
||||||
|
Alert.FIELD_LIST, Alert.TASK + " = ?",
|
||||||
|
new String[] { taskId.idAsString() }, null, null, null);
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
/** Get a list of tag identifiers for the given task */
|
||||||
|
public List<Date> getTaskAlerts(Activity activity, TaskIdentifier
|
||||||
|
taskId) throws SQLException {
|
||||||
|
List<Date> list = new LinkedList<Date>();
|
||||||
|
Cursor cursor = alertDatabase.query(ALERT_TABLE_NAME,
|
||||||
|
Alert.FIELD_LIST, Alert.TASK + " = ?",
|
||||||
|
new String[] { taskId.idAsString() }, null, null, null);
|
||||||
|
activity.startManagingCursor(cursor);
|
||||||
|
|
||||||
|
if(cursor.getCount() == 0)
|
||||||
|
return list;
|
||||||
|
do {
|
||||||
|
cursor.moveToNext();
|
||||||
|
list.add(new Alert(cursor).getDate());
|
||||||
|
} while(!cursor.isLast());
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Remove all alerts from the task */
|
||||||
|
public boolean removeAlerts(TaskIdentifier taskId)
|
||||||
|
throws SQLException{
|
||||||
|
return alertDatabase.delete(ALERT_TABLE_NAME,
|
||||||
|
String.format("%s = ?",
|
||||||
|
Alert.TASK),
|
||||||
|
new String[] { taskId.idAsString() }) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Add the given tag to the task */
|
||||||
|
public boolean addAlert(TaskIdentifier taskId, Date date)
|
||||||
|
throws SQLException {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(Alert.DATE, date.getTime());
|
||||||
|
values.put(Alert.TASK, taskId.getId());
|
||||||
|
return alertDatabase.insert(ALERT_TABLE_NAME, Alert.TASK,
|
||||||
|
values) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- boilerplate
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor - takes the context to allow the database to be
|
||||||
|
* opened/created
|
||||||
|
*/
|
||||||
|
public AlertController(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the notes database. If it cannot be opened, try to create a new
|
||||||
|
* instance of the database. If it cannot be created, throw an exception to
|
||||||
|
* signal the failure
|
||||||
|
*
|
||||||
|
* @return this (self reference, allowing this to be chained in an
|
||||||
|
* initialization call)
|
||||||
|
* @throws SQLException if the database could be neither opened or created
|
||||||
|
*/
|
||||||
|
public AlertController open() throws SQLException {
|
||||||
|
alertDatabase = new AlertDatabaseHelper(context,
|
||||||
|
ALERT_TABLE_NAME, ALERT_TABLE_NAME).getWritableDatabase();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Closes database resource */
|
||||||
|
public void close() {
|
||||||
|
alertDatabase.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +0,0 @@
|
|||||||
package com.timsu.astrid.data.task;
|
|
||||||
|
|
||||||
public class VisibilityProperty {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* ASTRID: Android's Simple Task Recording Dashboard
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Tim Su
|
||||||
|
*
|
||||||
|
* 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.widget;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.CompoundButton;
|
||||||
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
||||||
|
|
||||||
|
/** Date Control Set with an "enabled" checkbox" to toggle date / null */
|
||||||
|
public class DateWithNullControlSet extends DateControlSet {
|
||||||
|
|
||||||
|
private CheckBox activatedCheckBox;
|
||||||
|
|
||||||
|
public DateWithNullControlSet(Activity activity, int checkBoxId, int dateButtonId, int timeButtonId) {
|
||||||
|
super(activity);
|
||||||
|
activatedCheckBox = (CheckBox)activity.findViewById(checkBoxId);
|
||||||
|
dateButton = (Button)activity.findViewById(dateButtonId);
|
||||||
|
timeButton = (Button)activity.findViewById(timeButtonId);
|
||||||
|
|
||||||
|
activatedCheckBox.setOnCheckedChangeListener(
|
||||||
|
new OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(CompoundButton buttonView,
|
||||||
|
boolean isChecked) {
|
||||||
|
dateButton.setEnabled(isChecked);
|
||||||
|
timeButton.setEnabled(isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dateButton.setOnClickListener(this);
|
||||||
|
timeButton.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getDate() {
|
||||||
|
if(!activatedCheckBox.isChecked())
|
||||||
|
return null;
|
||||||
|
return super.getDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize the components for the given date field */
|
||||||
|
@Override
|
||||||
|
public void setDate(Date newDate) {
|
||||||
|
activatedCheckBox.setChecked(newDate != null);
|
||||||
|
dateButton.setEnabled(newDate != null);
|
||||||
|
timeButton.setEnabled(newDate != null);
|
||||||
|
|
||||||
|
super.setDate(newDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue