From 422984ac41bec1127e31750bd8cb3584ebeb53a1 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Fri, 23 Jul 2021 18:02:41 +0200 Subject: [PATCH] Manually change templates group and recyclebin group --- .../action/ProgressDatabaseTaskProvider.kt | 24 +++++ .../keepass/database/element/Database.kt | 34 +++++-- .../keepass/database/element/Group.kt | 6 ++ .../database/element/database/DatabaseKDBX.kt | 9 +- .../database/element/group/GroupVersioned.kt | 4 - .../database/element/node/NodeIdUUID.kt | 3 +- .../database/element/node/NodeVersioned.kt | 5 +- .../DatabaseTaskNotificationService.kt | 4 + .../NestedDatabaseSettingsFragment.kt | 57 ++++++++---- ...eBinGroupPreferenceDialogFragmentCompat.kt | 88 +++++++++++++++++++ ...atesGroupPreferenceDialogFragmentCompat.kt | 88 +++++++++++++++++++ app/src/main/res/xml/preferences_database.xml | 4 +- 12 files changed, 293 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseRecycleBinGroupPreferenceDialogFragmentCompat.kt create mode 100644 app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseTemplatesGroupPreferenceDialogFragmentCompat.kt diff --git a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDatabaseTaskProvider.kt b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDatabaseTaskProvider.kt index ca5c20207..b528ad47b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDatabaseTaskProvider.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/action/ProgressDatabaseTaskProvider.kt @@ -71,6 +71,8 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion. import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_MEMORY_USAGE_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_NAME_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_PARALLELISM_TASK +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK +import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getBundleFromListNodes import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment @@ -521,6 +523,28 @@ class ProgressDatabaseTaskProvider(private val activity: FragmentActivity) { , ACTION_DATABASE_REMOVE_UNLINKED_DATA_TASK) } + fun startDatabaseSaveRecycleBin(oldRecycleBin: Group?, + newRecycleBin: Group?, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldRecycleBin) + putParcelable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newRecycleBin) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK) + } + + fun startDatabaseSaveTemplatesGroup(oldTemplatesGroup: Group?, + newTemplatesGroup: Group?, + save: Boolean) { + start(Bundle().apply { + putParcelable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY, oldTemplatesGroup) + putParcelable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY, newTemplatesGroup) + putBoolean(DatabaseTaskNotificationService.SAVE_DATABASE_KEY, save) + } + , ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK) + } + fun startDatabaseSaveMaxHistoryItems(oldMaxHistoryItems: Int, newMaxHistoryItems: Int, save: Boolean) { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 7f79a3ff9..512ed7def 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -369,6 +369,15 @@ class Database { return null } + /** + * Do not modify groups here, used for read only + */ + fun getAllGroupsWithoutRoot(): List { + return mDatabaseKDB?.getGroupIndexes()?.filter { it != mDatabaseKDB?.rootGroup }?.map { Group(it) } + ?: mDatabaseKDBX?.getGroupIndexes()?.filter { it != mDatabaseKDBX?.rootGroup }?.map { Group(it) } + ?: listOf() + } + val manageHistory: Boolean get() = mDatabaseKDBX != null @@ -404,7 +413,7 @@ class Database { if (enable) { ensureRecycleBinExists(resources) } else { - removeRecycleBin() + mDatabaseKDBX?.removeRecycleBin() } } @@ -419,6 +428,15 @@ class Database { return null } + fun setRecycleBin(group: Group?) { + // Only the kdbx recycle bin can be changed + if (group != null) { + mDatabaseKDBX?.recycleBinUUID = group.nodeIdKDBX.id + } else { + mDatabaseKDBX?.removeTemplatesGroup() + } + } + /** * Determine if a configurable templates group is available or not for this version of database * @return true if a configurable templates group available @@ -442,6 +460,15 @@ class Database { return null } + fun setTemplatesGroup(group: Group?) { + // Only the kdbx templates group can be changed + if (group != null) { + mDatabaseKDBX?.entryTemplatesGroup = group.nodeIdKDBX.id + } else { + mDatabaseKDBX?.entryTemplatesGroup + } + } + val groupNamesNotAllowed: List get() { return mDatabaseKDB?.groupNamesNotAllowed ?: ArrayList() @@ -977,11 +1004,6 @@ class Database { mDatabaseKDBX?.ensureRecycleBinExists(resources) } - fun removeRecycleBin() { - // Don't allow remove backup in KDB - mDatabaseKDBX?.removeRecycleBin() - } - fun canRecycle(entry: Entry): Boolean { var canRecycle: Boolean? = null entry.entryKDB?.let { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Group.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Group.kt index d2a891f4c..3b9916619 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Group.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Group.kt @@ -455,4 +455,10 @@ class Group : Node, GroupVersionedInterface { result = 31 * result + (groupKDBX?.hashCode() ?: 0) return result } + + override fun toString(): String { + return groupKDB?.toString() ?: groupKDBX?.toString() ?: "Undefined" + } + + } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt index 377fbf99f..1a34073de 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/database/DatabaseKDBX.kt @@ -364,11 +364,16 @@ class DatabaseKDBX : DatabaseVersioned { entryTemplatesGroup = uuidTemplatesGroup.id entryTemplatesGroupChanged = uuidTemplatesGroup.lastModificationTime } else { - entryTemplatesGroup = UUID_ZERO - mTemplateEngine.clearCache() + removeTemplatesGroup() } } + fun removeTemplatesGroup() { + entryTemplatesGroup = UUID_ZERO + entryTemplatesGroupChanged = DateInstant() + mTemplateEngine.clearCache() + } + fun getTemplatesGroup(): GroupKDBX? { if (isTemplatesGroupEnabled()) { return getGroupById(entryTemplatesGroup) diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/group/GroupVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/group/GroupVersioned.kt index f34a91c9f..1031ae61b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/group/GroupVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/group/GroupVersioned.kt @@ -117,8 +117,4 @@ abstract class GroupVersioned else nodeIndexInParentForNaturalOrder } - - override fun toString(): String { - return titleGroup - } } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeIdUUID.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeIdUUID.kt index 06eecf05c..81fa5a149 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeIdUUID.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeIdUUID.kt @@ -22,6 +22,7 @@ package com.kunzisoft.keepass.database.element.node import android.os.Parcel import android.os.ParcelUuid import android.os.Parcelable +import com.kunzisoft.keepass.utils.UuidUtil import java.util.* class NodeIdUUID : NodeId { @@ -60,7 +61,7 @@ class NodeIdUUID : NodeId { } override fun toString(): String { - return id.toString() + return UuidUtil.toHexString(id) ?: id.toString() } companion object { diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeVersioned.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeVersioned.kt index 2964a4818..d2b5b4e6b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeVersioned.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/node/NodeVersioned.kt @@ -26,7 +26,6 @@ import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.entry.EntryVersionedInterface import com.kunzisoft.keepass.database.element.group.GroupVersionedInterface import com.kunzisoft.keepass.database.element.icon.IconImage -import org.joda.time.LocalDateTime /** * Abstract class who manage Groups and Entries @@ -149,4 +148,8 @@ abstract class NodeVersioned { + val oldRecycleBin = data.getParcelable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) + val newRecycleBin = data.getParcelable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) + val recycleBinToShow = + if (result.isSuccess) { + newRecycleBin + } else { + oldRecycleBin + } + mDatabase?.setRecycleBin(recycleBinToShow) + refreshRecycleBinGroup() + } + DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK -> { + val oldTemplatesGroup = data.getParcelable(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) + val newTemplatesGroup = data.getParcelable(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) + val templatesGroupToShow = + if (result.isSuccess) { + newTemplatesGroup + } else { + oldTemplatesGroup + } + mDatabase?.setTemplatesGroup(templatesGroupToShow) + refreshTemplatesGroup() + } DatabaseTaskNotificationService.ACTION_DATABASE_UPDATE_MAX_HISTORY_ITEMS_TASK -> { val oldMaxHistoryItems = data.getInt(DatabaseTaskNotificationService.OLD_ELEMENT_KEY) val newMaxHistoryItems = data.getInt(DatabaseTaskNotificationService.NEW_ELEMENT_KEY) @@ -539,6 +556,12 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment() { getString(R.string.database_data_remove_unlinked_attachments_key) -> { dialogFragment = DatabaseRemoveUnlinkedDataPreferenceDialogFragmentCompat.newInstance(preference.key) } + getString(R.string.recycle_bin_group_key) -> { + dialogFragment = DatabaseRecycleBinGroupPreferenceDialogFragmentCompat.newInstance(preference.key) + } + getString(R.string.templates_group_uuid_key) -> { + dialogFragment = DatabaseTemplatesGroupPreferenceDialogFragmentCompat.newInstance(preference.key) + } getString(R.string.max_history_items_key) -> { dialogFragment = MaxHistoryItemsPreferenceDialogFragmentCompat.newInstance(preference.key) } diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseRecycleBinGroupPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseRecycleBinGroupPreferenceDialogFragmentCompat.kt new file mode 100644 index 000000000..6220ed384 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseRecycleBinGroupPreferenceDialogFragmentCompat.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2021 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX 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. + * + * KeePassDX 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 KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings.preferencedialogfragment + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.element.Group +import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter + +class DatabaseRecycleBinGroupPreferenceDialogFragmentCompat + : DatabaseSavePreferenceDialogFragmentCompat(), + ListRadioItemAdapter.RadioItemSelectedCallback { + + private var mGroupRecycleBin: Group? = null + + override fun onBindDialogView(view: View) { + super.onBindDialogView(view) + + val recyclerView = view.findViewById(R.id.pref_dialog_list) + recyclerView.layoutManager = LinearLayoutManager(context) + + activity?.let { activity -> + val groupsAdapter = ListRadioItemAdapter(activity) + groupsAdapter.setRadioItemSelectedCallback(this) + recyclerView.adapter = groupsAdapter + + mDatabase?.let { database -> + mGroupRecycleBin = database.recycleBin?.apply { + groupsAdapter.setItems(database.getAllGroupsWithoutRoot(), this) + } + } + } + } + + override fun onItemSelected(item: Group) { + mGroupRecycleBin = item + } + + override fun onDialogClosed(positiveResult: Boolean) { + if (positiveResult) { + mDatabase?.let { database -> + if (database.allowConfigurableRecycleBin) { + val oldGroup = database.recycleBin + val newGroup = mGroupRecycleBin + database.setRecycleBin(newGroup) + mProgressDatabaseTaskProvider?.startDatabaseSaveRecycleBin( + oldGroup, + newGroup, + mDatabaseAutoSaveEnable + ) + } + } + } + } + + companion object { + + fun newInstance( + key: String): DatabaseRecycleBinGroupPreferenceDialogFragmentCompat { + val fragment = DatabaseRecycleBinGroupPreferenceDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + + return fragment + } + } +} diff --git a/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseTemplatesGroupPreferenceDialogFragmentCompat.kt b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseTemplatesGroupPreferenceDialogFragmentCompat.kt new file mode 100644 index 000000000..277a4391d --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/settings/preferencedialogfragment/DatabaseTemplatesGroupPreferenceDialogFragmentCompat.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2021 Jeremy Jamet / Kunzisoft. + * + * This file is part of KeePassDX. + * + * KeePassDX 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. + * + * KeePassDX 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 KeePassDX. If not, see . + * + */ +package com.kunzisoft.keepass.settings.preferencedialogfragment + +import android.os.Bundle +import android.view.View +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.kunzisoft.keepass.R +import com.kunzisoft.keepass.database.element.Group +import com.kunzisoft.keepass.settings.preferencedialogfragment.adapter.ListRadioItemAdapter + +class DatabaseTemplatesGroupPreferenceDialogFragmentCompat + : DatabaseSavePreferenceDialogFragmentCompat(), + ListRadioItemAdapter.RadioItemSelectedCallback { + + private var mGroupTemplates: Group? = null + + override fun onBindDialogView(view: View) { + super.onBindDialogView(view) + + val recyclerView = view.findViewById(R.id.pref_dialog_list) + recyclerView.layoutManager = LinearLayoutManager(context) + + activity?.let { activity -> + val groupsAdapter = ListRadioItemAdapter(activity) + groupsAdapter.setRadioItemSelectedCallback(this) + recyclerView.adapter = groupsAdapter + + mDatabase?.let { database -> + mGroupTemplates = database.templatesGroup?.apply { + groupsAdapter.setItems(database.getAllGroupsWithoutRoot(), this) + } + } + } + } + + override fun onItemSelected(item: Group) { + mGroupTemplates = item + } + + override fun onDialogClosed(positiveResult: Boolean) { + if (positiveResult) { + mDatabase?.let { database -> + if (database.allowConfigurableTemplatesGroup) { + val oldGroup = database.templatesGroup + val newGroup = mGroupTemplates + database.setTemplatesGroup(newGroup) + mProgressDatabaseTaskProvider?.startDatabaseSaveTemplatesGroup( + oldGroup, + newGroup, + mDatabaseAutoSaveEnable + ) + } + } + } + } + + companion object { + + fun newInstance( + key: String): DatabaseTemplatesGroupPreferenceDialogFragmentCompat { + val fragment = DatabaseTemplatesGroupPreferenceDialogFragmentCompat() + val bundle = Bundle(1) + bundle.putString(ARG_KEY, key) + fragment.arguments = bundle + + return fragment + } + } +} diff --git a/app/src/main/res/xml/preferences_database.xml b/app/src/main/res/xml/preferences_database.xml index 45f27128e..dc7513b41 100644 --- a/app/src/main/res/xml/preferences_database.xml +++ b/app/src/main/res/xml/preferences_database.xml @@ -84,7 +84,7 @@ android:title="@string/recycle_bin_title" android:summary="@string/recycle_bin_summary" android:checked="false"/> - @@ -101,7 +101,7 @@ android:title="@string/templates_group_enable_title" android:summary="@string/templates_group_enable_summary" android:checked="false"/> -