OSDN Git Service

画像一覧での一括取得機能を追加。
authorMRSa <mrsa@myad.jp>
Sat, 16 Mar 2019 13:40:57 +0000 (22:40 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 16 Mar 2019 13:40:57 +0000 (22:40 +0900)
app/src/main/java/net/osdn/gokigen/gr2control/logcat/LogCatFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/playback/ImageGridViewFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/playback/detail/ImageContentInfoEx.java
app/src/main/java/net/osdn/gokigen/gr2control/playback/detail/ImagePagerViewFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/playback/detail/MyContentDownloader.java
app/src/main/res/drawable/ic_refresh_grey_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_select_all_grey_24dp.xml [new file with mode: 0644]
app/src/main/res/menu/image_grid_view.xml
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml

index 845a0c1..ca270e1 100644 (file)
@@ -11,8 +11,8 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
-import android.widget.Toast;
 
+import com.google.android.material.snackbar.Snackbar;
 
 import net.osdn.gokigen.gr2control.R;
 
@@ -119,7 +119,8 @@ public class LogCatFragment extends ListFragment
                                     view.setSelection(dataItems.size());
 
                                     // 更新終了通知
-                                    Toast.makeText(getActivity(), getString(R.string.finish_refresh), Toast.LENGTH_SHORT).show();
+                                    Snackbar.make(getActivity().findViewById(R.id.fragment1), getString(R.string.finish_refresh), Snackbar.LENGTH_SHORT).show();
+                                    //Toast.makeText(getActivity(), getString(R.string.finish_refresh), Toast.LENGTH_SHORT).show();
                                 }
                                 catch (Exception ee)
                                 {
index 7c2d24f..dedb489 100644 (file)
@@ -2,6 +2,7 @@ package net.osdn.gokigen.gr2control.playback;
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -42,6 +43,7 @@ import net.osdn.gokigen.gr2control.camera.playback.IDownloadThumbnailImageCallba
 import net.osdn.gokigen.gr2control.camera.playback.IPlaybackControl;
 import net.osdn.gokigen.gr2control.playback.detail.ImageContentInfoEx;
 import net.osdn.gokigen.gr2control.playback.detail.ImagePagerViewFragment;
+import net.osdn.gokigen.gr2control.playback.detail.MyContentDownloader;
 
 import androidx.annotation.NonNull;
 import androidx.appcompat.app.ActionBar;
@@ -59,7 +61,7 @@ public class ImageGridViewFragment extends Fragment
        private final String OLYMPUS_RAW_SUFFIX = ".orf";
        private final String PENTAX_RAW_PEF_SUFFIX = ".pef";
 
-
+       private MyContentDownloader contentDownloader;
     private GridView gridView;
        private boolean gridViewIsScrolling;
        private IPlaybackControl playbackControl;
@@ -80,6 +82,15 @@ public class ImageGridViewFragment extends Fragment
        {
                this.playbackControl = playbackControl;
                this.runMode = runMode;
+               Activity activity = getActivity();
+               if (activity != null)
+               {
+            this.contentDownloader = new MyContentDownloader(getActivity(), playbackControl);
+        }
+        else
+        {
+            this.contentDownloader = null;
+        }
        }
 
        @Override
@@ -101,7 +112,9 @@ public class ImageGridViewFragment extends Fragment
                
                gridView = view.findViewById(R.id.gridView1);
                gridView.setAdapter(new GridViewAdapter(inflater));
-               gridView.setOnItemClickListener(new GridViewOnItemClickListener());
+        GridViewOnItemClickListener listener = new GridViewOnItemClickListener();
+               gridView.setOnItemClickListener(listener);
+        gridView.setOnItemLongClickListener(listener);
                gridView.setOnScrollListener(new GridViewOnScrollListener());
                
                return (view);
@@ -132,9 +145,26 @@ public class ImageGridViewFragment extends Fragment
                        refresh();
                        return (true);
                }
