|
|
@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
package net.micode.notes.ui;
|
|
|
|
|
|
|
|
import static android.widget.Toast.LENGTH_SHORT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
|
|
|
import android.app.AlertDialog;
|
|
|
|
|
|
|
|
import android.content.AsyncQueryHandler;
|
|
|
|
|
|
|
|
import android.content.ContentResolver;
|
|
|
|
|
|
|
|
import android.database.Cursor;
|
|
|
|
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
|
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
|
|
|
|
|
|
|
import android.graphics.drawable.Drawable;
|
|
|
|
|
|
|
|
import android.os.Bundle;
|
|
|
|
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
|
|
|
import android.view.Menu;
|
|
|
|
|
|
|
|
import android.view.MenuItem;
|
|
|
|
|
|
|
|
import android.view.View;
|
|
|
|
|
|
|
|
import android.widget.AdapterView;
|
|
|
|
|
|
|
|
import android.widget.AdapterView.OnItemClickListener;
|
|
|
|
|
|
|
|
import android.widget.ListView;
|
|
|
|
|
|
|
|
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.tool.DataUtils;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class TrashFolderActivity extends Activity {
|
|
|
|
|
|
|
|
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private BackgroundQueryHandler mBackgroundQueryHandler;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private NotesListAdapter mNotesListAdapter;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private ListView mNotesListView;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private long mCurrentFolderId;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private ContentResolver mContentResolver;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String TAG = "RecycleActivity";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private MenuItem menuItem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
|
|
setContentView(R.layout.recycle_bin);
|
|
|
|
|
|
|
|
initResources();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 查询背景状态,初始化页面背景,与背景切换功能中相同
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 切换自定义背景,与背景切换功能中相同
|
|
|
|
|
|
|
|
* @param path 图片地址
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void bitmapBg(String path){
|
|
|
|
|
|
|
|
Bitmap bm;
|
|
|
|
|
|
|
|
try{
|
|
|
|
|
|
|
|
File file=new File(path);
|
|
|
|
|
|
|
|
if (file.exists()){//bitmap转换图片
|
|
|
|
|
|
|
|
bm = BitmapFactory.decodeFile(path);
|
|
|
|
|
|
|
|
Drawable drawable = new BitmapDrawable(bm);
|
|
|
|
|
|
|
|
getWindow().setBackgroundDrawable(drawable);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}catch (Exception e){//抛出异常
|
|
|
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
|
|
|
Toast.makeText(this, "自定义背景切换失败", LENGTH_SHORT).show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onStart() {
|
|
|
|
|
|
|
|
super.onStart();
|
|
|
|
|
|
|
|
startAsyncNotesListQuery();//启动查询
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 初始化各种资源的函数
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@SuppressLint({"InflateParams", "WorldReadableFiles"})
|
|
|
|
|
|
|
|
private void initResources() {
|
|
|
|
|
|
|
|
mContentResolver = this.getContentResolver();
|
|
|
|
|
|
|
|
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
|
|
|
|
|
|
|
|
mCurrentFolderId = Notes.ID_TRASH_FOLER;
|
|
|
|
|
|
|
|
mNotesListView = findViewById(R.id.recycle_bin);
|
|
|
|
|
|
|
|
mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
|
|
|
|
|
|
|
|
null, false);
|
|
|
|
|
|
|
|
mNotesListView.setOnItemClickListener(new OnListItemClickListener());
|
|
|
|
|
|
|
|
mNotesListAdapter = new NotesListAdapter(this);
|
|
|
|
|
|
|
|
mNotesListAdapter.setChoiceMode(true);
|
|
|
|
|
|
|
|
mNotesListView.setAdapter(mNotesListAdapter);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 查询回收站便签列表,与NoteListActivity中相似
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void startAsyncNotesListQuery() {
|
|
|
|
|
|
|
|
//查询便签列表,与NoteListActivity类似
|
|
|
|
|
|
|
|
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
|
|
|
|
|
|
|
|
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, NORMAL_SELECTION, new String[]{
|
|
|
|
|
|
|
|
String.valueOf(mCurrentFolderId)
|
|
|
|
|
|
|
|
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SuppressLint("HandlerLeak")
|
|
|
|
|
|
|
|
private final class BackgroundQueryHandler extends AsyncQueryHandler {
|
|
|
|
|
|
|
|
public BackgroundQueryHandler(ContentResolver contentResolver) {
|
|
|
|
|
|
|
|
super(contentResolver);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
|
|
|
|
|
|
|
|
if (token == FOLDER_NOTE_LIST_QUERY_TOKEN) {
|
|
|
|
|
|
|
|
mNotesListAdapter.changeCursor(cursor);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public void onBackPressed() {
|
|
|
|
|
|
|
|
super.onBackPressed();
|
|
|
|
|
|
|
|
finish();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 顶部菜单生成,生成顶部的全选 还原 删除 按钮
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
|
|
|
|
|
|
//重置菜单
|
|
|
|
|
|
|
|
menu.clear();
|
|
|
|
|
|
|
|
//从自定义xml中获取样式
|
|
|
|
|
|
|
|
getMenuInflater().inflate(R.menu.recyclebin_options, menu);
|
|
|
|
|
|
|
|
//绑定全选按钮
|
|
|
|
|
|
|
|
menuItem = menu.findItem(R.id.select_all);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 删除所选便签的方法,直接永久删除便签,并调用弹窗供用户进行确认
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private void batchDelete() {
|
|
|
|
|
|
|
|
//如果没有选中任何便签
|
|
|
|
|
|
|
|
if (mNotesListAdapter.getSelectedCount() == 0) {
|
|
|
|
|
|
|
|
Log.e(TAG, "Send to desktop error");
|
|
|
|
|
|
|
|
//小弹窗提醒
|
|
|
|
|
|
|
|
Toast.makeText(this, R.string.error_delete_or_recover, LENGTH_SHORT).show();
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 构建确认弹窗
|
|
|
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
|
|
|
//设置弹窗标题
|
|
|
|
|
|
|
|
builder.setTitle(getString(R.string.alert_title_delete));
|
|
|
|
|
|
|
|
//设置弹窗图标
|
|
|
|
|
|
|
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
|
|
|
|
|
|
//设置弹窗消息
|
|
|
|
|
|
|
|
builder.setMessage(getString(R.string.alert_message_realdelete));
|
|
|
|
|
|
|
|
//设置积极选项
|
|
|
|
|
|
|
|
builder.setPositiveButton(android.R.string.ok,
|
|
|
|
|
|
|
|
(dialog, which) -> {//点击确认选项后的事件
|
|
|
|
|
|
|
|
if (!DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
|
|
|
|
|
|
|
|
.getSelectedItemIds())) {
|
|
|
|
|
|
|
|
Log.e(TAG, "Delete notes error, should not happens");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//重置所有便签的选择状态
|
|
|
|
|
|
|
|
mNotesListAdapter.selectAll(false);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
//设置消极选项
|
|
|
|
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
|
|
|
|
//弹出弹窗
|
|
|
|
|
|
|
|
builder.show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 还原所选中便签的方法,原理为将便签移出trash文件夹到根文件夹,构建弹窗供用户确认
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void recover() {
|
|
|
|
|
|
|
|
//如果没有选中任何便签
|
|
|
|
|
|
|
|
if (mNotesListAdapter.getSelectedCount() == 0) {
|
|
|
|
|
|
|
|
Log.e(TAG, "Send to desktop error");
|
|
|
|
|
|
|
|
//小弹窗提醒
|
|
|
|
|
|
|
|
Toast.makeText(this, R.string.error_delete_or_recover, LENGTH_SHORT).show();
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//构建弹窗
|
|
|
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
|
|
|
//设置弹窗标题
|
|
|
|
|
|
|
|
builder.setTitle(getString(R.string.recover));
|
|
|
|
|
|
|
|
//设置弹窗图标
|
|
|
|
|
|
|
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
|
|
|
|
|
|
//设置弹窗内消息
|
|
|
|
|
|
|
|
builder.setMessage(getString(R.string.alert_message_recover));
|
|
|
|
|
|
|
|
//设置积极选项
|
|
|
|
|
|
|
|
builder.setPositiveButton(android.R.string.ok,
|
|
|
|
|
|
|
|
(dialog, which) -> {//确认后执行的方法
|
|
|
|
|
|
|
|
if (mNotesListAdapter.getSelectedCount() != 0) {
|
|
|
|
|
|
|
|
//移动所选便签至根文件夹
|
|
|
|
|
|
|
|
DataUtils.batchMoveToFolder(mContentResolver,
|
|
|
|
|
|
|
|
mNotesListAdapter.getSelectedItemIds(), Notes.ID_ROOT_FOLDER);
|
|
|
|
|
|
|
|
//重置所有便签的选择状态
|
|
|
|
|
|
|
|
mNotesListAdapter.selectAll(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else//空选便签时执行
|
|
|
|
|
|
|
|
Log.e(TAG, "Recover error, no note was selected");
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
//设置消极选项
|
|
|
|
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
|
|
|
|
//显示弹窗
|
|
|
|
|
|
|
|
builder.show();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 当顶部菜单中的选项被选择时所执行的函数
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (item.getItemId() == R.id.recover) {//还原选项
|
|
|
|
|
|
|
|
//还原便签
|
|
|
|
|
|
|
|
recover();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (item.getItemId() == R.id.realdelete) {//删除选项
|
|
|
|
|
|
|
|
//删除便签
|
|
|
|
|
|
|
|
batchDelete();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (item.getItemId() == R.id.select_all) {//全选选项
|
|
|
|
|
|
|
|
//全选按钮状态切换
|
|
|
|
|
|
|
|
if (!mNotesListAdapter.isAllSelected()) {//若便签没有被全选的情况下点击全选按钮
|
|
|
|
|
|
|
|
//切换取消全选图标
|
|
|
|
|
|
|
|
item.setIcon(getResources().getDrawable(R.drawable.deselect_all));
|
|
|
|
|
|
|
|
//选择所有便签
|
|
|
|
|
|
|
|
mNotesListAdapter.selectAll(true);
|
|
|
|
|
|
|
|
} else {//如果便签已经被全选
|
|
|
|
|
|
|
|
//切换全选图标
|
|
|
|
|
|
|
|
item.setIcon(getResources().getDrawable(R.drawable.select_all));
|
|
|
|
|
|
|
|
//取消全选所有便签
|
|
|
|
|
|
|
|
mNotesListAdapter.selectAll(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* 点击便签事件监听器,当点击任意便签项时触发
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
private class OnListItemClickListener implements OnItemClickListener {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
|
|
|
|
|
|
//当点击的是便签项时
|
|
|
|
|
|
|
|
if (view instanceof NotesListItem) {
|
|
|
|
|
|
|
|
//从视图获取便签项
|
|
|
|
|
|
|
|
NoteItemData item = ((NotesListItem) view).getItemData();
|
|
|
|
|
|
|
|
//判断是不是便签,防止点击到文件夹的情况,与上一句一样基本上没用
|
|
|
|
|
|
|
|
if (item.getType() == Notes.TYPE_NOTE) {
|
|
|
|
|
|
|
|
//定位
|
|
|
|
|
|
|
|
position = position - mNotesListView.getHeaderViewsCount();
|
|
|
|
|
|
|
|
//改变单个便签的被选择状态
|
|
|
|
|
|
|
|
mNotesListAdapter.setCheckedItem(position, !mNotesListAdapter.isSelectedItem(position));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//用于判断是否手动全选了便签
|
|
|
|
|
|
|
|
if (mNotesListAdapter.isAllSelected())
|
|
|
|
|
|
|
|
//切换取消全选图标
|
|
|
|
|
|
|
|
menuItem.setIcon(getResources().getDrawable(R.drawable.deselect_all));
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
//切换全选图标
|
|
|
|
|
|
|
|
menuItem.setIcon(getResources().getDrawable(R.drawable.select_all));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|