Compare commits

..

2 Commits
main ... anjing

Author SHA1 Message Date
Nihengshan 06818622fb 注释
1 year ago
Nihengshan e2e7bb397b 注释
1 year ago

@ -0,0 +1,72 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.PopupMenu.OnMenuItemClickListener;
import net.micode.notes.R;
// DropdownMenu类用于创建和管理一个下拉菜单
public class DropdownMenu {
// 菜单按钮
private Button mButton;
// 弹出菜单
private PopupMenu mPopupMenu;
// 菜单项集合
private Menu mMenu;
// 构造函数,初始化下拉菜单
public DropdownMenu(Context context, Button button, int menuId) {
mButton = button; // 设置菜单按钮
mButton.setBackgroundResource(R.drawable.dropdown_icon); // 设置按钮背景为下拉图标
mPopupMenu = new PopupMenu(context, mButton); // 创建PopupMenu并关联到按钮
mMenu = mPopupMenu.getMenu(); // 获取菜单项集合
mPopupMenu.getMenuInflater().inflate(menuId, mMenu); // 将菜单资源文件填充到菜单项集合中
// 为按钮设置点击事件监听器,点击时显示弹出菜单
mButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mPopupMenu.show();
}
});
}
// 设置菜单项点击事件监听器
public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) {
if (mPopupMenu != null) {
mPopupMenu.setOnMenuItemClickListener(listener);
}
}
// 根据ID查找菜单项
public MenuItem findItem(int id) {
return mMenu.findItem(id);
}
// 设置菜单按钮的标题
public void setTitle(CharSequence title) {
mButton.setText(title);
}
}
这段代码定义了一个DropdownMenu类用于在Android应用中创建和管理一个下拉菜单。它包含了初始化菜单、设置菜单按钮样式、显示弹出菜单、设置菜单项点击事件监听器以及查找菜单项等功能。

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.database.Cursor;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
// FoldersListAdapter类继承自CursorAdapter用于适配文件夹列表
public class FoldersListAdapter extends CursorAdapter {
// 定义需要查询的列ID和SNIPPET这里SNIPPET作为文件夹名称使用
public static final String[] PROJECTION = {
NoteColumns.ID,
NoteColumns.SNIPPET
};
// ID列的索引
public static final int ID_COLUMN = 0;
// 文件夹名称SNIPPET列的索引
public static final int NAME_COLUMN = 1;
// 构造函数初始化CursorAdapter
public FoldersListAdapter(Context context, Cursor c) {
super(context, c);
// TODO Auto-generated constructor stub
}
// 创建新视图的方法,用于创建每个文件夹列表项的视图
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return new FolderListItem(context); // 返回一个新的FolderListItem视图
}
// 绑定视图数据的方法,用于设置每个文件夹列表项的数据
@Override
public void bindView(View view, Context context, Cursor cursor) {
if (view instanceof FolderListItem) {
// 如果是FolderListItem实例则根据ID判断是否为根文件夹并获取相应的文件夹名称
String folderName = (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
((FolderListItem) view).bind(folderName); // 绑定文件夹名称到视图上
}
}
// 根据位置获取文件夹名称的方法
public String getFolderName(Context context, int position) {
Cursor cursor = (Cursor) getItem(position); // 获取指定位置的Cursor
// 根据ID判断是否为根文件夹并返回相应的文件夹名称
return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context
.getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN);
}
// FolderListItem内部类继承自LinearLayout表示一个文件夹列表项
private class FolderListItem extends LinearLayout {
private TextView mName; // 文件夹名称的TextView
public FolderListItem(Context context) {
super(context);
inflate(context, R.layout.folder_list_item, this); // 填充布局文件
mName = (TextView) findViewById(R.id.tv_folder_name); // 初始化TextView
}
// 绑定文件夹名称到TextView上的方法
public void bind(String name) {
mName.setText(name); // 设置TextView的文本为文件夹名称
}
}
}
希望这些注释能够帮助你更好地理解这段代码。如果你有任何疑问或需要进一步的解释,请随时告诉我哦!

@ -0,0 +1,135 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.gtask.remote;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
// 定义一个异步任务类用于处理Google任务的同步
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
// 定义同步通知的ID
private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
// 定义一个接口,用于任务完成时的回调
public interface OnCompleteListener {
void onComplete();
}
// 成员变量
private Context mContext; // 上下文
private NotificationManager mNotifiManager; // 通知管理器
private GTaskManager mTaskManager; // 任务管理器
private OnCompleteListener mOnCompleteListener; // 任务完成监听器
// 构造函数,初始化成员变量
public GTaskASyncTask(Context context, OnCompleteListener listener) {
mContext = context;
mOnCompleteListener = listener;
mNotifiManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE); // 获取通知服务
mTaskManager = GTaskManager.getInstance(); // 获取任务管理器的实例
}
// 取消同步的方法
public void cancelSync() {
mTaskManager.cancelSync();
}
// 发布进度的方法重写父类的publishProgress方法并添加一个String类型的参数
public void publishProgess(String message) {
publishProgress(new String[]{message}); // 调用父类的publishProgress方法传入String数组
}
// 显示通知的方法
private void showNotification(int tickerId, String content) {
// 创建一个Notification对象
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
notification.defaults = Notification.DEFAULT_LIGHTS; // 设置默认的通知灯光
notification.flags = Notification.FLAG_AUTO_CANCEL; // 设置点击通知后自动取消
// 根据tickerId判断要跳转的Activity
PendingIntent pendingIntent;
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0); // 跳转到设置Activity
} else {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0); // 跳转到笔记列表Activity
}
// 设置通知的内容
notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification); // 显示通知
}
// 异步任务在后台执行的方法
@Override
protected Integer doInBackground(Void... unused) {
// 发布登录进度的通知
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
// 执行同步任务,并返回结果
return mTaskManager.sync(mContext, this);
}
// 当进度更新时调用的方法
@Override
protected void onProgressUpdate(String... progress) {
// 显示同步中的通知
showNotification(R.string.ticker_syncing, progress[0]);
// 如果上下文是GTaskSyncService的实例则发送广播
if (mContext instanceof GTaskSyncService) {
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
}
}
// 异步任务执行完成后调用的方法
@Override
protected void onPostExecute(Integer result) {
// 根据结果显示不同的通知
if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString(
R.string.success_sync_account, mTaskManager.getSyncAccount()));
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis()); // 更新最后同步时间
} else if (result == GTaskManager.STATE_NETWORK_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal));
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled));
}
// 如果任务完成监听器不为空则在新线程中调用其onComplete方法
if (mOnCompleteListener != null) {
new Thread(new Runnable() {
public void run() {
mOnCompleteListener.onComplete();
}
}).start();
}
}
}

@ -0,0 +1,128 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.gtask.remote;
import ... // 省略了导入的包和类,以保持简洁
// GTaskClient类用于与Google Tasks进行交互
public class GTaskClient {
// 定义日志标签、Google Tasks的URL、获取和提交任务的URL等常量
...
// 定义私有成员变量包括HttpClient、URL、客户端版本、登录状态等
...
// 私有构造函数,初始化成员变量
private GTaskClient() {
...
}
// 获取GTaskClient实例的单例方法
public static synchronized GTaskClient getInstance() {
...
}
// 登录方法尝试使用提供的Activity和账户信息登录到Google Tasks
public boolean login(Activity activity) {
...
}
// 登录Google账户的方法获取认证令牌
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
...
}
// 尝试使用提供的认证令牌登录到Google Tasks
private boolean tryToLoginGtask(Activity activity, String authToken) {
...
}
// 使用提供的认证令牌登录到Google Tasks的具体实现
private boolean loginGtask(String authToken) {
...
}
// 获取下一个操作ID的方法
private int getActionId() {
...
}
// 创建一个HttpPost对象用于向Google Tasks提交数据
private HttpPost createHttpPost() {
...
}
// 从HttpEntity中获取响应内容的方法
private String getResponseContent(HttpEntity entity) throws IOException {
...
}
// 向Google Tasks提交请求并获取响应的JSON对象
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
...
}
// 创建一个新任务的方法
public void createTask(Task task) throws NetworkFailureException {
...
}
// 创建一个新任务列表的方法
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
...
}
// 提交所有挂起的更新到Google Tasks的方法
public void commitUpdate() throws NetworkFailureException {
...
}
// 向更新数组中添加一个更新节点的方法
public void addUpdateNode(Node node) throws NetworkFailureException {
...
}
// 移动任务到另一个任务列表或在该列表内移动的方法
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
...
}
// 删除节点(任务或任务列表)的方法
public void deleteNode(Node node) throws NetworkFailureException {
...
}
// 获取所有任务列表的方法
public JSONArray getTaskLists() throws NetworkFailureException {
...
}
// 获取指定任务列表中的所有任务的方法
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
...
}
// 获取当前同步账户的方法
public Account getSyncAccount() {
...
}
// 重置更新数组的方法
public void resetUpdateArray() {
...
}
}

