diff --git a/app/src/main/java/com/keepassdroid/activities/GroupBaseActivity.java b/app/src/main/java/com/keepassdroid/activities/GroupBaseActivity.java index 868435613..863fb4749 100644 --- a/app/src/main/java/com/keepassdroid/activities/GroupBaseActivity.java +++ b/app/src/main/java/com/keepassdroid/activities/GroupBaseActivity.java @@ -45,7 +45,6 @@ import com.keepassdroid.adapters.NodeAdapter; import com.keepassdroid.app.App; import com.keepassdroid.compat.ActivityCompat; import com.keepassdroid.compat.EditorCompat; -import com.keepassdroid.database.Database; import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwGroup; import com.keepassdroid.database.PwNode; @@ -72,19 +71,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity protected PwGroup mCurrentGroup; - @Override - protected void onResume() { - super.onResume(); - refreshIfDirty(); - } - - public void refreshIfDirty() { - Database db = App.getDB(); - if ( db.dirty.contains(mCurrentGroup) ) { - db.dirty.remove(mCurrentGroup); - } - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -252,12 +238,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity // Refresh menu titles ActivityCompat.invalidateOptionsMenu(this); - // Mark all groups as dirty now to refresh them on load - Database db = App.getDB(); - db.markAllGroupsAsDirty(); - // We'll manually refresh this tree so we can remove it - db.dirty.remove(mCurrentGroup); - // Tell the adapter to refresh it's list mAdapter.notifyChangeSort(); mAdapter.rebuildList(mCurrentGroup); @@ -294,7 +274,6 @@ public abstract class GroupBaseActivity extends LockCloseListActivity public void run(PwNode pwNode) { super.run(); if (mSuccess) { - refreshIfDirty(); mAdapter.addNode(pwNode); } else { displayMessage(GroupBaseActivity.this); @@ -313,11 +292,13 @@ public abstract class GroupBaseActivity extends LockCloseListActivity @Override public void run() { if ( mSuccess) { - refreshIfDirty(); mAdapter.removeNode(pwNode); PwGroup parent = pwNode.getParent(); PwGroup recycleBin = App.getDB().pm.getRecycleBin(); - if (parent.equals(recycleBin) && !mCurrentGroup.equals(recycleBin)) { + // Add trash if it doesn't exists + if (parent.equals(recycleBin) + && mCurrentGroup.getParent() == null + && !mCurrentGroup.equals(recycleBin)) { mAdapter.addNode(parent); } } else { diff --git a/app/src/main/java/com/keepassdroid/database/Database.java b/app/src/main/java/com/keepassdroid/database/Database.java index 558c02e92..604d0a778 100644 --- a/app/src/main/java/com/keepassdroid/database/Database.java +++ b/app/src/main/java/com/keepassdroid/database/Database.java @@ -46,14 +46,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.SyncFailedException; -import java.util.HashSet; -import java.util.Set; /** * @author bpellin */ public class Database { - public Set dirty = new HashSet(); public PwDatabase pm; public Uri mUri; public SearchDbHelper searchHelper; @@ -220,7 +217,6 @@ public class Database { } public void clear() { - dirty.clear(); drawFactory.clear(); pm = null; @@ -228,16 +224,4 @@ public class Database { loaded = false; passwordEncodingError = false; } - - public void markAllGroupsAsDirty() { - for ( PwGroup group : pm.getGroups() ) { - dirty.add(group); - } - - // TODO: This should probably be abstracted out - // The root tree in v3 is not an 'official' tree - if ( pm instanceof PwDatabaseV3 ) { - dirty.add(pm.rootGroup); - } - } } diff --git a/app/src/main/java/com/keepassdroid/database/PwDatabase.java b/app/src/main/java/com/keepassdroid/database/PwDatabase.java index ea2b874ca..e46d70fb1 100644 --- a/app/src/main/java/com/keepassdroid/database/PwDatabase.java +++ b/app/src/main/java/com/keepassdroid/database/PwDatabase.java @@ -265,8 +265,9 @@ public abstract class PwDatabase { public void removeGroupFrom(PwGroup remove, PwGroup parent) { // Remove tree from parent tree - parent.removeChildGroup(remove); - + if (parent != null) { + parent.removeChildGroup(remove); + } groups.remove(remove.getId()); } @@ -331,6 +332,11 @@ public abstract class PwDatabase { } } + /** + * Define if a Group must be delete or recycle + * @param group Group to remove + * @return true if group can be recycle, false elsewhere + */ public boolean canRecycle(PwGroup group) { return false; } @@ -344,20 +350,39 @@ public abstract class PwDatabase { return false; } + public void recycle(PwGroup group) { + // Assume calls to this are protected by calling inRecyleBin + throw new RuntimeException("Call not valid for .kdb databases."); + } + public void recycle(PwEntry entry) { // Assume calls to this are protected by calling inRecyleBin throw new RuntimeException("Call not valid for .kdb databases."); } + public void undoRecycle(PwGroup group, PwGroup origParent) { + throw new RuntimeException("Call not valid for .kdb databases."); + } + public void undoRecycle(PwEntry entry, PwGroup origParent) { throw new RuntimeException("Call not valid for .kdb databases."); } + public void deleteGroup(PwGroup group) { + PwGroup parent = group.getParent(); + removeGroupFrom(group, parent); + parent.touch(false, true); + } + public void deleteEntry(PwEntry entry) { PwGroup parent = entry.getParent(); removeEntryFrom(entry, parent); parent.touch(false, true); + } + // TODO Delete group + public void undoDeleteGroup(PwGroup group, PwGroup origParent) { + addGroupTo(group, origParent); } public void undoDeleteEntry(PwEntry entry, PwGroup origParent) { diff --git a/app/src/main/java/com/keepassdroid/database/PwDatabaseV4.java b/app/src/main/java/com/keepassdroid/database/PwDatabaseV4.java index 1f5fc51eb..fe6c0b389 100644 --- a/app/src/main/java/com/keepassdroid/database/PwDatabaseV4.java +++ b/app/src/main/java/com/keepassdroid/database/PwDatabaseV4.java @@ -366,9 +366,7 @@ public class PwDatabaseV4 extends PwDatabase { if (!recycleBinEnabled) { return false; } - PwGroup recycle = getRecycleBin(); - return (recycle == null) || (!group.isContainedIn(recycle)); } @@ -377,11 +375,25 @@ public class PwDatabaseV4 extends PwDatabase { if (!recycleBinEnabled) { return false; } - PwGroup parent = entry.getParent(); return (parent != null) && canRecycle(parent); } - + + @Override + public void recycle(PwGroup group) { + ensureRecycleBin(); + + PwGroup parent = group.getParent(); + removeGroupFrom(group, parent); + parent.touch(false, true); + + PwGroup recycleBin = getRecycleBin(); + addGroupTo(group, recycleBin); + + group.touch(false, true); + // TODO ? group.touchLocation(); + } + @Override public void recycle(PwEntry entry) { ensureRecycleBin(); @@ -397,6 +409,15 @@ public class PwDatabaseV4 extends PwDatabase { entry.touchLocation(); } + @Override + public void undoRecycle(PwGroup group, PwGroup origParent) { + + PwGroup recycleBin = getRecycleBin(); + removeGroupFrom(group, recycleBin); + + addGroupTo(group, origParent); + } + @Override public void undoRecycle(PwEntry entry, PwGroup origParent) { @@ -409,15 +430,14 @@ public class PwDatabaseV4 extends PwDatabase { @Override public void deleteEntry(PwEntry entry) { super.deleteEntry(entry); - deletedObjects.add(new PwDeletedObject(entry.getUUID())); } @Override public void undoDeleteEntry(PwEntry entry, PwGroup origParent) { super.undoDeleteEntry(entry, origParent); - - deletedObjects.remove(entry); + // TODO undo delete entry + deletedObjects.remove(entry); } @Override diff --git a/app/src/main/java/com/keepassdroid/database/edit/AddEntry.java b/app/src/main/java/com/keepassdroid/database/edit/AddEntry.java index 80a8333b7..4535fea6c 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/AddEntry.java +++ b/app/src/main/java/com/keepassdroid/database/edit/AddEntry.java @@ -24,7 +24,6 @@ import android.content.Context; import com.keepassdroid.database.Database; import com.keepassdroid.database.PwDatabase; import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwGroup; public class AddEntry extends RunnableOnFinish { protected Database mDb; @@ -59,20 +58,11 @@ public class AddEntry extends RunnableOnFinish { @Override public void run() { PwDatabase pm = mDb.pm; - if ( mSuccess ) { - - PwGroup parent = mEntry.getParent(); - - // Mark parent tree dirty - mDb.dirty.add(parent); - - } else { + if ( !mSuccess ) { pm.removeEntryFrom(mEntry, mEntry.getParent()); } - + // TODO if add entry callback super.run(); } } - - } diff --git a/app/src/main/java/com/keepassdroid/database/edit/AddGroup.java b/app/src/main/java/com/keepassdroid/database/edit/AddGroup.java index 7bb09bc52..1bf3bd94c 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/AddGroup.java +++ b/app/src/main/java/com/keepassdroid/database/edit/AddGroup.java @@ -73,13 +73,11 @@ public class AddGroup extends RunnableOnFinish { @Override public void run() { PwDatabase pm = mDb.pm; - if ( mSuccess ) { - // Mark parent group dirty - mDb.dirty.add(mParent); - } else { - pm.removeGroupFrom(mGroup, mParent); + if ( !mSuccess ) { + pm.removeGroupFrom(mGroup, mParent); } + // TODO Better callback AfterAddNodeOnFinish afterAddNode = (AfterAddNodeOnFinish) super.mOnFinish; afterAddNode.mSuccess = mSuccess; diff --git a/app/src/main/java/com/keepassdroid/database/edit/DeleteEntry.java b/app/src/main/java/com/keepassdroid/database/edit/DeleteEntry.java index 3ed13dd54..f0c414018 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/DeleteEntry.java +++ b/app/src/main/java/com/keepassdroid/database/edit/DeleteEntry.java @@ -71,8 +71,6 @@ public class DeleteEntry extends RunnableOnFinish { // Commit database SaveDB save = new SaveDB(ctx, mDb, mFinish, mDontSave); save.run(); - - } private class AfterDelete extends OnFinish { @@ -81,7 +79,7 @@ public class DeleteEntry extends RunnableOnFinish { private PwEntry mEntry; private boolean recycled; - public AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry, boolean r) { + AfterDelete(OnFinish finish, PwGroup parent, PwEntry entry, boolean r) { super(finish); mParent = parent; @@ -92,18 +90,7 @@ public class DeleteEntry extends RunnableOnFinish { @Override public void run() { PwDatabase pm = mDb.pm; - if ( mSuccess ) { - // Mark parent dirty - if ( mParent != null ) { - mDb.dirty.add(mParent); - } - - if (recycled) { - PwGroup recycleBin = pm.getRecycleBin(); - mDb.dirty.add(recycleBin); - mDb.dirty.add(mDb.pm.rootGroup); - } - } else { + if ( !mSuccess ) { if (recycled) { pm.undoRecycle(mEntry, mParent); } @@ -111,11 +98,9 @@ public class DeleteEntry extends RunnableOnFinish { pm.undoDeleteEntry(mEntry, mParent); } } + // TODO Callback after delete entry super.run(); - } - } - } diff --git a/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java b/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java index 57edf8f04..342d4bcfe 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java +++ b/app/src/main/java/com/keepassdroid/database/edit/DeleteGroup.java @@ -19,30 +19,32 @@ */ package com.keepassdroid.database.edit; -import java.util.ArrayList; -import java.util.List; +import android.content.Context; -import com.keepassdroid.database.Database; -import com.keepassdroid.activities.GroupBaseActivity; import com.keepassdroid.app.App; +import com.keepassdroid.database.Database; +import com.keepassdroid.database.PwDatabase; import com.keepassdroid.database.PwEntry; import com.keepassdroid.database.PwGroup; +import java.util.ArrayList; +import java.util.List; + public class DeleteGroup extends RunnableOnFinish { - + + private Context mContext; private Database mDb; private PwGroup mGroup; - private GroupBaseActivity mAct; private boolean mDontSave; - public DeleteGroup(GroupBaseActivity act, Database db, PwGroup group, OnFinish finish) { + public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish) { super(finish); - setMembers(act, db, group, false); + setMembers(ctx, db, group, false); } - - public DeleteGroup(GroupBaseActivity act, Database db, PwGroup group, OnFinish finish, boolean dontSave) { + + public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, boolean dontSave) { super(finish); - setMembers(act, db, group, dontSave); + setMembers(ctx, db, group, dontSave); } public DeleteGroup(Database db, PwGroup group, OnFinish finish, boolean dontSave) { @@ -50,72 +52,81 @@ public class DeleteGroup extends RunnableOnFinish { setMembers(null, db, group, dontSave); } - private void setMembers(GroupBaseActivity act, Database db, PwGroup group, boolean dontSave) { + private void setMembers(Context ctx, Database db, PwGroup group, boolean dontSave) { mDb = db; mGroup = group; - mAct = act; + mContext = ctx; mDontSave = dontSave; - - mFinish = new AfterDelete(mFinish); } @Override public void run() { - - // Remove child entries - List childEnt = new ArrayList<>(mGroup.childEntries); - for ( int i = 0; i < childEnt.size(); i++ ) { - DeleteEntry task = new DeleteEntry(mAct, mDb, childEnt.get(i), null, true); - task.run(); - } - - // Remove child groups - List childGrp = new ArrayList<>(mGroup.childGroups); - for ( int i = 0; i < childGrp.size(); i++ ) { - DeleteGroup task = new DeleteGroup(mAct, mDb, childGrp.get(i), null, true); - task.run(); - } - - - // Remove from parent - PwGroup parent = mGroup.getParent(); - if ( parent != null ) { - parent.removeChildGroup(mGroup); - } - - // Remove from PwDatabaseV3 - mDb.pm.getGroups().remove(mGroup); - - // Save - SaveDB save = new SaveDB(mAct, mDb, mFinish, mDontSave); - save.run(); + PwDatabase pm = mDb.pm; + PwGroup parent = mGroup.getParent(); + // Remove Group from parent + boolean recycle = pm.canRecycle(mGroup); + if (recycle) { + pm.recycle(mGroup); + } + else { + // TODO tests + // Remove child entries + List childEnt = new ArrayList<>(mGroup.childEntries); + for ( int i = 0; i < childEnt.size(); i++ ) { + DeleteEntry task = new DeleteEntry(mContext, mDb, childEnt.get(i), null, true); + task.run(); + } + + // Remove child groups + List childGrp = new ArrayList<>(mGroup.childGroups); + for ( int i = 0; i < childGrp.size(); i++ ) { + DeleteGroup task = new DeleteGroup(mContext, mDb, childGrp.get(i), null, true); + task.run(); + } + pm.deleteGroup(mGroup); + + // Remove from PwDatabaseV3 + // TODO ENcapsulate + mDb.pm.getGroups().remove(mGroup); + } + + // Save + mFinish = new AfterDelete(mFinish, parent, mGroup, recycle); + + // Commit Database + SaveDB save = new SaveDB(mContext, mDb, mFinish, mDontSave); + save.run(); } private class AfterDelete extends OnFinish { - public AfterDelete(OnFinish finish) { + + private PwGroup mParent; + private PwGroup mGroup; + private boolean recycled; + + AfterDelete(OnFinish finish, PwGroup parent, PwGroup mGroup, boolean recycle) { super(finish); + + this.mParent = parent; + this.mGroup = mGroup; + this.recycled = recycle; } public void run() { - if ( mSuccess ) { - // Remove from tree global - mDb.pm.groups.remove(mGroup.getId()); - - // Remove tree from the dirty global (if it is present), not a big deal if this fails - mDb.dirty.remove(mGroup); - - // Mark parent dirty - PwGroup parent = mGroup.getParent(); - if ( parent != null ) { - mDb.dirty.add(parent); - } - mDb.dirty.add(mDb.pm.rootGroup); - } else { - // Let's not bother recovering from a failure to save a deleted tree. It is too much work. - App.setShutdown(); - } - + PwDatabase pm = mDb.pm; + if ( !mSuccess ) { + if (recycled) { + pm.undoRecycle(mGroup, mParent); + } + else { + // Let's not bother recovering from a failure to save a deleted tree. It is too much work. + App.setShutdown(); + // TODO TEST pm.undoDeleteGroup(mGroup, mParent); + } + } + // TODO Callback after delete group + super.run(); } } diff --git a/app/src/main/java/com/keepassdroid/database/edit/UpdateEntry.java b/app/src/main/java/com/keepassdroid/database/edit/UpdateEntry.java index b227bfbff..b54294ba0 100644 --- a/app/src/main/java/com/keepassdroid/database/edit/UpdateEntry.java +++ b/app/src/main/java/com/keepassdroid/database/edit/UpdateEntry.java @@ -23,7 +23,6 @@ import android.content.Context; import com.keepassdroid.database.Database; import com.keepassdroid.database.PwEntry; -import com.keepassdroid.database.PwGroup; public class UpdateEntry extends RunnableOnFinish { private Database mDb; @@ -61,32 +60,19 @@ public class UpdateEntry extends RunnableOnFinish { private class AfterUpdate extends OnFinish { private PwEntry mBackup; - public AfterUpdate(PwEntry backup, OnFinish finish) { + AfterUpdate(PwEntry backup, OnFinish finish) { super(finish); - mBackup = backup; } @Override public void run() { - if ( mSuccess ) { - // Mark group dirty if title or icon changes - if ( ! mBackup.isContentVisuallyTheSame(mNewE) ) { - PwGroup parent = mBackup.getParent(); - if ( parent != null ) { - // Mark parent group dirty - mDb.dirty.add(parent); - } - } - } else { + if ( !mSuccess ) { // If we fail to save, back out changes to global structure mOldE.assign(mBackup); } - + // TODO Callback for update entry super.run(); } - } - - }