+        if (id == R.id.action_batch_download_original_size_raw)
+        {
+            // オリジナルサイズのダウンロード
+            startDownloadBatch(false);
+            return (true);
+        }
+        if (id == R.id.action_batch_download_640x480_raw)
+        {
+            // 小さいサイズのダウンロード
+            startDownloadBatch(true);
+            return (true);
+        }
+        if (id == R.id.action_select_all)
+        {
+            selectUnselectAll();
+            return (true);
+        }
                return (super.onOptionsItemSelected(item));
        }
-       
+
        @Override
        public void onResume()
        {
@@ -376,7 +406,131 @@ public class ImageGridViewFragment extends Fragment
         Log.v(TAG, "refreshImpl() end");
     }
 
-       private static class GridCellViewHolder
+    /**
+     *   全選択・全選択解除
+     *
+     */
+    private void selectUnselectAll()
+    {
+        if ((contentList == null)||(contentList.size() == 0))
+        {
+            // 選択されていない時は終わる。
+            return;
+        }
+
+        int nofSelected = 0;
+        for (ImageContentInfoEx content : contentList)
+        {
+            if (content.isSelected())
+            {
+                nofSelected++;
+            }
+        }
+
+        // 全部選択されているときは全選択解除・そうでない時は全選択
+        boolean setSelected = (nofSelected != contentList.size());
+        for (ImageContentInfoEx content : contentList)
+        {
+            content.setSelected(setSelected);
+        }
+
+        // グリッドビューの再描画
+        redrawGridView();
+    }
+
+    private void redrawGridView()
+    {
+        // グリッドビューの再描画
+        Activity activity = getActivity();
+        if (activity != null)
+        {
+            getActivity().runOnUiThread(new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                    if (gridView != null)
+                    {
+                        gridView.invalidateViews();
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     *    一括ダウンロードの開始
+     *
+     * @param isSmall  小さいサイズ(JPEG)
+     */
+    private void startDownloadBatch(final boolean isSmall)
+    {
+        try
+        {
+            // 念のため、contentDownloader がなければ作る
+            if (contentDownloader == null)
+            {
+                Activity activity = getActivity();
+                if (activity == null)
+                {
+                    // activityが取れない時には終わる。
+                    return;
+                }
+                this.contentDownloader = new MyContentDownloader(getActivity(), playbackControl);
+            }
+            Thread thread = new Thread(new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                    try
+                    {
+                        // ダウンロード枚数を取得
+                        int totalSize = 0;
+                        for (ImageContentInfoEx content : contentList)
+                        {
+                            if (content.isSelected())
+                            {
+                                totalSize++;
+                            }
+                        }
+                        if (totalSize == 0)
+                        {
+                            // 画像が選択されていなかった...終了する
+                            return;
+                        }
+                        int count = 1;
+                        for (ImageContentInfoEx content : contentList)
+                        {
+                            if (content.isSelected())
+                            {
+                                contentDownloader.startDownload(content.getFileInfo(), " (" + count + "/" + totalSize + ") ", null, isSmall);
+                                count++;
+
+                                // 画像の選択を落とす
+                                content.setSelected(false);
+                            }
+                        }
+
+                        // グリッドビューの再描画
+                        redrawGridView();
+                    }
+                    catch (Exception e)
+                    {
+                        e.printStackTrace();
+                    }
+                }
+            });
+            thread.start();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+    private static class GridCellViewHolder
     {
                ImageView imageView;
                ImageView iconView;
@@ -458,7 +612,6 @@ public class ImageGridViewFragment extends Fragment
             {
                 viewHolder.imageView.setImageResource(R.drawable.ic_satellite_grey_24dp);
                                viewHolder.iconView.setImageDrawable(null);
-                viewHolder.selectView.setImageDrawable(null);
                                if (!gridViewIsScrolling)
                 {
                                        if (executor.isShutdown())
@@ -484,14 +637,23 @@ public class ImageGridViewFragment extends Fragment
                                        viewHolder.iconView.setImageDrawable(null);
                                }
                        }
+                       if (infoEx.isSelected())
+            {
+                viewHolder.selectView.setImageResource(R.drawable.ic_check_green_24dp);
+            }
+            else
+            {
+                viewHolder.selectView.setImageDrawable(null);
+            }
                        return convertView;
                }
        }
        
-       private class GridViewOnItemClickListener implements AdapterView.OnItemClickListener
+       private class GridViewOnItemClickListener implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener
     {
                @Override
-               public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+               public void onItemClick(AdapterView<?> parent, View view, int position, long id)
+        {
                ImagePagerViewFragment fragment = ImagePagerViewFragment.newInstance(playbackControl, runMode, contentList, position);
             FragmentActivity activity = getActivity();
                if (activity != null)
@@ -502,7 +664,48 @@ public class ImageGridViewFragment extends Fragment
                 transaction.commit();
             }
                }
-       }
+
+        @Override
+        public boolean onItemLongClick(final AdapterView<?> parent, View view, int position, long id)
+        {
+            try
+            {
+                if (contentList == null)
+                {
+                    return (false);
+                }
+                ImageContentInfoEx infoEx = contentList.get(position);
+                if (infoEx != null)
+                {
+                    boolean isChecked = infoEx.isSelected();
+                    infoEx.setSelected(!isChecked);
+                }
+                view.invalidate();
+                runOnUiThread(new Runnable()
+                {
+                    @Override
+                    public void run()
+                    {
+                        try
+                        {
+                            GridViewAdapter adapter = (GridViewAdapter) parent.getAdapter();
+                            adapter.notifyDataSetChanged();
+                        }
+                        catch (Exception e)
+                        {
+                            e.printStackTrace();
+                        }
+                    }
+                });
+                return (true);
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
+            return (false);
+        }
+    }
        
        private class GridViewOnScrollListener implements AbsListView.OnScrollListener
     {
index 3020f7b..d84abe0 100644 (file)
@@ -7,12 +7,14 @@ public class ImageContentInfoEx
     private final ICameraFileInfo fileInfo;
     private String rawSuffix;
     private boolean hasRaw;
+    private boolean selected;
 
     public ImageContentInfoEx(ICameraFileInfo fileInfo, boolean hasRaw, String rawSuffix)
     {
         this.fileInfo = fileInfo;
         this.hasRaw = hasRaw;
         this.rawSuffix = rawSuffix;
+        this.selected = false;
     }
 
     public void setHasRaw(boolean value, String rawSuffix)
@@ -35,4 +37,15 @@ public class ImageContentInfoEx
     {
         return (fileInfo);
     }
+
+    public void setSelected(boolean isSelected)
+    {
+        selected = isSelected;
+    }
+
+    public boolean isSelected()
+    {
+        return (selected);
+    }
+
 }
index 441267b..e4f3afc 100644 (file)
@@ -479,7 +479,7 @@ public class ImagePagerViewFragment extends Fragment
         * @param isRaw           RAWファイルをダウンロードするか
         * @param isSmallSize    小さいサイズの量にするか
      */
-       public void saveImageWithDialog(final boolean isRaw, final boolean isSmallSize)
+       private void saveImageWithDialog(final boolean isRaw, final boolean isSmallSize)
        {
         Log.v(TAG, "saveImageWithDialog() : raw : " + isRaw + " (small : " + isSmallSize + ")");
         try
@@ -495,7 +495,7 @@ public class ImagePagerViewFragment extends Fragment
                         if (infoEx != null)
                         {
                             ICameraFileInfo fileInfo = infoEx.getFileInfo();
-                            contentDownloader.startDownload(fileInfo, (isRaw) ? infoEx.getRawSuffix() : null, isSmallSize);
+                            contentDownloader.startDownload(fileInfo, "", (isRaw) ? infoEx.getRawSuffix() : null, isSmallSize);
                         }
                     }
                 });