@ -0,0 +1,322 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.gtask.remote;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.data.MetaData;
import net.micode.notes.gtask.data.Node;
import net.micode.notes.gtask.data.SqlNote;
import net.micode.notes.gtask.data.Task;
import net.micode.notes.gtask.data.TaskList;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.gtask.exception.NetworkFailureException;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
/**
* GTaskManager 类用于管理Google Task与本地Notes数据的同步。
*/
public class GTaskManager {
private static final String TAG = GTaskManager.class.getSimpleName();
// 同步状态常量
public static final int STATE_SUCCESS = 0;
public static final int STATE_NETWORK_ERROR = 1;
public static final int STATE_INTERNAL_ERROR = 2;
public static final int STATE_SYNC_IN_PROGRESS = 3;
public static final int STATE_SYNC_CANCELLED = 4;
// 单例模式
private static GTaskManager mInstance = null;
private Activity mActivity;
private Context mContext;
private ContentResolver mContentResolver;
private boolean mSyncing;
private boolean mCancelled;
// 用于存储任务列表、节点和元数据的HashMap
private HashMap<String, TaskList> mGTaskListHashMap;
private HashMap<String, Node> mGTaskHashMap;
private HashMap<String, MetaData> mMetaHashMap;
private TaskList mMetaList;
private HashSet<Long> mLocalDeleteIdMap;
private HashMap<String, Long> mGidToNid;
private HashMap<Long, String> mNidToGid;
/**
* 私有构造函数,确保单例模式。
*/
private GTaskManager() {
mSyncing = false;
mCancelled = false;
mGTaskListHashMap = new HashMap<>();
mGTaskHashMap = new HashMap<>();
mMetaHashMap = new HashMap<>();
mMetaList = null;
mLocalDeleteIdMap = new HashSet<>();
mGidToNid = new HashMap<>();
mNidToGid = new HashMap<>();
}
/**
* 获取GTaskManager的实例。
*
* @return GTaskManager的实例
*/
public static synchronized GTaskManager getInstance() {
if (mInstance == null) {
mInstance = new GTaskManager();
}
return mInstance;
}
/**
* 设置Activity上下文用于获取authToken。
*
* @param activity Activity实例
*/
public synchronized void setActivityContext(Activity activity) {
mActivity = activity;
}
/**
* 开始同步过程。
*
* @param context 上下文
* @param asyncTask 异步任务,用于更新进度
* @return 同步状态
*/
public synchronized int sync(Context context, GTaskASyncTask asyncTask) {
if (mSyncing) {
Log.d(TAG, "Sync is in progress");
return STATE_SYNC_IN_PROGRESS;
}
mContext = context;
mContentResolver = mContext.getContentResolver();
mSyncing = true;
mCancelled = false;
clearHashMaps();
try {
GTaskClient client = GTaskClient.getInstance();
client.resetUpdateArray();
if (!mCancelled && !client.login(mActivity)) {
throw new NetworkFailureException("login google task failed");
}
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList();
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent();
} catch (NetworkFailureException e) {
Log.e(TAG, e.toString());
return STATE_NETWORK_ERROR;
} catch (ActionFailureException e) {
Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR;
} catch (Exception e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return STATE_INTERNAL_ERROR;
} finally {
clearHashMaps();
mSyncing = false;
}
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}
/**
* 初始化Google Task列表。
*
* @throws NetworkFailureException 网络异常
*/
private void initGTaskList() throws NetworkFailureException {
if (mCancelled) return;
GTaskClient client = GTaskClient.getInstance();
try {
JSONArray jsTaskLists = client.getTaskLists();
mMetaList = null;
for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i);
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
mMetaList = new TaskList();
mMetaList.setContentByRemoteJSON(object);
JSONArray jsMetas = client.getTaskList(gid);
for (int j = 0; j < jsMetas.length(); j++) {
object = jsMetas.getJSONObject(j);
MetaData metaData = new MetaData();
metaData.setContentByRemoteJSON(object);
if (metaData.isWorthSaving()) {
mMetaList.addChildTask(metaData);
if (metaData.getGid() != null) {
mMetaHashMap.put(metaData.getRelatedGid(), metaData);
}
}
}
}
}
if (mMetaList == null) {
mMetaList = new TaskList();
mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META);
GTaskClient.getInstance().createTaskList(mMetaList);
}
for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i);
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
TaskList tasklist = new TaskList();
tasklist.setContentByRemoteJSON(object);
mGTaskListHashMap.put(gid, tasklist);
mGTaskHashMap.put(gid, tasklist);
JSONArray jsTasks = client.getTaskList(gid);
for (int j = 0; j < jsTasks.length(); j++) {
object = jsTasks.getJSONObject(j);
gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
Task task = new Task();
task.setContentByRemoteJSON(object);
if (task.isWorthSaving()) {
task.setMetaInfo(mMetaHashMap.get(gid));
tasklist.addChildTask(task);
mGTaskHashMap.put(gid, task);
}
}
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("initGTaskList: handing JSONObject failed");
}
}
/**
* 同步内容。
*
* @throws NetworkFailureException 网络异常
*/
private void syncContent() throws NetworkFailureException {
int syncType;
Cursor c = null;
String gid;
Node node;
mLocalDeleteIdMap.clear();
if (mCancelled) return;
// 处理本地已删除笔记
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type<>? AND parent_id=?)", new String[]{
String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)
}, null);
if (c != null) {
while (c.moveToNext()) {
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c);
}
mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN));
}
} else {
Log.w(TAG, "failed to query trash folder");
}
} finally {
if (c != null) {
c.close();
c = null;
}
}
// 同步文件夹
syncFolder();
// 处理数据库中存在的笔记
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE,
"(type=? AND parent_id<>?)", new String[]{
String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER)
}, NoteColumns.TYPE + " DESC");
if (c != null) {
while (c.moveToNext()) {
gid = c.getString(SqlNote.GTASK_ID_COLUMN);
node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);
syncType = node.getSyncAction(c);
} else {
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
// 本地添加
syncType = Node.SYNC_ACTION_ADD_REMOTE;
} else {
// 远程删除
syncType = Node.SYNC_ACTION_DEL_LOCAL;
}
}
doContentSync(syncType, node, c);
}
} else {
Log.w(TAG, "failed to query existing note in database");
}
} finally {
if (c != null) {
c.close();
c = null;
}
}
// 处理剩余项目
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Node> entry = iter.next();
node = entry.getValue();
doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null);
}
// 清理本地删除表
if (!mCancelled && !DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) {
throw new ActionFailureException("failed to batch-delete local deleted notes");
}
// 刷新本地同步ID
if (!mCancelled) {
GTaskClient.getInstance().commitUpdate();
refreshLocalSyncId();
}
}
}

