1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package com.android.documentsui.selection; 18 19 import static com.android.documentsui.base.DocumentInfo.getCursorInt; 20 import static com.android.documentsui.base.DocumentInfo.getCursorString; 21 22 import android.content.Context; 23 import android.content.pm.PackageManager; 24 import android.content.pm.ProviderInfo; 25 import android.database.Cursor; 26 import android.provider.DocumentsContract.Document; 27 import android.util.Log; 28 29 import com.android.documentsui.MenuManager; 30 import com.android.documentsui.archives.ArchivesProvider; 31 import com.android.documentsui.base.MimeTypes; 32 import com.android.documentsui.roots.RootCursorWrapper; 33 34 import java.util.function.Function; 35 36 /** 37 * A class that holds metadata 38 */ 39 public class SelectionMetadata 40 implements MenuManager.SelectionDetails, SelectionManager.ItemCallback { 41 42 private static final String TAG = "SelectionMetadata"; 43 44 private final Function<String, Cursor> mDocFinder; 45 46 private int mDirectoryCount = 0; 47 private int mFileCount = 0; 48 49 // Partial files are files that haven't been fully downloaded. 50 private int mPartialCount = 0; 51 private int mWritableDirectoryCount = 0; 52 private int mNoDeleteCount = 0; 53 private int mNoRenameCount = 0; 54 private int mInArchiveCount = 0; 55 private boolean mSupportsSettings = false; 56 SelectionMetadata(Function<String, Cursor> docFinder)57 public SelectionMetadata(Function<String, Cursor> docFinder) { 58 mDocFinder = docFinder; 59 } 60 61 @Override onItemStateChanged(String modelId, boolean selected)62 public void onItemStateChanged(String modelId, boolean selected) { 63 final Cursor cursor = mDocFinder.apply(modelId); 64 if (cursor == null) { 65 Log.w(TAG, "Model returned null cursor for document: " + modelId 66 + ". Ignoring state changed event."); 67 return; 68 } 69 70 final int delta = selected ? 1 : -1; 71 72 final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); 73 if (MimeTypes.isDirectoryType(mimeType)) { 74 mDirectoryCount += delta; 75 } else { 76 mFileCount += delta; 77 } 78 79 final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); 80 if ((docFlags & Document.FLAG_PARTIAL) != 0) { 81 mPartialCount += delta; 82 } 83 if ((docFlags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0) { 84 mWritableDirectoryCount += delta; 85 } 86 if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) { 87 mNoDeleteCount += delta; 88 } 89 if ((docFlags & Document.FLAG_SUPPORTS_RENAME) == 0) { 90 mNoRenameCount += delta; 91 } 92 if ((docFlags & Document.FLAG_PARTIAL) != 0) { 93 mPartialCount += delta; 94 } 95 mSupportsSettings = (docFlags & Document.FLAG_SUPPORTS_SETTINGS) != 0 && 96 (mFileCount + mDirectoryCount) == 1; 97 98 99 final String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); 100 if (ArchivesProvider.AUTHORITY.equals(authority)) { 101 mInArchiveCount += delta; 102 } 103 } 104 105 @Override onSelectionReset()106 public void onSelectionReset() { 107 mFileCount = 0; 108 mDirectoryCount = 0; 109 mPartialCount = 0; 110 mWritableDirectoryCount = 0; 111 mNoDeleteCount = 0; 112 mNoRenameCount = 0; 113 } 114 115 @Override containsDirectories()116 public boolean containsDirectories() { 117 return mDirectoryCount > 0; 118 } 119 120 @Override containsFiles()121 public boolean containsFiles() { 122 return mFileCount > 0; 123 } 124 125 @Override size()126 public int size() { 127 return mDirectoryCount + mFileCount; 128 } 129 130 @Override containsPartialFiles()131 public boolean containsPartialFiles() { 132 return mPartialCount > 0; 133 } 134 135 @Override canDelete()136 public boolean canDelete() { 137 return size() > 0 && mNoDeleteCount == 0; 138 } 139 140 @Override canExtract()141 public boolean canExtract() { 142 return size() > 0 && mInArchiveCount == size(); 143 } 144 145 @Override canRename()146 public boolean canRename() { 147 return mNoRenameCount == 0 && size() == 1; 148 } 149 150 @Override canViewInOwner()151 public boolean canViewInOwner() { 152 return mSupportsSettings; 153 } 154 155 @Override canPasteInto()156 public boolean canPasteInto() { 157 return mDirectoryCount == 1 && mWritableDirectoryCount == 1 && size() == 1; 158 } 159 160 @Override canOpenWith()161 public boolean canOpenWith() { 162 return size() == 1 && mDirectoryCount == 0 && mInArchiveCount == 0 && mPartialCount == 0; 163 } 164 } 165