2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.settings.deviceinfo;
19 import android.app.Activity;
20 import android.app.ListActivity;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.os.storage.StorageVolume;
24 import android.text.format.Formatter;
25 import android.util.Log;
26 import android.util.SparseBooleanArray;
27 import android.view.ActionMode;
28 import android.view.LayoutInflater;
29 import android.view.Menu;
30 import android.view.MenuInflater;
31 import android.view.MenuItem;
32 import android.view.View;
33 import android.view.View.OnClickListener;
34 import android.view.View.OnLongClickListener;
35 import android.view.ViewGroup;
36 import android.widget.BaseAdapter;
37 import android.widget.CompoundButton;
38 import android.widget.CompoundButton.OnCheckedChangeListener;
39 import android.widget.ListView;
41 import com.android.settings.R;
42 import com.android.settings.deviceinfo.StorageMeasurement.FileInfo;
45 import java.util.ArrayList;
46 import java.util.List;
49 * This class handles the selection and removal of Misc files.
51 public class MiscFilesHandler extends ListActivity {
52 private static final String TAG = "MemorySettings";
53 private String mNumSelectedFormat;
54 private String mNumBytesSelectedFormat;
55 private MemoryMearurementAdapter mAdapter;
56 private LayoutInflater mInflater;
59 public void onCreate(Bundle savedInstanceState) {
60 super.onCreate(savedInstanceState);
61 setFinishOnTouchOutside(true);
62 setTitle(R.string.misc_files);
63 mNumSelectedFormat = getString(R.string.misc_files_selected_count);
64 mNumBytesSelectedFormat = getString(R.string.misc_files_selected_count_bytes);
65 mAdapter = new MemoryMearurementAdapter(this);
66 mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
67 setContentView(R.layout.settings_storage_miscfiles_list);
68 ListView lv = getListView();
69 lv.setItemsCanFocus(true);
70 lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
71 lv.setMultiChoiceModeListener(new ModeCallback(this));
72 setListAdapter(mAdapter);
75 private class ModeCallback implements ListView.MultiChoiceModeListener {
76 private int mDataCount;
77 private final Context mContext;
79 public ModeCallback(Context context) {
81 mDataCount = mAdapter.getCount();
84 public boolean onCreateActionMode(ActionMode mode, Menu menu) {
85 final MenuInflater inflater = getMenuInflater();
86 inflater.inflate(R.menu.misc_files_menu, menu);
90 public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
94 public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
95 ListView lv = getListView();
96 switch (item.getItemId()) {
97 case R.id.action_delete:
98 // delete the files selected
99 SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
100 int checkedCount = getListView().getCheckedItemCount();
101 if (checkedCount > mDataCount) {
102 throw new IllegalStateException("checked item counts do not match. " +
103 "checkedCount: " + checkedCount + ", dataSize: " + mDataCount);
105 if (mDataCount > 0) {
106 ArrayList<Object> toRemove = new ArrayList<Object>();
107 for (int i = 0; i < mDataCount; i++) {
108 if (!checkedItems.get(i)) {
112 if (StorageMeasurement.LOGV) {
113 Log.i(TAG, "deleting: " + mAdapter.getItem(i));
116 File file = new File(mAdapter.getItem(i).mFileName);
117 if (file.isDirectory()) {
122 toRemove.add(mAdapter.getItem(i));
124 mAdapter.removeAll(toRemove);
125 mAdapter.notifyDataSetChanged();
126 mDataCount = mAdapter.getCount();
131 case R.id.action_select_all:
133 for (int i = 0; i < mDataCount; i++) {
134 lv.setItemChecked(i, true);
136 // update the title and subtitle with number selected and numberBytes selected
137 onItemCheckedStateChanged(mode, 1, 0, true);
143 // Deletes all files and subdirectories under given dir.
144 // Returns true if all deletions were successful.
145 // If a deletion fails, the method stops attempting to delete and returns false.
146 private boolean deleteDir(File dir) {
147 if (dir.isDirectory()) {
148 String[] children = dir.list();
149 for (int i=0; i < children.length; i++) {
150 boolean success = deleteDir(new File(dir, children[i]));
156 // The directory is now empty so delete it
160 public void onDestroyActionMode(ActionMode mode) {
161 // This block intentionally left blank
164 public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
166 ListView lv = getListView();
167 int numChecked = lv.getCheckedItemCount();
168 mode.setTitle(String.format(mNumSelectedFormat, numChecked, mAdapter.getCount()));
170 // total the sizes of all items selected so far
171 SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
172 long selectedDataSize = 0;
173 if (numChecked > 0) {
174 for (int i = 0; i < mDataCount; i++) {
175 if (checkedItems.get(i)) {
177 selectedDataSize += mAdapter.getItem(i).mSize;
181 mode.setSubtitle(String.format(mNumBytesSelectedFormat,
182 Formatter.formatFileSize(mContext, selectedDataSize),
183 Formatter.formatFileSize(mContext, mAdapter.getDataSize())));
187 class MemoryMearurementAdapter extends BaseAdapter {
188 private ArrayList<StorageMeasurement.FileInfo> mData = null;
189 private long mDataSize = 0;
190 private Context mContext;
192 public MemoryMearurementAdapter(Activity activity) {
194 final StorageVolume storageVolume = activity.getIntent().getParcelableExtra(
195 StorageVolume.EXTRA_STORAGE_VOLUME);
196 StorageMeasurement mMeasurement =
197 StorageMeasurement.getInstance(activity, storageVolume, false /*Unused as a key*/);
198 if (mMeasurement == null) return;
199 mData = (ArrayList<StorageMeasurement.FileInfo>) mMeasurement.mFileInfoForMisc;
201 for (StorageMeasurement.FileInfo info : mData) {
202 mDataSize += info.mSize;
208 public int getCount() {
209 return (mData == null) ? 0 : mData.size();
213 public StorageMeasurement.FileInfo getItem(int position) {
214 if (mData == null || mData.size() <= position) {
217 return mData.get(position);
221 public long getItemId(int position) {
222 if (mData == null || mData.size() <= position) {
225 return mData.get(position).mId;
228 public void removeAll(List<Object> objs) {
232 for (Object o : objs) {
234 mDataSize -= ((StorageMeasurement.FileInfo) o).mSize;
238 public long getDataSize() {
243 public void notifyDataSetChanged() {
244 super.notifyDataSetChanged();
248 public View getView(int position, View convertView, ViewGroup parent) {
249 final FileItemInfoLayout view = (convertView == null) ?
250 (FileItemInfoLayout) mInflater.inflate(R.layout.settings_storage_miscfiles,
251 parent, false) : (FileItemInfoLayout) convertView;
252 FileInfo item = getItem(position);
253 view.setFileName(item.mFileName);
254 view.setFileSize(Formatter.formatFileSize(mContext, item.mSize));
255 final ListView listView = (ListView) parent;
256 final int listPosition = position;
257 view.getCheckBox().setOnCheckedChangeListener(new OnCheckedChangeListener() {
260 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
261 listView.setItemChecked(listPosition, isChecked);
265 view.setOnLongClickListener(new OnLongClickListener() {
267 public boolean onLongClick(View v) {
268 if (listView.getCheckedItemCount() > 0) {
271 listView.setItemChecked(listPosition, !view.isChecked());
275 view.setOnClickListener(new OnClickListener() {
277 public void onClick(View v) {
278 if (listView.getCheckedItemCount() > 0) {
279 listView.setItemChecked(listPosition, !view.isChecked());