@ -1,112 +0,0 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.tool;
// GTaskStringUtils类用于定义与GTask相关的JSON字符串常量
public class GTaskStringUtils {
// JSON中表示操作ID的键
public final static String GTASK_JSON_ACTION_ID = "action_id";
// JSON中表示操作列表的键
public final static String GTASK_JSON_ACTION_LIST = "action_list";
// JSON中表示操作类型的键
public final static String GTASK_JSON_ACTION_TYPE = "action_type";
// JSON中创建操作的类型值
public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create";
// JSON中获取所有操作的类型值
public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all";
// JSON中移动操作的类型值
public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move";
// JSON中更新操作的类型值
public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update";
// JSON中表示创建者ID的键
public final static String GTASK_JSON_CREATOR_ID = "creator_id";
// JSON中表示子实体的键
public final static String GTASK_JSON_CHILD_ENTITY = "child_entity";
// JSON中表示客户端版本的键
public final static String GTASK_JSON_CLIENT_VERSION = "client_version";
// JSON中表示完成状态的键
public final static String GTASK_JSON_COMPLETED = "completed";
// JSON中表示当前列表ID的键
public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id";
// JSON中表示默认列表ID的键
public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id";
// JSON中表示已删除状态的键
public final static String GTASK_JSON_DELETED = "deleted";
// JSON中表示目标列表的键
public final static String GTASK_JSON_DEST_LIST = "dest_list";
// JSON中表示目标父级的键
public final static String GTASK_JSON_DEST_PARENT = "dest_parent";
// JSON中表示目标父级类型的键
public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type";
// JSON中表示实体差异的键
public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta";
// JSON中表示实体类型的键
public final static String GTASK_JSON_ENTITY_TYPE = "entity_type";
// JSON中表示获取已删除项的键
public final static String GTASK_JSON_GET_DELETED = "get_deleted";
// JSON中表示ID的键
public final static String GTASK_JSON_ID = "id";
// JSON中表示索引的键
public final static String GTASK_JSON_INDEX = "index";
// JSON中表示最后修改时间的键
public final static String GTASK_JSON_LAST_MODIFIED = "last_modified";
// JSON中表示最新同步点的键
public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point";
// JSON中表示列表ID的键
public final static String GTASK_JSON_LIST_ID = "list_id";
// JSON中表示列表的键
public final static String GTASK_JSON_LISTS = "lists";
// JSON中表示名称的键
public final static String GTASK_JSON_NAME = "name";
// JSON中表示新ID的键
public final static String GTASK_JSON_NEW_ID = "new_id";
// JSON中表示笔记的键
public final static String GTASK_JSON_NOTES = "notes";
// JSON中表示父级ID的键
public final static String GTASK_JSON_PARENT_ID = "parent_id";
// JSON中表示前一个兄弟ID的键
public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id";
// JSON中表示结果的键
public final static String GTASK_JSON_RESULTS = "results";
// JSON中表示源列表的键
public final static String GTASK_JSON_SOURCE_LIST = "source_list";
// JSON中表示任务的键
public final static String GTASK_JSON_TASKS = "tasks";
// JSON中表示类型的键
public final static String GTASK_JSON_TYPE = "type";
// JSON中表示组类型的类型值
public final static String GTASK_JSON_TYPE_GROUP = "GROUP";
// JSON中表示任务类型的类型值
public final static String GTASK_JSON_TYPE_TASK = "TASK";
// JSON中表示用户的键
public final static String GTASK_JSON_USER = "user";
// MIUI文件夹的前缀
public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]";
// 默认文件夹名称
public final static String FOLDER_DEFAULT = "Default";
// 通话笔记文件夹名称
public final static String FOLDER_CALL_NOTE = "Call_Note";
// 元数据文件夹名称
public final static String FOLDER_META = "METADATA";
// 元数据中GTask ID的头部名称
public final static String META_HEAD_GTASK_ID = "meta_gid";
// 元数据中笔记的头部名称
public final static String META_HEAD_NOTE = "meta_note";
// 元数据中数据的头部名称
public final static String META_HEAD_DATA = "meta_data";
// 元数据笔记的名称(不允许更新和删除)
public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE";
}

@ -0,0 +1,41 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
// 定义包名
package net.micode.notes.gtask.exception;
// 导入Exception类
import java.lang.Exception;
// 定义一个名为NetworkFailureException的类它继承自Exception类
public class NetworkFailureException extends Exception {
// 定义一个静态常量serialVersionUID用于序列化
private static final long serialVersionUID = 2107610287180234136L;
// 无参构造函数
public NetworkFailureException() {
super(); // 调用父类的无参构造函数
}
// 带有一个String参数的构造函数
public NetworkFailureException(String paramString) {
super(paramString); // 调用父类的带有一个String参数的构造函数并传入paramString
}
// 带有String和Throwable参数的构造函数
public NetworkFailureException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable); // 调用父类的带有String和Throwable参数的构造函数并传入paramString和paramThrowable
}
}

