Solve bugs when update node in list, start encapsulate code

This commit is contained in:
Jeremy
2018-02-12 00:22:03 +01:00
parent 795d6fa334
commit d568604117
18 changed files with 388 additions and 158 deletions

View File

@@ -74,8 +74,8 @@ public class DeleteEntry extends AndroidTestCase {
PwGroup results1 = dbHelp.search(db, ENTRY1_NAME);
PwGroup results2 = dbHelp.search(db, ENTRY2_NAME);
assertEquals("Entry1 was not removed from the search results", 0, results1.childEntries.size());
assertEquals("Entry2 was not removed from the search results", 0, results2.childEntries.size());
assertEquals("Entry1 was not removed from the search results", 0, results1.numbersOfChildEntries());
assertEquals("Entry2 was not removed from the search results", 0, results2.numbersOfChildEntries());
// Verify the group was deleted
group1 = getGroup(pm, GROUP1_NAME);

View File

@@ -43,7 +43,7 @@ public class SearchTest extends AndroidTestCase {
public void testSearch() {
PwGroup results = mDb.Search("Amazon");
assertTrue("Search result not found.", results.childEntries.size() > 0);
assertTrue("Search result not found.", results.numbersOfChildEntries() > 0);
}
@@ -51,14 +51,14 @@ public class SearchTest extends AndroidTestCase {
updateOmitSetting(false);
PwGroup results = mDb.Search("BackupOnly");
assertTrue("Search result not found.", results.childEntries.size() > 0);
assertTrue("Search result not found.", results.numbersOfChildEntries() > 0);
}
public void testBackupExcluded() {
updateOmitSetting(true);
PwGroup results = mDb.Search("BackupOnly");
assertFalse("Search result found, but should not have been.", results.childEntries.size() > 0);
assertFalse("Search result found, but should not have been.", results.numbersOfChildEntries() > 0);
}
private void updateOmitSetting(boolean setting) {

View File

@@ -34,13 +34,8 @@ import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.keepassdroid.database.Database;
import com.keepassdroid.fragments.GeneratePasswordDialogFragment;
import com.keepassdroid.fragments.IconPickerDialogFragment;
import com.keepassdroid.tasks.ProgressTask;
import com.kunzisoft.keepass.KeePass;
import com.kunzisoft.keepass.R;
import com.keepassdroid.app.App;
import com.keepassdroid.database.Database;
import com.keepassdroid.database.PwDatabase;
import com.keepassdroid.database.PwEntry;
import com.keepassdroid.database.PwEntryV3;
@@ -54,10 +49,15 @@ import com.keepassdroid.database.edit.AddEntry;
import com.keepassdroid.database.edit.OnFinish;
import com.keepassdroid.database.edit.RunnableOnFinish;
import com.keepassdroid.database.edit.UpdateEntry;
import com.keepassdroid.fragments.GeneratePasswordDialogFragment;
import com.keepassdroid.fragments.IconPickerDialogFragment;
import com.keepassdroid.icons.Icons;
import com.keepassdroid.tasks.ProgressTask;
import com.keepassdroid.utils.MenuUtil;
import com.keepassdroid.utils.Types;
import com.keepassdroid.utils.Util;
import com.kunzisoft.keepass.KeePass;
import com.kunzisoft.keepass.R;
import java.util.Calendar;
import java.util.Date;
@@ -189,7 +189,7 @@ public abstract class EntryEditActivity extends LockCloseHideActivity
PwEntry newEntry = populateNewEntry();
RunnableOnFinish task;
OnFinish onFinish = act.new AfterSave(new Handler());
OnFinish onFinish = new AfterSave();
Intent intentEntry = new Intent();
if ( mIsNew ) {
@@ -198,7 +198,7 @@ public abstract class EntryEditActivity extends LockCloseHideActivity
setResult(ADD_ENTRY_RESULT_CODE, intentEntry);
} else {
task = new UpdateEntry(act, App.getDB(), mEntry, newEntry, onFinish);
intentEntry.putExtra(ADD_OR_UPDATE_ENTRY_KEY, mEntry);
intentEntry.putExtra(ADD_OR_UPDATE_ENTRY_KEY, newEntry);
setResult(UPDATE_ENTRY_RESULT_CODE, intentEntry);
}
ProgressTask pt = new ProgressTask(act, task, R.string.saving_database);
@@ -322,8 +322,8 @@ public abstract class EntryEditActivity extends LockCloseHideActivity
private final class AfterSave extends OnFinish {
AfterSave(Handler handler) {
super(handler);
AfterSave() {
super(new Handler());
}
@Override

View File

@@ -251,7 +251,7 @@ public abstract class GroupActivity extends GroupBaseActivity
if (resultCode == EntryEditActivity.ADD_ENTRY_RESULT_CODE)
mAdapter.addNode(newNode);
if (resultCode == EntryEditActivity.UPDATE_ENTRY_RESULT_CODE)
mAdapter.updateNode(newNode);
mAdapter.updateLastNodeClicked();
}
break;
}

View File

@@ -261,8 +261,8 @@ public abstract class GroupBaseActivity extends LockCloseListActivity
db.dirty.remove(mGroup);
// Tell the adapter to refresh it's list
// TODO mAdapter.sort();
mAdapter.notifyDataSetChanged();
mAdapter.notifyChangeSort();
mAdapter.rebuildList(mGroup);
}
@Override

View File

@@ -1,3 +1,23 @@
/*
* Copyright 2018 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePass DX.
*
* KeePass DX 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 2 of the License, or
* (at your option) any later version.
*
* KeePass DX 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 KeePass DX. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
package com.keepassdroid.adapters;
import android.content.Context;
@@ -13,6 +33,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.keepassdroid.app.App;
import com.keepassdroid.database.PwGroup;
import com.keepassdroid.database.PwNode;
import com.keepassdroid.settings.PrefsUtil;
import com.kunzisoft.keepass.R;
@@ -27,25 +48,30 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
private Context context;
private LayoutInflater inflater;
private float textSize;
private boolean sortByName;
private OnNodeClickCallback onNodeClickCallback;
private int nodePositionToUpdate;
private NodeMenuListener nodeMenuListener;
public NodeAdapter(final Context context, PwNode mainNode) {
public NodeAdapter(final Context context, PwGroup mainNode) {
this.inflater = LayoutInflater.from(context);
this.context = context;
this.textSize = PrefsUtil.getListTextSize(context);
this.sortByName = PrefsUtil.isListSortByName(context);
this.nodePositionToUpdate = -1;
this.nodeSortedList = new SortedList<>(PwNode.class, new SortedListAdapterCallback<PwNode>(this) {
@Override public int compare(PwNode item1, PwNode item2) {
if(PrefsUtil.isListSortByName(context))
return item1.compareTo(item2);
// Choose sort depend of preferences
if(sortByName)
return new PwNode.NodeNameComparator().compare(item1, item2);
else
return item1.compareTo(item2); // TODO Different sort
return new PwNode.NodeCreationComparator().compare(item1, item2);
}
@Override public boolean areContentsTheSame(PwNode oldItem, PwNode newItem) {
return oldItem.equals(newItem);
return oldItem.isContentVisuallyTheSame(newItem);
}
@Override public boolean areItemsTheSame(PwNode item1, PwNode item2) {
@@ -55,22 +81,51 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
this.nodeSortedList.addAll(mainNode.getDirectChildren());
}
/**
* Rebuild the list by clear and build again for the group
*/
public void rebuildList(PwGroup group) {
this.nodeSortedList.clear();
this.nodeSortedList.addAll(group.getDirectChildren());
}
/**
* Add a node to the list
* @param node Node to add
*/
public void addNode(PwNode node) {
nodeSortedList.add(node);
}
public void updateNode(PwNode node) {
/**
* Update the last Node clicked in the list
*/
public void updateLastNodeClicked() {
// Don't really update here, sorted list knows each original ref, so we just notify a change
try {
nodeSortedList.updateItemAt(nodeSortedList.indexOf(node), node);
notifyItemChanged(nodePositionToUpdate);
nodeSortedList.recalculatePositionOfItemAt(nodePositionToUpdate);
} catch (IndexOutOfBoundsException e) {
Log.e(NodeAdapter.class.getName(), e.getMessage());
}
}
/**
* Remove node in the list
* @param node Node to delete
*/
public void removeNode(PwNode node) {
nodeSortedList.remove(node);
}
/**
* Notify a change sort of the list
*/
// TODO as interface
public void notifyChangeSort() {
this.sortByName = PrefsUtil.isListSortByName(context);
}
@Override
public int getItemViewType(int position) {
return nodeSortedList.get(position).getType().ordinal();
@@ -112,19 +167,39 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
return nodeSortedList.size();
}
/**
* Assign a listener when a node is clicked
*/
public void setOnNodeClickListener(OnNodeClickCallback onNodeClickCallback) {
this.onNodeClickCallback = onNodeClickCallback;
}
/**
* Assign a listener when an element of menu is clicked
*/
public void setNodeMenuListener(NodeMenuListener nodeMenuListener) {
this.nodeMenuListener = nodeMenuListener;
}
/**
* Callback listener to redefine to do an action when a node is click
*/
public interface OnNodeClickCallback {
void onNodeClick(PwNode node);
}
public class OnNodeClickListener implements View.OnClickListener {
/**
* Menu listener to redefine to do an action in menu
*/
public interface NodeMenuListener {
boolean onOpenMenuClick(PwNode node);
boolean onDeleteMenuClick(PwNode node);
}
/**
* Utility class for node listener
*/
private class OnNodeClickListener implements View.OnClickListener {
private PwNode node;
OnNodeClickListener(PwNode node) {
@@ -133,16 +208,15 @@ public class NodeAdapter extends RecyclerView.Adapter<BasicViewHolder> {
@Override
public void onClick(View v) {
nodePositionToUpdate = nodeSortedList.indexOf(node);
if (onNodeClickCallback != null)
onNodeClickCallback.onNodeClick(node);
}
}
public interface NodeMenuListener {
boolean onOpenMenuClick(PwNode node);
boolean onDeleteMenuClick(PwNode node);
}
/**
* Utility class for menu listener
*/
private class ContextMenuBuilder implements View.OnCreateContextMenuListener {
private PwNode node;

View File

@@ -256,7 +256,7 @@ public abstract class PwDatabase {
parent = rootGroup;
}
parent.childGroups.add(newGroup);
parent.addChildGroup(newGroup);
newGroup.setParent(parent);
groups.put(newGroup.getId(), newGroup);
@@ -265,7 +265,7 @@ public abstract class PwDatabase {
public void removeGroupFrom(PwGroup remove, PwGroup parent) {
// Remove tree from parent tree
parent.childGroups.remove(remove);
parent.removeChildGroup(remove);
groups.remove(remove.getId());
}
@@ -273,7 +273,7 @@ public abstract class PwDatabase {
public void addEntryTo(PwEntry newEntry, PwGroup parent) {
// Add entry to parent
if (parent != null) {
parent.childEntries.add(newEntry);
parent.addChildEntry(newEntry);
}
newEntry.setParent(parent);
@@ -283,7 +283,7 @@ public abstract class PwDatabase {
public void removeEntryFrom(PwEntry remove, PwGroup parent) {
// Remove entry for parent
if (parent != null) {
parent.childEntries.remove(remove);
parent.removeChildEntry(remove);
}
entries.remove(remove.getUUID());
}

View File

@@ -179,12 +179,12 @@ public class PwDatabaseV3 extends PwDatabase {
currentGroup.childEntries = getEntries(currentGroup);
// set parent in child entries
for (int i = 0; i < currentGroup.childEntries.size(); i++) {
for (int i = 0; i < currentGroup.numbersOfChildEntries(); i++) {
PwEntryV3 entry = (PwEntryV3) currentGroup.childEntries.get(i);
entry.parent = currentGroup;
}
// recursively construct child groups
for (int i = 0; i < currentGroup.childGroups.size(); i++) {
for (int i = 0; i < currentGroup.numbersOfChildGroups(); i++) {
PwGroupV3 grp = (PwGroupV3) currentGroup.childGroups.get(i);
grp.parent = currentGroup;
constructTree((PwGroupV3) currentGroup.childGroups.get(i));

View File

@@ -29,20 +29,8 @@ public abstract class PwEntry extends PwNode implements Cloneable {
protected static final String PMS_TAN_ENTRY = "<TAN>";
public static class EntryNameComparator implements Comparator<PwEntry> {
public int compare(PwEntry object1, PwEntry object2) {
return object1.getTitle().compareToIgnoreCase(object2.getTitle());
}
}
public PwIconStandard icon = PwIconStandard.FIRST;
public PwEntry() {
}
public static PwEntry getInstance(PwGroup parent) {
return PwEntry.getInstance(parent, true, true);
}
@@ -183,4 +171,53 @@ public abstract class PwEntry extends PwNode implements Cloneable {
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PwEntry pwEntry = (PwEntry) o;
return isSameType(pwEntry)
&& (getUUID() != null ? getUUID().equals(pwEntry.getUUID()) : pwEntry.getUUID() == null);
}
@Override
public int hashCode() {
return getUUID() != null ? getUUID().hashCode() : 0;
}
/**
* Comparator of Entry by Name
*/
public static class EntryNameComparator implements Comparator<PwEntry> {
public int compare(PwEntry object1, PwEntry object2) {
if (object1.equals(object2))
return 0;
int entryTitleComp = object1.getTitle().compareToIgnoreCase(object2.getTitle());
// If same title, can be different
if (entryTitleComp == 0) {
return object1.hashCode() - object2.hashCode();
}
return entryTitleComp;
}
}
/**
* Comparator of Entry by Creation
*/
public static class EntryCreationComparator implements Comparator<PwEntry> {
public int compare(PwEntry object1, PwEntry object2) {
if (object1.equals(object2))
return 0;
int entryCreationComp = object1.getCreationTime().compareTo(object2.getCreationTime());
// If same creation, can be different
if (entryCreationComp == 0) {
return object1.hashCode() - object2.hashCode();
}
return entryCreationComp;
}
}
}

View File

@@ -19,31 +19,51 @@
*/
package com.keepassdroid.database;
import com.keepassdroid.utils.StrUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import com.keepassdroid.utils.StrUtil;
public abstract class PwGroup extends PwNode {
// TODO Change dependency and make private
public List<PwGroup> childGroups = new ArrayList<>();
public List<PwEntry> childEntries = new ArrayList<>();
public String name = "";
public PwIconStandard icon;
@Override
public List<PwNode> getDirectChildren() {
List<PwNode> children = new ArrayList<>();
children.addAll(childGroups);
children.addAll(childEntries);
return children;
private List<PwNode> children = new ArrayList<>();
public void initNewGroup(String nm, PwGroupId newId) {
setId(newId);
name = nm;
}
@Override
public int numberOfDirectChildren() {
return childGroups.size() + childEntries.size();
public void addChildGroup(PwGroup group) {
this.childGroups.add(group);
}
public void addChildEntry(PwEntry entry) {
this.childEntries.add(entry);
}
public void removeChildGroup(PwGroup group) {
this.childGroups.remove(group);
}
public void removeChildEntry(PwEntry entry) {
this.childEntries.remove(entry);
}
public int numbersOfChildGroups() {
return childGroups.size();
}
public int numbersOfChildEntries() {
return childEntries.size();
}
@Override
@@ -51,9 +71,38 @@ public abstract class PwGroup extends PwNode {
return Type.GROUP;
}
/**
* @return List of direct children (one level below) as PwNode
*/
public List<PwNode> getDirectChildren() {
children.clear();
children.addAll(childGroups);
children.addAll(childEntries);
return children;
}
/**
* Number of direct elements in Node (one level below)
* @return Size of child elements, default is 0
*/
public int numberOfDirectChildren() {
return childGroups.size() + childEntries.size();
}
public abstract PwGroup getParent();
public abstract void setParent(PwGroup parent);
public boolean isContainedIn(PwGroup container) {
PwGroup cur = this;
while (cur != null) {
if (cur == container) {
return true;
}
cur = cur.getParent();
}
return false;
}
public abstract PwGroupId getId();
public abstract void setId(PwGroupId id);
@@ -70,43 +119,12 @@ public abstract class PwGroup extends PwNode {
return icon;
}
public static class GroupNameComparator implements Comparator<PwGroup> {
public int compare(PwGroup object1, PwGroup object2) {
return object1.getName().compareToIgnoreCase(object2.getName());
}
}
public abstract void setLastAccessTime(Date date);
public abstract void setLastModificationTime(Date date);
public void sortEntriesByName() {
Collections.sort(childEntries, new PwEntry.EntryNameComparator());
}
public void initNewGroup(String nm, PwGroupId newId) {
setId(newId);
name = nm;
}
public boolean isContainedIn(PwGroup container) {
PwGroup cur = this;
while (cur != null) {
if (cur == container) {
return true;
}
cur = cur.getParent();
}
return false;
}
public void touch(boolean modified, boolean touchParents) {
Date now = new Date();
setLastAccessTime(now);
if (modified) {
@@ -119,7 +137,6 @@ public abstract class PwGroup extends PwNode {
}
}
public void searchEntries(SearchParameters sp, List<PwEntry> listStorage) {
if (sp == null) { return; }
if (listStorage == null) { return; }
@@ -166,7 +183,6 @@ public abstract class PwGroup extends PwNode {
complement.add(entry);
}
}
pg = complement;
}
else {
@@ -200,19 +216,64 @@ public abstract class PwGroup extends PwNode {
if (entryHandler != null) {
for (PwEntry entry : childEntries) {
if (!entryHandler.operate(entry)) return false;
}
}
for (PwGroup group : childGroups) {
if ((groupHandler != null) && !groupHandler.operate(group)) return false;
group.preOrderTraverseTree(groupHandler, entryHandler);
}
return true;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PwGroup pwGroup = (PwGroup) o;
return isSameType(pwGroup)
&& (getId() != null ? getId().equals(pwGroup.getId()) : pwGroup.getId() == null);
}
@Override
public int hashCode() {
PwGroupId groupId = getId();
return groupId != null ? groupId.hashCode() : 0;
}
/**
* Group comparator by name
*/
public static class GroupNameComparator implements Comparator<PwGroup> {
public int compare(PwGroup object1, PwGroup object2) {
if (object1.equals(object2))
return 0;
int groupNameComp = object1.getName().compareToIgnoreCase(object2.getName());
// If same name, can be different
if (groupNameComp == 0) {
return object1.hashCode() - object2.hashCode();
}
return groupNameComp;
}
}
/**
* Group comparator by name
*/
public static class GroupCreationComparator implements Comparator<PwGroup> {
public int compare(PwGroup object1, PwGroup object2) {
if (object1.equals(object2))
return 0;
int groupCreationComp = object1.getCreationTime().compareTo(object2.getCreationTime());
// If same creation, can be different
if (groupCreationComp == 0) {
return object1.hashCode() - object2.hashCode();
}
return groupCreationComp;
}
}
}

View File

@@ -39,7 +39,7 @@ public class PwGroupIdV3 extends PwGroupId {
@Override
public int hashCode() {
Integer i = Integer.valueOf(id);
Integer i = id;
return i.hashCode();
}

View File

@@ -34,8 +34,6 @@ import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* @author Brian Pellin <bpellin@gmail.com>
* @author Naomaru Itoi <nao@phoneid.org>
@@ -43,8 +41,6 @@ import java.util.List;
* @author Dominik Reichl <dominik.reichl@t-online.de>
*/
public class PwGroupV3 extends PwGroup {
public PwGroupV3() {
}
public String toString() {
return name;
@@ -155,4 +151,11 @@ public class PwGroupV3 extends PwGroup {
tLastMod = new PwDate(date);
}
@Override
public Date getCreationTime() {
if(tCreation != null)
return tCreation.getJDate();
else
return new Date();
}
}

View File

@@ -48,9 +48,7 @@ public class PwGroupV4 extends PwGroup implements ITimeLogger {
private long usageCount = 0;
public Map<String, String> customData = new HashMap<String, String>();
public PwGroupV4() {
}
public PwGroupV4() {}
public PwGroupV4(boolean createUUID, boolean setTimes, String name, PwIconStandard icon) {
if (createUUID) {
@@ -87,7 +85,7 @@ public class PwGroupV4 extends PwGroup implements ITimeLogger {
public void AddEntry(PwEntryV4 pe, boolean takeOwnership, boolean updateLocationChanged) {
assert(pe != null);
childEntries.add(pe);
addChildEntry(pe);
if ( takeOwnership ) pe.parent = this;
@@ -102,7 +100,7 @@ public class PwGroupV4 extends PwGroup implements ITimeLogger {
public void buildChildGroupsRecursive(List<PwGroup> list) {
list.add(this);
for ( int i = 0; i < childGroups.size(); i++) {
for ( int i = 0; i < numbersOfChildGroups(); i++) {
PwGroupV4 child = (PwGroupV4) childGroups.get(i);
child.buildChildGroupsRecursive(list);
@@ -110,11 +108,11 @@ public class PwGroupV4 extends PwGroup implements ITimeLogger {
}
public void buildChildEntriesRecursive(List<PwEntry> list) {
for ( int i = 0; i < childEntries.size(); i++ ) {
for ( int i = 0; i < numbersOfChildEntries(); i++ ) {
list.add(childEntries.get(i));
}
for ( int i = 0; i < childGroups.size(); i++ ) {
for ( int i = 0; i < numbersOfChildGroups(); i++ ) {
PwGroupV4 child = (PwGroupV4) childGroups.get(i);
child.buildChildEntriesRecursive(list);
}

View File

@@ -20,71 +20,133 @@
*/
package com.keepassdroid.database;
import android.support.annotation.NonNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
import java.util.Date;
/**
* Abstract class who manage Groups and Entries
*/
public abstract class PwNode implements Comparable<PwNode>, Serializable {
public abstract class PwNode implements Serializable {
/**
* Get the type of Node
* Type of available Nodes
*/
public enum Type {
GROUP, ENTRY
}
/**
* @return Type of Node
*/
public abstract Type getType();
/**
* @return title to display as view
* @return Title to display as view
*/
public abstract String getDisplayTitle();
/**
* @return Visual icon
*/
public abstract PwIcon getIcon();
/**
* @return List of direct children (one level below) as PwNode
* @return Creation date and time of the node
*/
public List<PwNode> getDirectChildren() {
return new ArrayList<>();
}
public abstract Date getCreationTime();
public PwNode getDirectChildAt(int position) {
return getDirectChildren().get(position);
/**
* If the content (type, title, icon) is visually the same
* @param o Node to compare
* @return True if visually as o
*/
public boolean isContentVisuallyTheSame(PwNode o) {
return getType().equals(o.getType())
&& getDisplayTitle().equals(o.getDisplayTitle())
&& getIcon().equals(o.getIcon());
}
/**
* Number of direct elements in Node (one level below)
* @return Size of child elements, default is 0
* Define if it's the same type of another node
* @param otherNode The other node to test
* @return true if both have the same type
*/
public int numberOfDirectChildren() {
return getDirectChildren().size();
boolean isSameType(PwNode otherNode) {
return getType() != null ? getType().equals(otherNode.getType()) : otherNode.getType() == null;
}
/**
* Comparator of Node by Name, Groups first, Entries second
*/
public static class NodeNameComparator implements Comparator<PwNode> {
public int compare(PwNode object1, PwNode object2) {
if (object1.equals(object2))
return 0;
if (object1 instanceof PwGroup) {
if (object2 instanceof PwGroup) {
return new PwGroup.GroupNameComparator()
.compare((PwGroup) object1, (PwGroup) object2);
} else if (object2 instanceof PwEntry) {
return -1;
} else {
return -1;
}
} else if (object1 instanceof PwEntry) {
if(object2 instanceof PwEntry) {
return new PwEntry.EntryNameComparator()
.compare((PwEntry) object1, (PwEntry) object2);
} else if (object2 instanceof PwGroup) {
return 1;
} else {
return -1;
}
}
int nodeNameComp = object1.getDisplayTitle()
.compareToIgnoreCase(object2.getDisplayTitle());
// If same name, can be different
if (nodeNameComp == 0)
return object1.hashCode() - object2.hashCode();
return nodeNameComp;
}
}
/**
* Comparator of node by creation, Groups first, Entries second
*/
public static class NodeCreationComparator implements Comparator<PwNode> {
@Override
public int compareTo(@NonNull PwNode o) {
if (this instanceof PwGroup) {
if (o instanceof PwGroup) {
return new PwGroup.GroupNameComparator().compare((PwGroup) this, (PwGroup) o);
} else if (o instanceof PwEntry) {
return -1;
} else {
return -1;
}
} else if (this instanceof PwEntry) {
if(o instanceof PwEntry) {
return new PwEntry.EntryNameComparator().compare((PwEntry) this, (PwEntry) o);
} else if (o instanceof PwGroup) {
return 1;
} else {
return 1;
}
}
return this.getDisplayTitle().compareToIgnoreCase(o.getDisplayTitle());
}
public int compare(PwNode object1, PwNode object2) {
if (object1.equals(object2))
return 0;
public enum Type {
GROUP, ENTRY
if (object1 instanceof PwGroup) {
if (object2 instanceof PwGroup) {
return new PwGroup.GroupCreationComparator()
.compare((PwGroup) object1, (PwGroup) object2);
} else if (object2 instanceof PwEntry) {
return -1;
} else {
return -1;
}
} else if (object1 instanceof PwEntry) {
if(object2 instanceof PwEntry) {
return new PwEntry.EntryCreationComparator()
.compare((PwEntry) object1, (PwEntry) object2);
} else if (object2 instanceof PwGroup) {
return 1;
} else {
return -1;
}
}
int nodeCreationComp = object1.getCreationTime()
.compareTo(object2.getCreationTime());
// If same creation, can be different
if (nodeCreationComp == 0) {
return object1.hashCode() - object2.hashCode();
}
return nodeCreationComp;
}
}
}

View File

@@ -80,7 +80,7 @@ public class DeleteGroup extends RunnableOnFinish {
// Remove from parent
PwGroup parent = mGroup.getParent();
if ( parent != null ) {
parent.childGroups.remove(mGroup);
parent.removeChildGroup(mGroup);
}
// Remove from PwDatabaseV3

View File

@@ -71,16 +71,11 @@ public class UpdateEntry extends RunnableOnFinish {
public void run() {
if ( mSuccess ) {
// Mark group dirty if title or icon changes
// TODO CHange if not equal... Why only title and Icon ?
if ( ! mBackup.getTitle().equals(mNewE.getTitle()) || ! mBackup.getIcon().equals(mNewE.getIcon()) ) {
if ( ! mBackup.isContentVisuallyTheSame(mNewE) ) {
PwGroup parent = mBackup.getParent();
if ( parent != null ) {
// Resort entries
parent.sortEntriesByName();
// Mark parent group dirty
mDb.dirty.add(parent);
}
}
} else {

View File

@@ -260,7 +260,7 @@ public class PwDbV3Output extends PwDbOutput {
groupList.add(group);
// Recurse over children
for ( int i = 0; i < group.childGroups.size(); i++ ) {
for ( int i = 0; i < group.numbersOfChildGroups(); i++ ) {
sortGroup((PwGroupV3) group.childGroups.get(i), groupList);
}
}

View File

@@ -99,7 +99,7 @@ public class SearchResultsActivity extends GroupBaseActivity {
private void performSearch(String query) {
mGroup = mDb.Search(query.trim());
if ( mGroup == null || mGroup.childEntries.size() < 1 ) {
if ( mGroup == null || mGroup.numbersOfChildEntries() < 1 ) {
listView.setVisibility(View.GONE);
notFoundView.setVisibility(View.VISIBLE);
} else {