allow differnt sorting options
"touch" groups after editing to get correct sort order "modification date"
This commit is contained in:
		| @@ -53,6 +53,7 @@ namespace keepass2android | ||||
| 			Group.Name = _name; | ||||
| 			Group.IconId = _iconId; | ||||
| 			Group.CustomIconUuid = _customIconId; | ||||
| 			Group.Touch(true); | ||||
|  | ||||
| 			// Commit to disk | ||||
| 			SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun); | ||||
|   | ||||
| @@ -53,23 +53,15 @@ namespace keepass2android | ||||
| 			 | ||||
| 			public override void Run() { | ||||
| 				if ( Success ) { | ||||
| 					// Mark group dirty if title, icon or Expiry stuff changes | ||||
| 					if ( ! _backup.Strings.ReadSafe (PwDefs.TitleField).Equals(_updatedEntry.Strings.ReadSafe (PwDefs.TitleField))  | ||||
| 					    || ! _backup.IconId.Equals(_updatedEntry.IconId) | ||||
| 						|| !_backup.CustomIconUuid.Equals(_updatedEntry.CustomIconUuid) | ||||
| 					    || _backup.Expires != _updatedEntry.Expires | ||||
| 					    || (_backup.Expires && (! _backup.ExpiryTime.Equals(_updatedEntry.ExpiryTime))) | ||||
| 					    ) | ||||
| 					// Mark parent group dirty. Even only the last modification date changed, this might affect sort order | ||||
| 					PwGroup parent = _updatedEntry.ParentGroup; | ||||
| 					if ( parent != null ) { | ||||
|  | ||||
| 					{ | ||||
| 						PwGroup parent = _updatedEntry.ParentGroup; | ||||
| 						if ( parent != null ) { | ||||
| 						// Mark parent group dirty | ||||
| 						_app.GetDb().Dirty.Add(parent); | ||||
| 							 | ||||
| 							// Mark parent group dirty | ||||
| 							_app.GetDb().Dirty.Add(parent); | ||||
| 							 | ||||
| 						} | ||||
| 					} | ||||
| 					 | ||||
| 				} else { | ||||
| 					StatusLogger.UpdateMessage(UiStringKey.UndoingChanges); | ||||
| 					// If we fail to save, back out changes to global structure | ||||
|   | ||||
| @@ -16,6 +16,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file | ||||
|   */ | ||||
|  | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Android.App; | ||||
| using Android.Content; | ||||
| using Android.OS; | ||||
| @@ -331,19 +333,7 @@ namespace keepass2android | ||||
| 			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) { | ||||
| 			if ( ! base.OnPrepareOptionsMenu(menu) ) { | ||||
| @@ -351,7 +341,7 @@ namespace keepass2android | ||||
| 			} | ||||
|  | ||||
| 			Util.PrepareDonateOptionMenu(menu, this); | ||||
| 			SetSortMenuText(menu); | ||||
| 			 | ||||
| 			 | ||||
| 			return true; | ||||
| 		} | ||||
| @@ -378,7 +368,7 @@ namespace keepass2android | ||||
| 				return true; | ||||
| 				 | ||||
| 			case Resource.Id.menu_sort: | ||||
| 				ToggleSort(); | ||||
| 				ChangeSort(); | ||||
| 				return true; | ||||
| 			case Android.Resource.Id.Home: | ||||
| 				//Currently the action bar only displays the home button when we come from a previous activity. | ||||
| @@ -471,26 +461,41 @@ namespace keepass2android | ||||
| 			base.OnBackPressed(); | ||||
| 		} | ||||
|  | ||||
| 		private void ToggleSort() { | ||||
| 			// Toggle setting | ||||
| 			String sortKey = GetString(Resource.String.sort_key); | ||||
| 			bool sortByName = _prefs.GetBoolean(sortKey, Resources.GetBoolean(Resource.Boolean.sort_default)); | ||||
| 			ISharedPreferencesEditor editor = _prefs.Edit(); | ||||
| 			editor.PutBoolean(sortKey, ! sortByName); | ||||
| 			EditorCompat.Apply(editor); | ||||
| 		private void ChangeSort() | ||||
| 		{ | ||||
| 			var sortOrderManager = new GroupViewSortOrderManager(this); | ||||
| 			IEnumerable<string> sortOptions = sortOrderManager.SortOrders.Select( | ||||
| 				o => GetString(o.ResourceId) | ||||
| 				); | ||||
|  | ||||
| 			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(); | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
|   | ||||
| @@ -27,6 +27,182 @@ using keepass2android.view; | ||||
|  | ||||
| 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  | ||||
| 	{ | ||||
| @@ -36,12 +212,12 @@ namespace keepass2android | ||||
| 		private List<PwGroup> _groupsForViewing; | ||||
| 		private List<PwEntry> _entriesForViewing; | ||||
|  | ||||
| 		private readonly ISharedPreferences _prefs; | ||||
| 		 | ||||
| 		 | ||||
| 		public PwGroupListAdapter(GroupBaseActivity act, PwGroup group) { | ||||
| 			_act = act; | ||||
| 			_group = group; | ||||
| 			_prefs = PreferenceManager.GetDefaultSharedPreferences(act); | ||||
| 			 | ||||
| 			 | ||||
| 			FilterAndSort(); | ||||
| 			 | ||||
| @@ -68,45 +244,21 @@ namespace keepass2android | ||||
| 			{ | ||||
| 				_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 ( sortLists )  | ||||
| 			if ( sortOrder.RequiresSort ) | ||||
| 			{ | ||||
| 				var sortGroups = sortOrderManager.SortGroups; | ||||
| 				_groupsForViewing = new List<PwGroup>(_group.Groups); | ||||
| 				_groupsForViewing.Sort( (x, y) => { return String.Compare (x.Name, y.Name, true); }); | ||||
| 				_entriesForViewing.Sort( (x, 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); | ||||
| 					                       } | ||||
| 				                       } | ||||
| 				); | ||||
| 				_groupsForViewing.Sort( (x, y) => | ||||
| 					{ | ||||
| 						if (sortGroups) | ||||
| 							return sortOrder.CompareGroups(x, y); | ||||
| 						else | ||||
| 							return String.Compare (x.Name, y.Name, true); | ||||
| 					}); | ||||
| 				_entriesForViewing.Sort(sortOrder.CompareEntries); | ||||
| 			} else { | ||||
| 				_groupsForViewing =  new List<PwGroup>(_group.Groups); | ||||
| 			} | ||||
|   | ||||
							
								
								
									
										2624
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2624
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -49,7 +49,7 @@ | ||||
|  | ||||
| 	<item android:id="@+id/menu_sort" | ||||
|         android:icon="@android:drawable/ic_menu_sort_by_size" | ||||
|         android:title="@string/sort_name" | ||||
|         android:title="@string/sort_menu" | ||||
|         android:showAsAction="never" | ||||
|     /> | ||||
|      | ||||
|   | ||||
| @@ -56,7 +56,9 @@ | ||||
|     <string name="omitbackup_key">omitbackup</string>     | ||||
|     <string name="list_size_key">list_size</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="ShowGroupnameInSearchResult_key">ShowGroupnameInSearchResult_key</string> | ||||
| 	<string name="ShowUsernameInList_key">ShowUsernameInList_key</string> | ||||
| @@ -67,7 +69,6 @@ | ||||
|     <string name="BinaryDirectory_default">/mnt/sdcard/keepass2android/binaries/</string> | ||||
|     <bool name="maskpass_default">true</bool> | ||||
|     <bool name="keyfile_default">true</bool> | ||||
|     <bool name="sort_default">true</bool> | ||||
|     <bool name="omitbackup_default">true</bool> | ||||
|     <bool name="TanExpiresOnUse_default">true</bool> | ||||
|     <bool name="ShowUsernameInList_default">true</bool> | ||||
|   | ||||
| @@ -190,8 +190,13 @@ | ||||
| 	<string name="space">Space</string> | ||||
|   <string name="search_label">Search</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_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="search_hint">Find what</string> | ||||
|   <string name="search_results">Search results</string> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll