diff --git a/src/KeePass.sln b/src/KeePass.sln
index 4226fce5..7510e05e 100644
--- a/src/KeePass.sln
+++ b/src/KeePass.sln
@@ -1,6 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android", "keepass2android\keepass2android.csproj", "{A6CF8A86-37C1-4197-80FE-519DE2C842F5}"
@@ -35,6 +37,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterKeePlugin", "MasterKe
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaterialTest2", "MaterialTest2\MaterialTest2.csproj", "{B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -333,6 +337,7 @@ Global
{A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
@@ -378,6 +383,30 @@ Global
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|Win32.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.Release|x64.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU
+ {B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{2F7CB5B4-AC2A-4790-B0F3-42E6C9A060D5} = {CAC7DBC4-E21F-41E1-B33A-E3A04585F6A3}
diff --git a/src/KeePassLib2Android/PwDefs.cs b/src/KeePassLib2Android/PwDefs.cs
index 73f1827a..ec563a39 100644
--- a/src/KeePassLib2Android/PwDefs.cs
+++ b/src/KeePassLib2Android/PwDefs.cs
@@ -111,7 +111,7 @@ namespace KeePassLib
///
/// Default number of master key encryption/transformation rounds (making dictionary attacks harder).
///
- public const ulong DefaultKeyEncryptionRounds = 6000;
+ public const ulong DefaultKeyEncryptionRounds = 500000;
///
/// Default identifier string for the title field. Should not contain
diff --git a/src/Kp2aBusinessLogic/IDrawableFactory.cs b/src/Kp2aBusinessLogic/IDrawableFactory.cs
index fdf5733f..23f50031 100644
--- a/src/Kp2aBusinessLogic/IDrawableFactory.cs
+++ b/src/Kp2aBusinessLogic/IDrawableFactory.cs
@@ -7,9 +7,9 @@ namespace keepass2android
{
public interface IDrawableFactory
{
- void AssignDrawableTo (ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId);
+ void AssignDrawableTo (ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId, bool forGroup);
- Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId);
+ Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId, bool forGroup);
void Clear();
diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
index 67b75224..c899a0a6 100644
--- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
+++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj
@@ -55,8 +55,9 @@
+
-
+
diff --git a/src/Kp2aBusinessLogic/SelectStorageLocationActivityBase.cs b/src/Kp2aBusinessLogic/SelectStorageLocationActivityBase.cs
index 9e94df4a..c5ce53bc 100644
--- a/src/Kp2aBusinessLogic/SelectStorageLocationActivityBase.cs
+++ b/src/Kp2aBusinessLogic/SelectStorageLocationActivityBase.cs
@@ -21,10 +21,10 @@ namespace keepass2android
WriteDemanded = 2
}
- protected const int RequestCodeFileStorageSelectionForPrimarySelect = 983713;
- private const int RequestCodeFileStorageSelectionForCopyToWritableLocation = 983714;
- private const int RequestCodeFileFileBrowseForWritableLocation = 983715;
- private const int RequestCodeFileBrowseForOpen = 983716;
+ protected const int RequestCodeFileStorageSelectionForPrimarySelect = 33713;
+ private const int RequestCodeFileStorageSelectionForCopyToWritableLocation = 33714;
+ private const int RequestCodeFileFileBrowseForWritableLocation = 33715;
+ private const int RequestCodeFileBrowseForOpen = 33716;
protected IOConnectionInfo _selectedIoc;
diff --git a/src/Kp2aBusinessLogic/UiStringKey.cs b/src/Kp2aBusinessLogic/UiStringKey.cs
index 3bc22d20..32921742 100644
--- a/src/Kp2aBusinessLogic/UiStringKey.cs
+++ b/src/Kp2aBusinessLogic/UiStringKey.cs
@@ -57,6 +57,8 @@ namespace keepass2android
CopyFileRequiredForEditing,
DuplicateUuidsError,
DuplicateUuidsErrorAdditional,
- KdbBetaWarning
+ KdbBetaWarning,
+ DeletingItems,
+ AskDeletePermanentlyItems
}
}
diff --git a/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs b/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs
index 4fcd4139..4280697c 100644
--- a/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs
+++ b/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs
@@ -16,16 +16,19 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
+using System.Collections.Generic;
using Android.Content;
using KeePassLib;
+using KeePassLib.Interfaces;
namespace keepass2android
{
public class DeleteEntry : DeleteRunnable {
private readonly PwEntry _entry;
+ private UiStringKey _statusMessage;
- public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish):base(finish, app) {
+ public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish):base(finish, app) {
Ctx = ctx;
Db = app.GetDb();
_entry = entry;
@@ -48,76 +51,15 @@ namespace keepass2android
}
}
- public override void Run()
- {
- StatusLogger.UpdateMessage(UiStringKey.DeletingEntry);
- PwDatabase pd = Db.KpDatabase;
+ protected override void PerformDelete(List touchedGroups, List permanentlyDeletedGroups)
+ {
+ DoDeleteEntry(_entry, touchedGroups);
+ }
- PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true);
-
- bool bUpdateGroupList = false;
- DateTime dtNow = DateTime.Now;
- PwEntry pe = _entry;
- PwGroup pgParent = pe.ParentGroup;
- if(pgParent != null)
- {
- pgParent.Entries.Remove(pe);
- //TODO check if RecycleBin is deleted
- //TODO no recycle bin in KDB
-
- if ((DeletePermanently) || (!CanRecycle))
- {
- PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow);
- pd.DeletedObjects.Add(pdo);
-
- _onFinishToRun = new ActionOnFinish((success, message) =>
- {
- if (success)
- {
- // Mark parent dirty
- Db.Dirty.Add(pgParent);
- }
- else
- {
- // Let's not bother recovering from a failure to save a deleted entry. It is too much work.
- App.LockDatabase(false);
- }
- }, OnFinishToRun);
- }
- else // Recycle
- {
- EnsureRecycleBinExists(ref pgRecycleBin, ref bUpdateGroupList);
-
- pgRecycleBin.AddEntry(pe, true, true);
- pe.Touch(false);
-
- _onFinishToRun = new ActionOnFinish( (success, message) =>
- {
- if ( success ) {
- // Mark previous parent dirty
- Db.Dirty.Add(pgParent);
- // Mark new parent dirty
- Db.Dirty.Add(pgRecycleBin);
- // mark root dirty if recycle bin was created
- if (bUpdateGroupList)
- Db.Dirty.Add(Db.Root);
- } else {
- // Let's not bother recovering from a failure to save a deleted entry. It is too much work.
- App.LockDatabase(false);
- }
-
- }, OnFinishToRun);
- }
- }
-
- // Commit database
- SaveDb save = new SaveDb(Ctx, App, OnFinishToRun, false);
- save.SetStatusLogger(StatusLogger);
- save.Run();
-
-
- }
-
+ public override UiStringKey StatusMessage
+ {
+ get { return UiStringKey.DeletingEntry; }
+ }
}
}
diff --git a/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs b/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs
index 6341eb91..61b1d10a 100644
--- a/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs
+++ b/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs
@@ -16,6 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
*/
using System;
+using System.Collections.Generic;
using Android.Content;
using KeePassLib;
@@ -68,96 +69,15 @@ namespace keepass2android
}
}
-
- public override void Run() {
- StatusLogger.UpdateMessage(UiStringKey.DeletingGroup);
- //from KP Desktop
- PwGroup pg = _group;
- PwGroup pgParent = pg.ParentGroup;
- if(pgParent == null) return; // Can't remove virtual or root group
-
- PwDatabase pd = Db.KpDatabase;
- PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true);
-
- pgParent.Groups.Remove(pg);
-
- if ((DeletePermanently) || (!CanRecycle))
- {
- pg.DeleteAllObjects(pd);
-
- PwDeletedObject pdo = new PwDeletedObject(pg.Uuid, DateTime.Now);
- pd.DeletedObjects.Add(pdo);
- _onFinishToRun = new AfterDeletePermanently(OnFinishToRun, App, _group);
- }
- else // Recycle
- {
- bool groupListUpdateRequired = false;
- EnsureRecycleBinExists(ref pgRecycleBin, ref groupListUpdateRequired);
-
- pgRecycleBin.AddGroup(pg, true, true);
- pg.Touch(false);
- _onFinishToRun = new ActionOnFinish((success, message) =>
- {
- if ( success ) {
- // Mark new parent (Recycle bin) dirty
- PwGroup parent = _group.ParentGroup;
- if ( parent != null ) {
- Db.Dirty.Add(parent);
- }
- //Mark old parent dirty:
- Db.Dirty.Add(pgParent);
+ protected override void PerformDelete(List touchedGroups, List permanentlyDeletedGroups)
+ {
+ DoDeleteGroup(_group, touchedGroups, permanentlyDeletedGroups);
+ }
- // mark root dirty if recycle bin was created
- if (groupListUpdateRequired)
- Db.Dirty.Add(Db.Root);
- } else {
- // Let's not bother recovering from a failure to save a deleted group. It is too much work.
- App.LockDatabase(false);
- }
- }, OnFinishToRun);
- }
-
- // Save
- SaveDb save = new SaveDb(Ctx, App, OnFinishToRun, DontSave);
- save.SetStatusLogger(StatusLogger);
- save.Run();
-
- }
-
-
- private class AfterDeletePermanently : OnFinish {
- readonly IKp2aApp _app;
-
- readonly PwGroup _group;
-
- public AfterDeletePermanently(OnFinish finish, IKp2aApp app, PwGroup group):base(finish) {
- _app = app;
- _group = group;
- }
-
- public override void Run() {
- if ( Success ) {
- // Remove from group global
- _app.GetDb().Groups.Remove(_group.Uuid);
-
- // Remove group from the dirty global (if it is present), not a big deal if this fails (doesn't throw)
- _app.GetDb().Dirty.Remove(_group);
-
- // Mark parent dirty
- PwGroup parent = _group.ParentGroup;
- if ( parent != null ) {
- _app.GetDb().Dirty.Add(parent);
- }
- } else {
- // Let's not bother recovering from a failure to save a deleted group. It is too much work.
- _app.LockDatabase(false);
- }
-
- base.Run();
-
- }
-
- }
+ public override UiStringKey StatusMessage
+ {
+ get { return UiStringKey.DeletingGroup; }
+ }
}
}
diff --git a/src/Kp2aBusinessLogic/database/edit/DeleteMultipleItems.cs b/src/Kp2aBusinessLogic/database/edit/DeleteMultipleItems.cs
new file mode 100644
index 00000000..d70c4a2d
--- /dev/null
+++ b/src/Kp2aBusinessLogic/database/edit/DeleteMultipleItems.cs
@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using System.Linq;
+using Android.Content;
+using KeePassLib;
+using KeePassLib.Interfaces;
+
+namespace keepass2android
+{
+ public class DeleteMultipleItems : DeleteRunnable
+ {
+ private readonly List _elementsToDelete;
+ private readonly bool _canRecycle;
+
+ public DeleteMultipleItems(Context ctx, Database db, List elementsToDelete, OnFinish finish, IKp2aApp app)
+ : base(finish, app)
+ {
+ _elementsToDelete = elementsToDelete;
+ SetMembers(ctx, db);
+
+ //determine once. The property is queried for each delete operation, but might return false
+ //after one entry/group is deleted (and thus in recycle bin and thus can't be recycled anymore)
+ _canRecycle = DetermineCanRecycle();
+ }
+
+ private bool DetermineCanRecycle()
+ {
+ Android.Util.Log.Debug("KP2A", "CanRecycle?");
+ if (!App.GetDb().DatabaseFormat.CanRecycle)
+ {
+ Android.Util.Log.Debug("KP2A", "CanRecycle? No because of DB format.");
+ return false;
+ }
+
+
+ if (_elementsToDelete.OfType().Any(g => !CanRecycleGroup(g)))
+ {
+ return false;
+ }
+
+ if (_elementsToDelete.OfType().Any(e => !CanRecycleGroup(e.ParentGroup)))
+ {
+ return false;
+ }
+ Android.Util.Log.Debug("KP2A", "CanRecycle? Yes.");
+ return true;
+ }
+
+ public override bool CanRecycle
+ {
+ get { return _canRecycle; }
+ }
+
+ protected override UiStringKey QuestionsResourceId
+ {
+ get { return UiStringKey.AskDeletePermanentlyItems; }
+ }
+
+ protected override void PerformDelete(List touchedGroups, List permanentlyDeletedGroups)
+ {
+ foreach (var g in _elementsToDelete.OfType())
+ {
+ Android.Util.Log.Debug("KP2A", "Deleting " + g.Name);
+ DoDeleteGroup(g, touchedGroups, permanentlyDeletedGroups);
+
+ }
+
+ foreach (var e in _elementsToDelete.OfType())
+ {
+ Android.Util.Log.Debug("KP2A", "Deleting " + e.Strings.ReadSafe(PwDefs.TitleField));
+ DoDeleteEntry(e, touchedGroups);
+ }
+ }
+
+ public override UiStringKey StatusMessage
+ {
+ get { return UiStringKey.DeletingItems; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs b/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs
index df2c3f7e..e8fa4147 100644
--- a/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs
+++ b/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs
@@ -1,3 +1,5 @@
+using System;
+using System.Collections.Generic;
using Android.Content;
using KeePassLib;
@@ -5,12 +7,13 @@ namespace keepass2android
{
public abstract class DeleteRunnable : RunnableOnFinish
{
- protected DeleteRunnable(OnFinish finish, IKp2aApp app):base(finish)
+ protected DeleteRunnable(OnFinish finish, IKp2aApp app)
+ : base(finish)
{
- App = app;
+ App = app;
}
- protected IKp2aApp App;
+ protected IKp2aApp App;
protected Database Db;
@@ -22,9 +25,9 @@ namespace keepass2android
Db = db;
}
-
+
private bool _deletePermanently = true;
-
+
public bool DeletePermanently
{
get
@@ -44,52 +47,61 @@ namespace keepass2android
protected bool CanRecycleGroup(PwGroup pgParent)
{
- bool bShiftPressed = false;
PwDatabase pd = Db.KpDatabase;
PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true);
bool bPermanent = false;
if (pgParent != null)
{
if (pd.RecycleBinEnabled == false)
+ {
+ Android.Util.Log.Debug("KP2A", "CanRecycle? No, RecycleBinIsNotEnabled");
bPermanent = true;
- else if (bShiftPressed)
- bPermanent = true;
+ }
+
else if (pgRecycleBin == null)
{
} // Recycle
else if (pgParent == pgRecycleBin)
+ {
+ Android.Util.Log.Debug("KP2A", "CanRecycle? No, Can't recycle RecycleBin");
bPermanent = true;
+ }
+
else if (pgParent.IsContainedIn(pgRecycleBin))
+ {
+ Android.Util.Log.Debug("KP2A", "CanRecycle? No, "+pgParent.Name+" is in RecycleBin");
bPermanent = true;
+ }
+
}
return !bPermanent;
}
-
+
protected void EnsureRecycleBinExists(ref PwGroup pgRecycleBin,
- ref bool bGroupListUpdateRequired)
+ ref bool bGroupListUpdateRequired)
{
if ((Db == null) || (Db.KpDatabase == null)) { return; }
-
- if(pgRecycleBin == Db.KpDatabase.RootGroup)
+
+ if (pgRecycleBin == Db.KpDatabase.RootGroup)
{
pgRecycleBin = null;
}
-
- if(pgRecycleBin == null)
+
+ if (pgRecycleBin == null)
{
pgRecycleBin = new PwGroup(true, true, App.GetResourceString(UiStringKey.RecycleBin),
- PwIcon.TrashBin)
+ PwIcon.TrashBin)
{
- EnableAutoType = false,
- EnableSearching = false,
+ EnableAutoType = false,
+ EnableSearching = false,
IsExpanded = false
};
Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true);
Db.Groups[pgRecycleBin.Uuid] = pgRecycleBin;
Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid;
-
+
bGroupListUpdateRequired = true;
}
else { System.Diagnostics.Debug.Assert(pgRecycleBin.Uuid.Equals(Db.KpDatabase.RecycleBinUuid)); }
@@ -99,36 +111,155 @@ namespace keepass2android
{
get;
}
-
+
public void Start()
{
if (CanRecycle)
{
- App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
- QuestionsResourceId,
- (dlgSender, dlgEvt) =>
- {
- DeletePermanently = true;
- ProgressTask pt = new ProgressTask(App, Ctx, this);
- pt.Run();
- },
- (dlgSender, dlgEvt) => {
- DeletePermanently = false;
- ProgressTask pt = new ProgressTask(App, Ctx, this);
- pt.Run();
- },
- (dlgSender, dlgEvt) => {},
- Ctx);
+ App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title,
+ QuestionsResourceId,
+ (dlgSender, dlgEvt) =>
+ {
+ DeletePermanently = true;
+ ProgressTask pt = new ProgressTask(App, Ctx, this);
+ pt.Run();
+ },
+ (dlgSender, dlgEvt) =>
+ {
+ DeletePermanently = false;
+ ProgressTask pt = new ProgressTask(App, Ctx, this);
+ pt.Run();
+ },
+ (dlgSender, dlgEvt) => { },
+ Ctx);
-
- } else
+
+ }
+ else
{
ProgressTask pt = new ProgressTask(App, Ctx, this);
pt.Run();
}
}
+ protected void DoDeleteEntry(PwEntry pe, List touchedGroups)
+ {
+ PwDatabase pd = Db.KpDatabase;
+
+ PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true);
+
+ bool bUpdateGroupList = false;
+ DateTime dtNow = DateTime.Now;
+
+ PwGroup pgParent = pe.ParentGroup;
+ if (pgParent != null)
+ {
+ pgParent.Entries.Remove(pe);
+ //TODO check if RecycleBin is deleted
+ //TODO no recycle bin in KDB
+
+ if ((DeletePermanently) || (!CanRecycle))
+ {
+ PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow);
+ pd.DeletedObjects.Add(pdo);
+ touchedGroups.Add(pgParent);
+ }
+ else // Recycle
+ {
+ EnsureRecycleBinExists(ref pgRecycleBin, ref bUpdateGroupList);
+
+ pgRecycleBin.AddEntry(pe, true, true);
+ pe.Touch(false);
+
+ touchedGroups.Add(pgParent);
+ // Mark new parent dirty
+ touchedGroups.Add(pgRecycleBin);
+ // mark root dirty if recycle bin was created
+ touchedGroups.Add(Db.Root);
+ }
+ }
+ }
+
+
+ public override void Run()
+ {
+ StatusLogger.UpdateMessage(StatusMessage);
+
+ List touchedGroups = new List();
+ List permanentlyDeletedGroups = new List();
+ Android.Util.Log.Debug("KP2A", "Calling PerformDelete..");
+ PerformDelete(touchedGroups, permanentlyDeletedGroups);
+
+ _onFinishToRun = new ActionOnFinish((success, message) =>
+ {
+ if (success)
+ {
+ foreach (var g in touchedGroups)
+ Db.Dirty.Add(g);
+ foreach (var g in permanentlyDeletedGroups)
+ {
+ //remove groups from global lists if present there
+ Db.Dirty.Remove(g);
+ Db.Groups.Remove(g.Uuid);
+ }
+
+ }
+ else
+ {
+ // Let's not bother recovering from a failure to save. It is too much work.
+ App.LockDatabase(false);
+ }
+ }, OnFinishToRun);
+
+ // Commit database
+ SaveDb save = new SaveDb(Ctx, App, OnFinishToRun, false);
+ save.SetStatusLogger(StatusLogger);
+ save.Run();
+
+
+ }
+
+ protected abstract void PerformDelete(List touchedGroups, List permanentlyDeletedGroups);
+
+ public abstract UiStringKey StatusMessage { get; }
+
+ protected bool DoDeleteGroup(PwGroup pg, List touchedGroups, List permanentlyDeletedGroups)
+ {
+ PwGroup pgParent = pg.ParentGroup;
+ if (pgParent == null) return false;
+
+ PwDatabase pd = Db.KpDatabase;
+ PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true);
+
+ pgParent.Groups.Remove(pg);
+ touchedGroups.Add(pgParent);
+ if ((DeletePermanently) || (!CanRecycle))
+ {
+ pg.DeleteAllObjects(pd);
+
+ PwDeletedObject pdo = new PwDeletedObject(pg.Uuid, DateTime.Now);
+ pd.DeletedObjects.Add(pdo);
+
+
+ permanentlyDeletedGroups.Add(pg);
+
+ }
+ else // Recycle
+ {
+ bool groupListUpdateRequired = false;
+ EnsureRecycleBinExists(ref pgRecycleBin, ref groupListUpdateRequired);
+
+ pgRecycleBin.AddGroup(pg, true, true);
+ pg.Touch(false);
+ // Mark new parent (Recycle bin) touched
+ touchedGroups.Add(pg.ParentGroup);
+ // mark root touched if recycle bin was created
+ if (groupListUpdateRequired)
+ touchedGroups.Add(Db.Root);
+ }
+ return true;
+ }
}
}
diff --git a/src/Kp2aBusinessLogic/database/edit/MoveElement.cs b/src/Kp2aBusinessLogic/database/edit/MoveElement.cs
deleted file mode 100644
index 3b6bcfe0..00000000
--- a/src/Kp2aBusinessLogic/database/edit/MoveElement.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Text.RegularExpressions;
-using Android.Content;
-using KeePassLib;
-using KeePassLib.Interfaces;
-
-namespace keepass2android.database.edit
-{
- public class MoveElement: RunnableOnFinish
- {
- private readonly IStructureItem _elementToMove;
- private readonly PwGroup _targetGroup;
- private readonly Context _ctx;
- private readonly IKp2aApp _app;
-
- public MoveElement(IStructureItem elementToMove, PwGroup targetGroup, Context ctx, IKp2aApp app, OnFinish finish) : base(finish)
- {
- _elementToMove = elementToMove;
- _targetGroup = targetGroup;
- _ctx = ctx;
- _app = app;
- }
-
- public override void Run()
- {
-
- _app.GetDb().Dirty.Add(_elementToMove.ParentGroup);
-
- PwGroup pgParent = _elementToMove.ParentGroup;
- if (pgParent != _targetGroup)
- {
- if (pgParent != null) // Remove from parent
- {
- PwEntry entry = _elementToMove as PwEntry;
- if (entry != null)
- {
- pgParent.Entries.Remove(entry);
- _targetGroup.AddEntry(entry, true, true);
- }
- else
- {
- PwGroup group = (PwGroup)_elementToMove;
- if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
- {
- Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
- return;
- }
- pgParent.Groups.Remove(group);
- _targetGroup.AddGroup(group, true, true);
- }
- }
- }
-
- _onFinishToRun = new ActionOnFinish((success, message) =>
- {
- if (!success)
- { // Let's not bother recovering from a failure.
- _app.LockDatabase(false);
- }
- }, OnFinishToRun);
-
- // Save
- SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, false);
- save.SetStatusLogger(StatusLogger);
- save.Run();
- }
- }
-}
diff --git a/src/Kp2aBusinessLogic/database/edit/MoveElements.cs b/src/Kp2aBusinessLogic/database/edit/MoveElements.cs
new file mode 100644
index 00000000..8b923a22
--- /dev/null
+++ b/src/Kp2aBusinessLogic/database/edit/MoveElements.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+using Android.Content;
+using KeePassLib;
+using KeePassLib.Interfaces;
+
+namespace keepass2android.database.edit
+{
+ public class MoveElements: RunnableOnFinish
+ {
+ private readonly List _elementsToMove;
+ private readonly PwGroup _targetGroup;
+ private readonly Context _ctx;
+ private readonly IKp2aApp _app;
+
+ public MoveElements(List elementsToMove, PwGroup targetGroup, Context ctx, IKp2aApp app, OnFinish finish) : base(finish)
+ {
+ _elementsToMove = elementsToMove;
+ _targetGroup = targetGroup;
+ _ctx = ctx;
+ _app = app;
+ }
+
+ public override void Run()
+ {
+ //check if we will run into problems. Then finish with error before we start doing anything.
+ foreach (var _elementToMove in _elementsToMove)
+ {
+ PwGroup pgParent = _elementToMove.ParentGroup;
+ if (pgParent != _targetGroup)
+ {
+ if (pgParent != null)
+ {
+ PwGroup group = _elementToMove as PwGroup;
+ if (group != null)
+ {
+ if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
+ {
+ Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
+ return;
+ }
+
+ }
+
+ }
+ }
+
+ }
+
+ foreach (var elementToMove in _elementsToMove)
+ {
+
+ _app.GetDb().Dirty.Add(elementToMove.ParentGroup);
+
+ PwGroup pgParent = elementToMove.ParentGroup;
+ if (pgParent != _targetGroup)
+ {
+ if (pgParent != null) // Remove from parent
+ {
+ PwEntry entry = elementToMove as PwEntry;
+ if (entry != null)
+ {
+ pgParent.Entries.Remove(entry);
+ _targetGroup.AddEntry(entry, true, true);
+ }
+ else
+ {
+ PwGroup group = (PwGroup)elementToMove;
+ if ((_targetGroup == group) || (_targetGroup.IsContainedIn(group)))
+ {
+ Finish(false, _app.GetResourceString(UiStringKey.CannotMoveGroupHere));
+ return;
+ }
+ pgParent.Groups.Remove(group);
+ _targetGroup.AddGroup(group, true, true);
+ }
+ }
+ }
+
+ }
+
+
+ _onFinishToRun = new ActionOnFinish((success, message) =>
+ {
+ if (!success)
+ { // Let's not bother recovering from a failure.
+ _app.LockDatabase(false);
+ }
+ }, OnFinishToRun);
+
+ // Save
+ SaveDb save = new SaveDb(_ctx, _app, OnFinishToRun, false);
+ save.SetStatusLogger(StatusLogger);
+ save.Run();
+ }
+ }
+}
diff --git a/src/Kp2aUnitTests/TestDrawableFactory.cs b/src/Kp2aUnitTests/TestDrawableFactory.cs
index c2c02c9e..57d20a7c 100644
--- a/src/Kp2aUnitTests/TestDrawableFactory.cs
+++ b/src/Kp2aUnitTests/TestDrawableFactory.cs
@@ -9,12 +9,12 @@ namespace Kp2aUnitTests
{
internal class TestDrawableFactory : IDrawableFactory
{
- public void AssignDrawableTo(ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
+ public void AssignDrawableTo(ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId, bool forGroup)
{
}
- public Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
+ public Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId, bool forGroup)
{
return res.GetDrawable(Resource.Drawable.Icon);
}
diff --git a/src/MasterKeePlugin/SetupMasterEntryActivity.cs b/src/MasterKeePlugin/SetupMasterEntryActivity.cs
index 4f052d5e..b2ac4133 100644
--- a/src/MasterKeePlugin/SetupMasterEntryActivity.cs
+++ b/src/MasterKeePlugin/SetupMasterEntryActivity.cs
@@ -71,6 +71,10 @@ namespace MasterKeePlugin
_showPassword = !_showPassword;
MakePasswordMaskedOrVisible();
};
+ Android.Graphics.PorterDuff.Mode mMode = Android.Graphics.PorterDuff.Mode.SrcAtop;
+ Android.Graphics.Color color = new Android.Graphics.Color (224, 224, 224);
+ btnTogglePassword.SetColorFilter (color, mMode);
+
FindViewById(Resource.Id.button_ok).Click += delegate(object sender, EventArgs args)
{
diff --git a/src/MaterialTest/Resources/layout/toolbar.xml b/src/MaterialTest/Resources/layout/toolbar.xml
new file mode 100644
index 00000000..b6dc0a2e
--- /dev/null
+++ b/src/MaterialTest/Resources/layout/toolbar.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/src/MaterialTest/Resources/layout/toolbar2.xml b/src/MaterialTest/Resources/layout/toolbar2.xml
new file mode 100644
index 00000000..b6dc0a2e
--- /dev/null
+++ b/src/MaterialTest/Resources/layout/toolbar2.xml
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/src/MaterialTest/Resources/values-v21/styles.xml b/src/MaterialTest/Resources/values-v21/styles.xml
new file mode 100644
index 00000000..00f20009
--- /dev/null
+++ b/src/MaterialTest/Resources/values-v21/styles.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/src/MaterialTest/Resources/values/styles.xml b/src/MaterialTest/Resources/values/styles.xml
new file mode 100644
index 00000000..5f5cda29
--- /dev/null
+++ b/src/MaterialTest/Resources/values/styles.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/src/MaterialTest/packages.config b/src/MaterialTest/packages.config
new file mode 100644
index 00000000..3cbc47d1
--- /dev/null
+++ b/src/MaterialTest/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/MaterialTest2/Assets/AboutAssets.txt b/src/MaterialTest2/Assets/AboutAssets.txt
new file mode 100644
index 00000000..a9b0638e
--- /dev/null
+++ b/src/MaterialTest2/Assets/AboutAssets.txt
@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with your package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ InputStream input = Assets.Open ("my_asset.txt");
+ }
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
diff --git a/src/MaterialTest2/MainActivity.cs b/src/MaterialTest2/MainActivity.cs
new file mode 100644
index 00000000..0405c351
--- /dev/null
+++ b/src/MaterialTest2/MainActivity.cs
@@ -0,0 +1,214 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.Graphics;
+using Android.Runtime;
+using Android.Support.V4.View;
+using Android.Support.V4.Widget;
+using Android.Support.V7.App;
+
+using Android.Support.Design.Widget;
+
+using Android.Views;
+using Android.Widget;
+using Android.OS;
+using Android.Util;
+using Toolbar = Android.Support.V7.Widget.Toolbar;
+namespace MaterialTest2
+{
+ public class MyDrawerLayout : Android.Support.V4.Widget.DrawerLayout
+ {
+ private bool _fitsSystemWindows;
+
+ protected MyDrawerLayout(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public MyDrawerLayout(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
+ {
+ }
+
+ public MyDrawerLayout(Context context, IAttributeSet attrs) : base(context, attrs)
+ {
+ }
+
+ public MyDrawerLayout(Context context) : base(context)
+ {
+ }
+
+ private int[] mInsets = new int[4];
+
+ protected override bool FitSystemWindows(Rect insets)
+ {
+ if (Build.VERSION.SdkInt >= Build.VERSION_CODES.Kitkat)
+ {
+ // Intentionally do not modify the bottom inset. For some reason,
+ // if the bottom inset is modified, window resizing stops working.
+ // TODO: Figure out why.
+
+ mInsets[0] = insets.Left;
+ mInsets[1] = insets.Top;
+ mInsets[2] = insets.Right;
+
+ insets.Left = 0;
+ insets.Top = 0;
+ insets.Right = 0;
+ }
+
+ return base.FitSystemWindows(insets);
+
+ }
+ public int[] GetInsets()
+ {
+ return mInsets;
+ }
+ }
+
+
+ [Activity(Theme="@style/MyTheme", Label = "MaterialTest", MainLauncher = false, Icon = "@drawable/icon", WindowSoftInputMode = SoftInput.AdjustResize)]
+ public class MainActivity : AppCompatActivity
+ {
+ int count = 1;
+
+ private DrawerLayout mDrawerLayout;
+ //private RecyclerView mDrawerList;
+ private ActionBarDrawerToggle mDrawerToggle;
+
+ private string mDrawerTitle;
+
+ public override bool OnCreateOptionsMenu(IMenu menu)
+ {
+ MenuInflater.Inflate(Resource.Menu.menu_password, menu);
+ return true;
+ }
+
+ public override bool OnOptionsItemSelected(IMenuItem item)
+ {
+ switch (item.ItemId)
+ {
+ case Android.Resource.Id.Home:
+ mDrawerLayout.OpenDrawer(Android.Support.V4.View.GravityCompat.Start);
+ return true;
+ }
+ return base.OnOptionsItemSelected(item);
+ }
+
+ protected override void OnCreate(Bundle bundle)
+ {
+ base.OnCreate(bundle);
+
+ // Set our view from the "main" layout resource
+ SetContentView(Resource.Layout.Main);
+
+ mDrawerTitle = this.Title;
+ //mPlanetTitles = this.Resources.GetStringArray (Resource.Array.planets_array);
+ mDrawerLayout = FindViewById(Resource.Id.drawer_layout);
+ //mDrawerList = FindViewById (Resource.Id.left_drawer);
+
+
+ //mDrawerLayout.SetDrawerShadow (Resource.Drawable.drawer_shadow, GravityCompat.Start);
+ // improve performance by indicating the list if fixed size.
+ //mDrawerList.HasFixedSize = true;
+ //mDrawerList.SetLayoutManager (new LinearLayoutManager (this));
+ NavigationView nv;
+ // set up the drawer's list view with items and click listener
+ //mDrawerList.SetAdapter (new PlanetAdapter (mPlanetTitles, this));
+ // enable ActionBar app icon to behave as action to toggle nav drawer
+
+ // ActionBarDrawerToggle ties together the the proper interactions
+ // between the sliding drawer and the action bar app icon
+
+ mDrawerToggle = new MyActionBarDrawerToggle (this, mDrawerLayout,
+ Resource.Drawable.abc_ic_menu_copy_mtrl_am_alpha,
+ Resource.String.drawer_open,
+ Resource.String.drawer_close);
+
+ mDrawerLayout.SetDrawerListener (mDrawerToggle);
+
+ // Get our button from the layout resource,
+ // and attach an event to it
+ Button button = FindViewById