void Game::promoteVariation(const Index& ix, int v) { int at; std::vector<Entry>* vec = fetchRef(ix, &at); Q_ASSERT(vec); Q_ASSERT((*vec)[at].variations.count(v)==1); History vold = (*vec)[at].variations[v]; History vnew; for(int i=at+1; i<(int)vec->size(); i++) vnew.push_back((*vec)[i]); while((int)vec->size()>at+1) vec->pop_back(); for(int i=0; i<(int)vold.size(); i++) vec->push_back(vold[i]); (*vec)[at].variations[v] = vnew; saveUndo(UndoPromote(ix, v)); current = current.flipVariation(ix, v); onPromoteVariation(ix, v); //don't call onCurrentIndexChanged(), as the position did not change actually }
void Game::redo() { if(undo_pos >= (int)undo_history.size()) { kError() << "Nothing to redo"; return; } bool now_undo = undo_pos == 0; bool last_redo = undo_pos == (int)undo_history.size()-1; UndoOp* op = &(undo_history[undo_pos]); undo_pos++; if(boost::get<UndoAdd>(op)) { UndoAdd *a = boost::get<UndoAdd>(op); if(a->index.atVariationStart() ) { Entry* e = fetch(a->index.prev()); Q_ASSERT(e); int v = a->index.nested.back().variation; Q_ASSERT(e->variations.count(v) == 0); History h; h.push_back(a->entry); e->variations[v] = h; } else { int at; std::vector<Entry>* vec = fetchRef(a->index.prev(), &at); Q_ASSERT(vec); Q_ASSERT((int)vec->size() == at+1); vec->push_back(a->entry); } onAdded(a->index); current = a->index; onCurrentIndexChanged(); } else if(boost::get<UndoPromote>(op)) { UndoPromote *p = boost::get<UndoPromote>(op); int at; std::vector<Entry>* vec = fetchRef(p->index, &at); Q_ASSERT(vec); Q_ASSERT((*vec)[at].variations.count(p->variation)==1); History vold = (*vec)[at].variations[p->variation]; History vnew; for(int i=at+1; i<(int)vec->size(); i++) vnew.push_back((*vec)[i]); while((int)vec->size()>at+1) vec->pop_back(); for(int i=0; i<(int)vold.size(); i++) vec->push_back(vold[i]); (*vec)[at].variations[p->variation] = vnew; current = current.flipVariation(p->index, p->variation); onPromoteVariation(p->index, p->variation); //onCurrentIndexChanged(); } else if(boost::get<UndoTruncate>(op)) { UndoTruncate *t = boost::get<UndoTruncate>(op); int at; std::vector<Entry>* vec = fetchRef(t->index, &at); Q_ASSERT(vec); Q_ASSERT((int)vec->size() == at+1+(int)t->history.size()); while((int)vec->size() > at+1) vec->pop_back(); (*vec)[at].variations.clear(); (*vec)[at].vcomments.clear(); if(current > t->index) { current = t->index; onCurrentIndexChanged(); } if(t->history.size()) onRemoved(t->index.next()); for(Variations::iterator it = t->variations.begin(); it != t->variations.end(); ++it) onRemoved(t->index.next(it->first)); } else if(boost::get<UndoRemove>(op)) { UndoRemove *r = boost::get<UndoRemove>(op); Entry *e = fetch(r->index); e->variations.erase(r->variation); e->vcomments.erase(r->variation); onRemoved(r->index.next(r->variation)); } else if(boost::get<UndoClear>(op)) { UndoClear *c = boost::get<UndoClear>(op); Entry *e = fetch(c->index); e->variations.clear(); e->vcomments.clear(); for(Variations::iterator it = c->variations.begin(); it != c->variations.end(); ++it) onRemoved(c->index.next(it->first)); } else if(boost::get<UndoSetComment>(op)) { UndoSetComment *sc = boost::get<UndoSetComment>(op); Entry *e = fetch(sc->index); Q_ASSERT(e); if(sc->variation == -1) { e->comment = sc->new_comment; onSetComment(sc->index, sc->new_comment); } else { if(sc->new_comment.isEmpty()) e->vcomments.erase(sc->variation); else e->vcomments[sc->variation] = sc->new_comment; onSetVComment(sc->index, sc->variation, sc->new_comment); } } else kError() << "Unexpected type in boost::variant"; if(now_undo) onAvailableUndo(true); if(last_redo) onAvailableRedo(false); }