OSDN Git Service

CMFileManager: Allow for sorting by mime type in search.
authorAdnan Begovic <adnan@cyngn.com>
Tue, 25 Nov 2014 00:37:05 +0000 (18:37 -0600)
committerAdnan Begovic <adnan@cyngn.com>
Wed, 10 Dec 2014 22:26:45 +0000 (14:26 -0800)
Change-Id: Ib633f84532507f2a32d78978a3c0c87d62617fd8

AndroidManifest.xml
res/layout/search.xml
res/layout/search_spinner_item.xml [new file with mode: 0644]
res/values/strings.xml
res/values/styles.xml
src/com/cyanogenmod/filemanager/activities/NavigationActivity.java
src/com/cyanogenmod/filemanager/activities/SearchActivity.java
src/com/cyanogenmod/filemanager/adapters/SearchResultAdapter.java
src/com/cyanogenmod/filemanager/util/MimeTypeHelper.java

index 4214159..d442b2a 100644 (file)
@@ -82,6 +82,7 @@
       </intent-filter>
       <meta-data
         android:name="android.app.searchable"
+        android:value=".activities.SearchActivity"
         android:resource="@xml/searchable" />
     </activity>
 
index 2141f17..4d6a3c6 100644 (file)
       android:layout_marginLeft="@dimen/default_margin"
       android:singleLine="true"
       android:textAppearance="@style/secondary_text_appearance" />
+
+    <Spinner
+      android:id="@+id/search_status_type_spinner"
+      android:layout_width="wrap_content"
+      android:layout_height="match_parent"
+      android:layout_alignParentBottom="true"
+      android:layout_alignParentRight="true"
+      android:layout_marginBottom="@dimen/default_margin"
+      android:layout_marginRight="@dimen/default_margin"
+      android:gravity="left"
+      android:textColor="@android:color/white"
+      android:dropDownVerticalOffset="20dp" />
+
   </RelativeLayout>
 
   <com.cyanogenmod.filemanager.ui.widgets.FlingerListView
diff --git a/res/layout/search_spinner_item.xml b/res/layout/search_spinner_item.xml
new file mode 100644 (file)
index 0000000..ac14b99
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The CyanogenMod 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.
+ -->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="left"
+    android:textColor="@android:color/white" />
\ No newline at end of file
index 1455e92..aef1e5b 100644 (file)
     <string name="category_audio">AUDIO</string>
     <string name="category_video">VIDEO</string>
     <string name="category_security">SECURITY</string>
+    <string name="category_all">ALL</string>
 
     <!-- Compression - Compression modes dialog title -->
     <string name="compression_mode_title">Compression mode</string>
index 5170a23..294dc2d 100644 (file)
@@ -30,6 +30,7 @@
         <item name="android:colorPrimaryDark">@color/material_palette_blue_primary_dark</item>
         <item name="android:colorControlHighlight">@color/material_palette_blue_accent_dark</item>
         <item name="android:colorAccent">@color/material_palette_blue_primary_dark</item>
+        <item name="android:actionMenuTextColor">@android:color/white</item>
     </style>
 
     <!-- Base themes -->
@@ -42,6 +43,7 @@
         <item name="android:colorAccent">@color/material_palette_blue_primary</item>
         <item name="android:actionBarStyle">@style/FileManager.Widget.ActionBar.White</item>
         <item name="android:homeAsUpIndicator">@drawable/material_ripple_up_arrow</item>
+        <item name="android:actionMenuTextColor">@android:color/white</item>
     </style>
 
     <style name="FileManager.Theme.Material.NoActionBar" parent="@android:style/Theme.Material.NoActionBar">
@@ -54,6 +56,7 @@
         <item name="android:colorPrimaryDark">@color/material_palette_blue_primary_dark</item>
         <item name="android:colorControlHighlight">@color/material_palette_blue_accent_dark</item>
         <item name="android:colorAccent">@color/material_palette_blue_accent</item>
+        <item name="android:actionMenuTextColor">@android:color/white</item>
     </style>
 
     <style name="FileManager.Theme.Material" parent="@android:style/Theme.Material">
@@ -64,6 +67,7 @@
         <item name="android:colorAccent">@color/material_palette_blue_primary</item>
         <item name="android:actionBarStyle">@style/FileManager.Widget.ActionBar.White</item>
         <item name="android:homeAsUpIndicator">@drawable/material_ripple_up_arrow</item>
+        <item name="android:actionMenuTextColor">@android:color/white</item>
     </style>
 
     <!-- A theme with overlay -->
index 81ed1e4..c676692 100644 (file)
@@ -551,6 +551,10 @@ public class NavigationActivity extends Activity
     @Override
     protected void onResume() {
         super.onResume();
+        
+        if (mSearchView.getVisibility() == View.VISIBLE) {
+            closeSearch();
+        }
 
         // Check restrictions
         if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
@@ -1933,18 +1937,15 @@ public class NavigationActivity extends Activity
         return !this.mExitFlag;
     }
 
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public boolean onSearchRequested() {
-        Bundle bundle = new Bundle();
-        bundle.putString(
-                SearchActivity.EXTRA_SEARCH_DIRECTORY,
-                getCurrentNavigationView().getCurrentDir());
-        startSearch(Preferences.getLastSearch(), true, bundle, false);
-        closeSearch();
-        return true;
+    public void startActivity(Intent intent) {
+        // check if search intent
+        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+            intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
+                    getCurrentNavigationView().getCurrentDir());
+        }
+
+        super.startActivity(intent);
     }
 
     /**
index 7cc39f6..172f6be 100644 (file)
@@ -39,13 +39,15 @@ import android.view.View;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemLongClickListener;
+
+import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 import android.widget.ProgressBar;
+import android.widget.Spinner;
 import android.widget.TextView;
 import android.widget.Toast;
-
 import com.cyanogenmod.filemanager.FileManagerApplication;
 import com.cyanogenmod.filemanager.R;
 import com.cyanogenmod.filemanager.activities.preferences.SearchPreferenceFragment;
@@ -83,6 +85,7 @@ import com.cyanogenmod.filemanager.util.DialogHelper;
 import com.cyanogenmod.filemanager.util.ExceptionUtil;
 import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
 import com.cyanogenmod.filemanager.util.FileHelper;
+import com.cyanogenmod.filemanager.util.MimeTypeHelper;
 import com.cyanogenmod.filemanager.util.StorageHelper;
 
 import java.io.FileNotFoundException;
@@ -93,7 +96,8 @@ import java.util.List;
  * An activity for search files and folders.
  */
 public class SearchActivity extends Activity
-    implements OnItemClickListener, OnItemLongClickListener, OnRequestRefreshListener {
+    implements OnItemClickListener, OnItemLongClickListener, OnRequestRefreshListener,
+        AdapterView.OnItemSelectedListener {
 
     private static final String TAG = "SearchActivity"; //$NON-NLS-1$
 
@@ -240,7 +244,7 @@ public class SearchActivity extends Activity
 
                         // Resolve the symlinks
                         FileHelper.resolveSymlinks(
-                                    SearchActivity.this, SearchActivity.this.mResultList);
+                                SearchActivity.this, SearchActivity.this.mResultList);
 
                         // Draw the results
                         drawResults();
@@ -376,7 +380,7 @@ public class SearchActivity extends Activity
             restoreState(state);
         }
 
-        //Initialize action bars and search
+        //Initialize action bars and searc
         initTitleActionBar();
         initComponents();
 
@@ -496,11 +500,14 @@ public class SearchActivity extends Activity
      */
     private void initTitleActionBar() {
         //Configure the action bar options
-        getActionBar().setBackgroundDrawable(
+        // Set up the action bar to show a dropdown list.
+        final ActionBar actionBar = getActionBar();
+        actionBar.setDisplayShowTitleEnabled(false);
+        actionBar.setBackgroundDrawable(
                 getResources().getDrawable(R.drawable.bg_material_titlebar));
-        getActionBar().setDisplayOptions(
-                ActionBar.DISPLAY_SHOW_CUSTOM);
-        getActionBar().setDisplayHomeAsUpEnabled(true);
+        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+        actionBar.setDisplayHomeAsUpEnabled(true);
+
         View customTitle = getLayoutInflater().inflate(R.layout.simple_customtitle, null, false);
 
         TextView title = (TextView)customTitle.findViewById(R.id.customtitle_title);
@@ -509,8 +516,17 @@ public class SearchActivity extends Activity
         ButtonItem configuration = (ButtonItem)customTitle.findViewById(R.id.ab_button1);
         configuration.setImageResource(R.drawable.ic_material_light_config);
         configuration.setVisibility(View.VISIBLE);
+        actionBar.setCustomView(customTitle);
+
+        // Specify a SpinnerAdapter to populate the dropdown list.
+        Spinner typeSpinner = (Spinner) findViewById(R.id.search_status_type_spinner);
 
-        getActionBar().setCustomView(customTitle);
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+                R.layout.search_spinner_item,
+                MimeTypeHelper.MimeTypeCategory.getFriendlyLocalizedNames(this));
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        typeSpinner.setAdapter(adapter);
+        typeSpinner.setOnItemSelectedListener(this);
     }
 
     /**
@@ -587,13 +603,13 @@ public class SearchActivity extends Activity
             /**NON BLOCK**/
         }
 
-        //Recovery the search directory
-        Bundle bundle = getIntent().getBundleExtra(SearchManager.APP_DATA);
         //If data is not present, use root directory to do the search
         this.mSearchDirectory = FileHelper.ROOT_DIRECTORY;
-        if (bundle != null) {
-            this.mSearchDirectory =
-                    bundle.getString(EXTRA_SEARCH_DIRECTORY, FileHelper.ROOT_DIRECTORY);
+        String searchDirectory = getIntent()
+                .getStringExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY);
+
+        if (!TextUtils.isEmpty(searchDirectory)) {
+            this.mSearchDirectory = searchDirectory;
         }
 
         //Retrieve the query ¿from voice recognizer?
@@ -1289,6 +1305,7 @@ public class SearchActivity extends Activity
         theme.setTextColor(this, (TextView)v, "action_bar_text_color"); //$NON-NLS-1$
         v = findViewById(R.id.search_status_query_terms);
         theme.setTextColor(this, (TextView)v, "action_bar_text_color"); //$NON-NLS-1$
+
         //ListView
         if (this.mSearchListView.getAdapter() != null) {
             ((SearchResultAdapter)this.mSearchListView.getAdapter()).notifyDataSetChanged();
@@ -1297,5 +1314,19 @@ public class SearchActivity extends Activity
                 theme.getDrawable(this, "horizontal_divider_drawable")); //$NON-NLS-1$
         this.mSearchListView.invalidate();
     }
+
+    @Override
+    public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
+        String category = MimeTypeHelper.MimeTypeCategory.names()[i];
+        SearchResultAdapter adapter = ((SearchResultAdapter) this.mSearchListView.getAdapter());
+        if (adapter != null) {
+            adapter.setMimeFilter(category);
+        }
+    }
+
+    @Override
+    public void onNothingSelected(AdapterView<?> adapterView) {
+        //ignore
+    }
 }
 
index 98a28ef..29dd638 100644 (file)
@@ -18,6 +18,7 @@ package com.cyanogenmod.filemanager.adapters;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -25,28 +26,36 @@ import android.widget.ArrayAdapter;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.cyanogenmod.filemanager.FileManagerApplication;
 import com.cyanogenmod.filemanager.R;
 import com.cyanogenmod.filemanager.model.FileSystemObject;
 import com.cyanogenmod.filemanager.model.Query;
 import com.cyanogenmod.filemanager.model.SearchResult;
+import com.cyanogenmod.filemanager.preferences.AccessMode;
+import com.cyanogenmod.filemanager.preferences.DisplayRestrictions;
 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
 import com.cyanogenmod.filemanager.preferences.Preferences;
 import com.cyanogenmod.filemanager.ui.IconHolder;
 import com.cyanogenmod.filemanager.ui.ThemeManager;
 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
 import com.cyanogenmod.filemanager.ui.widgets.RelevanceView;
+import com.cyanogenmod.filemanager.util.FileHelper;
 import com.cyanogenmod.filemanager.util.MimeTypeHelper;
 import com.cyanogenmod.filemanager.util.SearchHelper;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * An implementation of {@link ArrayAdapter} for display search results.
  */
 public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
 
