diff --git a/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java new file mode 100644 index 0000000..2e9ac87 --- /dev/null +++ b/app/src/main/java/net/micode/notes/ui/NotesListAdapter.java @@ -0,0 +1,203 @@ +/* + * 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.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CursorAdapter; + +import net.micode.notes.data.Notes; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + + +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; + public int widgetType; + }; + + public NotesListAdapter(Context context) { + super(context, null); + mSelectedIndex = new HashMap(); + mContext = context; + mNotesCount = 0; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + return new NotesListItem(context); + } + + @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())); + } + } + + public void setCheckedItem(final int position, final boolean checked) { + mSelectedIndex.put(position, checked); + notifyDataSetChanged(); + } + + public boolean isInChoiceMode() { + return mChoiceMode; + } + + public void setChoiceMode(boolean mode) { + mSelectedIndex.clear(); + mChoiceMode = mode; + } + + 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); + } + } + } + } + + 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; + } + + 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); + /** + * Don't close cursor here, only the adapter could close it + */ + } else { + Log.e(TAG, "Invalid cursor"); + return null; + } + } + } + return itemSet; + } + + 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; + } + + public boolean isAllSelected() { + int checkedCount = getSelectedCount(); + return (checkedCount != 0 && checkedCount == mNotesCount); + } + + public boolean isSelectedItem(final int position) { + if (null == mSelectedIndex.get(position)) { + return false; + } + return mSelectedIndex.get(position); + } + + @Override + protected void onContentChanged() { + super.onContentChanged(); + calcNotesCount(); + } + + @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; + } + } + } + + public int retCount() { + int NotesCount = mNotesCount; + int ItemCount = getCount(); + for (int i = 0; i < ItemCount; i++) { + Cursor c = (Cursor) getItem(i); + if (c != null) { + if (NoteItemData.getNoteType(c) == Notes.TYPE_NOTE) { + NoteItemData NoteItem = new NoteItemData(mContext, c); + NotesCount += NoteItem.getNotesCount(); + } + } else { + Log.e(TAG, "Invalid cursor"); + return -1; + } + } + return NotesCount; + } +} + diff --git a/doc/邹兴云注释的代码/NoteWidgetProvider.java b/doc/邹兴云注释的代码/NoteWidgetProvider.java index 5c7f03a..f4070e9 100644 --- a/doc/邹兴云注释的代码/NoteWidgetProvider.java +++ b/doc/邹兴云注释的代码/NoteWidgetProvider.java @@ -65,16 +65,19 @@ public abstract class NoteWidgetProvider extends AppWidgetProvider { 具体地,使用 getContentResolver() 获取一个 ContentResolver 对象,调用 update() 方法对笔记数据库中的记录进行更新。更新的条件为 NoteColumns.WIDGET_ID + "=?",即 NoteColumns.WIDGET_ID 等于当前小部件 ID,更新的数据为 values 对象,其中 NoteColumns.WIDGET_ID 的值已经被设置为 AppWidgetManager.INVALID_APPWIDGET_ID。*/ - private Cursor getNoteWidgetInfo(Context context, int widgetId) {// 使用 getContentResolver() 方法获取 ContentResolver 对象,通过该对象进行对笔记数据库的查询操作 - return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, // 使用 query() 方法查询笔记数据库,返回一个 Cursor 对象 - return context.getContentResolver().query(// 查询的 URI,笔记数据库中笔记的内容保存在该 URI 下 + private Cursor getNoteWidgetInfo(Context context, int widgetId) { + return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, PROJECTION, - Notes.CONTENT_NOTE_URI, - PROJECTION, - NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?",// 查询的列,即笔记 ID、笔记背景颜色 ID 和笔记摘录内容 - new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) },//查询的条件,即笔记关联的小部件 ID 以及笔记的父 ID 不为回收站的笔记 - null);// 排序方式,这里为 null 表示不排序 - } + NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, + null); + }/*该方法使用上下文对象获取ContentResolver,用于查询内容提供程序以获取有关笔记小部件的信息。查询在Notes.CONTENT_NOTE_URI上执行,这是表示内容提供程序中笔记表的URI。 + +PROJECTION是一个字符串数组,指定要从表中检索的列。NoteColumns.WIDGET_ID和NoteColumns.PARENT_ID是要检索的两列。NoteColumns.WIDGET_ID是包含与笔记相关联的小部件的ID的列,NoteColumns.PARENT_ID是包含笔记的父文件夹的ID的列。 + +查询还包括一个选择参数,根据小部件ID和垃圾箱文件夹的ID过滤结果。选择参数使用“?”占位符语法构造,并将占位符的实际值作为字符串数组传递到selectionArgs参数中。sortOrder参数的null值表示应以默认顺序返回结果。 + +该方法返回一个Cursor对象,表示查询结果。Cursor可用于遍历结果集的行,并检索每行的列的值。*/ protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { update(context, appWidgetManager, appWidgetIds, false); diff --git a/src/app/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/app/src/main/java/net/micode/notes/ui/NotesListActivity.java index 0052618..b1e8330 100644 --- a/src/app/src/main/java/net/micode/notes/ui/NotesListActivity.java +++ b/src/app/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -93,7 +93,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private enum ListEditState { NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER - } + }; private ListEditState mState; @@ -797,6 +797,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt case R.id.menu_export_text: { exportNoteToText(); break; + } case R.id.menu_sync: { if (isSyncMode()) { @@ -818,6 +819,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt createNewNote(); break; } + case R.id.menu_countallNotes: { + showNumberofNotes(); + break; + } case R.id.menu_search: onSearchRequested(); break; @@ -970,4 +975,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt mTitleBar.setText("回收站"); mTitleBar.setVisibility(View.VISIBLE); } + + private void showNumberofNotes() { + AlertDialog.Builder btr = new AlertDialog.Builder(this); + btr.setTitle("目前便签数"); + btr.setMessage("目前有 " + Integer.toString(mNotesListAdapter.retCount()) + "个便签"); + btr.show(); + } } diff --git a/src/app/src/main/res/menu/note_list.xml b/src/app/src/main/res/menu/note_list.xml index 56443cc..7113951 100644 --- a/src/app/src/main/res/menu/note_list.xml +++ b/src/app/src/main/res/menu/note_list.xml @@ -19,23 +19,28 @@ xmlns:android="http://schemas.android.com/apk/res/android"> + android:title="@string/menu_create_folder"/> + android:title="@string/menu_export_text"/> + android:title="@string/menu_sync"/> + android:title="@string/menu_setting" /> + android:title="@string/menu_search"/> + + + diff --git a/src/app/src/main/res/values/strings.xml b/src/app/src/main/res/values/strings.xml index d88549e..a122299 100644 --- a/src/app/src/main/res/values/strings.xml +++ b/src/app/src/main/res/values/strings.xml @@ -119,6 +119,7 @@ Delete Call notes Input name + countallNotes" Searching Notes Search notes