allow removing EXIF values from the Properties dialog

This commit is contained in:
tibbi 2022-03-20 19:27:45 +01:00
parent 0956159a76
commit 3ddd537d86
3 changed files with 84 additions and 56 deletions

View file

@ -26,6 +26,8 @@ class PropertiesDialog() {
private lateinit var mPropertyView: ViewGroup
private lateinit var mResources: Resources
private lateinit var mActivity: Activity
private lateinit var mDialogView: View
private var mCountHiddenItems = false
/**
* A File Properties dialog constructor with an optional parameter, usable at 1 file selected
@ -43,30 +45,49 @@ class PropertiesDialog() {
mActivity = activity
mInflater = LayoutInflater.from(activity)
mResources = activity.resources
val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder!!
mDialogView = mInflater.inflate(R.layout.dialog_properties, null)
mCountHiddenItems = countHiddenItems
mPropertyView = mDialogView.properties_holder!!
addProperties(path)
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), activity.getIsPathDirectory(path))
val builder = AlertDialog.Builder(mActivity)
.setPositiveButton(R.string.ok, null)
if (!path.startsWith("content://")) {
builder.setNeutralButton(R.string.remove_exif, null)
}
builder.create().apply {
mActivity.setupDialogStuff(mDialogView, this, R.string.properties)
getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener {
removeEXIF(path)
}
}
}
private fun addProperties(path: String) {
val fileDirItem = FileDirItem(path, path.getFilenameFromPath(), mActivity.getIsPathDirectory(path))
addProperty(R.string.name, fileDirItem.name)
addProperty(R.string.path, fileDirItem.getParentPath())
addProperty(R.string.size, "", R.id.properties_size)
ensureBackgroundThread {
val fileCount = fileDirItem.getProperFileCount(activity, countHiddenItems)
val size = fileDirItem.getProperSize(activity, countHiddenItems).formatSize()
val fileCount = fileDirItem.getProperFileCount(mActivity, mCountHiddenItems)
val size = fileDirItem.getProperSize(mActivity, mCountHiddenItems).formatSize()
val directChildrenCount = if (fileDirItem.isDirectory) {
fileDirItem.getDirectChildrenCount(activity, countHiddenItems).toString()
fileDirItem.getDirectChildrenCount(mActivity, mCountHiddenItems).toString()
} else {
0
}
activity.runOnUiThread {
(view.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
this.mActivity.runOnUiThread {
(mDialogView.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
if (fileDirItem.isDirectory) {
(view.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
(view.findViewById<LinearLayout>(R.id.properties_direct_children_count).property_value as TextView).text = directChildrenCount.toString()
(mDialogView.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
(mDialogView.findViewById<LinearLayout>(R.id.properties_direct_children_count).property_value as TextView).text =
directChildrenCount.toString()
}
}
@ -75,27 +96,27 @@ class PropertiesDialog() {
val uri = MediaStore.Files.getContentUri("external")
val selection = "${MediaStore.MediaColumns.DATA} = ?"
val selectionArgs = arrayOf(path)
val cursor = activity.contentResolver.query(uri, projection, selection, selectionArgs, null)
val cursor = mActivity.contentResolver.query(uri, projection, selection, selectionArgs, null)
cursor?.use {
if (cursor.moveToFirst()) {
val dateModified = cursor.getLongValue(MediaStore.Images.Media.DATE_MODIFIED) * 1000L
updateLastModified(activity, view, dateModified)
updateLastModified(mActivity, mDialogView, dateModified)
} else {
updateLastModified(activity, view, fileDirItem.getLastModified(activity))
updateLastModified(mActivity, mDialogView, fileDirItem.getLastModified(mActivity))
}
}
val exif = if (isNougatPlus() && activity.isPathOnOTG(fileDirItem.path)) {
ExifInterface((activity as BaseSimpleActivity).getFileInputStreamSync(fileDirItem.path)!!)
val exif = if (isNougatPlus() && mActivity.isPathOnOTG(fileDirItem.path)) {
ExifInterface((mActivity as BaseSimpleActivity).getFileInputStreamSync(fileDirItem.path)!!)
} else if (isNougatPlus() && fileDirItem.path.startsWith("content://")) {
try {
ExifInterface(activity.contentResolver.openInputStream(Uri.parse(fileDirItem.path))!!)
ExifInterface(mActivity.contentResolver.openInputStream(Uri.parse(fileDirItem.path))!!)
} catch (e: Exception) {
return@ensureBackgroundThread
}
} else if (activity.isRestrictedSAFOnlyRoot(path)) {
} else if (mActivity.isRestrictedSAFOnlyRoot(path)) {
try {
ExifInterface(activity.contentResolver.openInputStream(activity.getAndroidSAFUri(path))!!)
ExifInterface(mActivity.contentResolver.openInputStream(mActivity.getAndroidSAFUri(path))!!)
} catch (e: Exception) {
return@ensureBackgroundThread
}
@ -105,14 +126,14 @@ class PropertiesDialog() {
val latLon = FloatArray(2)
if (exif.getLatLong(latLon)) {
activity.runOnUiThread {
mActivity.runOnUiThread {
addProperty(R.string.gps_coordinates, "${latLon[0]}, ${latLon[1]}")
}
}
val altitude = exif.getAltitude(0.0)
if (altitude != 0.0) {
activity.runOnUiThread {
mActivity.runOnUiThread {
addProperty(R.string.altitude, "${altitude}m")
}
}
@ -125,58 +146,52 @@ class PropertiesDialog() {
addProperty(R.string.files_count, "", R.id.properties_file_count)
}
fileDirItem.path.isImageSlow() -> {
fileDirItem.getResolution(activity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
fileDirItem.getResolution(mActivity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
}
fileDirItem.path.isAudioSlow() -> {
fileDirItem.getDuration(activity)?.let { addProperty(R.string.duration, it) }
fileDirItem.getTitle(activity)?.let { addProperty(R.string.song_title, it) }
fileDirItem.getArtist(activity)?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum(activity)?.let { addProperty(R.string.album, it) }
fileDirItem.getDuration(mActivity)?.let { addProperty(R.string.duration, it) }
fileDirItem.getTitle(mActivity)?.let { addProperty(R.string.song_title, it) }
fileDirItem.getArtist(mActivity)?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum(mActivity)?.let { addProperty(R.string.album, it) }
}
fileDirItem.path.isVideoSlow() -> {
fileDirItem.getDuration(activity)?.let { addProperty(R.string.duration, it) }
fileDirItem.getResolution(activity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
fileDirItem.getArtist(activity)?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum(activity)?.let { addProperty(R.string.album, it) }
fileDirItem.getDuration(mActivity)?.let { addProperty(R.string.duration, it) }
fileDirItem.getResolution(mActivity)?.let { addProperty(R.string.resolution, it.formatAsResolution()) }
fileDirItem.getArtist(mActivity)?.let { addProperty(R.string.artist, it) }
fileDirItem.getAlbum(mActivity)?.let { addProperty(R.string.album, it) }
}
}
if (fileDirItem.isDirectory) {
addProperty(R.string.last_modified, fileDirItem.getLastModified(activity).formatDate(activity))
addProperty(R.string.last_modified, fileDirItem.getLastModified(mActivity).formatDate(mActivity))
} else {
addProperty(R.string.last_modified, "", R.id.properties_last_modified)
try {
addExifProperties(path, activity)
addExifProperties(path, mActivity)
} catch (e: Exception) {
activity.showErrorToast(e)
mActivity.showErrorToast(e)
return
}
if (activity.baseConfig.appId.removeSuffix(".debug") == "com.simplemobiletools.filemanager.pro") {
if (mActivity.baseConfig.appId.removeSuffix(".debug") == "com.simplemobiletools.filemanager.pro") {
addProperty(R.string.md5, "", R.id.properties_md5)
ensureBackgroundThread {
val md5 = if (activity.isRestrictedSAFOnlyRoot(path)) {
activity.contentResolver.openInputStream(activity.getAndroidSAFUri(path))?.md5()
val md5 = if (mActivity.isRestrictedSAFOnlyRoot(path)) {
mActivity.contentResolver.openInputStream(mActivity.getAndroidSAFUri(path))?.md5()
} else {
File(path).md5()
}
activity.runOnUiThread {
mActivity.runOnUiThread {
if (md5 != null) {
(view.findViewById<LinearLayout>(R.id.properties_md5).property_value as TextView).text = md5
(mDialogView.findViewById<LinearLayout>(R.id.properties_md5).property_value as TextView).text = md5
} else {
view.findViewById<LinearLayout>(R.id.properties_md5).beGone()
mDialogView.findViewById<LinearLayout>(R.id.properties_md5).beGone()
}
}
}
}
}
AlertDialog.Builder(activity)
.setPositiveButton(R.string.ok, null)
.create().apply {
activity.setupDialogStuff(view, this, R.string.properties)
}
}
private fun updateLastModified(activity: Activity, view: View, timestamp: Long) {
@ -196,8 +211,9 @@ class PropertiesDialog() {
mActivity = activity
mInflater = LayoutInflater.from(activity)
mResources = activity.resources
val view = mInflater.inflate(R.layout.dialog_properties, null)
mPropertyView = view.properties_holder
mDialogView = mInflater.inflate(R.layout.dialog_properties, null)
mCountHiddenItems = countHiddenItems
mPropertyView = mDialogView.properties_holder
val fileDirItems = ArrayList<FileDirItem>(paths.size)
paths.forEach {
@ -219,15 +235,15 @@ class PropertiesDialog() {
val fileCount = fileDirItems.sumByInt { it.getProperFileCount(activity, countHiddenItems) }
val size = fileDirItems.sumByLong { it.getProperSize(activity, countHiddenItems) }.formatSize()
activity.runOnUiThread {
(view.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
(view.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
(mDialogView.findViewById<LinearLayout>(R.id.properties_size).property_value as TextView).text = size
(mDialogView.findViewById<LinearLayout>(R.id.properties_file_count).property_value as TextView).text = fileCount.toString()
}
}
AlertDialog.Builder(activity)
.setPositiveButton(R.string.ok, null)
.create().apply {
activity.setupDialogStuff(view, this, R.string.properties)
activity.setupDialogStuff(mDialogView, this, R.string.properties)
}
}
@ -266,6 +282,20 @@ class PropertiesDialog() {
}
}
private fun removeEXIF(path: String) {
ConfirmationDialog(mActivity, "", R.string.remove_exif_confirmation) {
try {
ExifInterface(path).removeValues()
mActivity.toast(R.string.exif_removed)
mPropertyView.properties_holder.removeAllViews()
addProperties(path)
} catch (e: Exception) {
mActivity.showErrorToast(e)
}
}
}
private fun isSameParent(fileDirItems: List<FileDirItem>): Boolean {
var parent = fileDirItems[0].getParentPath()
for (file in fileDirItems) {

View file

@ -30,7 +30,8 @@ fun ExifInterface.copyTo(destination: ExifInterface, copyOrientation: Boolean =
ExifInterface.TAG_ISO_SPEED_RATINGS,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_WHITE_BALANCE)
ExifInterface.TAG_WHITE_BALANCE
)
if (copyOrientation) {
attributes.add(ExifInterface.TAG_ORIENTATION)
@ -49,9 +50,7 @@ fun ExifInterface.copyTo(destination: ExifInterface, copyOrientation: Boolean =
}
}
fun ExifInterface.removeValues(path: String) {
val newExif = ExifInterface(path)
fun ExifInterface.removeValues() {
val attributes = arrayListOf(
// ExifInterface.TAG_ORIENTATION, // do not remove the orientation, it could lead to unexpected behaviour at displaying the file
ExifInterface.TAG_APERTURE_VALUE,
@ -80,10 +79,10 @@ fun ExifInterface.removeValues(path: String) {
)
attributes.forEach {
newExif.setAttribute(it, null)
setAttribute(it, null)
}
newExif.saveAttributes()
saveAttributes()
}
fun ExifInterface.getExifProperties(): String {

View file

@ -254,7 +254,6 @@
<string name="altitude">Altitude</string>
<string name="remove_exif">Remove EXIF</string>
<string name="remove_exif_confirmation">Are you sure you want to remove EXIF values like GPS coordinates, camera model etc?</string>
<string name="remove_exif_confirmation">Are you sure you want to remove EXIF values like GPS coordinates, camera model etc?</string>
<string name="exif_removed">EXIF values removed successfully</string>
<!-- Color customization -->