diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/backup/Backup2ZipService.java b/app/src/main/java/de/k3b/android/androFotoFinder/backup/Backup2ZipService.java index aa800ed3..f3d39fbd 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/backup/Backup2ZipService.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/backup/Backup2ZipService.java @@ -19,14 +19,25 @@ package de.k3b.android.androFotoFinder.backup; +import android.content.ContentResolver; import android.content.Context; +import android.database.Cursor; import android.net.Uri; import android.util.Log; import java.io.File; import java.io.InputStream; +import java.util.Date; +import de.k3b.android.androFotoFinder.media.MediaCursor; +import de.k3b.android.androFotoFinder.queries.FotoSql; +import de.k3b.android.androFotoFinder.tagDB.TagSql; +import de.k3b.database.QueryParameter; import de.k3b.io.FileUtils; +import de.k3b.io.IItemSaver; +import de.k3b.media.IMetaApi; +import de.k3b.media.Media2ExistingFileSaver; +import de.k3b.media.MediaCsvStringSaver; import de.k3b.zip.IZipConfig; import de.k3b.zip.LibZipGlobal; import de.k3b.zip.ZipConfigRepository; @@ -55,10 +66,20 @@ public static IZipConfig loadZipConfig(Uri uri, Context context) { return null; } - public static IZipConfig execute(IZipConfig mFilter) { - ZipConfigRepository repo = new ZipConfigRepository(mFilter); + public static IZipConfig execute(IZipConfig zipConfig, ContentResolver contentResolver) { + ZipConfigRepository repo = new ZipConfigRepository(zipConfig); final File zipConfigFile = repo.getZipConfigFile(); if (zipConfigFile != null) { + QueryParameter filter = getEffectiveQueryParameter(zipConfig); + + final MediaCsvStringSaver csv = new MediaCsvStringSaver(); + + /// !!! todo go on here + final IItemSaver file2Zip = null; + final Media2ExistingFileSaver media2file = new Media2ExistingFileSaver(file2Zip); + + execQuery(filter, contentResolver, csv, media2file); + if (repo.save()) { if (LibZipGlobal.debugEnabled) { Log.d(LibZipGlobal.LOG_TAG, mDebugPrefix + " Saved as " + repo); @@ -68,4 +89,58 @@ public static IZipConfig execute(IZipConfig mFilter) { } return null; } + + /** + * @return get query without filte-DateModified-min/max and with added zipConfig.getDateModifiedFrom + */ + private static QueryParameter getEffectiveQueryParameter(IZipConfig zipConfig) { + QueryParameter filter = QueryParameter.parse(zipConfig.getFilter()); + FotoSql.parseDateModifiedMax(filter, true); + FotoSql.parseDateModifiedMin(filter, true); + final Date dateModifiedFrom = zipConfig.getDateModifiedFrom(); + if (dateModifiedFrom != null) { + FotoSql.addWhereDateModifiedMinMax(filter, dateModifiedFrom.getTime(), 0); + } + + filter.clearColumns().addColumn(TagSql.SQL_COL_PK + ,TagSql.SQL_COL_PATH + ,TagSql.SQL_COL_DATE_TAKEN + ,TagSql.SQL_COL_EXT_TITLE + ,TagSql.SQL_COL_EXT_DESCRIPTION + ,TagSql.SQL_COL_EXT_TAGS + ,TagSql.SQL_COL_LAT + ,TagSql.SQL_COL_LON + ,TagSql.SQL_COL_EXT_RATING + ,TagSql.SQL_COL_EXT_MEDIA_TYPE); + + return filter; + } + + private static void execQuery(QueryParameter query, ContentResolver contentResolver, + IItemSaver... consumers) { + Cursor cursor = null; + try { + cursor = contentResolver.query(Uri.parse(query.toFrom()), query.toColumns(), + query.toAndroidWhere(), query.toAndroidParameters(), query.toOrderBy()); + + int itemCount = cursor.getCount(); + final int expectedCount = itemCount + itemCount; + + MediaCursor mediaItem = new MediaCursor(cursor); + while (cursor.moveToNext()) { + for (IItemSaver consumer : consumers){ + if (consumer != null) consumer.save(mediaItem); + } + } + } catch (Exception ex){ + Log.e(LibZipGlobal.LOG_TAG, mDebugPrefix + query, ex); + throw new RuntimeException(mDebugPrefix + query + "\n" + ex.getMessage(), ex); + } finally { + if (cursor != null) { + cursor.close(); + } + } + + + } } diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java b/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java index e3960286..0eb90239 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/backup/BackupActivity.java @@ -612,7 +612,7 @@ private boolean onOk() { Activity ctx = this; saveGuiToData(); gui.mHistory.saveHistory(); - IZipConfig newConfig = Backup2ZipService.execute(mFilter); + IZipConfig newConfig = Backup2ZipService.execute(mFilter, ctx.getContentResolver()); if (newConfig != null) { Toast.makeText(BackupActivity.this, newConfig.toString(), Toast.LENGTH_LONG).show(); diff --git a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java index c13e5d9c..223a8fbf 100644 --- a/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java +++ b/app/src/main/java/de/k3b/android/androFotoFinder/queries/FotoSql.java @@ -390,14 +390,22 @@ public static IGalleryFilter parseQuery(QueryParameter query, boolean removeFrom filter.setPath(getFilePath(query, removeFromSourceQuery)); // SQL_COL_LAST_MODIFIED in seconds since 1970; translate from MilliSecs - filter.setDateModified(getParamWithFix(query, FILTER_EXPR_DATE_MODIFIED_MIN, removeFromSourceQuery, LAST_MODIFIED_FACTOR), - getParamWithFix(query, FILTER_EXPR_DATE_MODIFIED_MAX, removeFromSourceQuery, LAST_MODIFIED_FACTOR)); + filter.setDateModified(parseDateModifiedMin(query, removeFromSourceQuery), + parseDateModifiedMax(query, removeFromSourceQuery)); return filter; } return null; } + public static long parseDateModifiedMax(QueryParameter query, boolean removeFromSourceQuery) { + return getParamWithFix(query, FILTER_EXPR_DATE_MODIFIED_MAX, removeFromSourceQuery, LAST_MODIFIED_FACTOR); + } + + public static long parseDateModifiedMin(QueryParameter query, boolean removeFromSourceQuery) { + return getParamWithFix(query, FILTER_EXPR_DATE_MODIFIED_MIN, removeFromSourceQuery, LAST_MODIFIED_FACTOR); + } + /** extracts geo infos from srcQuery to destFilter */ public static GeoRectangle parseQueryGeo(QueryParameter srcQuery, GeoRectangle destFilter, boolean removeFromSourceQuery) { if (null != getParams(srcQuery, FILTER_EXPR_NO_GPS, removeFromSourceQuery)) { diff --git a/app/src/main/res/menu/menu_gallery_multiselect_mode_all.xml b/app/src/main/res/menu/menu_gallery_multiselect_mode_all.xml index 33c7c81f..0995599f 100644 --- a/app/src/main/res/menu/menu_gallery_multiselect_mode_all.xml +++ b/app/src/main/res/menu/menu_gallery_multiselect_mode_all.xml @@ -48,7 +48,7 @@ diff --git a/app/src/main/res/menu/menu_gallery_non_selected_only.xml b/app/src/main/res/menu/menu_gallery_non_selected_only.xml index 4e6c7f2e..cb419ccd 100644 --- a/app/src/main/res/menu/menu_gallery_non_selected_only.xml +++ b/app/src/main/res/menu/menu_gallery_non_selected_only.xml @@ -54,7 +54,7 @@ diff --git a/fotolib2/src/main/java/de/k3b/io/IItemSaver.java b/fotolib2/src/main/java/de/k3b/io/IItemSaver.java new file mode 100644 index 00000000..dd309ae7 --- /dev/null +++ b/fotolib2/src/main/java/de/k3b/io/IItemSaver.java @@ -0,0 +1,25 @@ +package de.k3b.io; + +/* + * Copyright (c) 2019 by k3b. + * + * This file is part of AndroFotoFinder. + * + * 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 + */ + +/* abstract api to process an item */ +public interface IItemSaver { + boolean save(T item); +} diff --git a/fotolib2/src/main/java/de/k3b/media/Media2ExistingFileSaver.java b/fotolib2/src/main/java/de/k3b/media/Media2ExistingFileSaver.java new file mode 100644 index 00000000..07cb6e3c --- /dev/null +++ b/fotolib2/src/main/java/de/k3b/media/Media2ExistingFileSaver.java @@ -0,0 +1,34 @@ +package de.k3b.media; + +import java.io.File; + +import de.k3b.io.FileProcessor; +import de.k3b.io.IItemSaver; + +public class Media2ExistingFileSaver implements IItemSaver { + private final IItemSaver fileSaver; + public Media2ExistingFileSaver(IItemSaver fileSaver) { + this.fileSaver = fileSaver; + } + + @Override + public boolean save(IMetaApi item) { + if (item != null) { + String path = item.getPath(); + if (path != null) { + return saveFiles(new File(path), + FileProcessor.getExistingSidecarOrNull(path, true), + FileProcessor.getExistingSidecarOrNull(path, false)) > 0; + } + } + return false; + } + + private int saveFiles(File... files) { + int processed = 0; + for (File f: files) { + if ((f != null) && (f.exists()) && f.canRead() && this.fileSaver.save(f)) processed++; + } + return processed; + } +} diff --git a/fotolib2/src/main/java/de/k3b/media/MediaCsvSaver.java b/fotolib2/src/main/java/de/k3b/media/MediaCsvSaver.java index da9a2f62..6f32ad1f 100644 --- a/fotolib2/src/main/java/de/k3b/media/MediaCsvSaver.java +++ b/fotolib2/src/main/java/de/k3b/media/MediaCsvSaver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016 by k3b. + * Copyright (c) 2015-2019 by k3b. * * This file is part of AndroFotoFinder. * @@ -23,30 +23,39 @@ import java.util.Arrays; import de.k3b.csv2db.csv.CsvItem; +import de.k3b.io.IItemSaver; /** * Created by k3b on 13.10.2016. */ -public class MediaCsvSaver { - private final PrintWriter printer; +public class MediaCsvSaver implements IItemSaver { + private PrintWriter printer; private final MediaCsvItem csvLine; public MediaCsvSaver(PrintWriter printer) { - this.printer = printer; + setPrinter(printer); csvLine = new MediaCsvItem(); defineHeader(MediaCsvItem.MEDIA_CSV_STANDARD_HEADER); } - public void save(IMetaApi item) { + protected MediaCsvSaver setPrinter(PrintWriter printer) { + this.printer = printer; + return this; + } + + @Override + public boolean save(IMetaApi item) { if (item != null) { csvLine.clear(); MediaUtil.copy(csvLine, item, true, true); if (!csvLine.isEmpty()) { this.printer.write(csvLine.toString()); this.printer.write(CsvItem.DEFAULT_CHAR_LINE_DELIMITER); + return true; } } + return false; } private void defineHeader(String header) { diff --git a/fotolib2/src/main/java/de/k3b/media/MediaCsvStringSaver.java b/fotolib2/src/main/java/de/k3b/media/MediaCsvStringSaver.java new file mode 100644 index 00000000..da9b33c1 --- /dev/null +++ b/fotolib2/src/main/java/de/k3b/media/MediaCsvStringSaver.java @@ -0,0 +1,18 @@ +package de.k3b.media; + +import java.io.PrintWriter; +import java.io.StringWriter; + +public class MediaCsvStringSaver extends MediaCsvSaver{ + private StringWriter result = new StringWriter(); + private PrintWriter writer = new PrintWriter(result); + public MediaCsvStringSaver() { + super(null); + this.setPrinter(writer); + } + + @Override + public String toString() { + return result.toString(); + } +}