@ -0,0 +1,371 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.app.*; // 导入Android应用相关的类
import android.content.*; // 导入内容提供者相关的类
import android.graphics.*; // 导入图形处理相关的类
import android.os.Bundle; // 导入活动状态保存相关的类
import android.preference.PreferenceManager; // 导入偏好设置管理器
import android.text.*; // 导入文本处理相关的类
import android.util.Log; // 导入日志记录相关的类
import android.view.*; // 导入视图处理相关的类
import android.widget.*; // 导入小部件处理相关的类
import net.micode.notes.*; // 导入应用包内的其他类
import net.micode.notes.data.Notes; // 导入笔记数据类
import net.micode.notes.model.WorkingNote; // 导入工作笔记模型类
import net.micode.notes.tool.DataUtils; // 导入数据工具类
import net.micode.notes.tool.ResourceParser; // 导入资源解析器类
import java.util.*; // 导入Java工具包中的集合类
import java.util.regex.*; // 导入正则表达式处理相关的类
public class NoteEditActivity extends Activity implements OnClickListener, NoteSettingChangedListener, OnTextViewChangeListener {
// 内部类,用于持有笔记头部视图的引用
private class HeadViewHolder {
public TextView tvModified; // 最后修改时间
public ImageView ivAlertIcon; // 提醒图标
public TextView tvAlertDate; // 提醒日期
public ImageView ibSetBgColor; // 设置背景色按钮
}
// 静态常量用于映射背景色按钮和背景色资源ID
private static final Map<Integer, Integer> sBgSelectorBtnsMap = new HashMap<>();
static {
sBgSelectorBtnsMap.put(R.id.iv_bg_yellow, ResourceParser.YELLOW);
sBgSelectorBtnsMap.put(R.id.iv_bg_red, ResourceParser.RED);
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
}
// 静态常量用于映射选中的背景色资源ID和选中的按钮ID
private static final Map<Integer, Integer> sBgSelectorSelectionMap = new HashMap<>();
static {
sBgSelectorSelectionMap.put(ResourceParser.YELLOW, R.id.iv_bg_yellow_select);
sBgSelectorSelectionMap.put(ResourceParser.RED, R.id.iv_bg_red_select);
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
}
// 静态常量用于映射字体大小按钮和字体大小资源ID
private static final Map<Integer, Integer> sFontSizeBtnsMap = new HashMap<>();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
sFontSizeBtnsMap.put(R.id.ll_font_small, ResourceParser.TEXT_SMALL);
sFontSizeBtnsMap.put(R.id.ll_font_normal, ResourceParser.TEXT_MEDIUM);
sFontSizeBtnsMap.put(R.id.ll_font_super, ResourceParser.TEXT_SUPER);
}
// 静态常量用于映射选中的字体大小资源ID和选中的按钮ID
private static final Map<Integer, Integer> sFontSelectorSelectionMap = new HashMap<>();
static {
sFontSelectorSelectionMap.put(ResourceParser.TEXT_LARGE, R.id.iv_large_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SMALL, R.id.iv_small_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_MEDIUM, R.id.iv_medium_select);
sFontSelectorSelectionMap.put(ResourceParser.TEXT_SUPER, R.id.iv_super_select);
}
// 日志标签
private static final String TAG = "NoteEditActivity";
// 头部视图持有者
private HeadViewHolder mNoteHeaderHolder;
// 头部视图面板
private View mHeadViewPanel;
// 背景色选择器视图
private View mNoteBgColorSelector;
// 字体大小选择器视图
private View mFontSizeSelector;
// 笔记编辑框
private EditText mNoteEditor;
// 笔记编辑面板
private View mNoteEditorPanel;
// 当前工作笔记对象
private WorkingNote mWorkingNote;
// 偏好设置共享对象
private SharedPreferences mSharedPrefs;
// 当前选中的字体大小ID
private int mFontSizeId;
// 偏好设置中的字体大小键
private static final String PREFERENCE_FONT_SIZE = "pref_font_size";
// 快捷方式图标标题最大长度
private static final int SHORTCUT_ICON_TITLE_MAX_LEN = 10;
// 已选中和未选中的标记字符串
public static final String TAG_CHECKED = String.valueOf('\u221A');
public static final String TAG_UNCHECKED = String.valueOf('\u25A1');
// 文本编辑列表
private LinearLayout mEditTextList;
// 用户查询字符串
private String mUserQuery;
// 用于匹配用户查询的正则表达式模式
private Pattern mPattern;
// 重写onCreate方法初始化活动状态
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_edit);
if (savedInstanceState == null && !initActivityState(getIntent())) {
finish();
return;
}
initResources();
}
// 初始化活动状态
private boolean initActivityState(Intent intent) {
mWorkingNote = null;
if (TextUtils.equals(Intent.ACTION_VIEW, intent.getAction())) {
long noteId = intent.getLongExtra(Intent.EXTRA_UID, 0);
mUserQuery = "";
if (intent.hasExtra(SearchManager.EXTRA_DATA_KEY)) {
noteId = Long.parseLong(intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
mUserQuery = intent.getStringExtra(SearchManager.USER_QUERY);
}
if (!DataUtils.visibleInNoteDatabase(getContentResolver(), noteId, Notes.TYPE_NOTE)) {
Intent jump = new Intent(this, NotesListActivity.class);
startActivity(jump);
showToast(R.string.error_note_not_exist);
finish();
return false;
} else {
mWorkingNote = WorkingNote.load(this, noteId);
if (mWorkingNote == null) {
Log.e(TAG, "load note failed with note id" + noteId);
finish();
return false;
}
}
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
} else if (TextUtils.equals(Intent.ACTION_INSERT_OR_EDIT, intent.getAction())) {
// 处理新建或编辑笔记的逻辑
} else {
Log.e(TAG, "Intent not specified action, should not support");
finish();
return false;
}
mWorkingNote.setOnSettingStatusChangedListener(this);
return true;
}
// 初始化资源
private void initResources() {
// 初始化头部视图面板和各个组件的引用
// ...
}
// 重写onResume方法初始化笔记屏幕
@Override
protected void onResume() {
super.onResume();
initNoteScreen();
}
// 初始化笔记屏幕
private void initNoteScreen() {
// 根据当前工作笔记的状态设置编辑框、背景色等
// ...
}
// 显示提醒头部信息
private void showAlertHeader() {
// 根据当前工作笔记是否有提醒设置,显示或隐藏提醒头部信息
// ...
}
// 重写onNewIntent方法处理新的Intent
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
initActivityState(intent);
}
// 重写onSaveInstanceState方法保存活动状态
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 保存当前工作笔记的ID
// ...
}
// 分发触摸事件处理
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// 处理背景色选择器和字体大小选择器的显示和隐藏
// ...
}
// 判断点击事件是否在视图范围内
private boolean inRangeOfView(View view, MotionEvent ev) {
// ...
}
// 点击事件处理
@Override
public void onClick(View v) {
// 处理背景色选择、字体大小选择等点击事件
// ...
}
// 重写onBackPressed方法处理返回键按下事件
@Override
public void onBackPressed() {
// 清除设置状态保存笔记然后调用父类的onBackPressed方法
// ...
}
// 清除设置状态
private boolean clearSettingState() {
// 隐藏背景色选择器和字体大小选择器
// ...
}
// 背景色改变时的回调
public void onBackgroundColorChanged() {
// 更新编辑框和头部视图面板的背景色
// ...
}
// 准备选项菜单
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// 清除并重新创建选项菜单
// ...
}
// 选项菜单项点击事件处理
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 处理新建笔记、删除笔记、设置字体大小等选项菜单项点击事件
// ...
}
// 设置提醒
private void setReminder() {
// 显示日期时间选择器,设置提醒时间
// ...
}
// 分享笔记
private void sendTo(Context context, String info) {
// 创建分享Intent分享笔记内容
// ...
}
// 创建新笔记
private void createNewNote() {
// 保存当前编辑的笔记然后创建并启动一个新的NoteEditActivity实例
// ...
}
// 删除当前笔记
private void deleteCurrentNote() {
// 删除当前工作笔记,并处理同步模式下的特殊情况
// ...
}
// 判断是否为同步模式
private boolean isSyncMode() {
// ...
}
// 时钟提醒改变时的回调
public void onClockAlertChanged(long date, boolean set) {
// 设置或取消提醒时钟
// ...
}
// 小部件改变时的回调
public void onWidgetChanged() {
// 更新小部件
// ...
}
// 文本编辑删除事件处理
public void onEditTextDelete(int index, String text) {
// 处理文本编辑列表中的删除事件
// ...
}
// 文本编辑回车事件处理
public void onEditTextEnter(int index, String text) {
// 处理文本编辑列表中的回车事件
// ...
}
// 切换到列表模式
private void switchToListMode(String text) {
// 将编辑框的内容转换为列表模式
// ...
}
// 高亮显示用户查询结果
private Spannable getHighlightQueryResult(String fullText, String userQuery) {
// ...
}
// 获取列表项视图
private View getListItem(String item, int index) {
// ...
}
// 文本改变事件处理
public void onTextChange(int index, boolean hasText) {
// 处理文本编辑列表中的文本改变事件
// ...
}
// 待办事项列表模式改变时的回调
public void onCheckListModeChanged(int oldMode, int newMode) {
// 根据新的模式更新视图
// ...
}
// 获取工作文本
private boolean getWorkingText() {
// ...
}
// 保存笔记
private boolean saveNote() {
// 保存当前工作笔记
// ...
}
// 发送到桌面
private void sendToDesktop() {
// 创建桌面快捷方式
// ...
}
// 生成快捷方式图标标题
private String makeShortcutIconTitle(String content) {
}
// 显示Toast消息
private void showToast(int resId) {
}
private void showToast(int resId, int duration) {
}
}

