184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan/* 284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * Copyright (C) 2016 The Android Open Source Project 384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * 484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * Licensed under the Apache License, Version 2.0 (the "License"); 584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * you may not use this file except in compliance with the License. 684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * You may obtain a copy of the License at 784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * 884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * http://www.apache.org/licenses/LICENSE-2.0 984bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * 1084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * Unless required by applicable law or agreed to in writing, software 1184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * distributed under the License is distributed on an "AS IS" BASIS, 1284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * See the License for the specific language governing permissions and 1484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * limitations under the License. 1584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan */ 1684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 174f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKaypackage com.android.documentsui.selection; 1884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 19d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport static com.android.documentsui.base.DocumentInfo.getCursorInt; 20d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport static com.android.documentsui.base.DocumentInfo.getCursorString; 2184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 22253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mannimport android.content.Context; 23253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mannimport android.content.pm.PackageManager; 24253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mannimport android.content.pm.ProviderInfo; 2584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tanimport android.database.Cursor; 2684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tanimport android.provider.DocumentsContract.Document; 2784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tanimport android.util.Log; 2884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 2984bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tanimport com.android.documentsui.MenuManager; 305a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewskiimport com.android.documentsui.archives.ArchivesProvider; 31d071895ec72bbb9414f6672ff808ec42b8e2d850Steve McKayimport com.android.documentsui.base.MimeTypes; 325a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewskiimport com.android.documentsui.roots.RootCursorWrapper; 3384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 3484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tanimport java.util.function.Function; 3584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 3684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan/** 3784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan * A class that holds metadata 3884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan */ 394f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKaypublic class SelectionMetadata 404f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay implements MenuManager.SelectionDetails, SelectionManager.ItemCallback { 4184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 4284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private static final String TAG = "SelectionMetadata"; 437f7ee10edaac1214e23f267a595014b510562d1eBen Lin private final static int FLAG_CAN_DELETE = 447f7ee10edaac1214e23f267a595014b510562d1eBen Lin Document.FLAG_SUPPORTS_REMOVE | Document.FLAG_SUPPORTS_DELETE; 4584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 4684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private final Function<String, Cursor> mDocFinder; 4784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 4806c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan private int mDirectoryCount = 0; 4906c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan private int mFileCount = 0; 5006c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan 5184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan // Partial files are files that haven't been fully downloaded. 5284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private int mPartialCount = 0; 5384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private int mWritableDirectoryCount = 0; 5484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private int mNoDeleteCount = 0; 5584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan private int mNoRenameCount = 0; 565a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski private int mInArchiveCount = 0; 57253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann private boolean mSupportsSettings = false; 5884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 594f78ba643270b9d84da1952d8e408220b25ec6fdSteve McKay public SelectionMetadata(Function<String, Cursor> docFinder) { 6084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan mDocFinder = docFinder; 6184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 6284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 6384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 6484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public void onItemStateChanged(String modelId, boolean selected) { 6584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan final Cursor cursor = mDocFinder.apply(modelId); 6684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan if (cursor == null) { 6784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan Log.w(TAG, "Model returned null cursor for document: " + modelId 6884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan + ". Ignoring state changed event."); 6984bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan return; 7084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 7184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 7206c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan final int delta = selected ? 1 : -1; 7306c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan 7484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan final String mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE); 75d071895ec72bbb9414f6672ff808ec42b8e2d850Steve McKay if (MimeTypes.isDirectoryType(mimeType)) { 7606c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mDirectoryCount += delta; 7706c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan } else { 7806c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mFileCount += delta; 7984bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 8084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 8184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); 8284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan if ((docFlags & Document.FLAG_PARTIAL) != 0) { 8306c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mPartialCount += delta; 8484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 8584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan if ((docFlags & Document.FLAG_DIR_SUPPORTS_CREATE) != 0) { 8606c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mWritableDirectoryCount += delta; 8784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 887f7ee10edaac1214e23f267a595014b510562d1eBen Lin if ((docFlags & FLAG_CAN_DELETE) == 0) { 8906c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mNoDeleteCount += delta; 9084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 9184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan if ((docFlags & Document.FLAG_SUPPORTS_RENAME) == 0) { 9206c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan mNoRenameCount += delta; 9384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 945a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski if ((docFlags & Document.FLAG_PARTIAL) != 0) { 955a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski mPartialCount += delta; 965a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski } 97253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann mSupportsSettings = (docFlags & Document.FLAG_SUPPORTS_SETTINGS) != 0 && 98253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann (mFileCount + mDirectoryCount) == 1; 99253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann 1005a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski 1015a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski final String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY); 1025a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski if (ArchivesProvider.AUTHORITY.equals(authority)) { 1035a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski mInArchiveCount += delta; 1045a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski } 10584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 10684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 10784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 108b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan public void onSelectionReset() { 109b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mFileCount = 0; 110b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mDirectoryCount = 0; 111b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mPartialCount = 0; 112b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mWritableDirectoryCount = 0; 113b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mNoDeleteCount = 0; 114b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan mNoRenameCount = 0; 115b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan } 116b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan 117b8874fd0df55113d472c6704b91bd493c577caebGarfield Tan @Override 11884bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public boolean containsDirectories() { 11984bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan return mDirectoryCount > 0; 12084bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 12184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 12284bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 12306c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan public boolean containsFiles() { 12406c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan return mFileCount > 0; 12506c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan } 12606c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan 12706c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan @Override 12806c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan public int size() { 12906c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan return mDirectoryCount + mFileCount; 13006c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan } 13106c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan 13206c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan @Override 13384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public boolean containsPartialFiles() { 13484bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan return mPartialCount > 0; 13584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 13684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 13784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 1387f7ee10edaac1214e23f267a595014b510562d1eBen Lin public boolean containsFilesInArchive() { 1397f7ee10edaac1214e23f267a595014b510562d1eBen Lin return mInArchiveCount > 0; 1407f7ee10edaac1214e23f267a595014b510562d1eBen Lin } 1417f7ee10edaac1214e23f267a595014b510562d1eBen Lin 1427f7ee10edaac1214e23f267a595014b510562d1eBen Lin @Override 14384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public boolean canDelete() { 14406c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan return size() > 0 && mNoDeleteCount == 0; 14584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 14684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 14784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 1485a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski public boolean canExtract() { 1495a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski return size() > 0 && mInArchiveCount == size(); 1505a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski } 1515a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski 1525a8e378a4b550d8a8e31d3bcc93ec3bf485d7c16Tomasz Mikolajewski @Override 15384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public boolean canRename() { 15406c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan return mNoRenameCount == 0 && size() == 1; 15584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 15684bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan 15784bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan @Override 158253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann public boolean canViewInOwner() { 159253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann return mSupportsSettings; 160253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann } 161253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann 162253a99248f1f3d50cd357d902bfc52e7b9367446Jon Mann @Override 16384bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan public boolean canPasteInto() { 16406c4b1111ec49bb70ec6977e86322f1c8f9bbe58Garfield Tan return mDirectoryCount == 1 && mWritableDirectoryCount == 1 && size() == 1; 16584bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan } 166ac3e63e584a079c9efd84de66e65a8f6c05b773dTomasz Mikolajewski 167ac3e63e584a079c9efd84de66e65a8f6c05b773dTomasz Mikolajewski @Override 168ac3e63e584a079c9efd84de66e65a8f6c05b773dTomasz Mikolajewski public boolean canOpenWith() { 1698c9b9fba64a063ab04f0ff91ab9cfe8ee8348c60Tomasz Mikolajewski return size() == 1 && mDirectoryCount == 0 && mInArchiveCount == 0 && mPartialCount == 0; 170ac3e63e584a079c9efd84de66e65a8f6c05b773dTomasz Mikolajewski } 17184bd0f13bd02ea26acc937b00c050884dc7546efGarfield Tan} 172