+    private MimeTypeHelper.MimeTypeCategory mMimeFilter = MimeTypeHelper.MimeTypeCategory.NONE;
+
     /**
      * A class that conforms with the ViewHolder pattern to performance
      * the list view rendering.
@@ -90,6 +99,7 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     private final boolean mShowRelevanceWidget;
 
     private final List<String> mQueries;
+    private final List<SearchResult> mOriginalList;
 
     private boolean mDisposed;
 
@@ -116,6 +126,9 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     public SearchResultAdapter(
             Context context, List<SearchResult> files, int itemViewResourceId, Query queries) {
         super(context, RESOURCE_ITEM_NAME, files);
+
+        mOriginalList = new ArrayList<SearchResult>(files);
+
         this.mDisposed = false;
         final boolean displayThumbs = Preferences.getSharedPreferences().getBoolean(
                 FileManagerSettings.SETTINGS_DISPLAY_THUMBS.getId(),
@@ -160,6 +173,38 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     }
 
     /**
+     * Method that allows filtering the results by {@link MimeTypeHelper.MimeTypeCategory}
+     * @param mimeFilter the MimeTypeCategory to filter by
+     */
+    public void setMimeFilter(String mimeFilter) {
+        // Are we in ChRooted environment?
+        boolean chRooted =
+                FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
+
+        // Create display restrictions
+        Map<DisplayRestrictions, Object> restrictions =
+                new HashMap<DisplayRestrictions, Object>();
+        restrictions.put(
+                DisplayRestrictions.MIME_TYPE_RESTRICTION, MimeTypeHelper.ALL_MIME_TYPES);
+
+        List<SearchResult> newResults = SearchHelper.convertToResults(
+                FileHelper.applyUserPreferences(
+                        getFiles(), restrictions, true, chRooted), new Query().fillSlots(mQueries));
+
+        clear();
+        for (SearchResult result : newResults) {
+            // Only show results that are within our category, or all if no filter is set
+            if (TextUtils.equals(mimeFilter, MimeTypeHelper.MimeTypeCategory.NONE.name()) ||
+                    MimeTypeHelper.getCategory(getContext(), result.getFso()) ==
+                            MimeTypeHelper.MimeTypeCategory.valueOf(mimeFilter)) {
+                add(result);
+            }
+        }
+
+        this.notifyDataSetChanged();
+    }
+
+    /**
      * Method that dispose the elements of the adapter.
      */
     public void dispose() {
@@ -168,6 +213,7 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
         }
         this.mDisposed = true;
         clear();
+        this.mOriginalList.clear();
         this.mData = null;
         this.mIconHolder = null;
     }
@@ -224,6 +270,19 @@ public class SearchResultAdapter extends ArrayAdapter<SearchResult> {
     }
 
     /**
+     * Method that returns the files of the adapter.
+     *
+     * @return List<FileSystemObject> The adapter data
+     */
+    public List<FileSystemObject> getFiles()  {
+        final List<FileSystemObject> data = new ArrayList<FileSystemObject>();
+        for (SearchResult result : mOriginalList) {
+            data.add(result.getFso());
+        }
+        return data;
+    }
+
+    /**
      * Returns the position of the specified item in the array.
      *
      * @param item The item to retrieve the position of.
index 0283305..38212a2 100644 (file)
@@ -111,7 +111,35 @@ public final class MimeTypeHelper {
         /**
          * Security file (certificate, keys, ...)
          */
-        SECURITY
+        SECURITY;
+
+        public static String[] names() {
+            MimeTypeCategory[] categories = values();
+            String[] names = new String[categories.length];
+
+            for (int i = 0; i < categories.length; i++) {
+                names[i] = categories[i].name();
+            }
+
+            return names;
+        }
+
+        public static String[] getFriendlyLocalizedNames(Context context) {
+            MimeTypeCategory[] categories = values();
+            String[] localizedNames = new String[categories.length];
+
+            for (int i = 0; i < categories.length; i++) {
+                String description = getCategoryDescription(context, categories[i]);
+                if (TextUtils.equals("-", description)) {
+                    description = context.getString(R.string.category_all);
+                }
+                description = description.substring(0, 1).toUpperCase()
+                        + description.substring(1).toLowerCase();
+                localizedNames[i] = description;
+            }
+
+            return localizedNames;
+        }
     }
 
     /**