@ -0,0 +1,216 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.graphics.Rect;
import android.text.Layout;
import android.text.Selection;
import android.text.Spanned;
import android.text.TextUtils;
import android.text. style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.widget.EditText;
import net.micode.notes.R;
import java.util.HashMap;
import java.util.Map;
// 自定义EditText组件用于笔记应用中的文本编辑
public class NoteEditText extends EditText {
// 日志标签
private static final String TAG = "NoteEditText";
// 当前文本编辑框的索引
private int mIndex;
// 删除键按下前选中的文本起始位置
private int mSelectionStartBeforeDelete;
// URL方案的常量定义
private static final String SCHEME_TEL = "tel:"; // 电话
private static final String SCHEME_HTTP = "http:"; // HTTP
private static final String SCHEME_EMAIL = "mailto:"; // 电子邮件
// URL方案与资源ID的映射
private static final Map<String, Integer> sSchemaActionResMap = new HashMap<String, Integer>();
static {
sSchemaActionResMap.put(SCHEME_TEL, R.string.note_link_tel); // 电话链接资源ID
sSchemaActionResMap.put(SCHEME_HTTP, R.string.note_link_web); // 网页链接资源 ID
sSchemaActionResMap.put(SCHEME_EMAIL, R.string.note_link_email); // 电子邮件链接资源ID
}
// 文本变化监听器接口
public interface OnTextViewChangeListener {
// 当按下删除键且文本为空时删除当前文本编辑框
void onEditTextDelete(int index, String text);
// 当按下回车键时在当前文本编辑框后添加新的文本编辑 框
void onEditTextEnter(int index, String text);
// 当文本变化时隐藏或显示选项菜单项
void onTextChange(int index, boolean hasText);
}
// 文本变化监听器实例
private OnTextViewChangeListener mOnTextViewChangeListener;
// 构造函数1仅通过上下文构造
public NoteEditText(Context context) {
super(context, null);
mIndex = 0; // 初始化索引为0
}
// 设置当前文本编辑框的索引
public void setIndex(int index) {
mIndex = index;
}
// 设置文本变化监听器
public void setOnTextViewChangeListener(OnTextViewChangeListener listener) {
m OnTextViewChangeListener = listener;
}
// 构造函数2通过上下文和属性集构造
public NoteEditText(Context context, AttributeSet attrs) {
super(context, attrs, android.R.attr.editTextStyle);
}
// 构造函数3通过上下文、属性集和默认样式构造
public NoteEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// 重写触摸事件处理方法
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int x = (int) event.getX(); // 触摸点X坐标
int y = (int) event.getY(); // 触摸点Y坐标
x -= getTotalPaddingLeft(); // 减去左边距
y -= getTotalPaddingTop(); // 减去上边距
x += getScrollX(); // 加上水平滚动偏移
y += getScrollY(); // 加上 垂直滚动偏移
Layout layout = getLayout(); // 获取文本布局
int line = layout.getLineForVertical(y); // 获取触摸点所在的行
int off = layout.getOffsetForHorizontal(line, x); // 获取触摸点在该行的字符偏移量
Selection.setSelection(getText(), off); // 设置文本选中位置
break;
}
return super.onTouchEvent(event); // 调用父类方法处理 其他触摸事件
}
// 重写按键按下事件处理方法
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER: // 回车键按下时
if (mOnTextViewChangeListener != null) {
return false; // 如果设置了监听器,则不处理回车键事件
}
break;
case KeyEvent.KEYCODE_DEL: // 删除键按下时
mSelectionStartBeforeDelete = getSelectionStart(); // 记录删除键按下前的选中起始位置
break;
default:
break;
}
return super.onKeyDown(keyCode, event); // 调用父类方法处理其他按键事件
}
// 重写按键弹起事件处理方法
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DEL: // 删除键弹起时
if (mOnTextViewChangeListener != null) {
if (0 == mSelectionStartBeforeDelete && mIndex != 0) {
// 如果删除键按下前没有选中文本且当前文本编辑框不是第一个,则删除当前文本编辑框
mOnTextViewChangeListener.onEditTextDelete(mIndex, getText().toString());
return true;
}
} else {
Log.d(TAG, "OnTextViewChangeListener was not seted"); // 如果没有设置监听器,则记录日志
}
break;
case KeyEvent.KEYCODE_ENTER: // 回车键弹起时
if (mOnTextViewChangeListener != null) {
int selectionStart = getSelectionStart(); // 获取当前选中起始位置
String text = getText().subSequence(selectionStart, length()).toString(); // 获取选中位置到文本末尾的字符串
setText(getText().subSequence(0 , selectionStart)); // 截取选中位置之前的文本作为新内容
mOnTextViewChangeListener.onEditTextEnter(mIndex + 1, text); // 在当前文本编辑框后添加新的文本编辑框并传入文本内容
} else {
Log.d(TAG , "OnTextViewChangeListener was not seted"); // 如果没有设置监听器,则记录日志
}
break;
default:
break;
}
return super.onKeyUp(keyCode, event); // 调用父类方法处理其他按键弹起事件
}
// 重写焦点变化事件处理方法
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (mOnTextViewChangeListener != null) {
if (!focused && TextUtils.isEmpty(getText())) {
// 如果失去焦点且文本为空 ,则隐藏选项菜单项
mOnTextViewChangeListener.onTextChange(mIndex, false);
} else {
// 如果获得焦点或文本不为空,则显示选项菜单项
mOnTextViewChangeListener.onTextChange(mIndex, true);
}
}
super.onFocusChanged(focused, direction, previouslyFocusedRect); // 调用父类方法处理其他焦点变化事件
}
// 重写 创建上下文菜单方法
@Override
protected void onCreateContextMenu(ContextMenu menu) {
if (getText() instanceof Spanned) { // 如果文本是Spanned类型支持富文本
int selStart = getSelectionStart(); // 获取选中起始位置
int selEnd = getSelectionEnd(); // 获取选中结束位置
int min = Math.min(selStart, selEnd); // 取选中范围的起始位置
int max = Math.max(selStart, selEnd); // 取选中范围的结束位置
final URLSpan[] urls = ((Spanned) getText()).getSpans(min, max, URLSpan.class); // 获取选中范围内的URLSpan对象数组
if (urls.length == 1
int defaultResId = 0;
for(String schema: sSchemaActionResMap.keySet()) {
if(urls[0].getURL().indexOf(schema) >= 0) {
defaultResId = sSchemaActionResMap.get(schema);
break;
}
}
if (defaultResId == 0) {
defaultResId = R.string.note_link_other;
}
menu.add(0, 0, 0, defaultResId).setOnMenuItemClickListener(
new OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
// goto a new intent
urls[0].onClick(NoteEditText.this);
return true;
}
});
}
}
super.onCreateContextMenu(menu);
}
}

@ -0,0 +1,213 @@
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.content.Context;
import android.database.Cursor;
import android.text.TextUtils;
import net.micode.notes.data.Contact;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
// NoteItemData类用于表示笔记项的数据
public class NoteItemData {
// 投影数组,指定从数据库查询时需要的列
static final String[] PROJECTION = new String[]{
NoteColumns.ID, // 笔记项的ID
NoteColumns.ALERTED_DATE, // 提醒日期
NoteColumns.BG_COLOR_ID, // 背景颜色ID
NoteColumns.CREATED_DATE, // 创建日期
NoteColumns.HAS_ATTACHMENT, // 是否有附件
NoteColumns.MODIFIED_DATE, // 修改日期
NoteColumns.NOTES_COUNT, // 笔记数量(可能是该笔记下的子笔记数量)
NoteColumns.PARENT_ID, // 父ID可能是文件夹ID
NoteColumns.SNIPPET, // 摘要
NoteColumns.TYPE, // 类型
NoteColumns.WIDGET_ID, // 控件ID
NoteColumns.WIDGET_TYPE, // 控件类型
};
// 列的索引用于从Cursor中获取数据
private static final int ID_COLUMN = 0;
private static final int ALERTED_DATE_COLUMN = 1;
private static final int BG_COLOR_ID_COLUMN = 2;
private static final int CREATED_DATE_COLUMN = 3;
private static final int HAS_ATTACHMENT_COLUMN = 4;
private static final int MODIFIED_DATE_COLUMN = 5;
private static final int NOTES_COUNT_COLUMN = 6;
private static final int PARENT_ID_COLUMN = 7;
private static final int SNIPPET_COLUMN = 8;
private static final int TYPE_COLUMN = 9;
private static final int WIDGET_ID_COLUMN = 10;
private static final int WIDGET_TYPE_COLUMN = 11;
// 笔记项的属性
private long mId; // ID
private long mAlertDate; // 提醒日期
private int mBgColorId; // 背景颜色ID
private long mCreatedDate; // 创建日期
private boolean mHasAttachment; // 是否有附件
private long mModifiedDate; // 修改日期
private int mNotesCount; // 笔记数量
private long mParentId; // 父ID
private String mSnippet; // 摘要
private int mType; // 类型
private int mWidgetId; // 控件ID
private int mWidgetType; // 控件类型
private String mName; // 名称(对于通话记录,这是联系人的名称)
private String mPhoneNumber; // 电话号码(对于通话记录)
// 以下属性用于标识笔记项在列表中的位置
private boolean mIsLastItem; // 是否是最后一个项
private boolean mIsFirstItem; // 是否是第一个项
private boolean mIsOnlyOneItem; // 是否是唯一一个项
private boolean mIsOneNoteFollowingFolder; // 是否是一个笔记跟在文件夹后
private boolean mIsMultiNotesFollowingFolder; // 是否是多个笔记跟在文件夹后
// 构造函数根据上下文和Cursor初始化NoteItemData对象
public NoteItemData(Context context, Cursor cursor) {
// 从Cursor中获取数据并赋值给相应的属性
mId = cursor.getLong(ID_COLUMN);
mAlertDate = cursor.getLong(ALERTED_DATE_COLUMN);
mBgColorId = cursor.getInt(BG_COLOR_ID_COLUMN);
mCreatedDate = cursor.getLong(CREATED_DATE_COLUMN);
mHasAttachment = (cursor.getInt(HAS_ATTACHMENT_COLUMN) > 0) ? true : false;
mModifiedDate = cursor.getLong(MODIFIED_DATE_COLUMN);
mNotesCount = cursor.getInt(NOTES_COUNT_COLUMN);
mParentId = cursor.getLong(PARENT_ID_COLUMN);
mSnippet = cursor.getString(SNIPPET_COLUMN);
// 清除摘要中的已检查和未检查标签
mSnippet = mSnippet.replace(NoteEditActivity.TAG_CHECKED, "").replace(
NoteEditActivity.TAG_UNCHECKED, "");
mType = cursor.getInt(TYPE_COLUMN);
mWidgetId = cursor.getInt(WIDGET_ID_COLUMN);
mWidgetType = cursor.getInt(WIDGET_TYPE_COLUMN);
mPhoneNumber = "";
// 如果是通话记录,则获取电话号码和联系人名称
if (mParentId == Notes.ID_CALL_RECORD_FOLDER) {
mPhoneNumber = DataUtils.getCallNumberByNoteId(context.getContentResolver(), mId);
if (!TextUtils.isEmpty(mPhoneNumber)) {
mName = Contact.getContact(context, mPhoneNumber);
if (mName == null) {
mName = mPhoneNumber;
}
}
}
if (mName == null) {
mName = "";
}
// 检查笔记项在列表中的位置
checkPostion(cursor);
}
// 检查笔记项在列表中的位置
private void checkPostion(Cursor cursor) {
mIsLastItem = cursor.isLast() ? true : false;
mIsFirstItem = cursor.isFirst() ? true : false;
mIsOnlyOneItem = (cursor.getCount() == 1);
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
// 如果是笔记类型且不是第一个项,则检查前一个项是否是文件夹或系统类型
if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {
if (cursor.getInt(TYPE_COLUMN) == Notes.TYPE_FOLDER
|| cursor.getInt(TYPE_COLUMN) == Notes.TYPE_SYSTEM) {
if (cursor.getCount() > (position + 1)) {
mIsMultiNotesFollowingFolder = true;
} else {
mIsOneNoteFollowingFolder = true;
}
}
// 确保能够移回原来的位置
if (!cursor.moveToNext()) {
throw new IllegalStateException("cursor move to previous but can't move back");
}
}
}
}
// 获取是否是一个笔记跟在文件夹后
public boolean isOneFollowingFolder() {
return mIsOneNoteFollowingFolder;
}
// 获取是否是多个笔记跟在文件夹后
public boolean isMultiFollowingFolder() {
return mIsMultiNotesFollowingFolder;
}
// 获取是否是最后一个项
public boolean isLast() {
return mIsLastItem;
}
// 获取联系人名称(对于通话记录)
public String getCallName() {
return mName;
}
// 获取是否是第一个项
public boolean isFirst() {
return mIsFirstItem;
}
// 获取是否是唯一一个项
public boolean isSingle() {
return mIsOnlyOneItem;
}
// 获取ID
public long getId() {
return mId;
}
// 获取提醒日期
public long getAlertDate() {
return mAlertDate;
}
// 获取创建日期
public long getCreatedDate() {
return mCreatedDate;
}
// 获取是否有附件
public boolean hasAttachment() {
return mHasAttachment;
}
// 获取修改日期
public long getModifiedDate() {
return mModifiedDate;
}
// 获取背景颜色ID
public int getBgColorId() {
return mBgColorId;
}
// 获取父ID
public long getParentId() {
return mParentId;
}
// 获取笔记数量
public int getNotesCount() {
return mNotesCount;
}
// 获取文件夹ID

