diff --git a/BackupUtils.txt b/BackupUtils.txt new file mode 100644 index 0000000..f516e81 --- /dev/null +++ b/BackupUtils.txt @@ -0,0 +1,200 @@ +/* + * 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; + +import android.content.Context; +import android.database.Cursor; +import android.os.Environment; +import android.text.TextUtils; +import android.text.format.DateFormat; +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.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +/** + * BackupUtils 类提供了将应用程序中的笔记数据备份到文本文件的功能。 + */ +public class BackupUtils { + private static final String TAG = "BackupUtils"; + // Singleton 实例 + private static BackupUtils sInstance; + + /** + * 获取 BackupUtils 类的单例对象。 + * + * @param context Android 上下文对象。 + * @return BackupUtils 的单例对象。 + */ + public static synchronized BackupUtils getInstance(Context context) { + if (sInstance == null) { + sInstance = new BackupUtils(context); + } + return sInstance; + } + + /** + * 定义备份或恢复状态的常量。 + */ + // 目前,sd卡没有挂载 + public static final int STATE_SD_CARD_UNMOUONTED = 0; + // 备份文件不存在 + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; + // 数据格式不正确,可能被其他程序修改 + public static final int STATE_DATA_DESTROIED = 2; + // 一些运行时异常导致恢复或备份失败 + public static final int STATE_SYSTEM_ERROR = 3; + // 备份或恢复成功 + public static final int STATE_SUCCESS = 4; + + private TextExport mTextExport; + + /** + * BackupUtils 类的构造函数。 + * + * @param context Android 上下文对象。 + */ + private BackupUtils(Context context) { + mTextExport = new TextExport(context); + } + + /** + * 检查外部存储是否可用。 + * + * @return 如果外部存储可用,返回 true;否则返回 false。 + */ + private static boolean externalStorageAvailable() { + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } + + /** + * 导出笔记数据到文本文件。 + * + * @return 一个表示操作结果的状态码。 + */ + public int exportToText() { + return mTextExport.exportToText(); + } + + /** + * 获取导出的文本文件名。 + * + * @return 导出的文本文件名。 + */ + public String getExportedTextFileName() { + return mTextExport.mFileName; + } + + /** + * 获取导出的文本文件目录。 + * + * @return 导出的文本文件目录。 + */ + public String getExportedTextFileDir() { + return mTextExport.mFileDirectory; + } + + /** + * TextExport 类负责将笔记数据导出到文本文件。 + */ + private static class TextExport { + // 省略了部分代码注释,因为它们已经在代码中以注释的形式给出。 + // 这些代码主要是定义了一些用于查询数据库的投影数组,以及用于格式化输出文本的字符串数组。 + + private Context mContext; + private String mFileName; + private String mFileDirectory; + + /** + * TextExport 类的构造函数。 + * + * @param context Android 上下文对象。 + */ + public TextExport(Context context) { + // 初始化格式化字符串数组和上下文对象。 + } + + /** + * 根据资源ID获取格式化字符串。 + * + * @param id 资源ID。 + * @return 格式化字符串。 + */ + private String getFormat(int id) { + return TEXT_FORMAT[id]; + } + + /** + * 将指定文件夹中的笔记导出到文本文件。 + * + * @param folderId 文件夹ID。 + * @param ps PrintStream 对象,用于写入文本文件。 + */ + private void exportFolderToText(String folderId, PrintStream ps) { + // 查询属于该文件夹的笔记,并导出。 + } + + /** + * 将指定笔记导出到文本文件。 + * + * @param noteId 笔记ID。 + * @param ps PrintStream 对象,用于写入文本文件。 + */ + private void exportNoteToText(String noteId, PrintStream ps) { + // 查询属于该笔记的数据,并导出。 + } + + /** + * 将笔记数据导出为用户可读的文本格式。 + * + * @return 一个表示操作结果的状态码。 + */ + public int exportToText() { + // 检查外部存储是否可用,然后导出笔记数据到文本文件。 + } + + /** + * 获取指向导出文本文件的 PrintStream 对象。 + * + * @return PrintStream 对象,或者在出错时返回 null。 + */ + private PrintStream getExportToTextPrintStream() { + // 创建或获取文件,并返回 PrintStream 对象。 + } + } + + /** + * 在 SD 卡上生成用于存储导入数据的文本文件。 + * + * @param context Android 上下文对象。 + * @param filePathResId 文件路径资源ID。 + * @param fileNameFormatResId 文件名格式资源ID。 + * @return 生成的文件对象,或者在出错时返回 null。 + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { + // 根据资源ID生成文件路径和文件名,并创建文件。 + } +} \ No newline at end of file diff --git a/DataUtils.txt b/DataUtils.txt new file mode 100644 index 0000000..2b0d06b --- /dev/null +++ b/DataUtils.txt @@ -0,0 +1,152 @@ + +/** + * 工具类DataUtils,包含一系列用于操作便签数据的方法。 + */ +public class DataUtils { + public static final String TAG = "DataUtils"; + + /** + * 批量删除便签。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param ids 要删除的便签ID集合。 + * @return 如果删除成功返回true,否则返回false。 + */ + public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { + // 方法实现... + } + + /** + * 将单个便签移动到另一个文件夹。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param id 要移动的便签ID。 + * @param srcFolderId 当前文件夹ID。 + * @param desFolderId 目标文件夹ID。 + */ + public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { + // 方法实现... + } + + /** + * 批量将便签移动到指定文件夹。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param ids 要移动的便签ID集合。 + * @param folderId 目标文件夹ID。 + * @return 如果移动成功返回true,否则返回false。 + */ + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, long folderId) { + // 方法实现... + } + + /** + * 获取除系统文件夹外的所有文件夹数量。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @return 文件夹数量。 + */ + public static int getUserFolderCount(ContentResolver resolver) { + // 方法实现... + } + + /** + * 检查便签在数据库中是否可见。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param noteId 便签ID。 + * @param type 便签类型。 + * @return 如果便签可见返回true,否则返回false。 + */ + public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { + // 方法实现... + } + + /** + * 检查便签在数据库中是否存在。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param noteId 便签ID。 + * @return 如果便签存在返回true,否则返回false。 + */ + public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { + // 方法实现... + } + + /** + * 检查数据在数据库中是否存在。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param dataId 数据ID。 + * @return 如果数据存在返回true,否则返回false。 + */ + public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + // 方法实现... + } + + /** + * 检查指定名称的文件夹是否可见。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param name 文件夹名称。 + * @return 如果文件夹可见返回true,否则返回false。 + */ + public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + // 方法实现... + } + + /** + * 获取文件夹中便签的小部件属性集合。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param folderId 文件夹ID。 + * @return 小部件属性集合。 + */ + public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + // 方法实现... + } + + /** + * 根据便签ID获取关联的电话号码。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param noteId 便签ID。 + * @return 电话号码字符串。 + */ + public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + // 方法实现... + } + + /** + * 根据电话号码和通话日期获取便签ID。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param phoneNumber 电话号码。 + * @param callDate 通话日期。 + * @return 便签ID。 + */ + public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + // 方法实现... + } + + /** + * 根据ID获取便签的摘要。 + * + * @param resolver ContentResolver对象,用于访问内容提供者。 + * @param noteId 便签ID。 + * @return 便签摘要字符串。 + */ + public static String getSnippetById(ContentResolver resolver, long noteId) { + // 方法实现... + } + + /** + * 获取格式化后的便签摘要,去除换行符。 + * + * @param snippet 原始便签摘要。 + * @return 格式化后的便签摘要。 + */ + public static String getFormattedSnippet(String snippet) { + // 方法实现... + } +} diff --git a/DateTimePicker.txt b/DateTimePicker.txt new file mode 100644 index 0000000..b3bb76e --- /dev/null +++ b/DateTimePicker.txt @@ -0,0 +1,98 @@ + +/** + * 自定义日期时间选择器视图。 + */ +public class DateTimePicker extends FrameLayout { + // 类成员变量和常量定义 + private static final boolean DEFAULT_ENABLE_STATE = true; + private static final int HOURS_IN_HALF_DAY = 12; + // ... 其他常量定义 + + // 日期时间选择器的组件 + private final NumberPicker mDateSpinner; + private final NumberPicker mHourSpinner; + private final NumberPicker mMinuteSpinner; + private final NumberPicker mAmPmSpinner; + private Calendar mDate; + + // 日期显示值数组 + private String[] mDateDisplayValues = new String[DAYS_IN_ALL_WEEK]; + + // AM/PM标志 + private boolean mIsAm; + + // 是否为24小时视图 + private boolean mIs24HourView; + + // 启用状态 + private boolean mIsEnabled = DEFAULT_ENABLE_STATE; + + // 初始化标志 + private boolean mInitialising; + + // 日期时间改变监听器 + private OnDateTimeChangedListener mOnDateTimeChangedListener; + + // NumberPicker值改变监听器 + private NumberPicker.OnValueChangeListener mOnDateChangedListener = new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + // 日期改变时的处理逻辑 + } + }; + // ... 其他监听器定义 + + /** + * 定义日期时间改变监听器接口。 + */ + public interface OnDateTimeChangedListener { + void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute); + } + + /** + * 构造函数。 + */ + public DateTimePicker(Context context) { + // ... 实现代码 + } + + /** + * 设置当前日期。 + * @param date 长整型日期值。 + */ + public void setCurrentDate(long date) { + // ... 实现代码 + } + + /** + * 获取当前年份。 + * @return 当前年份。 + */ + public int getCurrentYear() { + // ... 实现代码 + } + + // ... 其他日期时间组件的getter和setter方法 + + /** + * 设置是否为24小时视图。 + * @param is24HourView 是否为24小时视图。 + */ + public void set24HourView(boolean is24HourView) { + // ... 实现代码 + } + + /** + * 设置日期时间改变监听器。 + * @param callback 监听器回调。 + */ + public void setOnDateTimeChangedListener(OnDateTimeChangedListener callback) { + // ... 实现代码 + } + + private void onDateTimeChanged() { + // 通知监听器日期时间改变 + } +} + diff --git a/DateTimePickerDialog.txt b/DateTimePickerDialog.txt new file mode 100644 index 0000000..713bb10 --- /dev/null +++ b/DateTimePickerDialog.txt @@ -0,0 +1,92 @@ +/** + * 日期时间选择器对话框,允许用户设置日期和时间。 + */ +public class DateTimePickerDialog extends AlertDialog implements OnClickListener { + // 当前日期时间 + private Calendar mDate = Calendar.getInstance(); + // 是否为24小时视图 + private boolean mIs24HourView; + // 日期时间设置监听器 + private OnDateTimeSetListener mOnDateTimeSetListener; + // 日期时间选择器组件 + private DateTimePicker mDateTimePicker; + + /** + * 日期时间设置监听器接口。 + */ + public interface OnDateTimeSetListener { + void OnDateTimeSet(AlertDialog dialog, long date); + } + + /** + * 构造函数。 + * @param context 上下文对象 + * @param date 初始日期时间 + */ + public DateTimePickerDialog(Context context, long date) { + super(context); + mDateTimePicker = new DateTimePicker(context); + setView(mDateTimePicker); + // 设置日期时间改变监听器 + mDateTimePicker.setOnDateTimeChangedListener(new OnDateTimeChangedListener() { + public void onDateTimeChanged(DateTimePicker view, int year, int month, + int dayOfMonth, int hourOfDay, int minute) { + mDate.set(Calendar.YEAR, year); + mDate.set(Calendar.MONTH, month); + mDate.set(Calendar.DAY_OF_MONTH, dayOfMonth); + mDate.set(Calendar.HOUR_OF_DAY, hourOfDay); + mDate.set(Calendar.MINUTE, minute); + updateTitle(mDate.getTimeInMillis()); + } + }); + mDate.setTimeInMillis(date); + mDate.set(Calendar.SECOND, 0); + mDateTimePicker.setCurrentDate(mDate.getTimeInMillis()); + // 设置确认和取消按钮 + setButton(context.getString(R.string.datetime_dialog_ok), this); + setButton2(context.getString(R.string.datetime_dialog_cancel), (OnClickListener)null); + // 设置24小时视图 + set24HourView(DateFormat.is24HourFormat(this.getContext())); + updateTitle(mDate.getTimeInMillis()); + } + + /** + * 设置是否为24小时视图。 + * @param is24HourView 是否为24小时视图 + */ + public void set24HourView(boolean is24HourView) { + mIs24HourView = is24HourView; + } + + /** + * 设置日期时间设置监听器。 + * @param callBack 监听器回调 + */ + public void setOnDateTimeSetListener(OnDateTimeSetListener callBack) { + mOnDateTimeSetListener = callBack; + } + + /** + * 更新对话框标题为当前日期时间。 + * @param date 长整型日期时间值 + */ + private void updateTitle(long date) { + int flag = + DateUtils.FORMAT_SHOW_YEAR | + DateUtils.FORMAT_SHOW_DATE | + DateUtils.FORMAT_SHOW_TIME; + flag |= mIs24HourView ? DateUtils.FORMAT_24HOUR : DateUtils.FORMAT_12HOUR; + setTitle(DateUtils.formatDateTime(this.getContext(), date, flag)); + } + + /** + * 点击事件处理。 + * @param arg0 对话框接口 + * @param arg1 按钮索引 + */ + public void onClick(DialogInterface arg0, int arg1) { + if (mOnDateTimeSetListener != null) { + mOnDateTimeSetListener.OnDateTimeSet(this, mDate.getTimeInMillis()); + } + } +} \ No newline at end of file diff --git a/DropdownMenu.txt b/DropdownMenu.txt new file mode 100644 index 0000000..c3a2414 --- /dev/null +++ b/DropdownMenu.txt @@ -0,0 +1,62 @@ +/** + * 下拉菜单类,用于创建和管理弹出式菜单。 + */ +public class DropdownMenu { + // 下拉按钮 + private Button mButton; + // 弹出式菜单 + private PopupMenu mPopupMenu; + // 菜单项 + private Menu mMenu; + + /** + * 构造函数。 + * @param context 上下文对象,用于获取资源和创建菜单。 + * @param button 显示下拉菜单的按钮。 + * @param menuId 要加载的菜单资源ID。 + */ + public DropdownMenu(Context context, Button button, int menuId) { + mButton = button; + // 设置按钮的背景资源为下拉图标 + mButton.setBackgroundResource(R.drawable.dropdown_icon); + // 创建PopupMenu实例,关联到按钮 + mPopupMenu = new PopupMenu(context, mButton); + // 获取菜单实例 + mMenu = mPopupMenu.getMenu(); + // 从资源文件中加载菜单项 + mPopupMenu.getMenuInflater().inflate(menuId, mMenu); + // 设置按钮的点击事件监听器,点击时显示菜单 + mButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mPopupMenu.show(); + } + }); + } + + /** + * 设置菜单项点击事件监听器。 + * @param listener 菜单项点击事件监听器。 + */ + public void setOnDropdownMenuItemClickListener(OnMenuItemClickListener listener) { + if (mPopupMenu != null) { + mPopupMenu.setOnMenuItemClickListener(listener); + } + } + + /** + * 查找具有指定ID的菜单项。 + * @param id 菜单项ID。 + * @return 菜单项对象。 + */ + public MenuItem findItem(int id) { + return mMenu.findItem(id); + } + + /** + * 设置下拉按钮的标题。 + * @param title 标题文本。 + */ + public void setTitle(CharSequence title) { + mButton.setText(title); + } +} \ No newline at end of file diff --git a/FoldersListAdapter.txt b/FoldersListAdapter.txt new file mode 100644 index 0000000..737768c --- /dev/null +++ b/FoldersListAdapter.txt @@ -0,0 +1,87 @@ +/** + * 文件夹列表适配器,用于显示和管理文件夹列表项。 + */ +public class FoldersListAdapter extends CursorAdapter { + // 投影数组,用于查询数据库时指定需要哪些列 + public static final String [] PROJECTION = { + NoteColumns.ID, + NoteColumns.SNIPPET + }; + + // 列索引常量 + public static final int ID_COLUMN = 0; + public static final int NAME_COLUMN = 1; + + /** + * 构造函数。 + * @param context 上下文对象,提供应用环境信息。 + * @param c 数据库游标,包含文件夹数据。 + */ + public FoldersListAdapter(Context context, Cursor c) { + super(context, c); + } + + /** + * 创建新的列表项视图。 + * @param context 上下文对象。 + * @param cursor 数据库游标。 + * @param parent 父视图组。 + * @return 新的列表项视图。 + */ + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return new FolderListItem(context); + } + + /** + * 绑定数据到列表项视图。 + * @param view 列表项视图。 + * @param context 上下文对象。 + * @param cursor 数据库游标。 + */ + @Override + public void bindView(View view, Context context, Cursor cursor) { + if (view instanceof FolderListItem) { + 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); + } + } + + /** + * 获取指定位置的文件夹名称。 + * @param context 上下文对象。 + * @param position 列表项位置。 + * @return 文件夹名称。 + */ + public String getFolderName(Context context, int position) { + Cursor cursor = (Cursor) getItem(position); + return (cursor.getLong(ID_COLUMN) == Notes.ID_ROOT_FOLDER) ? context + .getString(R.string.menu_move_parent_folder) : cursor.getString(NAME_COLUMN); + } + + /** + * 自定义文件夹列表项视图。 + */ + private class FolderListItem extends LinearLayout { + private TextView mName; + + /** + * 构造函数。 + * @param context 上下文对象。 + */ + public FolderListItem(Context context) { + super(context); + inflate(context, R.layout.folder_list_item, this); + mName = (TextView) findViewById(R.id.tv_folder_name); + } + + /** + * 绑定文件夹名称到视图。 + * @param name 文件夹名称。 + */ + public void bind(String name) { + mName.setText(name); + } + } +} \ No newline at end of file diff --git a/GTaskStringUtils.txt b/GTaskStringUtils.txt new file mode 100644 index 0000000..deeb898 --- /dev/null +++ b/GTaskStringUtils.txt @@ -0,0 +1,145 @@ + +/** + * 工具类GTaskStringUtils,包含处理Google Tasks(GTask)JSON数据时使用的常量字符串。 + */ +public class GTaskStringUtils { + + // GTask JSON中用于标识操作ID的键 + public final static String GTASK_JSON_ACTION_ID = "action_id"; + + // GTask JSON中用于标识操作列表的键 + public final static String GTASK_JSON_ACTION_LIST = "action_list"; + + // GTask JSON中用于标识操作类型的键 + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; + + // GTask JSON中用于标识创建任务的操作类型 + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; + + // GTask JSON中用于标识获取所有任务的操作类型 + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; + + // GTask JSON中用于标识移动任务的操作类型 + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; + + // GTask JSON中用于标识更新任务的操作类型 + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; + + // GTask JSON中用于标识创建者ID的键 + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; + + // GTask JSON中用于标识子实体的键 + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; + + // GTask JSON中用于标识客户端版本的键 + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; + + // GTask JSON中用于标识任务是否完成的键 + public final static String GTASK_JSON_COMPLETED = "completed"; + + // GTask JSON中用于标识当前列表ID的键 + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; + + // GTask JSON中用于标识默认列表ID的键 + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; + + // GTask JSON中用于标识任务是否被删除的键 + public final static String GTASK_JSON_DELETED = "deleted"; + + // GTask JSON中用于标识目标列表的键 + public final static String GTASK_JSON_DEST_LIST = "dest_list"; + + // GTask JSON中用于标识目标父实体的键 + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; + + // GTask JSON中用于标识目标父实体类型的键 + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; + + // GTask JSON中用于标识实体变化的键 + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; + + // GTask JSON中用于标识实体类型的键 + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; + + // GTask JSON中用于标识获取已删除任务的键 + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; + + // GTask JSON中用于标识ID的键 + public final static String GTASK_JSON_ID = "id"; + + // GTask JSON中用于标识索引的键 + public final static String GTASK_JSON_INDEX = "index"; + + // GTask JSON中用于标识最后修改时间的键 + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; + + // GTask JSON中用于标识最新同步点的键 + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; + + // GTask JSON中用于标识列表ID的键 + public final static String GTASK_JSON_LIST_ID = "list_id"; + + // GTask JSON中用于标识列表集合的键 + public final static String GTASK_JSON_LISTS = "lists"; + + // GTask JSON中用于标识名称的键 + public final static String GTASK_JSON_NAME = "name"; + + // GTask JSON中用于标识新ID的键 + public final static String GTASK_JSON_NEW_ID = "new_id"; + + // GTask JSON中用于标识备注的键 + public final static String GTASK_JSON_NOTES = "notes"; + + // GTask JSON中用于标识父ID的键 + public final static String GTASK_JSON_PARENT_ID = "parent_id"; + + // GTask JSON中用于标识前一个兄弟ID的键 + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; + + // GTask JSON中用于标识结果的键 + public final static String GTASK_JSON_RESULTS = "results"; + + // GTask JSON中用于标识源列表的键 + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; + + // GTask JSON中用于标识任务集合的键 + public final static String GTASK_JSON_TASKS = "tasks"; + + // GTask JSON中用于标识类型的键 + public final static String GTASK_JSON_TYPE = "type"; + + // GTask JSON中用于标识组类型的值 + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; + + // GTask JSON中用于标识任务类型的值 + public final static String GTASK_JSON_TYPE_TASK = "TASK"; + + // GTask 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"; +} + diff --git a/NoteEditActivity.txt b/NoteEditActivity.txt new file mode 100644 index 0000000..17cb2d8 --- /dev/null +++ b/NoteEditActivity.txt @@ -0,0 +1,77 @@ +/** + * 便签编辑活动,用于编辑和查看便签详情。 + */ +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 sBgSelectorBtnsMap = new HashMap(); + // 静态映射,用于字体大小选择器按钮和大小ID之间的映射 + private static final Map sFontSizeBtnsMap = new HashMap(); + + // 类成员变量 + // 头部视图持有者,包含头部相关控件的引用 + 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; + + /** + * 活动创建时调用。 + * @param savedInstanceState 保存的实例状态 + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.note_edit); + // 初始化活动状态 + if (savedInstanceState == null && !initActivityState(getIntent())) { + finish(); + return; + } + initResources(); + } + + /** + * 初始化活动状态。 + * @param intent 启动活动的Intent + * @return 是否成功初始化 + */ + private boolean initActivityState(Intent intent) { + // 根据传入的Intent初始化活动状态,例如加载便签数据等 + } + + /** + * 初始化资源。 + */ + private void initResources() { + // 初始化头部视图持有者,设置监听器,绑定数据等 + } + + // 其他方法,包括处理点击事件、保存便签、设置提醒等... +} \ No newline at end of file diff --git a/NoteEditText.txt b/NoteEditText.txt new file mode 100644 index 0000000..17cb2d8 --- /dev/null +++ b/NoteEditText.txt @@ -0,0 +1,77 @@ +/** + * 便签编辑活动,用于编辑和查看便签详情。 + */ +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 sBgSelectorBtnsMap = new HashMap(); + // 静态映射,用于字体大小选择器按钮和大小ID之间的映射 + private static final Map sFontSizeBtnsMap = new HashMap(); + + // 类成员变量 + // 头部视图持有者,包含头部相关控件的引用 + 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; + + /** + * 活动创建时调用。 + * @param savedInstanceState 保存的实例状态 + */ + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.note_edit); + // 初始化活动状态 + if (savedInstanceState == null && !initActivityState(getIntent())) { + finish(); + return; + } + initResources(); + } + + /** + * 初始化活动状态。 + * @param intent 启动活动的Intent + * @return 是否成功初始化 + */ + private boolean initActivityState(Intent intent) { + // 根据传入的Intent初始化活动状态,例如加载便签数据等 + } + + /** + * 初始化资源。 + */ + private void initResources() { + // 初始化头部视图持有者,设置监听器,绑定数据等 + } + + // 其他方法,包括处理点击事件、保存便签、设置提醒等... +} \ No newline at end of file diff --git a/NoteItemData.txt b/NoteItemData.txt new file mode 100644 index 0000000..4e8a5fe --- /dev/null +++ b/NoteItemData.txt @@ -0,0 +1,98 @@ +/** + * 便签项数据类,封装单个便签项的相关信息。 + */ +public class NoteItemData { + // 数据库查询字段投影 + static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.ALERTED_DATE, + // ... 其他字段 + }; + + // 列索引常量 + private static final int ID_COLUMN = 0; + private static final int ALERTED_DATE_COLUMN = 1; + // ... 其他列索引常量 + + // 便签项属性 + private long mId; + private long mAlertDate; + private int mBgColorId; + private long mCreatedDate; + private boolean mHasAttachment; + private long mModifiedDate; + private int mNotesCount; + private long mParentId; + private String mSnippet; + private int mType; + private int mWidgetId; + private int mWidgetType; + private String mName; + private String mPhoneNumber; + + // 位置相关标志 + private boolean mIsLastItem; + private boolean mIsFirstItem; + private boolean mIsOnlyOneItem; + private boolean mIsOneNoteFollowingFolder; + private boolean mIsMultiNotesFollowingFolder; + + /** + * 构造函数,从数据库游标中初始化便签项数据。 + * @param context 上下文对象,用于访问资源和数据。 + * @param cursor 数据库游标,包含便签项的数据。 + */ + public NoteItemData(Context context, Cursor cursor) { + // 从游标中获取数据并初始化成员变量 + // ... 初始化代码 + } + + /** + * 检查便签项在列表中的位置,设置位置相关标志。 + * @param cursor 数据库游标。 + */ + private void checkPostion(Cursor cursor) { + // 设置位置相关标志的逻辑 + // ... 实现代码 + } + + // 获取器方法,用于获取便签项的属性值 + 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; + } + + public long getId() { + return mId; + } + + // ... 其他获取器方法 + + /** + * 根据游标获取便签类型。 + * @param cursor 数据库游标。 + * @return 便签类型。 + */ + public static int getNoteType(Cursor cursor) { + return cursor.getInt(TYPE_COLUMN); + } +} \ No newline at end of file diff --git a/NoteWidgetProvider.txt b/NoteWidgetProvider.txt new file mode 100644 index 0000000..8a80601 --- /dev/null +++ b/NoteWidgetProvider.txt @@ -0,0 +1,80 @@ +/** + * 便签小部件提供者,用于管理便签小部件的数据和界面更新。 + */ +public abstract class NoteWidgetProvider extends AppWidgetProvider { + // 数据库查询字段投影 + public static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.BG_COLOR_ID, + NoteColumns.SNIPPET + }; + + // 列索引常量 + public static final int COLUMN_ID = 0; + public static final int COLUMN_BG_COLOR_ID = 1; + public static final int COLUMN_SNIPPET = 2; + + // 日志标签 + private static final String TAG = "NoteWidgetProvider"; + + /** + * 当小部件被删除时调用。 + * @param context 上下文对象 + * @param appWidgetIds 被删除的小部件ID数组 + */ + @Override + public void onDeleted(Context context, int[] appWidgetIds) { + // 更新数据库,将被删除小部件的WIDGET_ID设置为无效 + } + + /** + * 获取小部件相关的便签信息。 + * @param context 上下文对象 + * @param widgetId 小部件ID + * @return 便签信息游标 + */ + private Cursor getNoteWidgetInfo(Context context, int widgetId) { + // 查询数据库,获取与小部件ID相关的便签信息 + } + + /** + * 更新小部件界面。 + * @param context 上下文对象 + * @param appWidgetManager AppWidget管理器 + * @param appWidgetIds 小部件ID数组 + */ + protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 默认不启用隐私模式,调用带隐私模式参数的update方法 + } + + /** + * 更新小部件界面,支持隐私模式。 + * @param context 上下文对象 + * @param appWidgetManager AppWidget管理器 + * @param appWidgetIds 小部件ID数组 + * @param privacyMode 是否启用隐私模式 + */ + private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, + boolean privacyMode) { + // 遍历小部件ID数组,更新每个小部件的界面 + } + + /** + * 获取背景资源ID。 + * @param bgId 背景ID + * @return 背景资源ID + */ + protected abstract int getBgResourceId(int bgId); + + /** + * 获取小部件布局ID。 + * @return 布局ID + */ + protected abstract int getLayoutId(); + + /** + * 获取小部件类型。 + * @return 小部件类型 + */ + protected abstract int getWidgetType(); +} \ No newline at end of file diff --git a/NoteWidgetProvider_2x.txt b/NoteWidgetProvider_2x.txt new file mode 100644 index 0000000..ea496ce --- /dev/null +++ b/NoteWidgetProvider_2x.txt @@ -0,0 +1,48 @@ +/** + * 2x2网格大小的便签小部件提供者,继承自NoteWidgetProvider。 + */ +public class NoteWidgetProvider_2x extends NoteWidgetProvider { + + /** + * 当小部件需要更新时调用。 + * @param context 上下文对象,提供应用程序环境信息。 + * @param appWidgetManager AppWidget管理器,用于管理小部件。 + * @param appWidgetIds 需要更新的小部件ID数组。 + */ + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的update方法,更新小部件 + super.update(context, appWidgetManager, appWidgetIds); + } + + /** + * 获取小部件的布局资源ID。 + * @return 小部件布局资源ID。 + */ + @Override + protected int getLayoutId() { + // 返回2x2网格大小小部件的布局资源ID + return R.layout.widget_2x; + } + + /** + * 获取背景资源ID。 + * @param bgId 背景ID。 + * @return 对应背景资源ID的资源。 + */ + @Override + protected int getBgResourceId(int bgId) { + // 根据背景ID获取2x2网格大小小部件的背景资源ID + return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); + } + + /** + * 获取小部件类型。 + * @return 小部件类型。 + */ + @Override + protected int getWidgetType() { + // 返回2x2网格大小小部件的类型 + return Notes.TYPE_WIDGET_2X; + } +} \ No newline at end of file diff --git a/NoteWidgetProvider_4x.txt b/NoteWidgetProvider_4x.txt new file mode 100644 index 0000000..268a82b --- /dev/null +++ b/NoteWidgetProvider_4x.txt @@ -0,0 +1,47 @@ +/** + * 4x4网格大小的便签小部件提供者,继承自NoteWidgetProvider。 + */ +public class NoteWidgetProvider_4x extends NoteWidgetProvider { + + /** + * 当小部件需要更新时调用。 + * @param context 上下文对象,提供应用程序环境信息。 + * @param appWidgetManager AppWidget管理器,用于管理小部件。 + * @param appWidgetIds 需要更新的小部件ID数组。 + */ + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类的update方法,更新小部件 + super.update(context, appWidgetManager, appWidgetIds); + } + + /** + * 获取小部件的布局资源ID。 + * @return 小部件布局资源ID。 + */ + protected int getLayoutId() { + // 返回4x4网格大小小部件的布局资源ID + return R.layout.widget_4x; + } + + /** + * 获取背景资源ID。 + * @param bgId 背景ID。 + * @return 对应背景资源ID的资源。 + */ + @Override + protected int getBgResourceId(int bgId) { + // 根据背景ID获取4x4网格大小小部件的背景资源ID + return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); + } + + /** + * 获取小部件类型。 + * @return 小部件类型。 + */ + @Override + protected int getWidgetType() { + // 返回4x4网格大小小部件的类型 + return Notes.TYPE_WIDGET_4X; + } +} \ No newline at end of file diff --git a/NotesListActivity.txt b/NotesListActivity.txt new file mode 100644 index 0000000..0e7b7a8 --- /dev/null +++ b/NotesListActivity.txt @@ -0,0 +1,110 @@ +/** + * 便签列表活动,用于展示和管理便签列表。 + */ +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; + + // 定义菜单项ID + 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"; + private NoteItemData mFocusNoteDataItem; + + // onCreate方法,活动创建时调用 + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.note_list); + initResources(); + setAppInfoFromRawRes(); + } + + // 初始化资源 + private void initResources() { + // 初始化代码... + } + + // 从raw资源文件中设置应用信息 + private void setAppInfoFromRawRes() { + // 读取介绍信息并显示 + } + + // onStart方法,活动启动时调用 + @Override + protected void onStart() { + super.onStart(); + startAsyncNotesListQuery(); + } + + // 启动异步查询便签列表 + private void startAsyncNotesListQuery() { + // 查询代码... + } + + // 异步查询处理器 + private final class BackgroundQueryHandler extends AsyncQueryHandler { + // 构造函数和onQueryComplete方法... + } + + // 显示文件夹列表菜单 + 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) { + // 打开文件夹代码... + } + + // onClick方法,处理点击事件 + public void onClick(View v) { + // 处理点击事件代码... + } + + // 其他方法,包括处理选项菜单、上下文菜单、搜索请求等... +} \ No newline at end of file diff --git a/NotesListAdapter.txt b/NotesListAdapter.txt new file mode 100644 index 0000000..0de97fc --- /dev/null +++ b/NotesListAdapter.txt @@ -0,0 +1,219 @@ +/** + * 便签列表适配器,用于管理和显示便签列表的数据。 + */ +public class NotesListAdapter extends CursorAdapter { + // 日志标签 + private static final String TAG = "NotesListAdapter"; + // 类成员变量 + private Context mContext; // 上下文对象 + private HashMap mSelectedIndex; // 保存选中状态的索引 + private int mNotesCount; // 便签计数 + private boolean mChoiceMode; // 是否处于选择模式 + + /** + * 应用小部件属性类。 + */ + public static class AppWidgetAttribute { + public int widgetId; // 小部件ID + public int widgetType; // 小部件类型 + }; + + /** + * 构造函数。 + * @param context 上下文对象 + */ + public NotesListAdapter(Context context) { + super(context, null); + mSelectedIndex = new HashMap(); + mContext = context; + mNotesCount = 0; + } + + /** + * 创建新的列表项视图。 + * @param context 上下文对象 + * @param cursor 游标对象 + * @param parent 父视图组 + * @return 新的列表项视图 + */ + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return new NotesListItem(context); + } + + /** + * 绑定数据到列表项视图。 + * @param view 列表项视图 + * @param context 上下文对象 + * @param cursor 游标对象 + */ + @Override + public void bindView(View view, Context context, Cursor cursor) { + if (view instanceof NotesListItem) { + NoteItemData itemData = new NoteItemData(context, cursor); + ((NotesListItem) view).bind(context, itemData, mChoiceMode, isSelectedItem(cursor.getPosition())); + } + } + + /** + * 设置列表项的选中状态。 + * @param position 列表项位置 + * @param checked 是否选中 + */ + public void setCheckedItem(final int position, final boolean checked) { + mSelectedIndex.put(position, checked); + notifyDataSetChanged(); + } + + /** + * 获取是否处于选择模式。 + * @return 是否处于选择模式 + */ + public boolean isInChoiceMode() { + return mChoiceMode; + } + + /** + * 设置选择模式。 + * @param mode 是否开启选择模式 + */ + public void setChoiceMode(boolean mode) { + mSelectedIndex.clear(); + mChoiceMode = mode; + } + + /** + * 全选或全不选。 + * @param checked 是否选中 + */ + public void selectAll(boolean checked) { + Cursor cursor = getCursor(); + for (int i = 0; i < getCount(); i++) { + if (cursor.moveToPosition(i)) { + if (NoteItemData.getNoteType(cursor) == Notes.TYPE_NOTE) { + setCheckedItem(i, checked); + } + } + } + } + + /** + * 获取选中的便签ID集合。 + * @return 选中的便签ID集合 + */ + public HashSet getSelectedItemIds() { + HashSet itemSet = new HashSet(); + for (Integer position : mSelectedIndex.keySet()) { + if (mSelectedIndex.get(position) == true) { + Long id = getItemId(position); + if (id == Notes.ID_ROOT_FOLDER) { + Log.d(TAG, "Wrong item id, should not happen"); + } else { + itemSet.add(id); + } + } + } + return itemSet; + } + + /** + * 获取选中的小部件属性集合。 + * @return 选中的小部件属性集合 + */ + public HashSet getSelectedWidget() { + HashSet itemSet = new HashSet(); + for (Integer position : mSelectedIndex.keySet()) { + if (mSelectedIndex.get(position) == true) { + Cursor c = (Cursor) getItem(position); + if (c != null) { + AppWidgetAttribute widget = new AppWidgetAttribute(); + NoteItemData item = new NoteItemData(mContext, c); + widget.widgetId = item.getWidgetId(); + widget.widgetType = item.getWidgetType(); + itemSet.add(widget); + } else { + Log.e(TAG, "Invalid cursor"); + return null; + } + } + } + return itemSet; + } + + /** + * 获取选中数量。 + * @return 选中数量 + */ + public int getSelectedCount() { + Collection values = mSelectedIndex.values(); + if (null == values) { + return 0; + } + Iterator iter = values.iterator(); + int count = 0; + while (iter.hasNext()) { + if (true == iter.next()) { + count++; + } + } + return count; + } + + /** + * 判断是否全部选中。 + * @return 是否全部选中 + */ + public boolean isAllSelected() { + int checkedCount = getSelectedCount(); + return (checkedCount != 0 && checkedCount == mNotesCount); + } + + /** + * 判断指定位置的项是否选中。 + * @param position 项的位置 + * @return 是否选中 + */ + public boolean isSelectedItem(final int position) { + if (null == mSelectedIndex.get(position)) { + return false; + } + return mSelectedIndex.get(position); + } + + /** + * 当内容变化时调用。 + */ + @Override + protected void onContentChanged() { + super.onContentChanged(); + calcNotesCount(); + } + + /** + * 更改游标。 + * @param cursor 新的游标 + */ + @Override + public void changeCursor(Cursor cursor) { + super.changeCursor(cursor); + calcNotesCount(); + } + + /** + * 计算便签数量。 + */ + private void calcNotesCount() { + mNotesCount = 0; + for (int i = 0; i < getCount(); i++) { + Cursor c = (Cursor) getItem(i); + if (c != null) { + if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) { + mNotesCount++; + } + } else { + Log.e(TAG, "Invalid cursor"); + return; + } + } + } +} \ No newline at end of file diff --git a/NotesListItem.txt b/NotesListItem.txt new file mode 100644 index 0000000..cb7b5a1 --- /dev/null +++ b/NotesListItem.txt @@ -0,0 +1,124 @@ +/** + * 便签列表项视图,用于展示单个便签项的界面元素。 + */ +public class NotesListItem extends LinearLayout { + // 类成员变量 + private ImageView mAlert; // 提醒图标 + private TextView mTitle; // 便签标题 + private TextView mTime; // 便签修改时间 + private TextView mCallName; // 通话记录姓名 + private NoteItemData mItemData; // 便签项数据 + private CheckBox mCheckBox; // 选择框 + + /** + * 构造函数。 + * @param context 上下文对象 + */ + public NotesListItem(Context context) { + super(context); + // inflate the layout for this view + inflate(context, R.layout.note_item, this); + // 初始化视图组件 + mAlert = (ImageView) findViewById(R.id.iv_alert_icon); + mTitle = (TextView) findViewById(R.id.tv_title); + mTime = (TextView) findViewById(R.id.tv_time); + mCallName = (TextView) findViewById(R.id.tv_name); + mCheckBox = (CheckBox) findViewById(android.R.id.checkbox); + } + + /** + * 绑定数据到视图。 + * @param context 上下文对象 + * @param data 便签项数据 + * @param choiceMode 是否处于选择模式 + * @param checked 是否选中 + */ + public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) { + // 根据是否处于选择模式显示或隐藏选择框,并设置选中状态 + if (choiceMode && data.getType() == Notes.TYPE_NOTE) { + mCheckBox.setVisibility(View.VISIBLE); + mCheckBox.setChecked(checked); + } else { + mCheckBox.setVisibility(View.GONE); + } + + // 保存便签项数据 + mItemData = data; + // 根据便签项类型设置不同的视图显示 + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + // 通话记录文件夹特殊处理 + mCallName.setVisibility(View.GONE); + mAlert.setVisibility(View.VISIBLE); + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + mTitle.setText(context.getString(R.string.call_record_folder_name) + + context.getString(R.string.format_folder_files_count, data.getNotesCount())); + mAlert.setImageResource(R.drawable.call_record); + } else if (data.getParentId() == Notes.ID_CALL_RECORD_FOLDER) { + // 通话记录项特殊处理 + mCallName.setVisibility(View.VISIBLE); + mCallName.setText(data.getCallName()); + mTitle.setTextAppearance(context, R.style.TextAppearanceSecondaryItem); + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock); + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } else { + // 普通便签项处理 + mCallName.setVisibility(View.GONE); + mTitle.setTextAppearance(context, R.style.TextAppearancePrimaryItem); + if (data.getType() == Notes.TYPE_FOLDER) { + // 文件夹项处理 + mTitle.setText(data.getSnippet() + + context.getString(R.string.format_folder_files_count, + data.getNotesCount())); + mAlert.setVisibility(View.GONE); + } else { + // 普通便签处理 + mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet())); + if (data.hasAlert()) { + mAlert.setImageResource(R.drawable.clock); + mAlert.setVisibility(View.VISIBLE); + } else { + mAlert.setVisibility(View.GONE); + } + } + } + // 设置时间显示 + mTime.setText(DateUtils.getRelativeTimeSpanString(data.getModifiedDate())); + // 设置背景 + setBackground(data); + } + + /** + * 设置背景资源。 + * @param data 便签项数据 + */ + private void setBackground(NoteItemData data) { + // 根据便签项类型和位置设置不同的背景资源 + int id = data.getBgColorId(); + if (data.getType() == Notes.TYPE_NOTE) { + if (data.isSingle() || data.isOneFollowingFolder()) { + setBackgroundResource(NoteItemBgResources.getNoteBgSingleRes(id)); + } else if (data.isLast()) { + setBackgroundResource(NoteItemBgResources.getNoteBgLastRes(id)); + } else if (data.isFirst() || data.isMultiFollowingFolder()) { + setBackgroundResource(NoteItemBgResources.getNoteBgFirstRes(id)); + } else { + setBackgroundResource(NoteItemBgResources.getNoteBgNormalRes(id)); + } + } else { + setBackgroundResource(NoteItemBgResources.getFolderBgRes()); + } + } + + /** + * 获取便签项数据。 + * @return 便签项数据 + */ + public NoteItemData getItemData() { + return mItemData; + } +} \ No newline at end of file diff --git a/NotesPreferenceActivity.txt b/NotesPreferenceActivity.txt new file mode 100644 index 0000000..b466f3c --- /dev/null +++ b/NotesPreferenceActivity.txt @@ -0,0 +1,238 @@ +/** + * 便签应用的偏好设置活动,用于管理应用的设置。 + */ +public class NotesPreferenceActivity extends PreferenceActivity { + // 偏好设置文件名 + public static final String PREFERENCE_NAME = "notes_preferences"; + // 同步账户名称的键 + public static final String PREFERENCE_SYNC_ACCOUNT_NAME = "pref_key_account_name"; + // 最后同步时间的键 + public static final String PREFERENCE_LAST_SYNC_TIME = "pref_last_sync_time"; + // 设置背景颜色的键 + public static final String PREFERENCE_SET_BG_COLOR_KEY = "pref_key_bg_random_appear"; + // 同步账户的键 + private static final String PREFERENCE_SYNC_ACCOUNT_KEY = "pref_sync_account_key"; + // 权限过滤键 + private static final String AUTHORITIES_FILTER_KEY = "authorities"; + + // 类成员变量 + private PreferenceCategory mAccountCategory; // 账户类别 + private GTaskReceiver mReceiver; // 接收器 + private Account[] mOriAccounts; // 原始账户数组 + private boolean mHasAddedAccount; // 是否添加了账户 + + /** + * 活动创建时调用。 + * @param icicle 保存的实例状态 + */ + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + // 设置返回键 + getActionBar().setDisplayHomeAsUpEnabled(true); + // 加载偏好设置 + addPreferencesFromResource(R.xml.preferences); + // 初始化账户类别 + mAccountCategory = (PreferenceCategory) findPreference(PREFERENCE_SYNC_ACCOUNT_KEY); + // 注册接收器 + mReceiver = new GTaskReceiver(); + IntentFilter filter = new IntentFilter(); + filter.addAction(GTaskSyncService.GTASK_SERVICE_BROADCAST_NAME); + registerReceiver(mReceiver, filter); + // 初始化视图 + View header = LayoutInflater.from(this).inflate(R.layout.settings_header, null); + getListView().addHeaderView(header, null, true); + } + + /** + * 活动恢复时调用。 + */ + @Override + protected void onResume() { + super.onResume(); + // 自动设置同步账户 + if (mHasAddedAccount) { + Account[] accounts = getGoogleAccounts(); + if (mOriAccounts != null && accounts.length > mOriAccounts.length) { + for (Account accountNew : accounts) { + boolean found = false; + for (Account accountOld : mOriAccounts) { + if (TextUtils.equals(accountOld.name, accountNew.name)) { + found = true; + break; + } + } + if (!found) { + setSyncAccount(accountNew.name); + break; + } + } + } + } + // 刷新UI + refreshUI(); + } + + /** + * 活动销毁时调用。 + */ + @Override + protected void onDestroy() { + if (mReceiver != null) { + unregisterReceiver(mReceiver); + } + super.onDestroy(); + } + + /** + * 加载账户偏好设置。 + */ + private void loadAccountPreference() { + mAccountCategory.removeAll(); + // 创建账户偏好项 + Preference accountPref = new Preference(this); + final String defaultAccount = getSyncAccountName(this); + accountPref.setTitle(getString(R.string.preferences_account_title)); + accountPref.setSummary(getString(R.string.preferences_account_summary)); + accountPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + public boolean onPreferenceClick(Preference preference) { + if (!GTaskSyncService.isSyncing()) { + if (TextUtils.isEmpty(defaultAccount)) { + showSelectAccountAlertDialog(); + } else { + showChangeAccountConfirmAlertDialog(); + } + } else { + Toast.makeText(NotesPreferenceActivity.this, + R.string.preferences_toast_cannot_change_account, Toast.LENGTH_SHORT) + .show(); + } + return true; + } + }); + mAccountCategory.addPreference(accountPref); + } + + /** + * 加载同步按钮。 + */ + private void loadSyncButton() { + Button syncButton = (Button) findViewById(R.id.preference_sync_button); + TextView lastSyncTimeView = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + // 设置按钮状态 + if (GTaskSyncService.isSyncing()) { + syncButton.setText(getString(R.string.preferences_button_sync_cancel)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.cancelSync(NotesPreferenceActivity.this); + } + }); + } else { + syncButton.setText(getString(R.string.preferences_button_sync_immediately)); + syncButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + GTaskSyncService.startSync(NotesPreferenceActivity.this); + } + }); + } + syncButton.setEnabled(!TextUtils.isEmpty(getSyncAccountName(this))); + // 设置最后同步时间 + if (GTaskSyncService.isSyncing()) { + lastSyncTimeView.setText(GTaskSyncService.getProgressString()); + lastSyncTimeView.setVisibility(View.VISIBLE); + } else { + long lastSyncTime = getLastSyncTime(this); + if (lastSyncTime != 0) { + lastSyncTimeView.setText(getString(R.string.preferences_last_sync_time, + DateFormat.format(getString(R.string.preferences_last_sync_time_format), + lastSyncTime))); + lastSyncTimeView.setVisibility(View.VISIBLE); + } else { + lastSyncTimeView.setVisibility(View.GONE); + } + } + } + + /** + * 刷新UI。 + */ + private void refreshUI() { + loadAccountPreference(); + loadSyncButton(); + } + + /** + * 显示选择账户的对话框。 + */ + private void showSelectAccountAlertDialog() { + // 对话框代码... + } + + /** + * 显示更改账户的确认对话框。 + */ + private void showChangeAccountConfirmAlertDialog() { + // 对话框代码... + } + + /** + * 获取Google账户。 + * @return 账户数组 + */ + private Account[] getGoogleAccounts() { + AccountManager accountManager = AccountManager.get(this); + return accountManager.getAccountsByType("com.google"); + } + + /** + * 设置同步账户。 + * @param account 账户名 + */ + private void setSyncAccount(String account) { + // 设置同步账户代码... + } + + /** + * 移除同步账户。 + */ + private void removeSyncAccount() { + // 移除同步账户代码... + } + + /** + * 获取同步账户名。 + * @param context 上下文对象 + * @return 同步账户名 + */ + public static String getSyncAccountName(Context context) { + // 获取同步账户名代码... + } + + /** + * 设置最后同步时间。 + * @param context 上下文对象 + * @param time 最后同步时间 + */ + public static void setLastSyncTime(Context context, long time) { + // 设置最后同步时间代码... + } + + /** + * 获取最后同步时间。 + * @param context 上下文对象 + * @return 最后同步时间 + */ + public static long getLastSyncTime(Context context) { + // 获取最后同步时间代码... + } + + /** + * GTask接收器,用于接收同步服务的广播。 + */ + private class GTaskReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + refreshUI(); + if (intent.getBooleanExtra(GTaskSyncService.GTASK_SERVICE_BROADCAST_IS_SYNCING, false)) { + TextView syncStatus = (TextView) findViewById(R.id.prefenerece_sync_status_textview); + syncS \ No newline at end of file diff --git a/ResourceParser.txt b/ResourceParser.txt new file mode 100644 index 0000000..5f77c3e --- /dev/null +++ b/ResourceParser.txt @@ -0,0 +1,188 @@ + +/** + * 工具类ResourceParser,用于解析和管理应用中的资源。 + */ +public class ResourceParser { + + // 定义背景颜色常量 + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4; + + // 默认背景颜色 + public static final int BG_DEFAULT_COLOR = YELLOW; + + // 定义文本大小常量 + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3; + + // 默认文本大小 + public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; + + /** + * NoteBgResources内部类,用于管理便签背景资源。 + */ + public static class NoteBgResources { + // 编辑状态下的背景资源数组 + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red + }; + + // 编辑状态下标题的背景资源数组 + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red + }; + + // 获取便签背景资源 + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + } + + // 获取便签标题背景资源 + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + } + } + + /** + * 根据上下文获取默认背景ID。 + * @param context 上下文对象 + * @return 默认背景ID + */ + public static int getDefaultBgId(Context context) { + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length); + } else { + return BG_DEFAULT_COLOR; + } + } + + /** + * NoteItemBgResources内部类,用于管理便签项背景资源。 + */ + public static class NoteItemBgResources { + // 定义不同类型的背景资源数组 + private final static int [] BG_FIRST_RESOURCES = new int [] { + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up + }; + private final static int [] BG_NORMAL_RESOURCES = new int [] { + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle + }; + private final static int [] BG_LAST_RESOURCES = new int [] { + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, + }; + private final static int [] BG_SINGLE_RESOURCES = new int [] { + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single + }; + + // 获取不同类型的便签项背景资源 + public static int getNoteBgFirstRes(int id) { + return BG_FIRST_RESOURCES[id]; + } + + public static int getNoteBgLastRes(int id) { + return BG_LAST_RESOURCES[id]; + } + + public static int getNoteBgSingleRes(int id) { + return BG_SINGLE_RESOURCES[id]; + } + + public static int getNoteBgNormalRes(int id) { + return BG_NORMAL_RESOURCES[id]; + } + + // 获取文件夹背景资源 + public static int getFolderBgRes() { + return R.drawable.list_folder; + } + } + + /** + * WidgetBgResources内部类,用于管理小部件背景资源。 + */ + public static class WidgetBgResources { + // 定义2x小部件背景资源数组 + private final static int [] BG_2X_RESOURCES = new int [] { + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, + }; + + // 获取2x小部件背景资源 + public static int getWidget2xBgResource(int id) { + return BG_2X_RESOURCES[id]; + } + + // 定义4x小部件背景资源数组 + private final static int [] BG_4X_RESOURCES = new int [] { + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red + }; + + // 获取4x小部件背景资源 + public static int getWidget4xBgResource(int id) { + return BG_4X_RESOURCES[id]; + } + } + + /** + * TextAppearanceResources内部类,用于管理文本外观资源。 + */ + public static class TextAppearanceResources { + // 定义文本外观资源数组 + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper + }; + + // 获取文本外观资源 + public static int getTexAppearanceResource(int id) { + if (id >= TEXTAPPEARANCE_RESOURCES.length) { + return BG_DEFAULT_FONT_SIZE; + } + return TEXTAPPEARANCE_RESOURCES[id]; + } + + // 获取资源数组的大小 + public static int getResourcesSize() { + return TEXTAPPEARANCE_RESOURCES.length; + } + } +}