Ticket #8901: cutlist_undo_stack_v2.patch

File cutlist_undo_stack_v2.patch, 11.1 KB (added by Jim Stichnoth <stichnot@…>, 9 years ago)
  • libs/libmythtv/deletemap.h

     
    44#include "programinfo.h"
    55#include "playercontext.h"
    66
     7class DeleteMap;
     8
     9typedef struct DeleteMapUndoEntry
     10{
     11    frm_dir_map_t deleteMap;
     12    QString message; // how we got from previous map to this map
     13    DeleteMapUndoEntry(frm_dir_map_t dm, QString msg);
     14    DeleteMapUndoEntry(void);
     15} DeleteMapUndoEntry;
     16
    717class DeleteMap
    818{
    919  public:
    1020    DeleteMap(): m_editing(false),   m_nextCutStart(0), m_changed(true),
    11                  m_seekamountpos(4), m_seekamount(30) { }
     21                 m_seekamountpos(4), m_seekamount(30),
     22                 m_undoStackPointer(-1) { Push(""); }
    1223
    1324    bool HandleAction(QString &action, uint64_t frame, uint64_t played,
    1425                      uint64_t total, double rate);
     
    3344
    3445    void Clear(void);
    3546    void ReverseAll(uint64_t total);
    36     void Add(uint64_t frame, uint64_t total, MarkTypes type);
     47    void Add(uint64_t frame, uint64_t total, MarkTypes type,
     48             QString undoMessage);
    3749    void NewCut(uint64_t frame, uint64_t total);
    38     void Delete(uint64_t frame, uint64_t total);
     50    void Delete(uint64_t frame, uint64_t total, QString undoMessage);
    3951    void Reverse(uint64_t frame, uint64_t total);
    4052    void MoveRelative(uint64_t frame, uint64_t total, bool right);
    4153    void Move(uint64_t frame, uint64_t to, uint64_t total);
     
    4961    void TrackerReset(uint64_t frame, uint64_t total);
    5062    bool TrackerWantsToJump(uint64_t frame, uint64_t total, uint64_t &to);
    5163
     64    bool Undo(void);
     65    bool Redo(void);
     66    bool HasUndo(void) { return m_undoStackPointer > 0; }
     67    bool HasRedo(void) { return m_undoStackPointer < m_undoStack.size() - 1; }
     68    QString GetUndoMessage(void);
     69    QString GetRedoMessage(void);
     70
    5271  private:
    5372    void Add(uint64_t frame, MarkTypes type);
    5473    MarkTypes Delete(uint64_t frame);
    5574
     75    void Push(QString undoMessage);
     76
    5677    bool          m_editing;
    5778    uint64_t      m_nextCutStart;
    5879    frm_dir_map_t m_deleteMap;
     
    6081    bool          m_changed;
    6182    int           m_seekamountpos;
    6283    int           m_seekamount;
     84
     85    // Invariant: m_undoStack[m_undoStackPointer].deleteMap == m_deleteMap
     86    QVector<DeleteMapUndoEntry> m_undoStack;
     87    int m_undoStackPointer;
    6388};
    6489
    6590#endif // DELETEMAP_H
  • libs/libmythtv/mythplayer.h

     
    301301    uint64_t GetNearestMark(uint64_t frame, bool right);
    302302    bool IsTemporaryMark(uint64_t frame);
    303303    bool HasTemporaryMark(void);
     304    bool DeleteMapHasUndo(void) { return deleteMap.HasUndo(); }
     305    bool DeleteMapHasRedo(void) { return deleteMap.HasRedo(); }
     306    QString DeleteMapGetUndoMessage(void) { return deleteMap.GetUndoMessage(); }
     307    QString DeleteMapGetRedoMessage(void) { return deleteMap.GetRedoMessage(); }
    304308
    305309    // Decoder stuff..
    306310    VideoFrame *GetNextVideoFrame(bool allow_unsafe = true);
  • libs/libmythtv/tv_play.cpp

     
    774774            "Jump back 10x the normal amount"), ",,<");
    775775    REG_KEY("TV Editing", "BIGJUMPFWD",  QT_TRANSLATE_NOOP("MythControls",
    776776            "Jump forward 10x the normal amount"), ">,.");
     777    REG_KEY("TV Editing", "UNDO",        QT_TRANSLATE_NOOP("MythControls",
     778            "Undo"), "Ctrl+Z");
     779    REG_KEY("TV Editing", "REDO",        QT_TRANSLATE_NOOP("MythControls",
     780            "Redo"), "Ctrl+Y");
    777781
    778782    /* Teletext keys */
    779783    REG_KEY("Teletext Menu", "NEXTPAGE",    QT_TRANSLATE_NOOP("MythControls",
     
    93109314        if ("EDIT_CUT_POINTS" == type)
    93119315            osd->DialogAddButton(QObject::tr("Cut List Options"),
    93129316                                 "DIALOG_CUTPOINT_CUTLISTOPTIONS_0", true);
     9317        if (ctx->player->DeleteMapHasUndo())
     9318            osd->DialogAddButton(QObject::tr("Undo") + " - " +
     9319                                 ctx->player->DeleteMapGetUndoMessage(),
     9320                                 QString("DIALOG_CUTPOINT_UNDO_0"));
     9321        if (ctx->player->DeleteMapHasRedo())
     9322            osd->DialogAddButton(QObject::tr("Redo") + " - " +
     9323                                 ctx->player->DeleteMapGetRedoMessage(),
     9324                                 QString("DIALOG_CUTPOINT_REDO_0"));
    93139325    }
    93149326    else if ("CUT_LIST_OPTIONS" == type)
    93159327    {
  • libs/libmythtv/deletemap.cpp

     
    1010#define EDIT_CHECK if(!m_editing) \
    1111  { VERBOSE(VB_IMPORTANT, LOC_ERR + "Cannot edit outside editmode."); return; }
    1212
     13DeleteMapUndoEntry::DeleteMapUndoEntry(frm_dir_map_t dm, QString msg) :
     14    deleteMap(dm), message(msg) { }
     15
     16DeleteMapUndoEntry::DeleteMapUndoEntry(void)
     17{
     18    frm_dir_map_t dm;
     19    deleteMap = dm;
     20    message = "";
     21}
     22
     23void DeleteMap::Push(QString undoMessage)
     24{
     25    DeleteMapUndoEntry entry(m_deleteMap, undoMessage);
     26    // Remove all "redo" entries
     27    while (m_undoStack.size() > m_undoStackPointer + 1)
     28        m_undoStack.pop_back();
     29    m_undoStack.append(entry);
     30    m_undoStackPointer ++;
     31}
     32
     33bool DeleteMap::Undo(void)
     34{
     35    if (!HasUndo())
     36        return false;
     37    m_undoStackPointer --;
     38    m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap;
     39    m_changed = true;
     40    return true;
     41}
     42
     43bool DeleteMap::Redo(void)
     44{
     45    if (!HasRedo())
     46        return false;
     47    m_undoStackPointer ++;
     48    m_deleteMap = m_undoStack[m_undoStackPointer].deleteMap;
     49    m_changed = true;
     50    return true;
     51}
     52
     53QString DeleteMap::GetUndoMessage(void)
     54{
     55    return (HasUndo() ? m_undoStack[m_undoStackPointer].message :
     56            QObject::tr("(No more undo operations)"));
     57}
     58
     59QString DeleteMap::GetRedoMessage(void)
     60{
     61    return (HasRedo() ? m_undoStack[m_undoStackPointer + 1].message :
     62            QObject::tr("(No more redo operations)"));
     63}
     64
    1365bool DeleteMap::HandleAction(QString &action, uint64_t frame,
    1466                             uint64_t played, uint64_t total, double rate)
    1567{
     
    2981    else if (action == "MOVENEXT")
    3082        MoveRelative(frame, total, true);
    3183    else if (action == "CUTTOBEGINNING")
    32         Add(frame, total, MARK_CUT_END);
     84        Add(frame, total, MARK_CUT_END, QObject::tr("Cut To Beginning"));
    3385    else if (action == "CUTTOEND")
    34         Add(frame, total, MARK_CUT_START);
     86        Add(frame, total, MARK_CUT_START, QObject::tr("Cut To End"));
    3587    else if (action == "NEWCUT")
    3688        NewCut(frame, total);
    3789    else if (action == "DELETE")
    38         Delete(frame, total);
     90        Delete(frame, total, QObject::tr("Delete Cut Area"));
     91    else if (action == "UNDO")
     92        Undo();
     93    else if (action == "REDO")
     94        Redo();
    3995    else
    4096        handled = false;
    4197    return handled;
     
    154210{
    155211    m_deleteMap.clear();
    156212    m_changed = true;
     213    Push(QObject::tr("Clear Cut List"));
    157214}
    158215
    159216/// Reverses the direction of each mark in the map.
     
    165222        Add(it.key(), it.value() == MARK_CUT_END ? MARK_CUT_START :
    166223                                                   MARK_CUT_END);
    167224    CleanMap(total);
     225    Push(QObject::tr("Invert Cut List"));
    168226}
    169227
    170228/**
     
    172230 *        existing redundant mark of that type is removed. This simplifies
    173231 *        the cleanup code.
    174232 */
    175 void DeleteMap::Add(uint64_t frame, uint64_t total, MarkTypes type)
     233void DeleteMap::Add(uint64_t frame, uint64_t total, MarkTypes type,
     234                    QString undoMessage)
    176235{
    177236    EDIT_CHECK
    178237    if ((MARK_CUT_START != type) && (MARK_CUT_END != type) &&
     
    186245        {
    187246            // Delete the temporary mark before putting a real mark at its
    188247            // location
    189             Delete(frame, total);
     248            Delete(frame, total, "");
    190249        }
    191250        else // Don't add a mark on top of a mark
    192251            return;
     
    241300        Delete((uint64_t)remove);
    242301    Add(frame, type);
    243302    CleanMap(total);
     303    if (!undoMessage.isEmpty())
     304        Push(undoMessage);
    244305}
    245306
    246307/// Remove the mark at the given frame.
    247 void DeleteMap::Delete(uint64_t frame, uint64_t total)
     308void DeleteMap::Delete(uint64_t frame, uint64_t total, QString undoMessage)
    248309{
    249310    EDIT_CHECK
    250311    if (m_deleteMap.isEmpty())
     
    271332    if (prev != next)
    272333        Delete(next);
    273334    CleanMap(total);
     335    if (!undoMessage.isEmpty())
     336        Push(undoMessage);
    274337}
    275338
    276339/// Reverse the direction of the mark at the given frame.
     
    278341{
    279342    EDIT_CHECK
    280343    int type = Delete(frame);
    281     Add(frame, total, type == MARK_CUT_END ? MARK_CUT_START : MARK_CUT_END);
     344    Add(frame, total, type == MARK_CUT_END ? MARK_CUT_START : MARK_CUT_END, "");
     345    Push(QObject::tr("Reverse Mark Direction"));
    282346}
    283347
    284348/// Add a new cut marker (to start or end a cut region)
     
    376440        Add(frame, MARK_PLACEHOLDER);
    377441
    378442    CleanMap(total);
     443    Push(QObject::tr("New Cut"));
    379444}
    380445
    381446/// Move the previous (!right) or next (right) cut to frame.
     
    397462        {
    398463            // If on a mark, don't collapse a cut region to 0;
    399464            // instead, delete the region
    400             Delete(frame, total);
     465            Delete(frame, total, QObject::tr("Delete Cut Area"));
    401466            return;
    402467        }
    403468        else if (MARK_PLACEHOLDER == type)
    404469        {
    405470            // Delete the temporary mark before putting a real mark at its
    406471            // location
    407             Delete(frame, total);
     472            Delete(frame, total, "");
    408473        }
    409474    }
    410475
     
    424489        else if (frame == total)
    425490            type = MARK_CUT_END;
    426491    }
    427     Add(to, total, type);
     492    Add(to, total, type, QObject::tr("Move Mark"));
    428493}
    429494
    430495/// Private addition to the deleteMap.
     
    582647    Clear();
    583648    m_deleteMap = map;
    584649    m_deleteMap.detach();
     650    Push(QObject::tr("Set New Cut List"));
    585651}
    586652
    587653/// Loads the given commercial break map into the deleteMap.
     
    593659        Add(it.key(), it.value() == MARK_COMM_START ?
    594660                MARK_CUT_START : MARK_CUT_END);
    595661    CleanMap(total);
     662    Push(QObject::tr("Load Commskip List"));
    596663}
    597664
    598665/// Loads the delete map from the database.
     
    606673    ctx->playingInfo->QueryCutList(m_deleteMap);
    607674    ctx->UnlockPlayingInfo(__FILE__, __LINE__);
    608675    CleanMap(total);
     676    Push(QObject::tr("Load Cut List"));
    609677}
    610678
    611679/// Saves the delete map to the database.
  • libs/libmythtv/mythplayer.cpp

     
    34853485        {
    34863486            if (IsInDelete(frame))
    34873487            {
    3488                 deleteMap.Delete(frame, totalFrames);
     3488                deleteMap.Delete(frame, totalFrames,
     3489                                 QObject::tr("Delete cut area"));
    34893490                refresh = true;
    34903491            }
    34913492        }