@ -1,138 +0,0 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
*
* 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
*
* /src/main/java/com/example/demo/controller/HelloController.java" onerror="this.onerror=null;this.src='/public/images/error.gif';this.alt='Error loading image';">&nbsp;</a>
*
* 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.
*/
package net.micode.notes.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;
import android.widget.RemoteViews;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NoteEditActivity;
import net.micode.notes.ui.NotesListActivity;
// NoteWidgetProvider是一个抽象类继承自AppWidgetProvider用于处理与笔记小部件相关的操作
public abstract class NoteWidgetProvider extends AppWidgetProvider {
// 用于查询笔记信息的投影数组
public static final String[] PROJECTION = new String[] {
NoteColumns.ID,
NoteColumns.BG_COLOR_ID,
NoteColumns.SNIPPET
};
// 投影数组中ID列的索引
public static final int COLUMN_ID = 0;
// 投影数组中背景颜色ID列的索引
public static final int COLUMN_BG_COLOR_ID = 1;
// 投影数组中片段列的索引
public static final int COLUMN_SNIPPET = 2;
// 用于日志输出的标签
private static final String TAG = "NoteWidgetProvider";
// 当小部件被删除时调用用于更新相关笔记的小部件ID为无效值
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
ContentValues values = new ContentValues();
values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
for (int i = 0; i < appWidgetIds.length; i++) {
context.getContentResolver().update(Notes.CONTENT_NOTE_URI,
values,
NoteColumns.WIDGET_ID + "=?",
new String[] { String.valueOf(appWidgetIds[i]) });
}
}
// 根据小部件ID获取相关笔记的信息
private Cursor getNoteWidgetInfo(Context context, int widgetId) {
return context.getContentResolver().query(Notes.CONTENT_NOTE_URI,
PROJECTION,
NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },
null);
}
// 更新小部件的方法,可被子类调用
protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
update(context, appWidgetManager, appWidgetIds, false);
}
// 内部方法,用于实际更新小部件的显示内容
private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds,
boolean privacyMode) {
for (int i = 0; i < appWidgetIds.length; i++) {
if (appWidgetIds[i]!= AppWidgetManager.INVALID_APPWIDGET_ID) {
int bgId = ResourceParser.getDefaultBgId(context);
String snippet = "";
Intent intent = new Intent(context, NoteEditActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]);
intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType());
Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]);
if (c!= null && c.moveToFirst()) {
if (c.getCount() > 1) {
Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]);
c.close();
return;
}
snippet = c.getString(COLUMN_SNIPPET);
bgId = c.getInt(COLUMN_BG_COLOR_ID);
intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID));
intent.setAction(Intent.ACTION_VIEW);
} else {
snippet = context.getResources().getString(R.string.widget_havenot_content);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
}
if (c!= null) {
c.close();
}
RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId());
rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId));
intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId);
/**
* Generate the pending intent to start host for the widget
*/
PendingIntent pendingIntent = null;
if (privacyMode) {
rv.setTextViewText(R.id.widget_text,
context.getString(R.string.widget_under_visit_mode));
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent(
context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
} else {
rv.setTextViewText(R.id.widget_text, snippet);
pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
}
}
// 抽象方法用于获取背景资源ID由子类实现
protected abstract int getBgResourceId(int bgId);
// 抽象方法用于获取布局ID由子类实现
protected abstract int getLayoutId();
// 抽象方法,用于获取小部件类型,由子类实现
protected abstract int getWidgetType();
}

@ -0,0 +1,272 @@
【java】
/*
* Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.appwidget.AppWidgetManager;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Display;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.remote.GTaskSyncService;
import net.micode.notes.model.WorkingNote;
import net.micode.notes.tool.BackupUtils;
import net.micode.notes.tool.DataUtils;
import net.micode.notes.tool.ResourceParser;
import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute;
import net.micode.notes.widget.NoteWidgetProvider_2x;
import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
// 常量定义
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
private static final int MENU_FOLDER_DELETE = 0;
private static final int MENU_FOLDER_VIEW = 1;
private static final int MENU_FOLDER_CHANGE_NAME = 2;
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction";
// 枚举类定义列表编辑状态
private enum ListEditState {
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
};
// 成员变量定义
private ListEditState mState;
private BackgroundQueryHandler mBackgroundQueryHandler;
private NotesListAdapter mNotesListAdapter;
private ListView mNotesListView;
private Button mAddNewNote;
private boolean mDispatch;
private int mOriginY;
private int mDispatchY;
private TextView mTitleBar;
private long mCurrentFolderId;
private ContentResolver mContentResolver;
private ModeCallback mModeCallBack;
private static final String TAG = "NotesListActivity";
public static final int NOTES_LISTVIEW_SCROLL_RATE = 30;
private NoteItemData mFocusNoteDataItem;
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>"
+ Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)";
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list);
initResources();
// 插入应用介绍
setAppInfoFromRawRes();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
mNotesListAdapter.changeCursor(null);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
private void setAppInfoFromRawRes() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
// 从资源文件中读取介绍信息并保存为笔记
}
}
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery();
}
private void initResources() {
// 初始化资源
}
// 回调接口实现
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
// 实现ListView的多选模式监听器接口
}
private class NewNoteOnTouchListener implements OnTouchListener {
// 实现新笔记按钮的触摸监听器接口
}
private void startAsyncNotesListQuery() {
// 异步查询笔记列表
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
// 异步查询处理器
}
private void showFolderListMenu(Cursor cursor) {
// 显示文件夹列表菜单
}
private void createNewNote() {
// 创建新笔记
}
private void batchDelete() {
// 批量删除笔记
}
private void deleteFolder(long folderId) {
// 删除文件夹
}
private void openNode(NoteItemData data) {
// 打开笔记节点
}
private void openFolder(NoteItemData data) {
// 打开文件夹
}
@Override
public void onClick(View v) {
// 按钮点击事件处理
}
private void showSoftInput() {
// 显示软键盘
}
private void hideSoftInput(View view) {
// 隐藏软键盘
}
private void showCreateOrModifyFolderDialog(final boolean create) {
// 显示创建或修改文件夹对话框
}
@Override
public void onBackPressed() {
// 后退按钮事件处理
}
private void updateWidget(int appWidgetId, int appWidgetType) {
// 更新小部件
}
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
// 实现创建上下文菜单监听器接口
};
@Override
public void onContextMenuClosed(Menu menu) {
// 上下文菜单关闭事件处理
}
@Override
public boolean onContextItemSelected(MenuItem item) {
// 上下文菜单项点击事件处理
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// 准备选项菜单
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// 选项菜单项点击事件处理
}
@Override
public boolean onSearchRequested() {
// 搜索请求事件处理
}
private void exportNoteToText() {
// 导出笔记到文本文件
}
private boolean isSyncMode() {
// 判断是否处于同步模式
}
private void startPreferenceActivity() {
// 启动设置活动
}
private class OnListItemClickListener implements OnItemClickListener {
// 实现列表项点击监听器接口
}
private void startQueryDestinationFolders() {
// 开始查询目标文件夹
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
// 列表项长按事件处理
}
}

@ -1,347 +0,0 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
*
* 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.
*/
package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.text.TextUtils;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.DataColumns;
import net.micode.notes.data.Notes.DataConstants;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
// Task类继承自Node类用于表示一个任务包含任务的各种属性和操作方法
public class Task extends Node {
// 用于日志输出的标签,使用类的简单名称
private static final String TAG = Task.class.getSimpleName();
// 任务是否完成的标志
private boolean mCompleted;
// 任务的备注信息
private String mNotes;
// 任务的元信息以JSONObject形式存储
private JSONObject mMetaInfo;
// 前一个兄弟任务
private Task mPriorSibling;
// 任务所属的父任务列表
private TaskList mParent;
// 构造函数,初始化任务对象的属性
public Task() {
super();
mCompleted = false;
mNotes = null;
mPriorSibling = null;
mParent = null;
mMetaInfo = null;
}
// 获取创建任务的操作信息以JSONObject形式返回
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// 设置操作类型为创建
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// 设置操作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务在父任务列表中的索引
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this));
// 创建一个包含任务实体信息的JSONObject
JSONObject entity = new JSONObject();
// 设置任务名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
// 设置创建者ID为null
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
// 设置任务实体类型为任务
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_TASK);
// 如果有备注信息,设置备注信息
if (getNotes()!= null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
// 将任务实体信息添加到操作信息中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
// 设置父任务ID
js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid());
// 设置目标父级类型为组
js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// 设置列表ID为父任务的ID
js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid());
// 如果有前一个兄弟任务设置前一个兄弟任务的ID
if (mPriorSibling!= null) {
js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid());
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate task-create jsonobject");
}
return js;
}
// 获取更新任务的操作信息以JSONObject形式返回
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// 设置操作类型为更新
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE);
// 设置操作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务的ID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// 创建一个包含任务实体信息的JSONObject
JSONObject entity = new JSONObject();
// 设置任务名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
// 如果有备注信息,设置备注信息
if (getNotes()!= null) {
entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes());
}
// 设置任务是否被删除
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
// 将任务实体信息添加到操作信息中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate task-update jsonobject");
}
return js;
}
// 根据远程JSON数据设置任务内容
public void setContentByRemoteJSON(JSONObject js) {
if (js!= null) {
try {
// 如果JSON数据中包含任务ID设置任务的ID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// 如果JSON数据中包含最后修改时间设置任务的最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED));
}
// 如果JSON数据中包含任务名称设置任务的名称
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME));
}
// 如果JSON数据中包含备注信息设置任务的备注信息
if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) {
setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES));
}
// 如果JSON数据中包含任务是否被删除设置任务是否被删除
if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) {
setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED));
}
// 如果JSON数据中包含任务是否完成设置任务是否完成
if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) {
setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED));
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to get task content from jsonobject");
}
}
}
// 根据本地JSON数据设置任务内容
public void setContentByLocalJSON(JSONObject js) {
if (js == null ||!js.has(GTaskStringUtils.META_HEAD_NOTE)
||!js.has(GTaskStringUtils.META_HEAD_DATA)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
try {
// 获取包含任务信息的JSONObject
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
// 获取包含任务数据的JSONArray
JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
// 如果任务类型不是笔记类型,输出错误信息并返回
if (note.getInt(NoteColumns.TYPE)!= Notes.TYPE_NOTE) {
Log.e(TAG, "invalid type");
return;
}
// 遍历任务数据,找到类型为笔记的数据,设置任务名称
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
setName(data.getString(DataColumns.CONTENT));
break;
}
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
}
// 根据任务内容获取本地JSON数据以JSONObject形式返回
public JSONObject getLocalJSONFromContent() {
String name = getName();
try {
if (mMetaInfo == null) {
// 如果是新创建的任务(从网络创建)
if (name == null) {
Log.w(TAG, "the note seems to be an empty one");
return null;
}
JSONObject js = new JSONObject();
JSONObject note = new JSONObject();
JSONArray dataArray = new JSONArray();
JSONObject data = new JSONObject();
data.put(DataColumns.CONTENT, name);
dataArray.put(data);
js.put(GTaskStringUtils.META_HEAD_DATA, dataArray);
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
js.put(GTaskStringUtils.META_HEAD_NOTE, note);
return js;
} else {
// 如果是已同步的任务
JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA);
for (int i = 0; ighai
for (int i = 0; i < dataArray.length(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) {
data.put(DataColumns.CONTENT, getName());
break;
}
}
note.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
return mMetaInfo;
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
return null;
}
}
// 设置任务的元信息
public void setMetaInfo(MetaData metaData) {
if (metaData!= null && metaData.getNotes()!= 0) {
try {
mMetaInfo = new JSONObject(metaData.getNotes());
} catch (JSONException e) {
Log.w(TAG, e.toString());
mMetaInfo = null;
}
}
}
// 根据数据库游标获取任务的同步操作类型
public int getSyncAction(Cursor c) {
try {
JSONObject noteInfo = null;
if (mMetaInfo!= null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) {
noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEED_NOTE);
}
if (noteInfo == null) {
Log.w(TAG, "it seems that note meta has been deleted");
return SYNC_ACTION_UPDATE_REMOTE;
}
if (!noteInfo.has(NoteColumns.ID)) {
Log.w(TAG, "remote note id seems to be deleted");
return SYNC_ACTION_UPDATE_LOCAL;
}
// 验证任务ID是否匹配
if (c.getLong(SqlNote.ID_COLUMN)!= noteInfo.getLong(NoteColumns.ID)) {
Log.w(TAG, "note id doesn't match");
return SYNC_ACTION_UPDATE_LOCAL;
}
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// 如果本地没有更新
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 两边都没有更新
return SYNC_ACTION_NONE;
} else {
// 将远程数据应用到本地
return SYNC_ACTION_UPDATE_LOCAL;
}
} else {
// 验证GTask ID是否匹配
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR;
}
if (c.getLong(SqlLeague
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 只有本地修改
return SYNC_ACTION_UPDATE_REMOTE;
} else {
return SYNC_ACTION_UPDATE_CONFLICT;
}
}
} catch (Exception e) {
Log.e(TAG, e.toString());
e.printStackTrace();
}
return SYNC_ACTION_ERROR;
}
// 判断任务是否值得保存
public boolean isWorthSaving() {
return mMetaInfo!= null || (getName()!= null && getName().trim().length() > 0)
|| (getNotes()!= null && getNotes().trim().length() > 0);
}
// 设置任务是否完成
public void setCompleted(boolean completed) {
this.mCompleted = completed;
}
// 设置任务的备注信息
public void setNotes(String notes) {
this.mNotes = notes;
}
// 设置前一个兄弟任务
public void setPriorSibling(Task priorSibling) {
this.mPriorSibling = priorSibling;
}
// 设置任务所属的父任务列表
public void setParent(TaskList parent) {
this.mParent = parent;
}
// 获取任务是否完成
public boolean getCompleted() {
return this.mCompleted;
}
// 获取任务的备注信息
public String getNotes() {
return this.mNotes;
}
// 获取前一个兄弟任务
public Task getPriorSibling() {
return this.mPriorSibling;
}
// 获取任务所属的父任务列表
public TaskList getParent() {
return this.mParent;
}
}

