diff --git a/src/commands/CmdLengthen.cpp b/src/commands/CmdLengthen.cpp index f0dc4a36..2ad0eaea 100644 --- a/src/commands/CmdLengthen.cpp +++ b/src/commands/CmdLengthen.cpp @@ -59,7 +59,30 @@ int CmdLengthen ( Interval filter; auto tracked = getTracked (database, rules, filter); - // Apply tags to ids. + bool dirty = true; + + for (auto& id : ids) + { + if (id > static_cast (tracked.size ())) + throw format ("ID '@{1}' does not correspond to any tracking.", id); + + if (tracked[tracked.size() - id].synthetic && dirty) + { + auto latest = getLatestInterval(database); + auto exclusions = getAllExclusions (rules, filter.range); + + Interval modified {latest}; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) + database.addInterval (interval); + + dirty = false; + } + } + + // Lengthen intervals specified by ids for (auto& id : ids) { if (id > static_cast (tracked.size ())) diff --git a/src/commands/CmdMove.cpp b/src/commands/CmdMove.cpp index e083b105..8bd2762e 100644 --- a/src/commands/CmdMove.cpp +++ b/src/commands/CmdMove.cpp @@ -64,9 +64,23 @@ int CmdMove ( Interval filter; auto tracked = getTracked (database, rules, filter); + if (id > static_cast (tracked.size ())) throw format ("ID '@{1}' does not correspond to any tracking.", id); + if (tracked[tracked.size() - id].synthetic) + { + auto latest = getLatestInterval(database); + auto exclusions = getAllExclusions (rules, filter.range); + + Interval modified {latest}; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) + database.addInterval (interval); + } + // Move start time. Interval i = tracked[tracked.size () - id]; Datetime start (new_start); diff --git a/src/commands/CmdShorten.cpp b/src/commands/CmdShorten.cpp index bd040769..5a4a6825 100644 --- a/src/commands/CmdShorten.cpp +++ b/src/commands/CmdShorten.cpp @@ -59,7 +59,30 @@ int CmdShorten ( Interval filter; auto tracked = getTracked (database, rules, filter); - // Apply tags to ids. + bool dirty = true; + + for (auto& id : ids) + { + if (id > static_cast (tracked.size ())) + throw format ("ID '@{1}' does not correspond to any tracking.", id); + + if (tracked[tracked.size() - id].synthetic && dirty) + { + auto latest = getLatestInterval(database); + auto exclusions = getAllExclusions (rules, filter.range); + + Interval modified {latest}; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) + database.addInterval (interval); + + dirty = false; + } + } + + // Shorten intervals specified by ids for (auto& id : ids) { if (id > static_cast (tracked.size ())) diff --git a/src/commands/CmdTag.cpp b/src/commands/CmdTag.cpp index 64485c12..46054d32 100644 --- a/src/commands/CmdTag.cpp +++ b/src/commands/CmdTag.cpp @@ -57,6 +57,29 @@ int CmdTag ( Interval filter; auto tracked = getTracked (database, rules, filter); + bool dirty = true; + + for (auto& id : ids) + { + if (id > static_cast (tracked.size ())) + throw format ("ID '@{1}' does not correspond to any tracking.", id); + + if (tracked[tracked.size() - id].synthetic && dirty) + { + auto latest = getLatestInterval(database); + auto exclusions = getAllExclusions (rules, filter.range); + + Interval modified {latest}; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) + database.addInterval (interval); + + dirty = false; + } + } + // Apply tags to ids. for (auto& id : ids) { diff --git a/src/commands/CmdUntag.cpp b/src/commands/CmdUntag.cpp index 936965a3..562d19e7 100644 --- a/src/commands/CmdUntag.cpp +++ b/src/commands/CmdUntag.cpp @@ -57,6 +57,29 @@ int CmdUntag ( Interval filter; auto tracked = getTracked (database, rules, filter); + bool dirty = true; + + for (auto& id : ids) + { + if (id > static_cast (tracked.size ())) + throw format ("ID '@{1}' does not correspond to any tracking.", id); + + if (tracked[tracked.size() - id].synthetic && dirty) + { + auto latest = getLatestInterval(database); + auto exclusions = getAllExclusions (rules, filter.range); + + Interval modified {latest}; + + // Update database. + database.deleteInterval (latest); + for (auto& interval : flatten (modified, exclusions)) + database.addInterval (interval); + + dirty = false; + } + } + // Apply tags to ids. for (auto& id : ids) {