allow differnt sorting options

"touch" groups after editing to get correct sort order "modification date"
This commit is contained in:
Philipp Crocoll 2014-12-23 20:29:27 +01:00
parent b61904c01c
commit fa7365323c
8 changed files with 1563 additions and 1395 deletions

View File

@ -53,6 +53,7 @@ namespace keepass2android
Group.Name = _name; Group.Name = _name;
Group.IconId = _iconId; Group.IconId = _iconId;
Group.CustomIconUuid = _customIconId; Group.CustomIconUuid = _customIconId;
Group.Touch(true);
// Commit to disk // Commit to disk
SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun); SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun);

View File

@ -53,23 +53,15 @@ namespace keepass2android
public override void Run() { public override void Run() {
if ( Success ) { if ( Success ) {
// Mark group dirty if title, icon or Expiry stuff changes // Mark parent group dirty. Even only the last modification date changed, this might affect sort order
if ( ! _backup.Strings.ReadSafe (PwDefs.TitleField).Equals(_updatedEntry.Strings.ReadSafe (PwDefs.TitleField)) PwGroup parent = _updatedEntry.ParentGroup;
|| ! _backup.IconId.Equals(_updatedEntry.IconId) if ( parent != null ) {
|| !_backup.CustomIconUuid.Equals(_updatedEntry.CustomIconUuid)
|| _backup.Expires != _updatedEntry.Expires
|| (_backup.Expires && (! _backup.ExpiryTime.Equals(_updatedEntry.ExpiryTime)))
)
{ // Mark parent group dirty
PwGroup parent = _updatedEntry.ParentGroup; _app.GetDb().Dirty.Add(parent);
if ( parent != null ) {
// Mark parent group dirty
_app.GetDb().Dirty.Add(parent);
}
} }
} else { } else {
StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); StatusLogger.UpdateMessage(UiStringKey.UndoingChanges);
// If we fail to save, back out changes to global structure // If we fail to save, back out changes to global structure

View File

@ -16,6 +16,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/ */
using System; using System;
using System.Collections.Generic;
using System.Linq;
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.OS; using Android.OS;
@ -331,19 +333,7 @@ namespace keepass2android
return true; return true;
} }
private void SetSortMenuText(IMenu menu) {
bool sortByName = _prefs.GetBoolean(GetString(Resource.String.sort_key), Resources.GetBoolean(Resource.Boolean.sort_default));
int resId;
if ( sortByName ) {
resId = Resource.String.sort_db;
} else {
resId = Resource.String.sort_name;
}
menu.FindItem(Resource.Id.menu_sort).SetTitle(resId);
}
public override bool OnPrepareOptionsMenu(IMenu menu) { public override bool OnPrepareOptionsMenu(IMenu menu) {
if ( ! base.OnPrepareOptionsMenu(menu) ) { if ( ! base.OnPrepareOptionsMenu(menu) ) {
@ -351,7 +341,7 @@ namespace keepass2android
} }
Util.PrepareDonateOptionMenu(menu, this); Util.PrepareDonateOptionMenu(menu, this);
SetSortMenuText(menu);
return true; return true;
} }
@ -378,7 +368,7 @@ namespace keepass2android
return true; return true;
case Resource.Id.menu_sort: case Resource.Id.menu_sort:
ToggleSort(); ChangeSort();
return true; return true;
case Android.Resource.Id.Home: case Android.Resource.Id.Home:
//Currently the action bar only displays the home button when we come from a previous activity. //Currently the action bar only displays the home button when we come from a previous activity.
@ -471,26 +461,41 @@ namespace keepass2android
base.OnBackPressed(); base.OnBackPressed();
} }
private void ToggleSort() { private void ChangeSort()
// Toggle setting {
String sortKey = GetString(Resource.String.sort_key); var sortOrderManager = new GroupViewSortOrderManager(this);
bool sortByName = _prefs.GetBoolean(sortKey, Resources.GetBoolean(Resource.Boolean.sort_default)); IEnumerable<string> sortOptions = sortOrderManager.SortOrders.Select(
ISharedPreferencesEditor editor = _prefs.Edit(); o => GetString(o.ResourceId)
editor.PutBoolean(sortKey, ! sortByName); );
EditorCompat.Apply(editor);
int selectedBefore = sortOrderManager.GetCurrentSortOrderIndex();
new AlertDialog.Builder(this)
.SetSingleChoiceItems(sortOptions.ToArray(), selectedBefore, (sender, args) =>
{
int selectedAfter = args.Which;
sortOrderManager.SetNewSortOrder(selectedAfter);
// Refresh menu titles
ActivityCompat.InvalidateOptionsMenu(this);
// Mark all groups as dirty now to refresh them on load
Database db = App.Kp2a.GetDb();
db.MarkAllGroupsAsDirty();
// We'll manually refresh this group so we can remove it
db.Dirty.Remove(Group);
// Tell the adapter to refresh it's list
BaseAdapter adapter = (BaseAdapter)ListAdapter;
adapter.NotifyDataSetChanged();
})
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
.Show();
// Refresh menu titles
ActivityCompat.InvalidateOptionsMenu(this);
// Mark all groups as dirty now to refresh them on load
Database db = App.Kp2a.GetDb();
db.MarkAllGroupsAsDirty();
// We'll manually refresh this group so we can remove it
db.Dirty.Remove(Group);
// Tell the adapter to refresh it's list
BaseAdapter adapter = (BaseAdapter) ListAdapter;
adapter.NotifyDataSetChanged();
} }

View File

@ -27,6 +27,182 @@ using keepass2android.view;
namespace keepass2android namespace keepass2android
{ {
public interface IGroupViewSortOrder
{
int ResourceId { get; }
bool RequiresSort { get; }
int CompareEntries(PwEntry a, PwEntry b);
int CompareGroups(PwGroup a, PwGroup b);
}
class ModDateSortOrder : IGroupViewSortOrder
{
public int ResourceId
{
get { return Resource.String.sort_moddate; }
}
public bool RequiresSort
{
get { return true; }
}
public int CompareEntries(PwEntry a, PwEntry b)
{
return a.LastModificationTime.CompareTo(b.LastModificationTime);
}
public int CompareGroups(PwGroup a, PwGroup b)
{
return a.LastModificationTime.CompareTo(b.LastModificationTime);
}
}
class CreationDateSortOrder : IGroupViewSortOrder
{
public int ResourceId
{
get { return Resource.String.sort_db; }
}
public bool RequiresSort
{
get { return true; }
}
public int CompareEntries(PwEntry a, PwEntry b)
{
return a.CreationTime.CompareTo(b.CreationTime);
}
public int CompareGroups(PwGroup a, PwGroup b)
{
return a.CreationTime.CompareTo(b.CreationTime);
}
}
public class DefaultSortOrder: IGroupViewSortOrder
{
public int ResourceId
{
get { return Resource.String.sort_default; }
}
public bool RequiresSort
{
get { return false; }
}
public int CompareEntries(PwEntry a, PwEntry b)
{
return 0;
}
public int CompareGroups(PwGroup a, PwGroup b)
{
return 0;
}
}
public class NameSortOrder: IGroupViewSortOrder
{
public int ResourceId
{
get { return Resource.String.sort_name; }
}
public bool RequiresSort
{
get { return true; }
}
public int CompareEntries(PwEntry x, PwEntry y)
{
String nameX = x.Strings.ReadSafe(PwDefs.TitleField);
String nameY = y.Strings.ReadSafe(PwDefs.TitleField);
if (nameX.ToLower() != nameY.ToLower())
return String.Compare(nameX, nameY, StringComparison.OrdinalIgnoreCase);
else
{
if (PwDefs.IsTanEntry(x) && PwDefs.IsTanEntry(y))
{
//compare the user name fields (=TAN index)
String userX = x.Strings.ReadSafe(PwDefs.UserNameField);
String userY = y.Strings.ReadSafe(PwDefs.UserNameField);
if (userX != userY)
{
try
{
return int.Parse(userX).CompareTo(int.Parse(userY));
}
catch (Exception)
{
//ignore
}
return String.Compare(userX, userY, StringComparison.OrdinalIgnoreCase);
}
}
//use creation time for non-tan entries:
return x.CreationTime.CompareTo(y.CreationTime);
}
}
public int CompareGroups(PwGroup a, PwGroup b)
{
return String.CompareOrdinal(a.Name, b.Name);
}
}
public class GroupViewSortOrderManager
{
private readonly Context _context;
private readonly IGroupViewSortOrder[] _orders = new IGroupViewSortOrder[] { new DefaultSortOrder(), new NameSortOrder(), new ModDateSortOrder(), new CreationDateSortOrder()};
private readonly ISharedPreferences _prefs;
public GroupViewSortOrderManager(Context context)
{
_context = context;
_prefs = PreferenceManager.GetDefaultSharedPreferences(_context);
}
public IGroupViewSortOrder[] SortOrders
{
get { return _orders; }
}
public bool SortGroups
{
get { return true; }
//_prefs.GetBoolean(_context.GetString(Resource.String.sortgroups_key), false); }
}
public IGroupViewSortOrder GetCurrentSortOrder()
{
return SortOrders[GetCurrentSortOrderIndex()];
}
public int GetCurrentSortOrderIndex()
{
String sortKeyOld = _context.GetString(Resource.String.sort_key_old);
String sortKey = _context.GetString(Resource.String.sort_key);
int sortId = _prefs.GetInt(sortKey, -1);
if (sortId == -1)
{
sortId = _prefs.GetBoolean(sortKeyOld, true) ? 1 : 0;
}
return sortId;
}
public void SetNewSortOrder(int selectedAfter)
{
String sortKey = _context.GetString(Resource.String.sort_key);
ISharedPreferencesEditor editor = _prefs.Edit();
editor.PutInt(sortKey, selectedAfter);
//editor.PutBoolean(_context.GetString(Resource.String.sortgroups_key), false);
EditorCompat.Apply(editor);
}
}
public class PwGroupListAdapter : BaseAdapter public class PwGroupListAdapter : BaseAdapter
{ {
@ -36,12 +212,12 @@ namespace keepass2android
private List<PwGroup> _groupsForViewing; private List<PwGroup> _groupsForViewing;
private List<PwEntry> _entriesForViewing; private List<PwEntry> _entriesForViewing;
private readonly ISharedPreferences _prefs;
public PwGroupListAdapter(GroupBaseActivity act, PwGroup group) { public PwGroupListAdapter(GroupBaseActivity act, PwGroup group) {
_act = act; _act = act;
_group = group; _group = group;
_prefs = PreferenceManager.GetDefaultSharedPreferences(act);
FilterAndSort(); FilterAndSort();
@ -68,45 +244,21 @@ namespace keepass2android
{ {
_entriesForViewing.Add(entry); _entriesForViewing.Add(entry);
} }
GroupViewSortOrderManager sortOrderManager = new GroupViewSortOrderManager(_act);
var sortOrder = sortOrderManager.GetCurrentSortOrder();
bool sortLists = _prefs.GetBoolean(_act.GetString(Resource.String.sort_key), _act.Resources.GetBoolean(Resource.Boolean.sort_default)); if ( sortOrder.RequiresSort )
if ( sortLists )
{ {
var sortGroups = sortOrderManager.SortGroups;
_groupsForViewing = new List<PwGroup>(_group.Groups); _groupsForViewing = new List<PwGroup>(_group.Groups);
_groupsForViewing.Sort( (x, y) => { return String.Compare (x.Name, y.Name, true); }); _groupsForViewing.Sort( (x, y) =>
_entriesForViewing.Sort( (x, y) => {
{ if (sortGroups)
String nameX = x.Strings.ReadSafe(PwDefs.TitleField); return sortOrder.CompareGroups(x, y);
String nameY = y.Strings.ReadSafe(PwDefs.TitleField); else
if (nameX.ToLower() != nameY.ToLower()) return String.Compare (x.Name, y.Name, true);
return String.Compare(nameX, nameY, StringComparison.OrdinalIgnoreCase); });
else _entriesForViewing.Sort(sortOrder.CompareEntries);
{
if (PwDefs.IsTanEntry(x) && PwDefs.IsTanEntry(y))
{
//compare the user name fields (=TAN index)
String userX = x.Strings.ReadSafe(PwDefs.UserNameField);
String userY = y.Strings.ReadSafe(PwDefs.UserNameField);
if (userX != userY)
{
try
{
return int.Parse(userX).CompareTo(int.Parse(userY));
}
catch (Exception)
{
//ignore
}
return String.Compare(userX, userY, StringComparison.OrdinalIgnoreCase);
}
}
//use creation time for non-tan entries:
return x.CreationTime.CompareTo(y.CreationTime);
}
}
);
} else { } else {
_groupsForViewing = new List<PwGroup>(_group.Groups); _groupsForViewing = new List<PwGroup>(_group.Groups);
} }

File diff suppressed because it is too large Load Diff

View File

@ -49,7 +49,7 @@
<item android:id="@+id/menu_sort" <item android:id="@+id/menu_sort"
android:icon="@android:drawable/ic_menu_sort_by_size" android:icon="@android:drawable/ic_menu_sort_by_size"
android:title="@string/sort_name" android:title="@string/sort_menu"
android:showAsAction="never" android:showAsAction="never"
/> />

View File

@ -56,7 +56,9 @@
<string name="omitbackup_key">omitbackup</string> <string name="omitbackup_key">omitbackup</string>
<string name="list_size_key">list_size</string> <string name="list_size_key">list_size</string>
<string name="design_key">design_key</string> <string name="design_key">design_key</string>
<string name="sort_key">sort_key</string> <string name="sort_key_old">sort_key</string>
<string name="sort_key">sort_key_new</string>
<string name="sortgroups_key">sortgroups_key</string>
<string name="TanExpiresOnUse_key">TanExpiresOnUse_key</string> <string name="TanExpiresOnUse_key">TanExpiresOnUse_key</string>
<string name="ShowGroupnameInSearchResult_key">ShowGroupnameInSearchResult_key</string> <string name="ShowGroupnameInSearchResult_key">ShowGroupnameInSearchResult_key</string>
<string name="ShowUsernameInList_key">ShowUsernameInList_key</string> <string name="ShowUsernameInList_key">ShowUsernameInList_key</string>
@ -67,7 +69,6 @@
<string name="BinaryDirectory_default">/mnt/sdcard/keepass2android/binaries/</string> <string name="BinaryDirectory_default">/mnt/sdcard/keepass2android/binaries/</string>
<bool name="maskpass_default">true</bool> <bool name="maskpass_default">true</bool>
<bool name="keyfile_default">true</bool> <bool name="keyfile_default">true</bool>
<bool name="sort_default">true</bool>
<bool name="omitbackup_default">true</bool> <bool name="omitbackup_default">true</bool>
<bool name="TanExpiresOnUse_default">true</bool> <bool name="TanExpiresOnUse_default">true</bool>
<bool name="ShowUsernameInList_default">true</bool> <bool name="ShowUsernameInList_default">true</bool>

View File

@ -190,8 +190,13 @@
<string name="space">Space</string> <string name="space">Space</string>
<string name="search_label">Search</string> <string name="search_label">Search</string>
<string name="show_password">Show password</string> <string name="show_password">Show password</string>
<string name="sort_menu">Sort by...</string>
<string name="sort_name">Sort by name</string> <string name="sort_name">Sort by name</string>
<string name="sort_db">Sort by creation date</string> <string name="sort_db">Sort by creation date</string>
<string name="sort_moddate">Sort by modification date</string>
<string name="sort_default">Keep default order</string>
<string name="special">Special</string> <string name="special">Special</string>
<string name="search_hint">Find what</string> <string name="search_hint">Find what</string>
<string name="search_results">Search results</string> <string name="search_results">Search results</string>