Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Cutlist editor: Fix the broken undo/redo capability.

  • Loading branch information...
commit 0bb22c16a4a6e73fe533bf639a8561bef9a49633 1 parent afa03f2
@stichnot stichnot authored
View
72 mythtv/libs/libmythtv/deletemap.cpp
@@ -15,33 +15,43 @@
} \
} while(0)
-DeleteMapUndoEntry::DeleteMapUndoEntry(frm_dir_map_t dm, QString msg) :
+DeleteMapUndoEntry::DeleteMapUndoEntry(const frm_dir_map_t &dm,
+ const QString &msg) :
deleteMap(dm), message(msg) { }
-DeleteMapUndoEntry::DeleteMapUndoEntry(void)
-{
- frm_dir_map_t dm;
- deleteMap = dm;
- message = "";
-}
+DeleteMapUndoEntry::DeleteMapUndoEntry(void) : message("") { }
-void DeleteMap::Push(QString undoMessage)
+void DeleteMap::Push(const QString &undoMessage)
{
DeleteMapUndoEntry entry(m_deleteMap, undoMessage);
// Remove all "redo" entries
- while (m_undoStack.size() > m_undoStackPointer + 1)
+ while (m_undoStack.size() > m_undoStackPointer)
m_undoStack.pop_back();
m_undoStack.append(entry);
m_undoStackPointer ++;
SaveMap(true);
}
+void DeleteMap::PushDeferred(const frm_dir_map_t &savedMap,
+ const QString &undoMessage)
+{
+ // Temporarily roll back to the initial state, push the undo
+ // entry, then restore the correct state.
+ frm_dir_map_t tmp = m_deleteMap;
+ m_deleteMap = savedMap;
+ Push(undoMessage);
+ m_deleteMap = tmp;
+ SaveMap(true);
+}
+
bool DeleteMap::Undo(void)
{
if (!HasUndo())
return false;
m_undoStackPointer --;
+ frm_dir_map_t tmp = m_deleteMap;
m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap;
+ m_undoStack[m_undoStackPointer].deleteMap = tmp;
m_changed = true;
SaveMap(true);
return true;
@@ -51,8 +61,10 @@ bool DeleteMap::Redo(void)
{
if (!HasRedo())
return false;
- m_undoStackPointer ++;
+ frm_dir_map_t tmp = m_deleteMap;
m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap;
+ m_undoStack[m_undoStackPointer].deleteMap = tmp;
+ m_undoStackPointer ++;
m_changed = true;
SaveMap(true);
return true;
@@ -60,13 +72,13 @@ bool DeleteMap::Redo(void)
QString DeleteMap::GetUndoMessage(void) const
{
- return (HasUndo() ? m_undoStack[m_undoStackPointer].message :
+ return (HasUndo() ? m_undoStack[m_undoStackPointer - 1].message :
tr("(Nothing to undo)"));
}
QString DeleteMap::GetRedoMessage(void) const
{
- return (HasRedo() ? m_undoStack[m_undoStackPointer + 1].message :
+ return (HasRedo() ? m_undoStack[m_undoStackPointer].message :
tr("(Nothing to redo)"));
}
@@ -243,22 +255,22 @@ bool DeleteMap::IsEmpty(void) const
/// Clears the deleteMap.
void DeleteMap::Clear(QString undoMessage)
{
- m_deleteMap.clear();
- m_changed = true;
if (!undoMessage.isEmpty())
Push(undoMessage);
+ m_deleteMap.clear();
+ m_changed = true;
}
/// Reverses the direction of each mark in the map.
void DeleteMap::ReverseAll(void)
{
EDIT_CHECK;
+ Push(tr("Reverse Cuts"));
frm_dir_map_t::Iterator it = m_deleteMap.begin();
for ( ; it != m_deleteMap.end(); ++it)
Add(it.key(), it.value() == MARK_CUT_END ? MARK_CUT_START :
MARK_CUT_END);
CleanMap();
- Push(tr("Reverse Cuts"));
}
/**
@@ -335,8 +347,6 @@ void DeleteMap::Add(uint64_t frame, MarkTypes type, QString undoMessage)
Delete((uint64_t)remove);
Add(frame, type);
CleanMap();
- if (!undoMessage.isEmpty())
- Push(undoMessage);
}
/// Remove the mark at the given frame.
@@ -346,6 +356,9 @@ void DeleteMap::Delete(uint64_t frame, QString undoMessage)
if (m_deleteMap.isEmpty())
return;
+ if (!undoMessage.isEmpty())
+ Push(undoMessage);
+
uint64_t prev = GetNearestMark(frame, false);
uint64_t next = GetNearestMark(frame, true);
@@ -358,7 +371,7 @@ void DeleteMap::Delete(uint64_t frame, QString undoMessage)
if (MARK_PLACEHOLDER == type)
next = prev = frame;
else if (MARK_CUT_END == type)
- next = frame;
+ next = frame;
else if (MARK_CUT_START == type)
prev = frame;
}
@@ -367,8 +380,6 @@ void DeleteMap::Delete(uint64_t frame, QString undoMessage)
if (prev != next)
Delete(next);
CleanMap();
- if (!undoMessage.isEmpty())
- Push(undoMessage);
}
/// Add a new cut marker (to start or end a cut region)
@@ -376,6 +387,10 @@ void DeleteMap::NewCut(uint64_t frame)
{
EDIT_CHECK;
+ // Defer pushing the undo entry until the end, when we're sure a
+ // change has been made.
+ frm_dir_map_t initialDeleteMap = m_deleteMap;
+
// find any existing temporary marker to determine cut range
int64_t existing = -1;
frm_dir_map_t::Iterator it;
@@ -468,7 +483,7 @@ void DeleteMap::NewCut(uint64_t frame)
Add(frame, MARK_PLACEHOLDER);
CleanMap();
- Push(tr("New Cut"));
+ PushDeferred(initialDeleteMap, tr("New Cut"));
}
/// Move the previous (!right) or next (right) cut to frame.
@@ -685,24 +700,25 @@ void DeleteMap::CleanMap(void)
/// Use the given map.
void DeleteMap::SetMap(const frm_dir_map_t &map)
{
- Clear();
- m_deleteMap = map;
- m_deleteMap.detach();
// Can't save an undo point for SetMap() or transcodes fail.
// Leaving as a marker for refactor.
//Push(tr("Set New Cut List"));
+
+ Clear();
+ m_deleteMap = map;
+ m_deleteMap.detach();
}
/// Loads the given commercial break map into the deleteMap.
void DeleteMap::LoadCommBreakMap(frm_dir_map_t &map)
{
+ Push(tr("Load Detected Commercials"));
Clear();
frm_dir_map_t::Iterator it = map.begin();
for ( ; it != map.end(); ++it)
Add(it.key(), it.value() == MARK_COMM_START ?
MARK_CUT_START : MARK_CUT_END);
CleanMap();
- Push(tr("Load Detected Commercials"));
}
/// Loads the delete map from the database.
@@ -711,13 +727,13 @@ void DeleteMap::LoadMap(QString undoMessage)
if (!m_ctx || !m_ctx->playingInfo || gCoreContext->IsDatabaseIgnored())
return;
+ if (!undoMessage.isEmpty())
+ Push(undoMessage);
Clear();
m_ctx->LockPlayingInfo(__FILE__, __LINE__);
m_ctx->playingInfo->QueryCutList(m_deleteMap);
m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
CleanMap();
- if (!undoMessage.isEmpty())
- Push(undoMessage);
}
/// Returns true if an auto-save map was loaded.
@@ -734,7 +750,7 @@ bool DeleteMap::LoadAutoSaveMap(void)
m_ctx->UnlockPlayingInfo(__FILE__, __LINE__);
CleanMap();
if (result)
- Push(tr("Load Auto-saved Cuts"));
+ PushDeferred(tmpDeleteMap, tr("Load Auto-saved Cuts"));
else
m_deleteMap = tmpDeleteMap;
View
12 mythtv/libs/libmythtv/deletemap.h
@@ -14,7 +14,7 @@ typedef struct DeleteMapUndoEntry
{
frm_dir_map_t deleteMap;
QString message; // how we got from previous map to this map
- DeleteMapUndoEntry(frm_dir_map_t dm, QString msg);
+ DeleteMapUndoEntry(const frm_dir_map_t &dm, const QString &msg);
DeleteMapUndoEntry(void);
} DeleteMapUndoEntry;
@@ -26,9 +26,8 @@ class MTV_PUBLIC DeleteMap
m_nextCutStartIsValid(false),
m_nextCutStart(0), m_changed(true),
m_seekamountpos(4), m_seekamount(1.0),
- m_ctx(NULL), m_cachedTotalForOSD(0), m_undoStackPointer(-1)
+ m_ctx(NULL), m_cachedTotalForOSD(0), m_undoStackPointer(0)
{
- Push("");
}
void SetPlayerContext(PlayerContext *ctx) { m_ctx = ctx; }
@@ -86,7 +85,7 @@ class MTV_PUBLIC DeleteMap
bool Redo(void);
bool HasUndo(void) const { return m_undoStackPointer > 0; }
bool HasRedo(void) const
- { return m_undoStackPointer < m_undoStack.size() - 1; }
+ { return m_undoStackPointer < m_undoStack.size(); }
QString GetUndoMessage(void) const;
QString GetRedoMessage(void) const;
@@ -94,7 +93,9 @@ class MTV_PUBLIC DeleteMap
void Add(uint64_t frame, MarkTypes type);
MarkTypes Delete(uint64_t frame);
- void Push(QString undoMessage);
+ void Push(const QString &undoMessage);
+ void PushDeferred(const frm_dir_map_t &savedMap,
+ const QString &undoMessage);
QString CreateTimeString(uint64_t frame, bool use_cutlist,
double frame_rate, bool full_resolution) const;
@@ -110,7 +111,6 @@ class MTV_PUBLIC DeleteMap
PlayerContext *m_ctx;
uint64_t m_cachedTotalForOSD;
- // Invariant: m_undoStack[m_undoStackPointer].deleteMap == m_deleteMap
QVector<DeleteMapUndoEntry> m_undoStack;
int m_undoStackPointer;
};
Please sign in to comment.
Something went wrong with that request. Please try again.