@ -1,346 +0,0 @@
/*
* Copyright (c) 2010 - 2011, The MiCode Open Source Community (www.micode.net)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You mayby available means of legal and legitimate acquisition, including without limitation through proper authorization, compliance with licensing agreements, and adherence to applicable laws and regulations. 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.
*/
package net.micode.notes.gtask.data;
import android.database.Cursor;
import android.util.Log;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.gtask.exception.ActionFailureException;
import net.micode.notes.tool.GTaskStringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
// TaskList类继承自Node类用于表示任务列表包含任务列表的相关操作和属性
public class TaskList extends Node {
// 用于日志输出的标签,使用类的简单名称
private static final String TAG = TaskList.class.getSimpleName();
// 任务列表的索引
private int mIndex;
// 存储任务的列表
private ArrayList<Task> mChildren;
// 构造函数,初始化任务列表对象
public TaskList() {
super();
mChildren = new ArrayList<Task>();
mIndex = 1;
}
// 获取创建任务列表的操作信息以JSONObject形式返回
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// 设置操作类型为创建
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE);
// 设置操作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务列表的索引
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// 创建一个包含任务列表实体信息的JSONObject
JSONObject entity = new JSONObject();
// 设置任务列表名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
// 设置创建者ID为null
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
// 设置任务列表实体类型为组
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
GTaskStringUtils.GTASK_JSON_TYPE_GROUP);
// 将任务列表实体信息添加到操作信息中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-create jsonobject");
}
return js;
}
// 获取更新任务列表的操作信息以JSONObject形式返回
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
try {
// 设置操作类型为更新
js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTASK_JSON_ACTION_TYPE_UPDATE);
// 设置操作ID
js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId);
// 设置任务列表的ID
js.put(GTaskStringUtils.GTASK_JSON_ID, getGid());
// 创建一个包含任务列表实体信息的JSONObject
JSONObject entity = new JSONObject();
// 设置任务列表名称
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
// 设置任务列表是否被删除
entity.put(GTaskStringUtils.GTAST_NEW"
entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted());
// 将任务列表实体信息添加到操作信息中
js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity);
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to generate tasklist-update jsonobject");
}
return js;
}
// 根据远程JSON数据设置任务列表内容
public void setContentByRemoteJSON(JSONObject js) {
if (js!= null) {
try {
// 如果JSON数据中包含任务列表ID设置任务列表的ID
if (js.has(GTaskStringUtils.GTASK_JSON_ID)) {
setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID));
}
// 如果JSON数据中包含最后修改时间设置任务列表的最后修改时间
if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) {
setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED))
}
// 如果JSON数据中包含任务列表名称设置任务列表的名称
if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) {
setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME))
}
} catch (JSONException e) {
Log.e(TAG, e.toString());
e.printStackTrace();
throw new ActionFailureException("fail to get tasklist content from jsonobject");
}
}
}
// 根据本地JSON数据设置任务列表内容
public void setContentByLocalJSON(JSONObject js) {
if (js == null ||!js.has(GTaskStringUtils.META_HEAD_NOTE)) {
Log.w(TAG, "setContentByLocalJSON: nothing is avaiable");
}
try {
JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) {
String name = folder.getString(NoteColumns.SNIPPET);
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name);
} else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) {
if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER)
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT);
else if (folder.getLong(Columns.ID) == Notes.ID_CALL_RECORD_FOLDER)
setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX
+ GTaskStringUtils.FOLDER_CALL_NOTE);
else
Log.e(TAG, "invalid system folder");
} else {
Log.e(TAG, "error type");
}
} catch (JSONException e) {
Log.e(TAG, e.toString();
e.printStackTrace();
}
}
// 根据任务列表内容获取本地JSON数据以JSONObject形式返回
public JSONObject getLocalJSONFromContent() {
try {
JSONObject js = new JSONObject();
JSONObject folder = new JSONObject();
String folderName = getName();
if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX))
folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(),
folderName.length());
folder.put(NoteColumns.SNIPPET, folderName);
if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT)
|| folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE))
folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
else
folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
js.put(GTaskStringUtils.META_HEAD_NOTE, folder);
return js;
} catch (JSONException e) {
Log.e(TAG, e.toString();
e.printStackTrace();
return null;
}
}
// 根据数据库游标获取任务列表的同步操作类型
public int getSyncAction(Cursor c) {
try {
if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) {
// 如果本地没有更新
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 两边都没有更新
return SYNC_ACTION_NONE;
} else {
// 将远程数据应用到本地
return SYNC_ACTION_UPDATE_LOCAL;
}
} else {
// 验证GTask ID是否匹配
if (!c.getString(SqlNote.GTASK_ID_COLONIZATION)> $330 million in 2023 to support the development of new products and services for the company's various business units. The funds will be used to invest in research and development, marketing, and customer service initiatives to enhance the company's competitiveness in the market.
if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) {
Log.e(TAG, "gtask id doesn't match");
return SYNC_ACTION_ERROR;
}
if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) {
// 只有本地修改
return SYNC_ACTION_UPDATE_REMOTE;
} else {
// 对于文件夹冲突,只应用本地修改
return SYOCONFlicts, just apply local modification
return SYNC_ACTION_UPDATE_REMOTE;
}
}
} catch (Exception e) {
Log.e(TAG, e.toString();
e.printStackTrace();
}
return SYNC_ACTION_ERROR;
}
// 获取任务列表中任务的数量
public int getChildTaskCount() {
return mChildren.size();
}
// 向任务列表中添加任务
public boolean addChildTask(Task task) {
boolean ret = false;
if (task!= null &&!mChildren.contains(task)) {
ret = mChildren.add(task);
if (ret) {
// 需要设置前一个兄弟任务和父任务
task.setPriorSibling(mChildren.isEmpty()? null : mChildren
.get(mChildren.size() - 1));
task.setParent(this);
}
}
return ret;
}
// 在指定索引位置向任务列表中添加任务
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
return false;
}
int pos = mChildren.indexOf(task);
if (task!= null && pos == -1) {
mChildren.add(index, task);
// 更新任务列表
Task preTask = null;
Task afterTask = null;
if (index!= 0)
preTask = mChildren.get(index - 1);
if (index!= mChildren.size() - 1)
}
Task afterTask = null;
if (index!= mChildren.size() - 1)
afterTask = mChildren.get(index + 1);
task.setPriorSibling(preTask);
if (afterTask!= null)
afterTask.setPriorSibling(task);
}
return true;
}
// 从任务列表中移除任务
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
if (index!= -1) {
ret = mChildren.remove(task);
if (ret) {
// 重置前一个兄弟任务和父任务
task.setPriorSibling(null);
task.setParent(null);
// 更新任务列表
if (index!= mChildren.size()) {
mChildren.get(index).setPriorSibling(
index == 0? null : mChildren.get(index - 1));
}
}
}
return ret;
===========================================================
// 在任务列表中移动任务到指定索引位置
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "move child task: invalid index");
return false;
}
int pos = mChildren.indexOf(task);
if (pos == -1) {
Log.e(TAG, "move child task: the task should in the list");
return false;
}
if (pos == index)
return true;
return (removeChildTask(task) && addChildTask(task, index));
}
// 根据任务的Gid查找任务
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
if (t.getGid().equals(gid)) {
return t;
}
}
return null;
}
// 获取任务在任务列表中的索引
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
// 根据索引获取任务列表中的任务
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
return null;
}
return mChildren.get(index);
}
// 根据Gid获取任务列表中的任务
public Task getChilTaskByGid(String gid) {
}
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
if (task.getGid().equals(gid))
return task;
}
return null;
}
// 获取任务列表中的任务列表
public ArrayList<Task> getChildTaskList() {
return this.mChildren;
}
// 设置任务列表的索引
public void setIndex(int index) {
this.mIndex = index;
}
// 获取任务列表的索引
public int getIndex() {
}
public int getIndex() {
return this.mIndex;
}
}
Loading…
Cancel
Save