index 3ac2e01..69e4967 100644 (file)
@@ -11,7 +11,9 @@ import android.net.Uri;
 import android.os.Environment;
 import android.provider.MediaStore;
 import android.util.Log;
-import android.widget.Toast;
+import android.view.View;
+
+import com.google.android.material.snackbar.Snackbar;
 
 import net.osdn.gokigen.gr2control.R;
 import net.osdn.gokigen.gr2control.camera.ICameraFileInfo;
@@ -33,7 +35,7 @@ import androidx.preference.PreferenceManager;
  *   コンテントのダウンロード
  *
  */
-class MyContentDownloader implements IDownloadContentCallback
+public class MyContentDownloader implements IDownloadContentCallback
 {
     private final String TAG = toString();
     private final Activity activity;
@@ -53,7 +55,7 @@ class MyContentDownloader implements IDownloadContentCallback
      *   コンストラクタ
      *
      */
-    MyContentDownloader(@NonNull Activity activity, @NonNull final IPlaybackControl playbackControl)
+    public MyContentDownloader(@NonNull Activity activity, @NonNull final IPlaybackControl playbackControl)
     {
         this.activity = activity;
         this.playbackControl = playbackControl;
@@ -63,7 +65,7 @@ class MyContentDownloader implements IDownloadContentCallback
      *   ダウンロードの開始
      *
      */
-    void startDownload(final ICameraFileInfo fileInfo, String replaceJpegSuffix, boolean isSmallSize)
+    public void startDownload(final ICameraFileInfo fileInfo, final String appendTitle, String replaceJpegSuffix, boolean isSmallSize)
     {
         if (fileInfo == null)
         {
@@ -85,18 +87,26 @@ class MyContentDownloader implements IDownloadContentCallback
             if (targetFileName.toUpperCase().contains(RAW_SUFFIX_1))
             {
                 mimeType = "image/x-adobe-dng";
+                isSmallSize = false;
             }
             else if (targetFileName.toUpperCase().contains(RAW_SUFFIX_2))
             {
                 mimeType = "image/x-olympus-orf";
+                isSmallSize = false;
             }
             else if (targetFileName.toUpperCase().contains(RAW_SUFFIX_3))
             {
                 mimeType = "image/x-pentax-pef";
+                isSmallSize = false;
             }
             else if (targetFileName.toUpperCase().contains(MOVIE_SUFFIX))
             {
                 mimeType =  "video/mp4";
+                isSmallSize = false;
+            }
+            else
+            {
+                mimeType = "image/jpeg";
             }
 
             ////// ダイアログの表示
@@ -104,7 +114,7 @@ class MyContentDownloader implements IDownloadContentCallback
                 @Override
                 public void run() {
                     downloadDialog = new ProgressDialog(activity);
-                    downloadDialog.setTitle(activity.getString(R.string.dialog_download_file_title));
+                    downloadDialog.setTitle(activity.getString(R.string.dialog_download_file_title) + appendTitle);
                     downloadDialog.setMessage(activity.getString(R.string.dialog_download_message) + " " + targetFileName);
                     downloadDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                     downloadDialog.setCancelable(false);
@@ -226,7 +236,9 @@ class MyContentDownloader implements IDownloadContentCallback
                     {
                         downloadDialog.dismiss();
                     }
-                    Toast.makeText(activity, activity.getString(R.string.download_control_save_success) + " " + targetFileName, Toast.LENGTH_SHORT).show();
+                    View view = activity.findViewById(R.id.fragment1);
+                    Snackbar.make(view, activity.getString(R.string.download_control_save_success) + " " + targetFileName, Snackbar.LENGTH_SHORT).show();
+                    //Toast.makeText(activity, activity.getString(R.string.download_control_save_success) + " " + targetFileName, Toast.LENGTH_SHORT).show();
                     System.gc();
                 }
             });
diff --git a/app/src/main/res/drawable/ic_refresh_grey_24dp.xml b/app/src/main/res/drawable/ic_refresh_grey_24dp.xml
new file mode 100644 (file)
index 0000000..fee77b8
--- /dev/null
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:tint="#C0C0C0"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_select_all_grey_24dp.xml b/app/src/main/res/drawable/ic_select_all_grey_24dp.xml
new file mode 100644 (file)
index 0000000..d8ab502
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#C0C0C0"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M3,5h2L5,3c-1.1,0 -2,0.9 -2,2zM3,13h2v-2L3,11v2zM7,21h2v-2L7,19v2zM3,9h2L5,7L3,7v2zM13,3h-2v2h2L13,3zM19,3v2h2c0,-1.1 -0.9,-2 -2,-2zM5,21v-2L3,19c0,1.1 0.9,2 2,2zM3,17h2v-2L3,15v2zM9,3L7,3v2h2L9,3zM11,21h2v-2h-2v2zM19,13h2v-2h-2v2zM19,21c1.1,0 2,-0.9 2,-2h-2v2zM19,9h2L21,7h-2v2zM19,17h2v-2h-2v2zM15,21h2v-2h-2v2zM15,5h2L17,3h-2v2zM7,17h10L17,7L7,7v10zM9,9h6v6L9,15L9,9z"/>
+</vector>
index 966083a..9e593e8 100644 (file)
@@ -2,12 +2,46 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:compat="http://schemas.android.com/apk/res-auto" >
 
+
+    <item
+        android:id="@+id/action_select_all"
+        compat:showAsAction="ifRoom"
+        android:icon="@drawable/ic_select_all_grey_24dp"
+        android:title="@string/action_select_all"
+        android:visible="true" />
+
     <item
         android:id="@+id/action_refresh"
         compat:showAsAction="ifRoom"
-        android:icon="@drawable/ic_refresh_black_24dp"
+        android:icon="@drawable/ic_refresh_grey_24dp"
         android:title="@string/action_refresh"
-        android:visible="false" />
+        android:visible="true" />
+
+    <item android:id="@+id/action_batch_download_with_raw"
+        compat:showAsAction="ifRoom"
+        android:icon="@drawable/ic_file_download_white_24dp"
+        android:title="@string/action_download"
+        android:visible="true" >
+        <menu>
+            <item
+                android:id="@+id/action_batch_download_original_size_raw"
+                compat:showAsAction="never"
+                android:title="@string/action_download_original_size"/>
+
+            <item
+                android:id="@+id/action_batch_download_640x480_raw"
+                compat:showAsAction="never"
+                android:title="@string/action_batch_download_640x480"/>
+
+            <!---->
+            <item
+                android:id="@+id/action_batch_download_raw"
+                compat:showAsAction="never"
+                android:visible="false"
+                android:title="@string/action_batch_download_raw"/>
+            <!---->
+        </menu>
+    </item>
 
     <item
         android:id="@+id/action_datetime_synchronize"
index aa784f5..087b547 100644 (file)
     <string name="action_download_original_size">オリジナルサイズ</string>
     <string name="action_download_640x480">小さいサイズ</string>
     <string name="action_download_raw">RAW</string>
+    <string name="action_batch_download_640x480">小さいサイズ(JPEG)</string>
+    <string name="action_batch_download_raw">オリジナルサイズ(RAWも取得)</string>
     <string name="action_delete_picture">削除</string>
     <string name="dialog_get_information_title">画像の情報</string>
+    <string name="action_select_all">全選択/全選択解除</string>
     <string name="label_aelock">AEL/AFL</string>
     <string name="label_c_af">C-AF</string>
     <string name="white_balance">WB</string>
index f7e7036..1e538a8 100644 (file)
     <string name="action_download_1024x768">1024 x 768</string>
     <string name="action_download_640x480">Small Size</string>
     <string name="action_download_raw">RAW</string>
+    <string name="action_batch_download_640x480">Small Size(JPEG)</string>
+    <string name="action_batch_download_raw">Original Size(with RAW)</string>
     <string name="action_delete_picture">Delete</string>
+    <string name="action_select_all">Select All/Unselect All</string>
 
     <string name="dialog_get_information_title">Getting Picture Information</string>
     <string name="download_control_get_information_title">Information</string>