implemented action items for move and delete (includes extension of apptasks to delete/move multiple items)
fixed display issue in QuickUnlock fixed text color of recent files
This commit is contained in:
@@ -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<PwGroup> touchedGroups, List<PwGroup> 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; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<PwGroup> touchedGroups, List<PwGroup> 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; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<PwGroup> 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<PwGroup> touchedGroups = new List<PwGroup>();
|
||||
List<PwGroup> permanentlyDeletedGroups = new List<PwGroup>();
|
||||
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<PwGroup> touchedGroups, List<PwGroup> permanentlyDeletedGroups);
|
||||
|
||||
public abstract UiStringKey StatusMessage { get; }
|
||||
|
||||
protected bool DoDeleteGroup(PwGroup pg, List<PwGroup> touchedGroups, List<PwGroup> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user