summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/data/CameraDataAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/camera/data/CameraDataAdapter.java')
-rw-r--r--src/com/android/camera/data/CameraDataAdapter.java348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
new file mode 100644
index 000000000..3605f7190
--- /dev/null
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 com.android.camera.data;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.View;
+
+import com.android.camera.Storage;
+import com.android.camera.ui.FilmStripView.ImageData;
+import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * A {@link LocalDataAdapter} that provides data in the camera folder.
+ */
+public class CameraDataAdapter implements LocalDataAdapter {
+ private static final String TAG = CameraDataAdapter.class.getSimpleName();
+
+ private static final int DEFAULT_DECODE_SIZE = 3000;
+ private static final String[] CAMERA_PATH = { Storage.DIRECTORY + "%" };
+
+ private List<LocalData> mImages;
+
+ private Listener mListener;
+ private Drawable mPlaceHolder;
+
+ private int mSuggestedWidth = DEFAULT_DECODE_SIZE;
+ private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
+
+ private LocalData mLocalDataToDelete;
+
+ public CameraDataAdapter(Drawable placeHolder) {
+ mPlaceHolder = placeHolder;
+ }
+
+ @Override
+ public void requestLoad(ContentResolver resolver) {
+ QueryTask qtask = new QueryTask();
+ qtask.execute(resolver);
+ }
+
+ @Override
+ public int getTotalNumber() {
+ if (mImages == null) {
+ return 0;
+ }
+ return mImages.size();
+ }
+
+ @Override
+ public ImageData getImageData(int id) {
+ return getData(id);
+ }
+
+ @Override
+ public void suggestViewSizeBound(int w, int h) {
+ if (w <= 0 || h <= 0) {
+ mSuggestedWidth = mSuggestedHeight = DEFAULT_DECODE_SIZE;
+ } else {
+ mSuggestedWidth = (w < DEFAULT_DECODE_SIZE ? w : DEFAULT_DECODE_SIZE);
+ mSuggestedHeight = (h < DEFAULT_DECODE_SIZE ? h : DEFAULT_DECODE_SIZE);
+ }
+ }
+
+ @Override
+ public View getView(Context c, int dataID) {
+ if (mImages == null) {
+ return null;
+ }
+ if (dataID >= mImages.size() || dataID < 0) {
+ return null;
+ }
+
+ return mImages.get(dataID).getView(
+ c, mSuggestedWidth, mSuggestedHeight,
+ mPlaceHolder.getConstantState().newDrawable());
+ }
+
+ @Override
+ public void setListener(Listener listener) {
+ mListener = listener;
+ if (mImages != null) {
+ mListener.onDataLoaded();
+ }
+ }
+
+ @Override
+ public void onDataFullScreen(int dataID, boolean fullScreen) {
+ if (dataID < mImages.size() && dataID >= 0) {
+ mImages.get(dataID).onFullScreen(fullScreen);
+ }
+ }
+
+ @Override
+ public void onDataCentered(int dataID, boolean centered) {
+ // do nothing.
+ }
+
+ @Override
+ public boolean canSwipeInFullScreen(int dataID) {
+ if (dataID < mImages.size() && dataID > 0) {
+ return mImages.get(dataID).canSwipeInFullScreen();
+ }
+ return true;
+ }
+
+ @Override
+ public void removeData(Context c, int dataID) {
+ if (dataID >= mImages.size()) return;
+ LocalData d = mImages.remove(dataID);
+ // Delete previously removed data first.
+ executeDeletion(c);
+ mLocalDataToDelete = d;
+ mListener.onDataRemoved(dataID, d);
+ }
+
+ private void insertData(LocalData data) {
+ if (mImages == null) {
+ mImages = new ArrayList<LocalData>();
+ }
+
+ // Since this function is mostly for adding the newest data,
+ // a simple linear search should yield the best performance over a
+ // binary search.
+ int pos = 0;
+ Comparator<LocalData> comp = new LocalData.NewestFirstComparator();
+ for (; pos < mImages.size()
+ && comp.compare(data, mImages.get(pos)) > 0; pos++);
+ mImages.add(pos, data);
+ if (mListener != null) {
+ mListener.onDataInserted(pos, data);
+ }
+ }
+
+ @Override
+ public void addNewVideo(ContentResolver cr, Uri uri) {
+ Cursor c = cr.query(uri,
+ LocalData.Video.QUERY_PROJECTION,
+ MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
+ LocalData.Video.QUERY_ORDER);
+ if (c != null && c.moveToFirst()) {
+ insertData(LocalData.Video.buildFromCursor(c));
+ }
+ }
+
+ @Override
+ public void addNewPhoto(ContentResolver cr, Uri uri) {
+ Cursor c = cr.query(uri,
+ LocalData.Photo.QUERY_PROJECTION,
+ MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
+ LocalData.Photo.QUERY_ORDER);
+ if (c != null && c.moveToFirst()) {
+ insertData(LocalData.Photo.buildFromCursor(c));
+ }
+ }
+
+ @Override
+ public int findDataByContentUri(Uri uri) {
+ // TODO: find the data.
+ return -1;
+ }
+
+ @Override
+ public boolean undoDataRemoval() {
+ if (mLocalDataToDelete == null) return false;
+ LocalData d = mLocalDataToDelete;
+ mLocalDataToDelete = null;
+ insertData(d);
+ return true;
+ }
+
+ @Override
+ public boolean executeDeletion(Context c) {
+ if (mLocalDataToDelete == null) return false;
+
+ DeletionTask task = new DeletionTask(c);
+ task.execute(mLocalDataToDelete);
+ mLocalDataToDelete = null;
+ return true;
+ }
+
+ @Override
+ public void flush() {
+ replaceData(null);
+ }
+
+ private LocalData getData(int id) {
+ if (mImages == null || id >= mImages.size() || id < 0) {
+ return null;
+ }
+ return mImages.get(id);
+ }
+
+ // Update all the data but keep the camera data if already set.
+ private void replaceData(List<LocalData> list) {
+ boolean changed = (list != mImages);
+ LocalData cameraData = null;
+ if (mImages != null && mImages.size() > 0) {
+ cameraData = mImages.get(0);
+ if (cameraData.getType() != ImageData.TYPE_CAMERA_PREVIEW) {
+ cameraData = null;
+ }
+ }
+
+ mImages = list;
+ if (cameraData != null) {
+ // camera view exists, so we make sure at least 1 data is in the list.
+ if (mImages == null) {
+ mImages = new ArrayList<LocalData>();
+ }
+ mImages.add(0, cameraData);
+ if (mListener != null) {
+ // Only the camera data is not changed, everything else is changed.
+ mListener.onDataUpdated(new UpdateReporter() {
+ @Override
+ public boolean isDataRemoved(int id) {
+ return false;
+ }
+
+ @Override
+ public boolean isDataUpdated(int id) {
+ if (id == 0) return false;
+ return true;
+ }
+ });
+ }
+ } else {
+ // both might be null.
+ if (changed) {
+ mListener.onDataLoaded();
+ }
+ }
+ }
+
+ private class QueryTask extends AsyncTask<ContentResolver, Void, List<LocalData>> {
+ @Override
+ protected List<LocalData> doInBackground(ContentResolver... resolver) {
+ List<LocalData> l = new ArrayList<LocalData>();
+ // Photos
+ Cursor c = resolver[0].query(
+ LocalData.Photo.CONTENT_URI,
+ LocalData.Photo.QUERY_PROJECTION,
+ MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH,
+ LocalData.Photo.QUERY_ORDER);
+ if (c != null && c.moveToFirst()) {
+ // build up the list.
+ while (true) {
+ LocalData data = LocalData.Photo.buildFromCursor(c);
+ if (data != null) {
+ l.add(data);
+ } else {
+ Log.e(TAG, "Error loading data:"
+ + c.getString(LocalData.Photo.COL_DATA));
+ }
+ if (c.isLast()) {
+ break;
+ }
+ c.moveToNext();
+ }
+ }
+ if (c != null) {
+ c.close();
+ }
+
+ c = resolver[0].query(
+ LocalData.Video.CONTENT_URI,
+ LocalData.Video.QUERY_PROJECTION,
+ MediaStore.Video.Media.DATA + " like ? ", CAMERA_PATH,
+ LocalData.Video.QUERY_ORDER);
+ if (c != null && c.moveToFirst()) {
+ // build up the list.
+ c.moveToFirst();
+ while (true) {
+ LocalData data = LocalData.Video.buildFromCursor(c);
+ if (data != null) {
+ l.add(data);
+ } else {
+ Log.e(TAG, "Error loading data:"
+ + c.getString(LocalData.Video.COL_DATA));
+ }
+ if (!c.isLast()) {
+ c.moveToNext();
+ } else {
+ break;
+ }
+ }
+ }
+ if (c != null) {
+ c.close();
+ }
+
+ if (l.size() == 0) return null;
+
+ Collections.sort(l, new LocalData.NewestFirstComparator());
+ return l;
+ }
+
+ @Override
+ protected void onPostExecute(List<LocalData> l) {
+ replaceData(l);
+ }
+ }
+
+ private class DeletionTask extends AsyncTask<LocalData, Void, Void> {
+ Context mContext;
+
+ DeletionTask(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ protected Void doInBackground(LocalData... data) {
+ for (int i = 0; i < data.length; i++) {
+ if (!data[i].isDataActionSupported(LocalData.ACTION_DELETE)) {
+ Log.v(TAG, "Deletion is not supported:" + data[i]);
+ continue;
+ }
+ data[i].delete(mContext);
+ }
+ return null;
+ }
+ }
+}