diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java b/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java index 1e5edca5..f516d93c 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/AndroFotoFinderApp.java @@ -23,7 +23,6 @@ import android.app.Application; import android.content.Context; import android.database.sqlite.SQLiteDatabase; -import android.provider.MediaStore; import android.support.annotation.NonNull; import android.util.Log; import android.widget.Toast; @@ -51,6 +50,7 @@ import de.k3b.android.androFotoFinder.queries.MergedMediaRepository; import de.k3b.android.osmdroid.forge.MapsForgeSupport; import de.k3b.android.util.LogCat; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.widget.ActivityWithCallContext; import de.k3b.android.widget.LocalizedActivity; import de.k3b.database.QueryParameter; @@ -115,11 +115,10 @@ public static void setMediaImageDbReplacement(Context context, boolean useMediaI MediaContent2DBUpdateService.instance.rebuild(context, null); } - context.getApplicationContext().getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, GlobalMediaContentObserver.getInstance(context)); - context.getApplicationContext().getContentResolver().registerContentObserver(MediaStore.Files.getContentUri("external"), true, GlobalMediaContentObserver.getInstance(context)); + PhotoChangeNotifyer.registerContentObserver(context, GlobalMediaContentObserver.getInstance(context)); } else { - context.getApplicationContext().getContentResolver().unregisterContentObserver(GlobalMediaContentObserver.getInstance(context)); + PhotoChangeNotifyer.unregisterContentObserver(context, GlobalMediaContentObserver.getInstance(context)); if ((oldMediaDBApi != null) && (MediaContent2DBUpdateService.instance != null)) { // switching from mediaImageDbReplacement to Contentprovider MediaContent2DBUpdateService.instance.clearMediaCopy(); diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryListAdapter.java b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryListAdapter.java index 2448ac65..9865b073 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryListAdapter.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryListAdapter.java @@ -32,9 +32,9 @@ import de.k3b.android.androFotoFinder.Global; import de.k3b.android.androFotoFinder.R; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.io.AlbumFile; import de.k3b.io.Directory; -import de.k3b.io.FileUtils; import de.k3b.io.IDirectory; import de.k3b.io.IExpandableListViewNavigation; @@ -42,7 +42,8 @@ * Maps android independent IExpandableListViewNavigation to android specific ExpandableListAdapter so it can be viewed in ExpandableList */ -public class DirectoryListAdapter extends BaseExpandableListAdapter implements IExpandableListViewNavigation { +public class DirectoryListAdapter extends BaseExpandableListAdapter implements + IExpandableListViewNavigation, PhotoChangeNotifyer.PhotoChangedListener { private LayoutInflater inflater; @@ -219,4 +220,12 @@ public static Spanned getDirectoryDisplayText(String prefix, IDirectory director Directory.appendCount(result, directory, options); return Html.fromHtml(result.toString()); } + + /** + * PhotoChangeNotifyer.PhotoChangedListener + **/ + @Override + public void onNotifyPhotoChanged() { + notifyDataSetChanged(); + } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryPickerFragment.java b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryPickerFragment.java index 84f33d02..92530d12 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryPickerFragment.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/directory/DirectoryPickerFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -70,6 +70,7 @@ import de.k3b.android.util.ClipboardUtil; import de.k3b.android.util.FileManagerUtil; import de.k3b.android.util.IntentUtil; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.util.PhotoPropertiesMediaFilesScanner; import de.k3b.android.widget.Dialogs; import de.k3b.database.QueryParameter; @@ -456,8 +457,8 @@ protected boolean onPopUpClick(MenuItem menuItem, IDirectory popUpSelection) { } } - public void notifyDataSetChanged() { - if (this.mAdapter != null) this.mAdapter.notifyDataSetChanged(); + public void notifyPhotoChanged() { + PhotoChangeNotifyer.notifyPhotoChanged(this.getActivity(), this.mAdapter); } private boolean onCopy(IDirectory selection) { @@ -607,7 +608,7 @@ private void onRenameDirAnswer(final IDirectory srcDir, String newFolderName) { } else { // update dirpicker srcDir.rename(srcDirFile.getName(), newFolderName); - notifyDataSetChanged(); + notifyPhotoChanged(); } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/directory/SaveAsPickerFragment.java b/app/src/main/java/de/k3b/android/androFotoFinder/directory/SaveAsPickerFragment.java index ffcd0231..1e72545c 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/directory/SaveAsPickerFragment.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/directory/SaveAsPickerFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 by k3b. + * Copyright (c) 2018-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -20,7 +20,6 @@ package de.k3b.android.androFotoFinder.directory; import android.app.Activity; -import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -29,11 +28,8 @@ import java.io.File; -import de.k3b.android.androFotoFinder.AffUtils; import de.k3b.android.androFotoFinder.R; -import de.k3b.android.androFotoFinder.imagedetail.ImageDetailActivityViewPager; import de.k3b.android.androFotoFinder.queries.FotoSql; -import de.k3b.android.util.AndroidFileCommands; import de.k3b.android.util.OsUtils; import de.k3b.io.AlbumFile; import de.k3b.io.FileUtils; @@ -41,7 +37,6 @@ import de.k3b.io.OSDirOrVirtualAlbumFile; import de.k3b.io.OSDirectory; import de.k3b.io.StringUtils; -import de.k3b.io.collections.SelectedFiles; /** * a picker with a fale name field and a directory picker. @@ -132,7 +127,7 @@ protected void onDirectoryPick(IDirectory selection) { // close dialog and return to caller super.onDirectoryPick(result); onFilePick(new File(result.getAbsolute())); - this.notifyDataSetChanged(); + this.notifyPhotoChanged(); dismiss(); } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorAdapter.java b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorAdapter.java index 972cf9ef..c6aa79fe 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorAdapter.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -40,6 +40,7 @@ import de.k3b.android.androFotoFinder.imagedetail.HugeImageLoader; import de.k3b.android.androFotoFinder.queries.FotoSql; import de.k3b.android.util.DBUtils; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.io.collections.SelectedFiles; import de.k3b.io.collections.SelectedItems; import de.k3b.media.PhotoPropertiesUtil; @@ -60,7 +61,7 @@ * * Created by k3b on 02.06.2015. */ -public class GalleryCursorAdapter extends CursorAdapter { +public class GalleryCursorAdapter extends CursorAdapter implements PhotoChangeNotifyer.PhotoChangedListener { private static final int MAX_IMAGE_DIMENSION = HugeImageLoader.getMaxTextureSize(); // Identifies a particular Loader or a LoaderManager being used in this component @@ -234,4 +235,12 @@ public long getImageId(int position) { return DBUtils.getLong(cursor, FotoSql.SQL_COL_PK, 0); } + /** + * PhotoChangeNotifyer.PhotoChangedListener + **/ + @Override + public void onNotifyPhotoChanged() { + notifyDataSetChanged(); + } + } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java index e3d5d693..a06d6094 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/gallery/cursor/GalleryCursorFragment.java @@ -82,8 +82,8 @@ import de.k3b.android.androFotoFinder.tagDB.TagsPickerFragment; import de.k3b.android.util.AndroidFileCommands; import de.k3b.android.util.DBUtils; -import de.k3b.android.util.DataChangeNotifyer; import de.k3b.android.util.OsUtils; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.util.PhotoPropertiesMediaFilesScanner; import de.k3b.android.util.ResourceUtils; import de.k3b.android.widget.AboutDialogPreference; @@ -121,7 +121,7 @@ * if (view-non-select) menu_gallery_non_selected_only + menu_gallery_non_multiselect */ public class GalleryCursorFragment extends Fragment implements Queryable, DirectoryGui, Common, - TagsPickerFragment.ITagsPicker, DataChangeNotifyer.DataChangedListener { + TagsPickerFragment.ITagsPicker, PhotoChangeNotifyer.PhotoChangedListener { private static final String INSTANCE_STATE_LAST_VISIBLE_POSITION = "lastVisiblePosition"; private static final String INSTANCE_STATE_SELECTED_ITEM_IDS = "selectedItems"; private static final String INSTANCE_STATE_OLD_TITLE = "oldTitle"; @@ -209,7 +209,7 @@ public SelectedItems getSelectedItems() { return mSelectedItems; } - public void onNotifyDataChanged() { + public void onNotifyPhotoChanged() { requeryIfDataHasChanged(); } @@ -243,7 +243,7 @@ private void requery(String why) { private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { if (AndroidFileCommands.canProcessFile(this.getActivity(), false)) { - DataChangeNotifyer.setDataChangedListener(this); + PhotoChangeNotifyer.setPhotoChangedListener(this); mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), @@ -551,7 +551,7 @@ protected void doInBackground(Long id, Cursor cursor) { protected void onPostExecute(SelectedItems selectedItems) { if (!isCancelled()) { onMissingDisplayNamesComplete(mStatus); - onNotifyDataChanged(); + onNotifyPhotoChanged(); } } }; @@ -935,7 +935,7 @@ protected void onPostExecute(SelectedItems selectedItems) { } else { onDuplicatesFound(null, mStatus); } - onNotifyDataChanged(); + onNotifyPhotoChanged(); } else { if (mStatus != null) { mStatus.append("\nTask canceled"); @@ -1039,109 +1039,8 @@ protected void onDirectoryPick(IDirectory selection) { } } - class LocalCursorLoader implements LoaderManager.LoaderCallbacks { - /** - * called by LoaderManager.getLoader(ACTIVITY_ID) to (re)create loader - * that attaches to last query/cursor if it still exist i.e. after rotation - */ - @Override - public Loader onCreateLoader(int aLoaderID, Bundle bundle) { - if (loaderID == aLoaderID) { - QueryParameter query = getCurrentQuery(); - mRequeryInstanceCount++; - if (Global.debugEnabledSql) { - Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onCreateLoader" - + getDebugContext() + - " : query = " + query); - } - return FotoSql.createCursorLoader(getActivity().getApplicationContext(), query); - } - - // An invalid id was passed in - return null; - } - - /** - * called after media db content has changed - */ - @Override - public void onLoadFinished(Loader _loader, Cursor data) { - mLastVisiblePosition = mGalleryView.getLastVisiblePosition(); - - final Activity context = getActivity(); - if (data == null) { - CursorLoaderWithException loader = (CursorLoaderWithException) _loader; - String title; - String message = context.getString(R.string.global_err_sql_message_format, loader.getException().getMessage(), loader.getQuery().toSqlString()); - if (loader.getException() != null) { - if (0 != loader.getQuery().toSqlString().compareTo(getCurrentQuery(FotoSql.queryDetail).toSqlString())) { - // query is not default query. revert to default query - mGalleryContentQuery = FotoSql.queryDetail; - requery("requery after query-errror"); - title = context.getString(R.string.global_err_sql_title_reload); - } else { - title = context.getString(R.string.global_err_system); - context.finish(); - } - Dialogs.messagebox(context, title, message); - return; - } - } - - mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); - // do change the data - mAdapter.swapCursor(data); - - if (mLastVisiblePosition > 0) { - mGalleryView.smoothScrollToPosition(mLastVisiblePosition); - mLastVisiblePosition = -1; - } - - final int resultCount = (data == null) ? 0 : data.getCount(); - if (Global.debugEnabled) { - Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onLoadFinished" - + getDebugContext() + - " fount " + resultCount + " rows"); - } - - // do change the data - mAdapter.notifyDataSetChanged(); - - if (mLastVisiblePosition > 0) { - mGalleryView.smoothScrollToPosition(mLastVisiblePosition); - mLastVisiblePosition = -1; - } - - // show the changes - - if (context instanceof OnGalleryInteractionListener) { - ((OnGalleryInteractionListener) context).setResultCount(resultCount); - } - multiSelectionReplaceTitleIfNecessary(); - } - - /** - * called by LoaderManager. after search criteria were changed or if activity is destroyed. - */ - @Override - public void onLoaderReset(Loader loader) { - if (Global.debugEnabled) { - Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onLoaderReset" + getDebugContext()); - } - // rember position where we have to scroll to after refreshLocal is finished. - mLastVisiblePosition = mGalleryView.getLastVisiblePosition(); - - mAdapter.swapCursor(null); - mAdapter.notifyDataSetChanged(); - } - - @NonNull - protected String getDebugContext() { - return "(@" + loaderID + ", #" + mRequeryInstanceCount + - ", LastVisiblePosition=" + mLastVisiblePosition + -// ", Path='" + mInitialFilePath + - "')"; - } + public void notifyPhotoChanged() { + PhotoChangeNotifyer.notifyPhotoChanged(this.getActivity(), this.mAdapter); } private boolean onPickOk() { @@ -1415,25 +1314,109 @@ private void onMissingDisplayNamesComplete(StringBuffer debugMessage) { } } - private class TagUpdateTask extends TagTask> { - - TagUpdateTask(SelectedFiles fotos) { - super(GalleryCursorFragment.this.getActivity(), R.string.tags_activity_title); - this.getWorkflow().init(GalleryCursorFragment.this.getActivity(), fotos, null); + class LocalCursorLoader implements LoaderManager.LoaderCallbacks { + /** + * called by LoaderManager.getLoader(ACTIVITY_ID) to (re)create loader + * that attaches to last query/cursor if it still exist i.e. after rotation + */ + @Override + public Loader onCreateLoader(int aLoaderID, Bundle bundle) { + if (loaderID == aLoaderID) { + QueryParameter query = getCurrentQuery(); + mRequeryInstanceCount++; + if (Global.debugEnabledSql) { + Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onCreateLoader" + + getDebugContext() + + " : query = " + query); + } + return FotoSql.createCursorLoader(getActivity().getApplicationContext(), query); + } + // An invalid id was passed in + return null; } + /** + * called after media db content has changed + */ @Override - protected Integer doInBackground(List... params) { - return getWorkflow().updateTags(params[0], params[1]); + public void onLoadFinished(Loader _loader, Cursor data) { + mLastVisiblePosition = mGalleryView.getLastVisiblePosition(); + + final Activity context = getActivity(); + if (data == null) { + CursorLoaderWithException loader = (CursorLoaderWithException) _loader; + String title; + String message = context.getString(R.string.global_err_sql_message_format, loader.getException().getMessage(), loader.getQuery().toSqlString()); + if (loader.getException() != null) { + if (0 != loader.getQuery().toSqlString().compareTo(getCurrentQuery(FotoSql.queryDetail).toSqlString())) { + // query is not default query. revert to default query + mGalleryContentQuery = FotoSql.queryDetail; + requery("requery after query-errror"); + title = context.getString(R.string.global_err_sql_title_reload); + } else { + title = context.getString(R.string.global_err_system); + context.finish(); + } + Dialogs.messagebox(context, title, message); + return; + } + } + + mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); + // do change the data + mAdapter.swapCursor(data); + + if (mLastVisiblePosition > 0) { + mGalleryView.smoothScrollToPosition(mLastVisiblePosition); + mLastVisiblePosition = -1; + } + + final int resultCount = (data == null) ? 0 : data.getCount(); + if (Global.debugEnabled) { + Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onLoadFinished" + + getDebugContext() + + " fount " + resultCount + " rows"); + } + + // do change the data + notifyPhotoChanged(); + + if (mLastVisiblePosition > 0) { + mGalleryView.smoothScrollToPosition(mLastVisiblePosition); + mLastVisiblePosition = -1; + } + + // show the changes + + if (context instanceof OnGalleryInteractionListener) { + ((OnGalleryInteractionListener) context).setResultCount(resultCount); + } + multiSelectionReplaceTitleIfNecessary(); } + /** + * called by LoaderManager. after search criteria were changed or if activity is destroyed. + */ @Override - protected void onPostExecute(Integer itemCount) { - super.onPostExecute(itemCount); - onNotifyDataChanged(); + public void onLoaderReset(Loader loader) { + if (Global.debugEnabled) { + Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onLoaderReset" + getDebugContext()); + } + // rember position where we have to scroll to after refreshLocal is finished. + mLastVisiblePosition = mGalleryView.getLastVisiblePosition(); + + mAdapter.swapCursor(null); + notifyPhotoChanged(); } + @NonNull + protected String getDebugContext() { + return "(@" + loaderID + ", #" + mRequeryInstanceCount + + ", LastVisiblePosition=" + mLastVisiblePosition + +// ", Path='" + mInitialFilePath + + "')"; + } } /** is called when removeDuplicates() found duplicates */ @@ -1512,4 +1495,25 @@ private boolean toggleSelection(long imageID) { } } + private class TagUpdateTask extends TagTask> { + + TagUpdateTask(SelectedFiles fotos) { + super(GalleryCursorFragment.this.getActivity(), R.string.tags_activity_title); + this.getWorkflow().init(GalleryCursorFragment.this.getActivity(), fotos, null); + + } + + @Override + protected Integer doInBackground(List... params) { + return getWorkflow().updateTags(params[0], params[1]); + } + + @Override + protected void onPostExecute(Integer itemCount) { + super.onPostExecute(itemCount); + onNotifyPhotoChanged(); + } + + } + } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java index 52553ef0..89edc228 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImageDetailActivityViewPager.java @@ -64,10 +64,10 @@ import de.k3b.android.androFotoFinder.tagDB.TagTask; import de.k3b.android.androFotoFinder.tagDB.TagsPickerFragment; import de.k3b.android.util.AndroidFileCommands; -import de.k3b.android.util.DataChangeNotifyer; import de.k3b.android.util.FileManagerUtil; import de.k3b.android.util.IntentUtil; import de.k3b.android.util.OsUtils; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.util.PhotoPropertiesMediaFilesScanner; import de.k3b.android.util.PhotoPropertiesMediaFilesScannerAsyncTask; import de.k3b.android.widget.AboutDialogPreference; @@ -94,7 +94,7 @@ */ public class ImageDetailActivityViewPager extends ActivityWithAutoCloseDialogs implements Common, TagsPickerFragment.ITagsPicker, - DataChangeNotifyer.DataChangedListener { + PhotoChangeNotifyer.PhotoChangedListener { private static final String INSTANCE_STATE_MODIFY_COUNT = "mModifyCount"; private static final String INSTANCE_STATE_LAST_SCROLL_POSITION = "lastScrollPosition"; /** #70: remember on config change (screen rotation) */ @@ -250,7 +250,7 @@ public boolean onOptionsItemSelected(MenuItem menuItem) { result = cmdMoveOrCopyWithDestDirPicker(true, mFileCommands.getLastCopyToPath(), getCurrentFoto()); break; case R.id.menu_item_rename: - DataChangeNotifyer.setDataChangedListener(this); + PhotoChangeNotifyer.setPhotoChangedListener(this); result = onRenameQueston(getCurrentFoto(), getCurrentImageId(), getCurrentFilePath(), null); break; case R.id.menu_exif: @@ -566,7 +566,7 @@ protected void onPause() { unhideActionBar(DISABLE_HIDE_ACTIONBAR, "onPause"); Global.debugMemory(mDebugPrefix, "onPause"); startStopSlideShow(false); - DataChangeNotifyer.setDataChangedListener(null); // notify triggererd in onResume + PhotoChangeNotifyer.setPhotoChangedListener(null); // notify triggererd in onResume super.onPause(); } @@ -682,7 +682,7 @@ private void onRenameAnswer(SelectedFiles currentFoto, final long fotoId, final errorMessage = getString(R.string.image_err_file_exists_format, dest.getAbsoluteFile()); } - DataChangeNotifyer.setDataChangedListener(this); + PhotoChangeNotifyer.setPhotoChangedListener(this); if (errorMessage != null) { // dest-file already exists Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); @@ -914,7 +914,7 @@ public boolean onPrepareOptionsMenu(Menu menu) { private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { if (AndroidFileCommands.canProcessFile(this, false)) { - DataChangeNotifyer.setDataChangedListener(this); + PhotoChangeNotifyer.setPhotoChangedListener(this); mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), @@ -1009,7 +1009,7 @@ private boolean onEditExif(MenuItem menuItem, SelectedFiles currentFoto, final l return true; } - public void onNotifyDataChanged() { + public void onNotifyPhotoChanged() { requeryIfDataHasChanged(); } @@ -1041,7 +1041,7 @@ private boolean tagsShowEditDialog(SelectedFiles fotos) { dlg.setRemoveNames(new ArrayList()); dlg.setBaseQuery(mGalleryContentQuery); setAutoClose(dlg, null, null); - DataChangeNotifyer.setDataChangedListener(this); + PhotoChangeNotifyer.setPhotoChangedListener(this); dlg.show(getFragmentManager(), "editTags"); return true; } @@ -1184,6 +1184,41 @@ private void setContextMode(Object modeName) { } } + public void notifyPhotoChanged() { + PhotoChangeNotifyer.notifyPhotoChanged(this, this.mAdapter); + } + + class LocalFileCommands extends AndroidFileCommands { + @Override + protected void onPostProcess(String what, int opCode, SelectedFiles selectedFiles, int modifyCount, int itemCount, String[] oldPathNames, String[] newPathNames) { + mInitialFilePath = null; + switch (opCode) { + case OP_MOVE: + case OP_RENAME: + if ((newPathNames != null) && (newPathNames.length > 0)) { + // so selection will be restored to this after load complete + mInitialFilePath = newPathNames[0]; + } + break; + case OP_COPY: + if ((oldPathNames != null) && (oldPathNames.length > 0)) { + // so selection will be restored to this after load complete + mInitialFilePath = oldPathNames[0]; + } + break; + default: + break; + } + + super.onPostProcess(what, opCode, selectedFiles, modifyCount, itemCount, oldPathNames, newPathNames); + + if ((opCode == OP_RENAME) || (opCode == OP_MOVE) || (opCode == OP_DELETE) || (opCode == OP_RENAME)) { + reloadIfDataHasChanged(); + } + } + + } + public static class MoveOrCopyDestDirPicker extends DirectoryPickerFragment { protected static AndroidFileCommands sFileCommands = null; @@ -1233,41 +1268,42 @@ protected void onDirectoryPick(IDirectory selection) { mModifyCount++; // copy or move initiated getActivity().setResult((mModifyCount == 0) ? RESULT_NOCHANGE : RESULT_CHANGE); - DataChangeNotifyer.setDataChangedListener(((ImageDetailActivityViewPager) getActivity())); + PhotoChangeNotifyer.setPhotoChangedListener(((ImageDetailActivityViewPager) getActivity())); sFileCommands.onMoveOrCopyDirectoryPick(getMove(), getSrcFotos(), selection); dismiss(); } } - class LocalFileCommands extends AndroidFileCommands { + private class TagUpdateTask extends TagTask> { + + TagUpdateTask(SelectedFiles fotos) { + super(ImageDetailActivityViewPager.this, R.string.tags_activity_title); + this.getWorkflow().init(ImageDetailActivityViewPager.this, fotos, null); + + } + @Override - protected void onPostProcess(String what, int opCode, SelectedFiles selectedFiles, int modifyCount, int itemCount, String[] oldPathNames, String[] newPathNames) { - mInitialFilePath = null; - switch (opCode) { - case OP_MOVE: - case OP_RENAME: - if ((newPathNames != null) && (newPathNames.length > 0)) { - // so selection will be restored to this after load complete - mInitialFilePath = newPathNames[0]; - } - break; - case OP_COPY: - if ((oldPathNames != null) && (oldPathNames.length > 0)) { - // so selection will be restored to this after load complete - mInitialFilePath = oldPathNames[0]; - } - break; - default: - break; - } + protected Integer doInBackground(List... params) { + return getWorkflow().updateTags(params[0], params[1]); + } - super.onPostProcess(what, opCode, selectedFiles, modifyCount, itemCount, oldPathNames, newPathNames); + @Override + protected void onPostExecute(Integer itemCount) { + super.onPostExecute(itemCount); + reloadIfDataHasChanged(); + } + } - if ((opCode == OP_RENAME) || (opCode == OP_MOVE) || (opCode == OP_DELETE) || (opCode == OP_RENAME)) { - reloadIfDataHasChanged(); + /** + * #70: adds/removes/replases contextColumnExpression + */ + private static void addContextColumn(QueryParameter query, String contextColumnExpression) { + if (query != null) { + query.removeFirstColumnThatContains(CONTEXT_COLUMN_ALIAS); + if ((contextColumnExpression != null) && (contextColumnExpression.trim().length() > 0)) { + query.addColumn(contextColumnExpression + CONTEXT_COLUMN_ALIAS); } } - } /** @@ -1323,7 +1359,7 @@ public void onLoadFinished(Loader loader, Cursor data) { } // do change the data - mAdapter.notifyDataSetChanged(); + notifyPhotoChanged(); mViewPager.setAdapter(mAdapter); // show the changes @@ -1342,7 +1378,7 @@ public void onLoaderReset(Loader loader) { Log.i(Global.LOG_CONTEXT, mDebugPrefix + " onLoaderReset" + getDebugContext()); } - mAdapter.notifyDataSetChanged(); + notifyPhotoChanged(); } @NonNull @@ -1353,34 +1389,4 @@ private String getDebugContext() { "')"; } } - - private class TagUpdateTask extends TagTask> { - - TagUpdateTask(SelectedFiles fotos) { - super(ImageDetailActivityViewPager.this, R.string.tags_activity_title); - this.getWorkflow().init(ImageDetailActivityViewPager.this, fotos, null); - - } - - @Override - protected Integer doInBackground(List... params) { - return getWorkflow().updateTags(params[0], params[1]); - } - - @Override - protected void onPostExecute(Integer itemCount) { - super.onPostExecute(itemCount); - reloadIfDataHasChanged(); - } - } - - /** #70: adds/removes/replases contextColumnExpression */ - private static void addContextColumn(QueryParameter query, String contextColumnExpression) { - if (query != null) { - query.removeFirstColumnThatContains(CONTEXT_COLUMN_ALIAS); - if ((contextColumnExpression != null) && (contextColumnExpression.trim().length() > 0)) { - query.addColumn(contextColumnExpression + CONTEXT_COLUMN_ALIAS); - } - } - } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImagePagerAdapterFromCursor.java b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImagePagerAdapterFromCursor.java index a26e5276..4b42854c 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImagePagerAdapterFromCursor.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/imagedetail/ImagePagerAdapterFromCursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -49,6 +49,7 @@ import de.k3b.android.util.DBUtils; import de.k3b.android.util.GarbageCollector; import de.k3b.android.util.MenuUtils; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.util.ResourceUtils; import de.k3b.media.PhotoPropertiesBulkUpdateService; @@ -58,7 +59,7 @@ * Translates between position in ViewPager and content page content with image * Created by k3b on 04.07.2015. */ -public class ImagePagerAdapterFromCursor extends PagerAdapter { +public class ImagePagerAdapterFromCursor extends PagerAdapter implements PhotoChangeNotifyer.PhotoChangedListener { private static final int MAX_IMAGE_DIMENSION = HugeImageLoader.getMaxTextureSize(); /** colum alias for optinal sql expression to show ContextDetails */ @@ -463,4 +464,12 @@ public int getMenuId() { public void setContext(MenuItem context) { if (mImageButtonController != null) mImageButtonController.setContext(context); } + + /** + * PhotoChangeNotifyer.PhotoChangedListener + **/ + @Override + public void onNotifyPhotoChanged() { + notifyDataSetChanged(); + } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/GlobalMediaContentObserver.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/GlobalMediaContentObserver.java index f4d2feb6..8bfb9fd0 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/GlobalMediaContentObserver.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/GlobalMediaContentObserver.java @@ -24,7 +24,7 @@ import android.os.Handler; import android.util.Log; -import de.k3b.android.util.DataChangeNotifyer; +import de.k3b.android.util.PhotoChangeNotifyer; /** * collect notifications that media content has changed @@ -34,13 +34,13 @@ public class GlobalMediaContentObserver extends ContentObserver { private static Handler delayedChangeNotifiyHandler = null; private static Runnable delayedRunner = null; private static Context appContext; - private static DataChangeNotifyer.DataChangedListener dataChangedListener = null; + private static PhotoChangeNotifyer.PhotoChangedListener photoChangedListener = null; private GlobalMediaContentObserver() { super(null); } - public static GlobalMediaContentObserver getInstance(Context appContext) { + public static GlobalMediaContentObserver getInstance(final Context appContext) { if (instance == null) { GlobalMediaContentObserver.appContext = appContext; @@ -72,12 +72,12 @@ public void onChange(boolean selfChange, Uri uri) { * * @param appContext */ - private void onExternalDataChangeCompleted(Context appContext) { + private static void onExternalDataChangeCompleted(Context appContext) { Log.d(MediaDBRepository.LOG_TAG, "Media content changed "); // todo fix database - if (dataChangedListener != null) { - dataChangedListener.onNotifyDataChanged(); + if (photoChangedListener != null) { + photoChangedListener.onNotifyPhotoChanged(); } } } \ No newline at end of file diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/tagDB/TagsPickerFragment.java b/app/src/main/java/de/k3b/android/androFotoFinder/tagDB/TagsPickerFragment.java index 262f7c33..4d34dbec 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/tagDB/TagsPickerFragment.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/tagDB/TagsPickerFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 by k3b. + * Copyright (c) 2017-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -843,10 +843,10 @@ private int tagAdd(Tag parent, String itemExpression) { } } mDataAdapter.notifyDataSetInvalidated(); - mDataAdapter.notifyDataSetChanged(); + notifyDataSetChanged(); mDataAdapter.reloadList(); TagRepository.getInstance().save(); - mDataAdapter.notifyDataSetChanged(); + notifyDataSetChanged(); } return changeCount; } @@ -860,7 +860,7 @@ private void tagChange(Tag tag, Tag parent) { mDataAdapter.reloadList(); } TagRepository.getInstance().save(); - mDataAdapter.notifyDataSetChanged(); + notifyDataSetChanged(); } private boolean onPaste(Tag currentMenuSelection) { @@ -940,4 +940,8 @@ private void refershResultList() { private void refreshCounter() { TagsPickerFragment.this.mDataAdapter.getCount(); } + + public void notifyDataSetChanged() { + mDataAdapter.notifyDataSetChanged(); + } } diff --git a/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java b/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java index 8d001f99..127ab497 100644 --- a/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java +++ b/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java @@ -173,12 +173,12 @@ private static int getResourceId(int opCode) { } - public boolean onOptionsItemSelected(final MenuItem item, final SelectedFiles selectedFileNames, DataChangeNotifyer.DataChangedListener dataChangedListener) { + public boolean onOptionsItemSelected(final MenuItem item, final SelectedFiles selectedFileNames, PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) { if ((selectedFileNames != null) && (selectedFileNames.size() > 0)) { // Handle item selection switch (item.getItemId()) { case R.id.cmd_delete: - return cmdDeleteFileWithQuestion(selectedFileNames, dataChangedListener); + return cmdDeleteFileWithQuestion(selectedFileNames, photoChangedListener); default:break; } } @@ -277,7 +277,7 @@ private void setLastCopyToPath(String copyToPath) { } public boolean cmdDeleteFileWithQuestion(final SelectedFiles fotos, - final DataChangeNotifyer.DataChangedListener dataChangedListener) { + final PhotoChangeNotifyer.PhotoChangedListener photoChangedListener) { String[] pathNames = fotos.getFileNames(); String errorMessage = checkWriteProtected(R.string.delete_menu_title, SelectedFiles.getFiles(pathNames)); @@ -308,8 +308,8 @@ public void onClick( final int id) { mActiveAlert = null; deleteFiles(fotos, null); - if (dataChangedListener != null) { - dataChangedListener.onNotifyDataChanged(); + if (photoChangedListener != null) { + photoChangedListener.onNotifyPhotoChanged(); } } } diff --git a/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java b/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java deleted file mode 100644 index 54371bcf..00000000 --- a/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019-2020 by k3b. - * - * This file is part of AndroFotoFinder / #APhotoManager. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see - */ - -package de.k3b.android.util; - -public class DataChangeNotifyer { - public static DataChangedListener dataChangedListener = null; - - public static void setDataChangedListener(DataChangedListener dataChangedListener) { - DataChangeNotifyer.dataChangedListener = dataChangedListener; - } - - public interface DataChangedListener { - void onNotifyDataChanged(); - } - -} diff --git a/app/src/main/java/de/k3b/android/util/PhotoChangeNotifyer.java b/app/src/main/java/de/k3b/android/util/PhotoChangeNotifyer.java new file mode 100644 index 00000000..da422188 --- /dev/null +++ b/app/src/main/java/de/k3b/android/util/PhotoChangeNotifyer.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019-2020 by k3b. + * + * This file is part of AndroFotoFinder / #APhotoManager. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see + */ + +package de.k3b.android.util; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.provider.MediaStore; + +import de.k3b.android.androFotoFinder.queries.FotoSql; + +/** + * implements hiding Android specific Data change notifikation + **/ +public class PhotoChangeNotifyer { + public static PhotoChangedListener photoChangedListener = null; + + public static void setPhotoChangedListener(PhotoChangedListener photoChangedListener) { + PhotoChangeNotifyer.photoChangedListener = photoChangedListener; + } + + public static void notifyPhotoChanged(Context context, PhotoChangedListener adapter) { + if (adapter != null) adapter.onNotifyPhotoChanged(); + + if (false) { + context.getApplicationContext().getContentResolver().notifyChange(FotoSql.SQL_TABLE_EXTERNAL_CONTENT_URI_FILE, null, false); + } + } + + public static final void registerContentObserver(Context context, ContentObserver observer) { + final ContentResolver contentResolver = context.getApplicationContext().getContentResolver(); + contentResolver.registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, true, observer); + contentResolver.registerContentObserver(MediaStore.Files.getContentUri("external"), true, observer); + } + + public static void unregisterContentObserver(Context context, ContentObserver instance) { + context.getApplicationContext().getContentResolver().unregisterContentObserver(instance); + } + + public interface PhotoChangedListener { + void onNotifyPhotoChanged(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java index f05c7f91..0fab7106 100644 --- a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java +++ b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java @@ -53,8 +53,8 @@ protected Integer doInBackground(String[]... pathNames) { private static void notifyIfThereAreChanges(Integer modifyCount, Context context, String why) { if (modifyCount > 0) { PhotoPropertiesMediaFilesScanner.notifyChanges(context, why); - if (DataChangeNotifyer.dataChangedListener != null) { - DataChangeNotifyer.dataChangedListener.onNotifyDataChanged(); + if (PhotoChangeNotifyer.photoChangedListener != null) { + PhotoChangeNotifyer.photoChangedListener.onNotifyPhotoChanged(); } } diff --git a/app/src/main/java/de/k3b/android/widget/BaseQueryActivity.java b/app/src/main/java/de/k3b/android/widget/BaseQueryActivity.java index eae81b05..99534cde 100644 --- a/app/src/main/java/de/k3b/android/widget/BaseQueryActivity.java +++ b/app/src/main/java/de/k3b/android/widget/BaseQueryActivity.java @@ -55,6 +55,7 @@ import de.k3b.android.androFotoFinder.tagDB.TagSql; import de.k3b.android.androFotoFinder.tagDB.TagsPickerFragment; import de.k3b.android.osmdroid.OsmdroidUtil; +import de.k3b.android.util.PhotoChangeNotifyer; import de.k3b.android.util.PhotoPropertiesMediaFilesScanner; import de.k3b.database.QueryParameter; import de.k3b.io.AlbumFile; @@ -673,8 +674,8 @@ public boolean onOk(List addNames, List removeNames) { protected void onCreate(Bundle savedInstanceState) { Global.debugMemory(mDebugPrefix, "onCreate"); super.onCreate(savedInstanceState); - this.getContentResolver().registerContentObserver(FotoSql.SQL_TABLE_EXTERNAL_CONTENT_URI, true, mMediaObserverDirectory); - this.getContentResolver().registerContentObserver(FotoSql.SQL_TABLE_EXTERNAL_CONTENT_URI_FILE, true, mMediaObserverDirectory); + PhotoChangeNotifyer.registerContentObserver(this, mMediaObserverDirectory); + } protected void onCreateData(Bundle savedInstanceState) { @@ -966,7 +967,7 @@ public void onLowMemory() { @Override protected void onDestroy() { super.onDestroy(); - this.getContentResolver().unregisterContentObserver(mMediaObserverDirectory); + PhotoChangeNotifyer.unregisterContentObserver(this, mMediaObserverDirectory); this.mGalleryQueryParameter.mGalleryContentBaseQuery = null; invalidateDirectories(mDebugPrefix + "#onDestroy"); }