diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/AndroidTransactionLogger.java b/app/src/main/java/de/k3b/android/androFotoFinder/AndroidTransactionLogger.java index bdc68c6f..a06087ed 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/AndroidTransactionLogger.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/AndroidTransactionLogger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 by k3b. + * Copyright (c) 2017-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -19,8 +19,6 @@ package de.k3b.android.androFotoFinder; -import android.app.Activity; - import java.io.Closeable; import java.io.IOException; @@ -37,7 +35,7 @@ public class AndroidTransactionLogger extends TransactionLoggerBase implements Closeable { private AndroidFileCommands execLog; - public AndroidTransactionLogger(Activity ctx, long now, AndroidFileCommands execLog) { + public AndroidTransactionLogger(AndroidFileCommands execLog, long now) { super(execLog, now); this.execLog = execLog; 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 02696b3f..0d490aca 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -82,6 +82,7 @@ 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.PhotoPropertiesMediaFilesScanner; import de.k3b.android.util.ResourceUtils; @@ -119,7 +120,8 @@ * if (isMultiSelectionActive()) menu_gallery_multiselect_mode_all + menu_image_commands * if (view-non-select) menu_gallery_non_selected_only + menu_gallery_non_multiselect */ -public class GalleryCursorFragment extends Fragment implements Queryable, DirectoryGui,Common, TagsPickerFragment.ITagsPicker { +public class GalleryCursorFragment extends Fragment implements Queryable, DirectoryGui, Common, + TagsPickerFragment.ITagsPicker, DataChangeNotifyer.DataChangedListener { 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"; @@ -149,6 +151,8 @@ public class GalleryCursorFragment extends Fragment implements Queryable, Direc private GridView mGalleryView; private ShareActionProvider mShareActionProvider; + long mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); + private GalleryCursorAdapterFromArray mAdapter = null; private OnGalleryInteractionListener mGalleryListener; @@ -205,127 +209,57 @@ public SelectedItems getSelectedItems() { return mSelectedItems; } - 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; - } - } - - // 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(); + public void onNotifyDataChanged() { + requeryIfDataHasChanged(); + } - if (mLastVisiblePosition > 0) { - mGalleryView.smoothScrollToPosition(mLastVisiblePosition); - mLastVisiblePosition = -1; - } + /** incremented every time a new curster/query is generated */ + private int mRequeryInstanceCount = 0; - // show the changes + protected LocalCursorLoader mCurorLoader = null; - if (context instanceof OnGalleryInteractionListener) { - ((OnGalleryInteractionListener) context).setResultCount(resultCount); - } - multiSelectionReplaceTitleIfNecessary(); + private void requeryIfDataHasChanged() { + if (FotoSql.getMediaDBApi().mustRequery(mUpdateId)) { + requery("requeryIfDataHasChanged"); } + } - /** 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(); + private void requery(String why) { + mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); + if (Global.debugEnabled) { + Log.i(Global.LOG_CONTEXT, mDebugPrefix + why + " requery\n" + ((mGalleryContentQuery != null) ? mGalleryContentQuery.toSqlString() : null)); } - @NonNull - protected String getDebugContext() { - return "(@" + loaderID + ", #" + mRequeryInstanceCount + - ", LastVisiblePosition=" + mLastVisiblePosition + -// ", Path='" + mInitialFilePath + - "')"; + if (mGalleryContentQuery != null) { + // query has been initialized + if (mCurorLoader == null) { + mCurorLoader = new LocalCursorLoader(); + getLoaderManager().initLoader(loaderID, null, mCurorLoader); + } else { + getLoaderManager().restartLoader(loaderID, null, this.mCurorLoader); + } } } - /** incremented every time a new curster/query is generated */ - private int mRequeryInstanceCount = 0; - - protected LocalCursorLoader mCurorLoader = null; - - protected class LocalFileCommands extends AndroidFileCommands { + private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { + if (AndroidFileCommands.canProcessFile(this.getActivity(), false)) { + DataChangeNotifyer.setDataChangedListener(this); + mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); - @Override - protected void onPostProcess(String what, int opCode, SelectedFiles selectedFiles, int modifyCount, int itemCount, String[] oldPathNames, String[] newPathNames) { - if (Global.clearSelectionAfterCommand || (opCode == OP_DELETE) || (opCode == OP_MOVE)) { - mShowSelectedOnly = true; - multiSelectionCancel(); + mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), + (move) ? FotoSql.QUERY_TYPE_GROUP_MOVE : FotoSql.QUERY_TYPE_GROUP_COPY, + lastCopyToPath); + if (!LockScreen.isLocked(this.getActivity())) { + mDestDirPicker.setContextMenuId(R.menu.menu_context_pick_osdir); } - super.onPostProcess(what, opCode, selectedFiles, modifyCount, itemCount, oldPathNames, newPathNames); - - if ((mAdapter.isInArrayMode()) && ((opCode == OP_RENAME) || (opCode == OP_MOVE) || (opCode == OP_DELETE))) { - mAdapter.refreshLocal(); - mGalleryView.setAdapter(mAdapter); - } + mDestDirPicker.setBaseQuery(getCurrentQuery()); + mDestDirPicker.show(getActivity().getFragmentManager(), "osdir"); } + return false; } + public GalleryCursorFragment() { mDebugPrefix = "GalleryCursorFragment#" + (id++) + " "; Global.debugMemory(mDebugPrefix, "ctor"); @@ -599,20 +533,31 @@ public void requery(Activity context, QueryParameter parameters, String why) { requery(why); } - private void requery(String why) { - if (Global.debugEnabled) { - Log.i(Global.LOG_CONTEXT, mDebugPrefix + why + " requery\n" + ((mGalleryContentQuery != null) ? mGalleryContentQuery.toSqlString() : null)); - } + /** + * image entries may not have DISPLAY_NAME which is essential for calculating the item-s folder. + */ + private void repairMissingDisplayNames() { + SqlJobTaskBase task = new SqlJobTaskBase(this.getActivity(), "Searching media database for missing 'displayname'-s:\n", null) { + private int mPathColNo = -2; + private int mResultCount = 0; - if (mGalleryContentQuery != null) { - // query has been initialized - if (mCurorLoader == null) { - mCurorLoader = new LocalCursorLoader(); - getLoaderManager().initLoader(loaderID, null, mCurorLoader); - } else { - getLoaderManager().restartLoader(loaderID, null, this.mCurorLoader); + @Override + protected void doInBackground(Long id, Cursor cursor) { + if (mPathColNo == -2) mPathColNo = cursor.getColumnIndex(FotoSql.SQL_COL_PATH); + mResultCount += PhotoPropertiesMediaFilesScanner.getInstance(getActivity()).updatePathRelatedFields(getActivity(), cursor, cursor.getString(mPathColNo), mColumnIndexPK, mPathColNo); } - } + + @Override + protected void onPostExecute(SelectedItems selectedItems) { + if (!isCancelled()) { + onMissingDisplayNamesComplete(mStatus); + onNotifyDataChanged(); + } + } + }; + QueryParameter query = FotoSql.queryGetMissingDisplayNames; + FotoSql.setWhereVisibility(query, VISIBILITY.PRIVATE_PUBLIC); + task.execute(query); } private QueryParameter getCurrentQuery() { @@ -966,19 +911,43 @@ private void cmdShowDetails() { // setAutoClose(null, dlg, null); } - 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); - - } + private void removeDuplicates() { + SqlJobTaskBase task = new SqlJobTaskBase(this.getActivity(), "Searching for duplcates in media database:\n", null) { + @Override + protected void doInBackground(Long id, Cursor cursor) { + this.mSelectedItems.add(id); + if (mStatus != null) { + mStatus + .append("\nduplicate found ") + .append(id) + .append("#") + .append(DBUtils.getString(cursor, FotoSql.SQL_COL_DISPLAY_TEXT, "???")) + //.append("\n") + ; + } + } - @Override - protected Integer doInBackground(List... params) { - return getWorkflow().updateTags(params[0], params[1]); - } + @Override + protected void onPostExecute(SelectedItems selectedItems) { + if (!isCancelled()) { + if ((selectedItems != null) && (selectedItems.size() > 0)) { + onDuplicatesFound(selectedItems, mStatus); + } else { + onDuplicatesFound(null, mStatus); + } + onNotifyDataChanged(); + } else { + if (mStatus != null) { + mStatus.append("\nTask canceled"); + Log.w(Global.LOG_CONTEXT, mDebugPrefix + mStatus); + } + } + } + }; + QueryParameter query = FotoSql.queryGetDuplicates; + FotoSql.setWhereVisibility(query, VISIBILITY.PRIVATE_PUBLIC); + task.execute(query); } private boolean onEditExif(MenuItem menuItem, SelectedFiles fotos) { @@ -1070,21 +1039,109 @@ protected void onDirectoryPick(IDirectory selection) { } } - private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { - if (AndroidFileCommands.canProcessFile(this.getActivity(), false)) { - mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); + 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); + } - mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), - (move) ? FotoSql.QUERY_TYPE_GROUP_MOVE : FotoSql.QUERY_TYPE_GROUP_COPY, - lastCopyToPath); - if (!LockScreen.isLocked(this.getActivity())) { - mDestDirPicker.setContextMenuId(R.menu.menu_context_pick_osdir); + // 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; + } } - mDestDirPicker.setBaseQuery(getCurrentQuery()); - mDestDirPicker.show(getActivity().getFragmentManager(), "osdir"); + 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 + + "')"; } - return false; } private boolean onPickOk() { @@ -1330,28 +1387,25 @@ private void fixMediaDatabase() { } } - /** image entries may not have DISPLAY_NAME which is essential for calculating the item-s folder. */ - private void repairMissingDisplayNames() { - SqlJobTaskBase task = new SqlJobTaskBase(this.getActivity(), "Searching media database for missing 'displayname'-s:\n", null) { - private int mPathColNo = -2; - private int mResultCount = 0; + protected class LocalFileCommands extends AndroidFileCommands { - @Override - protected void doInBackground(Long id, Cursor cursor) { - if (mPathColNo == -2) mPathColNo = cursor.getColumnIndex(FotoSql.SQL_COL_PATH); - mResultCount += PhotoPropertiesMediaFilesScanner.getInstance(getActivity()).updatePathRelatedFields(getActivity(), cursor, cursor.getString(mPathColNo), mColumnIndexPK, mPathColNo); + @Override + protected void onPostProcess(String what, int opCode, SelectedFiles selectedFiles, int modifyCount, int itemCount, String[] oldPathNames, String[] newPathNames) { + if (Global.clearSelectionAfterCommand || (opCode == OP_DELETE) || (opCode == OP_MOVE)) { + mShowSelectedOnly = true; + multiSelectionCancel(); } - @Override - protected void onPostExecute(SelectedItems selectedItems) { - if (!isCancelled()) { - onMissingDisplayNamesComplete(mStatus); - } + super.onPostProcess(what, opCode, selectedFiles, modifyCount, itemCount, oldPathNames, newPathNames); + + if ((mAdapter.isInArrayMode()) && ((opCode == OP_RENAME) || (opCode == OP_MOVE) || (opCode == OP_DELETE))) { + mAdapter.refreshLocal(); + mGalleryView.setAdapter(mAdapter); } - }; - QueryParameter query = FotoSql.queryGetMissingDisplayNames; - FotoSql.setWhereVisibility(query, VISIBILITY.PRIVATE_PUBLIC); - task.execute(query); + if ((opCode == OP_RENAME) || (opCode == OP_MOVE) || (opCode == OP_DELETE) || (opCode == OP_RENAME)) { + requeryIfDataHasChanged(); + } + } } /** called after MissingDisplayNamesComplete finished */ @@ -1361,42 +1415,25 @@ private void onMissingDisplayNamesComplete(StringBuffer debugMessage) { } } - private void removeDuplicates() { - SqlJobTaskBase task = new SqlJobTaskBase(this.getActivity(), "Searching for duplcates in media database:\n", null) { - @Override - protected void doInBackground(Long id, Cursor cursor) { - this.mSelectedItems.add(id); - if (mStatus != null) { - mStatus - .append("\nduplicate found ") - .append(id) - .append("#") - .append(DBUtils.getString(cursor,FotoSql.SQL_COL_DISPLAY_TEXT,"???")) - //.append("\n") - ; - } - } + private class TagUpdateTask extends TagTask> { - @Override - protected void onPostExecute(SelectedItems selectedItems) { - if (!isCancelled()) { - if ((selectedItems != null) && (selectedItems.size() > 0)) { - onDuplicatesFound(selectedItems, mStatus); - } else { - onDuplicatesFound(null, mStatus); - } - } else { - if (mStatus != null) { - mStatus.append("\nTask canceled"); - Log.w(Global.LOG_CONTEXT, mDebugPrefix + mStatus); - } + 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); + onNotifyDataChanged(); + } - } - } - }; - QueryParameter query = FotoSql.queryGetDuplicates; - FotoSql.setWhereVisibility(query, VISIBILITY.PRIVATE_PUBLIC); - task.execute(query); } /** is called when removeDuplicates() found duplicates */ 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 4a8b5f2d..e7f72f3d 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 @@ -1,6 +1,6 @@ /******************************************************************************* * Copyright 2011, 2012 Chris Banes. - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -64,6 +64,7 @@ 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; @@ -92,7 +93,8 @@ * Swipe left/right to show previous/next image. */ -public class ImageDetailActivityViewPager extends ActivityWithAutoCloseDialogs implements Common, TagsPickerFragment.ITagsPicker { +public class ImageDetailActivityViewPager extends ActivityWithAutoCloseDialogs implements Common, TagsPickerFragment.ITagsPicker, + DataChangeNotifyer.DataChangedListener { 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) */ @@ -167,36 +169,6 @@ public class ImageDetailActivityViewPager extends ActivityWithAutoCloseDialogs i long mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); - 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)) { - refreshIfNecessary(); - } - } - - } - @Override protected void onResume() { unhideActionBar(Global.actionBarHideTimeInMilliSecs, "onResume"); @@ -220,7 +192,7 @@ protected void onResume() { // workaround fragment lifecycle is newFragment.attach oldFragment.detach. // this makes shure that the visible fragment has commands MoveOrCopyDestDirPicker.sFileCommands = mFileCommands; - refreshIfNecessary(); + reloadIfDataHasChanged(); } @Override @@ -278,6 +250,7 @@ public boolean onOptionsItemSelected(MenuItem menuItem) { result = cmdMoveOrCopyWithDestDirPicker(true, mFileCommands.getLastCopyToPath(), getCurrentFoto()); break; case R.id.menu_item_rename: + DataChangeNotifyer.setDataChangedListener(this); result = onRenameQueston(getCurrentFoto(), getCurrentImageId(), getCurrentFilePath(), null); break; case R.id.menu_exif: @@ -365,6 +338,36 @@ public void run() { } + @Override + protected void onActivityResult(final int requestCode, + final int resultCode, final Intent intent) { + super.onActivityResult(requestCode, resultCode, intent); + if (mDestDirPicker != null) + mDestDirPicker.onActivityResult(requestCode, resultCode, intent); + + final boolean locked = LockScreen.isLocked(this); + if (this.locked != locked) { + this.locked = locked; + mMustReplaceMenue = true; + invalidateOptionsMenu(); + } + + if (requestCode == ACTION_RESULT_FORWARD) { + // forward result from child-activity to parent-activity + setResult(resultCode, intent); + finish(); + } else if (requestCode == ACTION_RESULT_MUST_MEDIA_SCAN) { + // #64 after edit the content might have been changed. update media DB. + String orgiginalFileToScan = getCurrentFilePath(); + + if (orgiginalFileToScan != null) { + PhotoPropertiesMediaFilesScanner.getInstance(this).updateMediaDatabase_Android42(this, null, orgiginalFileToScan); + } + } + + reloadIfDataHasChanged(); + } + /** * shows a new instance of ImageDetailActivityViewPager. * @@ -559,32 +562,12 @@ private void copyExtras(Intent dest, Bundle source, String... keys) { } @Override - protected void onActivityResult(final int requestCode, - final int resultCode, final Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); - if (mDestDirPicker != null) mDestDirPicker.onActivityResult(requestCode,resultCode,intent); - - final boolean locked = LockScreen.isLocked(this); - if (this.locked != locked) { - this.locked = locked; - mMustReplaceMenue = true; - invalidateOptionsMenu(); - } - - if (requestCode == ACTION_RESULT_FORWARD) { - // forward result from child-activity to parent-activity - setResult(resultCode, intent); - finish(); - } else if (requestCode == ACTION_RESULT_MUST_MEDIA_SCAN) { - // #64 after edit the content might have been changed. update media DB. - String orgiginalFileToScan = getCurrentFilePath(); - - if (orgiginalFileToScan != null) { - PhotoPropertiesMediaFilesScanner.getInstance(this).updateMediaDatabase_Android42(this, null, orgiginalFileToScan); - } - } - - refreshIfNecessary(); + protected void onPause() { + unhideActionBar(DISABLE_HIDE_ACTIONBAR, "onPause"); + Global.debugMemory(mDebugPrefix, "onPause"); + startStopSlideShow(false); + DataChangeNotifyer.setDataChangedListener(null); // notify triggererd in onResume + super.onPause(); } private static boolean mustForward(Intent intent) { @@ -674,12 +657,43 @@ public void setTitle(CharSequence title) { } */ - @Override - protected void onPause () { - unhideActionBar(DISABLE_HIDE_ACTIONBAR, "onPause"); - Global.debugMemory(mDebugPrefix, "onPause"); - startStopSlideShow(false); - super.onPause(); + private void onRenameAnswer(SelectedFiles currentFoto, final long fotoId, final String fotoSourcePath, String newFileName) { + File src = new File(fotoSourcePath); + File dest = new File(src.getParentFile(), newFileName); + + File srcXmpShort = FileProcessor.getSidecar(src, false); + boolean hasSideCarShort = ((srcXmpShort != null) && (mFileCommands.osFileExists(srcXmpShort))); + File srcXmpLong = FileProcessor.getSidecar(src, true); + boolean hasSideCarLong = ((srcXmpLong != null) && (mFileCommands.osFileExists(srcXmpLong))); + + File destXmpShort = FileProcessor.getSidecar(dest, false); + File destXmpLong = FileProcessor.getSidecar(dest, true); + + if (src.equals(dest)) return; // new name == old name ==> nothing to do + + String errorMessage = null; + if (hasSideCarShort && mFileCommands.osFileExists(destXmpShort)) { + errorMessage = getString(R.string.image_err_file_exists_format, destXmpShort.getAbsoluteFile()); + } + if (hasSideCarLong && mFileCommands.osFileExists(destXmpLong)) { + errorMessage = getString(R.string.image_err_file_exists_format, destXmpLong.getAbsoluteFile()); + } + if (mFileCommands.osFileExists(dest)) { + errorMessage = getString(R.string.image_err_file_exists_format, dest.getAbsoluteFile()); + } + + DataChangeNotifyer.setDataChangedListener(this); + if (errorMessage != null) { + // dest-file already exists + Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); + onRenameQueston(currentFoto, fotoId, fotoSourcePath, newFileName); + } else if (mFileCommands.rename(currentFoto, dest, null)) { + mModifyCount++; + } else { + // rename failed + errorMessage = getString(R.string.image_err_file_rename_format, src.getAbsoluteFile()); + Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); + } } private boolean onRenameQueston(final SelectedFiles currentFoto, final long fotoId, final String fotoPath, final String _newName) { @@ -898,43 +912,19 @@ public boolean onPrepareOptionsMenu(Menu menu) { return super.onPrepareOptionsMenu(menu); } - private void onRenameAnswer(SelectedFiles currentFoto, final long fotoId, final String fotoSourcePath, String newFileName) { - File src = new File(fotoSourcePath); - File dest = new File(src.getParentFile(), newFileName); - - File srcXmpShort = FileProcessor.getSidecar(src, false); - boolean hasSideCarShort = ((srcXmpShort != null) && (mFileCommands.osFileExists(srcXmpShort))); - File srcXmpLong = FileProcessor.getSidecar(src, true); - boolean hasSideCarLong = ((srcXmpLong != null) && (mFileCommands.osFileExists(srcXmpLong))); - - File destXmpShort = FileProcessor.getSidecar(dest, false); - File destXmpLong = FileProcessor.getSidecar(dest, true); - - if (src.equals(dest)) return; // new name == old name ==> nothing to do - - String errorMessage = null; - if (hasSideCarShort && mFileCommands.osFileExists(destXmpShort)) { - errorMessage = getString(R.string.image_err_file_exists_format, destXmpShort.getAbsoluteFile()); - } - if (hasSideCarLong && mFileCommands.osFileExists(destXmpLong)) { - errorMessage = getString(R.string.image_err_file_exists_format, destXmpLong.getAbsoluteFile()); - } - if (mFileCommands.osFileExists(dest)) { - errorMessage = getString(R.string.image_err_file_exists_format, dest.getAbsoluteFile()); - } + private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { + if (AndroidFileCommands.canProcessFile(this, false)) { + DataChangeNotifyer.setDataChangedListener(this); + mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); - if (errorMessage != null) { - // dest-file already exists - Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); - onRenameQueston(currentFoto, fotoId, fotoSourcePath, newFileName); - } else if (mFileCommands.rename(currentFoto, dest, null)) { - mModifyCount++; - refreshIfNecessary(); - } else { - // rename failed - errorMessage = getString(R.string.image_err_file_rename_format, src.getAbsoluteFile()); - Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); + mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), + (move) ? FotoSql.QUERY_TYPE_GROUP_MOVE : FotoSql.QUERY_TYPE_GROUP_COPY, + lastCopyToPath); + mDestDirPicker.setContextMenuId(LockScreen.isLocked(this) ? 0 : R.menu.menu_context_pick_osdir); + mDestDirPicker.setBaseQuery(mGalleryContentQuery); + mDestDirPicker.show(this.getFragmentManager(), "osdirimage"); } + return false; } private static final int SLIDESHOW_HANDLER_ID = 2; @@ -986,26 +976,6 @@ private void cmdShowDetails(String fullFilePath, long currentImageId) { } - private boolean cmdMoveOrCopyWithDestDirPicker(final boolean move, String lastCopyToPath, final SelectedFiles fotos) { - if (AndroidFileCommands.canProcessFile(this, false)) { - mDestDirPicker = MoveOrCopyDestDirPicker.newInstance(move, fotos); - - mDestDirPicker.defineDirectoryNavigation(OsUtils.getRootOSDirectory(null), - (move) ? FotoSql.QUERY_TYPE_GROUP_MOVE : FotoSql.QUERY_TYPE_GROUP_COPY, - lastCopyToPath); - mDestDirPicker.setContextMenuId(LockScreen.isLocked(this) ? 0 : R.menu.menu_context_pick_osdir); - mDestDirPicker.setBaseQuery(mGalleryContentQuery); - mDestDirPicker.show(this.getFragmentManager(), "osdirimage"); - } - return false; - } - - private boolean onEditExif(MenuItem menuItem, SelectedFiles currentFoto, final long fotoId, final String fotoPath) { - PhotoPropertiesEditActivity.showActivity(" menu " + menuItem.getTitle(), - this, null, fotoPath, currentFoto, 0, true); - return true; - } - /** * #70: Gui has changed ContextExpression * @@ -1020,7 +990,7 @@ private void onDefineContext(String modeName, String contextSqlColumnExpression) // sql detail expression has changed and initialization has completed: requery this.mContextColumnExpression = contextSqlColumnExpression; // prevent executing again - startRequery(); + requery(); } this.mContextColumnExpression = contextSqlColumnExpression; // prevent executing again @@ -1033,15 +1003,31 @@ private void onDefineContext(String modeName, String contextSqlColumnExpression) } - private void refreshIfNecessary() { + private boolean onEditExif(MenuItem menuItem, SelectedFiles currentFoto, final long fotoId, final String fotoPath) { + PhotoPropertiesEditActivity.showActivity(" menu " + menuItem.getTitle(), + this, null, fotoPath, currentFoto, 0, true); + return true; + } + + public void onNotifyDataChanged() { + requeryIfDataHasChanged(); + } + + private void reloadIfDataHasChanged() { if ((mAdapter != null) && (mViewPager != null) && (mAdapter.isInArrayMode())) { mAdapter.refreshLocal(); mViewPager.setAdapter(mAdapter); // show the changes onLoadCompleted(); - } else if (FotoSql.getMediaDBApi().mustRequery(mUpdateId)) { - startRequery(); + } else { + requeryIfDataHasChanged(); + } + } + + private void requeryIfDataHasChanged() { + if (FotoSql.getMediaDBApi().mustRequery(mUpdateId)) { + requery(); } } @@ -1055,10 +1041,23 @@ private boolean tagsShowEditDialog(SelectedFiles fotos) { dlg.setRemoveNames(new ArrayList()); dlg.setBaseQuery(mGalleryContentQuery); setAutoClose(dlg, null, null); + DataChangeNotifyer.setDataChangedListener(this); dlg.show(getFragmentManager(), "editTags"); return true; } + private void requery() { + mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); + if (mCurorLoader == null) { + // query has not been initialized + mCurorLoader = new LocalCursorLoader(); + getLoaderManager().initLoader(ACTIVITY_ID, null, mCurorLoader); + } else { + // query has changed + getLoaderManager().restartLoader(ACTIVITY_ID, null, this.mCurorLoader); + } + } + /** called by {@link TagsPickerFragment} */ @Override public boolean onCancel(String msg) { @@ -1185,18 +1184,6 @@ private void setContextMode(Object modeName) { } } - private void startRequery() { - mUpdateId = FotoSql.getMediaDBApi().getCurrentUpdateId(); - if (mCurorLoader == null) { - // query has not been initialized - mCurorLoader = new LocalCursorLoader(); - getLoaderManager().initLoader(ACTIVITY_ID, null, mCurorLoader); - } else { - // query has changed - getLoaderManager().restartLoader(ACTIVITY_ID, null, this.mCurorLoader); - } - } - public static class MoveOrCopyDestDirPicker extends DirectoryPickerFragment { protected static AndroidFileCommands sFileCommands = null; @@ -1246,12 +1233,43 @@ protected void onDirectoryPick(IDirectory selection) { mModifyCount++; // copy or move initiated getActivity().setResult((mModifyCount == 0) ? RESULT_NOCHANGE : RESULT_CHANGE); + DataChangeNotifyer.setDataChangedListener(((ImageDetailActivityViewPager) getActivity())); sFileCommands.onMoveOrCopyDirectoryPick(getMove(), getSrcFotos(), selection); dismiss(); - ((ImageDetailActivityViewPager) getActivity()).refreshIfNecessary(); } } + 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(); + } + } + + } + /** * executes sql to load image detail data in a background task that may survive * conriguration change (i.e. device rotation) @@ -1352,7 +1370,7 @@ protected Integer doInBackground(List... params) { @Override protected void onPostExecute(Integer itemCount) { super.onPostExecute(itemCount); - refreshIfNecessary(); + reloadIfDataHasChanged(); } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaImageDbReplacement.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaImageDbReplacement.java index 2463b4d5..caa409f5 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaImageDbReplacement.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/MediaImageDbReplacement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -334,18 +334,30 @@ public boolean mustRequery(long updateId) { return modified; } + private static int transactionNumber = 0; + @Override public void beginTransaction() { + if (Global.debugEnabledSql) { + Log.i(LOG_TAG, "beginTransaction #" + (++transactionNumber)); + } + db.beginTransaction(); } @Override public void setTransactionSuccessful() { + if (Global.debugEnabledSql) { + Log.i(LOG_TAG, "setTransactionSuccessful #" + transactionNumber); + } db.setTransactionSuccessful(); } @Override public void endTransaction() { + if (Global.debugEnabledSql) { + Log.i(LOG_TAG, "endTransaction #" + transactionNumber); + } db.endTransaction(); } public static class Impl { 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 dfc5f634..ea7c1f46 100644 --- a/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java +++ b/app/src/main/java/de/k3b/android/util/AndroidFileCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -37,6 +37,7 @@ import java.io.File; import java.util.Date; +import de.k3b.android.androFotoFinder.AndroidTransactionLogger; import de.k3b.android.androFotoFinder.Global; import de.k3b.android.androFotoFinder.LockScreen; import de.k3b.android.androFotoFinder.R; @@ -44,7 +45,6 @@ import de.k3b.android.androFotoFinder.media.AndroidPhotoPropertiesBulkUpdateService; import de.k3b.android.androFotoFinder.queries.DatabaseHelper; import de.k3b.android.androFotoFinder.queries.FotoSql; -import de.k3b.android.androFotoFinder.queries.IMediaDBApi; import de.k3b.android.androFotoFinder.tagDB.TagSql; import de.k3b.android.androFotoFinder.transactionlog.TransactionLogSql; import de.k3b.database.QueryParameter; @@ -258,15 +258,9 @@ public void onMoveOrCopyDirectoryPick(boolean move, SelectedFiles selectedFiles, protected int moveOrCopyFiles(final boolean move, String what, PhotoPropertiesDiffCopy exifChanges, SelectedFiles fotos, File[] destFiles, IProgessListener progessListener) { - IMediaDBApi api = FotoSql.getMediaDBApi(); - try { - api.beginTransaction(); - int result = super.moveOrCopyFiles(move, what, exifChanges, fotos, destFiles, progessListener); - api.setTransactionSuccessful(); - return result; - } finally { - api.endTransaction(); - } + int result = super.moveOrCopyFiles(move, what, exifChanges, fotos, destFiles, progessListener); + // api.setTransactionSuccessful(); + return result; } @NonNull @@ -572,6 +566,10 @@ public PhotoPropertiesBulkUpdateService createWorkflow(TransactionLoggerBase log return new AndroidPhotoPropertiesBulkUpdateService(mContext, logger, dbgContext); } + @Override + protected TransactionLoggerBase createTransactionLogger(long now) { + return new AndroidTransactionLogger(this, now); + } /** adds android database specific logging to base implementation */ @Override @@ -587,6 +585,9 @@ public void addTransactionLog( ContentValues values = TransactionLogSql.set(null, currentMediaID, fileFullPath, modificationDate, mediaTransactionLogEntryType, commandData); db.insert(TransactionLogSql.TABLE, null, values); + if (Global.debugEnabledSql) { + Log.i(FotoSql.LOG_TAG, "addTransactionLog: " + values); + } } } } diff --git a/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java b/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java new file mode 100644 index 00000000..54371bcf --- /dev/null +++ b/app/src/main/java/de/k3b/android/util/DataChangeNotifyer.java @@ -0,0 +1,33 @@ +/* + * 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/PhotoPropertiesMediaFilesScanner.java b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java index 47c89d18..c4d8c2fe 100644 --- a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java +++ b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -45,6 +45,7 @@ import de.k3b.android.androFotoFinder.Global; import de.k3b.android.androFotoFinder.media.PhotoPropertiesMediaDBContentValues; import de.k3b.android.androFotoFinder.queries.FotoSql; +import de.k3b.android.androFotoFinder.queries.IMediaDBApi; import de.k3b.android.androFotoFinder.tagDB.TagSql; import de.k3b.database.QueryParameter; import de.k3b.geo.api.GeoPointDto; @@ -159,19 +160,27 @@ public static int hideFolderMedia(Activity context, String path) { } public int updateMediaDatabase_Android42(Context context, String[] oldPathNames, String... newPathNames) { - final boolean hasNew = excludeNomediaFiles(newPathNames) > 0; - final boolean hasOld = excludeNomediaFiles(oldPathNames) > 0; - int result = 0; - - if (hasNew && hasOld) { - result = renameInMediaDatabase(context, oldPathNames, newPathNames); - } else if (hasOld) { - result = deleteInMediaDatabase(context, oldPathNames); - } if (hasNew) { - result = insertIntoMediaDatabase(context, newPathNames); + IMediaDBApi api = FotoSql.getMediaDBApi(); + try { + api.beginTransaction(); + final boolean hasNew = excludeNomediaFiles(newPathNames) > 0; + final boolean hasOld = excludeNomediaFiles(oldPathNames) > 0; + int result = 0; + + if (hasNew && hasOld) { + result = renameInMediaDatabase(context, oldPathNames, newPathNames); + } else if (hasOld) { + result = deleteInMediaDatabase(context, oldPathNames); + } + if (hasNew) { + result = insertIntoMediaDatabase(context, newPathNames); + } + TagSql.fixPrivate(); + api.setTransactionSuccessful(); + return result; + } finally { + api.endTransaction(); } - TagSql.fixPrivate(); - return result; } /** @@ -275,7 +284,10 @@ private int renameInMediaDatabase(Context context, String[] oldPathNames, String String newPathName = newPathNames[i]; if ((oldPathName != null) && (newPathName != null)) { - old2NewFileNames.put(oldPathName, newPathName); + //!!! ?seiteneffekt update other fields? + if (oldPathName.compareToIgnoreCase(newPathName) != 0) { + old2NewFileNames.put(oldPathName, newPathName); + } } else if (oldPathName != null) { deleteFileNames.add(oldPathName); } else if (newPathName != null) { 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 2d2439bf..f05c7f91 100644 --- a/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java +++ b/app/src/main/java/de/k3b/android/util/PhotoPropertiesMediaFilesScannerAsyncTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 by k3b. + * Copyright (c) 2016-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -50,17 +50,13 @@ protected Integer doInBackground(String[]... pathNames) { return mScanner.updateMediaDatabase_Android42(mContext, pathNames[0], pathNames[1]); } - @Override - protected void onPostExecute(Integer modifyCount) { - super.onPostExecute(modifyCount); - String message = this.mContext.getString(R.string.scanner_update_result_format, modifyCount); - Toast.makeText(this.mContext, message, Toast.LENGTH_LONG).show(); - if (Global.debugEnabled) { - Log.i(Global.LOG_CONTEXT, CONTEXT + "A42 scanner finished: " + message); - } - + private static void notifyIfThereAreChanges(Integer modifyCount, Context context, String why) { if (modifyCount > 0) { - PhotoPropertiesMediaFilesScanner.notifyChanges(mContext, mWhy); + PhotoPropertiesMediaFilesScanner.notifyChanges(context, why); + if (DataChangeNotifyer.dataChangedListener != null) { + DataChangeNotifyer.dataChangedListener.onNotifyDataChanged(); + } + } } @@ -73,12 +69,22 @@ public static void updateMediaDBInBackground(PhotoPropertiesMediaFilesScanner sc } else { // Continute in background task int modifyCount = scanner.updateMediaDatabase_Android42(context.getApplicationContext(), oldPathNames, newPathNames); - if (modifyCount > 0) { - PhotoPropertiesMediaFilesScanner.notifyChanges(context, why + " within current non-gui-task"); - } + notifyIfThereAreChanges(modifyCount, context, why + " within current non-gui-task"); } } + @Override + protected void onPostExecute(Integer modifyCount) { + super.onPostExecute(modifyCount); + String message = this.mContext.getString(R.string.scanner_update_result_format, modifyCount); + Toast.makeText(this.mContext, message, Toast.LENGTH_LONG).show(); + if (Global.debugEnabled) { + Log.i(Global.LOG_CONTEXT, CONTEXT + "A42 scanner finished: " + message); + } + + notifyIfThereAreChanges(modifyCount, mContext, mWhy); + } + /** return true if this is executed in the gui thread */ private static boolean isGuiThread() { return (Looper.myLooper() == Looper.getMainLooper()); diff --git a/app/src/main/java/de/k3b/android/widget/UpdateTask.java b/app/src/main/java/de/k3b/android/widget/UpdateTask.java index 81aee347..05cea078 100644 --- a/app/src/main/java/de/k3b/android/widget/UpdateTask.java +++ b/app/src/main/java/de/k3b/android/widget/UpdateTask.java @@ -1,14 +1,30 @@ -package de.k3b.android.widget; - -/** - * Created by EVE on 20.11.2017. +/* + * Copyright (c) 2017-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.widget; import android.app.Activity; import android.util.Log; import de.k3b.android.androFotoFinder.Global; import de.k3b.android.androFotoFinder.R; +import de.k3b.android.androFotoFinder.queries.FotoSql; +import de.k3b.android.androFotoFinder.queries.IMediaDBApi; import de.k3b.android.util.AndroidFileCommands; import de.k3b.io.IProgessListener; import de.k3b.io.collections.SelectedFiles; @@ -23,7 +39,7 @@ public class UpdateTask extends AsyncTaskWithProgressDialog imple private final AndroidFileCommands cmd; public UpdateTask(Activity ctx, AndroidFileCommands cmd, - PhotoPropertiesDiffCopy exifChanges) { + PhotoPropertiesDiffCopy exifChanges) { super(ctx, R.string.exif_menu_title); this.exifChanges = exifChanges; this.cmd = cmd; @@ -33,13 +49,25 @@ public UpdateTask(Activity ctx, AndroidFileCommands cmd, protected Integer doInBackground(SelectedFiles... params) { publishProgress("..."); + int result = 0; if (exifChanges != null) { SelectedFiles items = params[0]; - return cmd.applyExifChanges(true, exifChanges, items, null); - + if (true) { + result = cmd.applyExifChanges(true, exifChanges, items, null); + } else { + // disabled: does not work because of overlapping transactions + IMediaDBApi api = FotoSql.getMediaDBApi(); + try { + api.beginTransaction(); + result = cmd.applyExifChanges(true, exifChanges, items, null); + api.setTransactionSuccessful(); + } finally { + api.endTransaction(); + } + } } - return 0; + return result; } @Override diff --git a/fotolib2/src/main/java/de/k3b/io/FileCommands.java b/fotolib2/src/main/java/de/k3b/io/FileCommands.java index 2963be8b..9f627ceb 100644 --- a/fotolib2/src/main/java/de/k3b/io/FileCommands.java +++ b/fotolib2/src/main/java/de/k3b/io/FileCommands.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018 by k3b. + * Copyright (c) 2015-2020 by k3b. * * This file is part of AndroFotoFinder / #APhotoManager. * @@ -274,7 +274,7 @@ protected int moveOrCopyFiles(final boolean move, String what, PhotoPropertiesDi int pos = 0; long now = new Date().getTime(); MediaTransactionLogEntryType moveOrCopyCommand = (move) ? MediaTransactionLogEntryType.MOVE : MediaTransactionLogEntryType.COPY; - TransactionLoggerBase logger = (exifChanges == null) ? null : new TransactionLoggerBase(this, now); + TransactionLoggerBase logger = (exifChanges == null) ? null : createTransactionLogger(now); boolean sameFile; while (pos < fileCount) { @@ -373,6 +373,10 @@ protected int moveOrCopyFiles(final boolean move, String what, PhotoPropertiesDi return itemCount; } + protected TransactionLoggerBase createTransactionLogger(long now) { + return new TransactionLoggerBase(this, now); + } + private PhotoAutoprocessingDto getPhotoAutoprocessingDto(File destDirFolder) { PhotoAutoprocessingDto autoProccessData = null; try {