Shinya Kitaoka 79e39b
#include <memory></memory>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "cellselection.h"
manongjohn b248d8
#include "cellkeyframeselection.h"
manongjohn b248d8
#include "keyframeselection.h"
manongjohn b248d8
#include "keyframedata.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Tnz6 includes
Toshihiro Shimizu 890ddd
#include "tapp.h"
Toshihiro Shimizu 890ddd
#include "duplicatepopup.h"
Toshihiro Shimizu 890ddd
#include "overwritepopup.h"
Toshihiro Shimizu 890ddd
#include "selectionutils.h"
Toshihiro Shimizu 890ddd
#include "columnselection.h"
shun-iwasawa aa65b8
#include "reframepopup.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/tselectionhandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/gutil.h"
Toshihiro Shimizu 890ddd
#include "historytypes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tscenehandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tobjecthandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/stageobjectutil.h"
Toshihiro Shimizu 890ddd
#include "toonz/hook.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/childstack.h"
Jeremy Bullock 1cf798
#include "toonz/tframehandle.h"
Jeremy Bullock 1cf798
#include "toonz/tcolumnhandle.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
#include "tmsgcore.h"
Toshihiro Shimizu 890ddd
#include "trandom.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qlabel></qlabel>
Toshihiro Shimizu 890ddd
#include <qpushbutton></qpushbutton>
Toshihiro Shimizu 890ddd
#include <qmainwindow></qmainwindow>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "tcg/tcg_macros.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <ctime></ctime>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Reverse Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ReverseUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ReverseUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
      : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override { redo(); }  // Reverse is idempotent :)
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Reverse"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ReverseUndo::redo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_r1 >= m_r0 && m_c1 >= m_c0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->reverseCells(m_r0, m_c0,
Shinya Kitaoka 120a6e
                                                                  m_r1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::reverseCells() {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new ReverseUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Swing Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class SwingUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  SwingUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
      : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Swing"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SwingUndo::redo() const {
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->swingCells(m_r0, m_c0,
Shinya Kitaoka 120a6e
                                                                m_r1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void SwingUndo::undo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_r1 >= m_r0 && m_c1 >= m_c0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c)
Shinya Kitaoka 120a6e
    TApp::instance()->getCurrentXsheet()->getXsheet()->removeCells(m_r1 + 1, c,
Shinya Kitaoka 120a6e
                                                                   m_r1 - m_r0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::swingCells() {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new SwingUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Increment Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class IncrementUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  mutable std::vector<std::pair<trect, txshcell="">> m_undoCells;</std::pair<trect,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable bool m_ok;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  IncrementUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
      : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1), m_ok(true) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Autoexpose"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void IncrementUndo::redo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_r1 >= m_r0 && m_c1 >= m_c0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_undoCells.clear();
Shinya Kitaoka 120a6e
  m_ok = TApp::instance()->getCurrentXsheet()->getXsheet()->incrementCells(
Shinya Kitaoka 120a6e
      m_r0, m_c0, m_r1, m_c1, m_undoCells);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void IncrementUndo::undo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_r1 >= m_r0 && m_c1 >= m_c0 && m_ok, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = m_undoCells.size() - 1; i >= 0; --i) {
Shinya Kitaoka 120a6e
    const TRect &r = m_undoCells[i].first;
Shinya Kitaoka 120a6e
    int size       = r.x1 - r.x0 + 1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (m_undoCells[i].second.isEmpty())
Shinya Kitaoka 120a6e
      xsh->removeCells(r.x0, r.y0, size);
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      xsh->insertCells(r.x0, r.y0, size);
Shinya Kitaoka 120a6e
      for (int j = 0; j < size; ++j)
Shinya Kitaoka 120a6e
        xsh->setCell(r.x0 + j, r.y0, m_undoCells[i].second);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::incrementCells() {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 2a7129
  std::unique_ptr<incrementundo> undo(new IncrementUndo(</incrementundo>
Shinya Kitaoka 120a6e
      m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (undo->redo(), !undo->m_ok) {
Shinya Kitaoka 120a6e
    DVGui::error(
Shinya Kitaoka 120a6e
        QObject::tr("Invalid selection: each selected column must contain one "
Shinya Kitaoka 120a6e
                    "single level with increasing frame numbering."));
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Random Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class RandomUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> m_shuffle;  //!< Shuffled indices</int>
Shinya Kitaoka 120a6e
  std::vector<int> m_elffuhs;  //!< Inverse shuffle indices</int>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RandomUndo(int r0, int c0, int r1, int c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void shuffleCells(int row, int col, const std::vector<int> &data) const;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override {
Shinya Kitaoka 120a6e
    return sizeof(*this) + 2 * sizeof(int) * m_shuffle.size();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Random"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RandomUndo::RandomUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
    : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1) {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_r1 >= m_r0 && m_c1 >= m_c0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int r, rowCount = r1 - r0 + 1;
Shinya Kitaoka 120a6e
  std::vector<std::pair<unsigned int="" int,="">> rndTable(rowCount);</std::pair<unsigned>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRandom rnd(std::time(0));  // Standard seeding
Shinya Kitaoka 120a6e
  for (r = 0; r < rowCount; ++r) rndTable[r] = std::make_pair(rnd.getUInt(), r);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::sort(rndTable.begin(), rndTable.end());  // Random sort shuffle
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_shuffle.resize(rowCount);
Shinya Kitaoka 120a6e
  m_elffuhs.resize(rowCount);
Shinya Kitaoka 120a6e
  for (r = 0; r < rowCount; ++r) {
Shinya Kitaoka 120a6e
    m_shuffle[r]                  = rndTable[r].second;
Shinya Kitaoka 120a6e
    m_elffuhs[rndTable[r].second] = r;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RandomUndo::shuffleCells(int row, int col,
Shinya Kitaoka 120a6e
                              const std::vector<int> &data) const {</int>
Shinya Kitaoka 120a6e
  int rowCount = data.size();
Shinya Kitaoka 120a6e
  assert(rowCount > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<txshcell> bCells(rowCount), aCells(rowCount);</txshcell>
Shinya Kitaoka 120a6e
  xsh->getCells(row, col, rowCount, &bCells[0]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int i = 0; i < rowCount; ++i) aCells[data[i]] = bCells[i];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  xsh->setCells(row, col, rowCount, &aCells[0]);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RandomUndo::undo() const {
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) shuffleCells(m_r0, c, m_elffuhs);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RandomUndo::redo() const {
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) shuffleCells(m_r0, c, m_shuffle);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::randomCells() {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new RandomUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Step Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class StepUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  int m_rowsCount, m_colsCount;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m_step;
Shinya Kitaoka 120a6e
  int m_newRows;
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  StepUndo(int r0, int c0, int r1, int c1, int step);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  QString getHistoryString() override {
Shinya Kitaoka 120a6e
    return QObject::tr("Step %1").arg(QString::number(m_step));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
StepUndo::StepUndo(int r0, int c0, int r1, int c1, int step)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_c0(c0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_c1(c1)
Shinya Kitaoka 120a6e
    , m_rowsCount(r1 - r0 + 1)
Shinya Kitaoka 120a6e
    , m_colsCount(c1 - c0 + 1)
Shinya Kitaoka 120a6e
    , m_step(step)
Shinya Kitaoka 120a6e
    , m_newRows(m_rowsCount * (step - 1))
Shinya Kitaoka 120a6e
    , m_cells(new TXshCell[m_rowsCount * m_colsCount]) {
Shinya Kitaoka 120a6e
  assert(m_rowsCount > 0 && m_colsCount > 0 && step > 0);
otakuto e28b5e
  assert(m_cells);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int r = r0; r <= r1; ++r)
Shinya Kitaoka 120a6e
    for (int c = c0; c <= c1; ++c)
Shinya Kitaoka 120a6e
      m_cells[k++] =
Shinya Kitaoka 120a6e
          TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StepUndo::redo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->stepCells(m_r0, m_c0, m_r1,
Shinya Kitaoka 120a6e
                                                               m_c1, m_step);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StepUndo::undo() const {
otakuto e28b5e
  TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells, return );
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) xsh->removeCells(m_r1 + 1, c, m_newRows);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int r = m_r0; r <= m_r1; ++r)
Shinya Kitaoka 120a6e
    for (int c = m_c0; c <= m_c1; ++c) {
Shinya Kitaoka 120a6e
      if (m_cells[k].isEmpty())
Shinya Kitaoka 120a6e
        xsh->clearCells(r, c);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        xsh->setCell(r, c, m_cells[k]);
Shinya Kitaoka 120a6e
      k++;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  app->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::stepCells(int step) {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo = new StepUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1,
Shinya Kitaoka 120a6e
                             m_range.m_c1, step);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Shinya Kitaoka 120a6e
  m_range.m_r1 += (step - 1) * m_range.getRowCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Each Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class EachUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  int m_rowsCount, m_colsCount;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int m_each;
Shinya Kitaoka 120a6e
  int m_newRows;
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  EachUndo(int r0, int c0, int r1, int c1, int each);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  QString getHistoryString() override {
Shinya Kitaoka 120a6e
    return QObject::tr("Each %1").arg(QString::number(m_each));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
EachUndo::EachUndo(int r0, int c0, int r1, int c1, int each)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_c0(c0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_c1(c1)
Shinya Kitaoka 120a6e
    , m_rowsCount(r1 - r0 + 1)
Shinya Kitaoka 120a6e
    , m_colsCount(c1 - c0 + 1)
Shinya Kitaoka 120a6e
    , m_each(each)
Shinya Kitaoka 120a6e
    , m_newRows((m_rowsCount % each) ? m_rowsCount / each + 1
Shinya Kitaoka 120a6e
                                     : m_rowsCount / each)
Shinya Kitaoka 120a6e
    , m_cells(new TXshCell[m_rowsCount * m_colsCount]) {
Shinya Kitaoka 120a6e
  assert(m_rowsCount > 0 && m_colsCount > 0 && each > 0);
otakuto e28b5e
  assert(m_cells);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int r = r0; r <= r1; ++r)
Shinya Kitaoka 120a6e
    for (int c = c0; c <= c1; ++c)
Shinya Kitaoka 120a6e
      m_cells[k++] =
Shinya Kitaoka 120a6e
          TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EachUndo::redo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->eachCells(m_r0, m_c0, m_r1,
Shinya Kitaoka 120a6e
                                                               m_c1, m_each);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void EachUndo::undo() const {
otakuto e28b5e
  TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0 && m_cells, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c)
Shinya Kitaoka 120a6e
    xsh->insertCells(m_r0 + m_newRows, c, m_rowsCount - m_newRows);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int r = m_r0; r <= m_r1; ++r)
Shinya Kitaoka 120a6e
    for (int c = m_c0; c <= m_c1; ++c) {
Shinya Kitaoka 120a6e
      if (m_cells[k].isEmpty())
Shinya Kitaoka 120a6e
        xsh->clearCells(r, c);
Shinya Kitaoka 120a6e
      else
Shinya Kitaoka 120a6e
        xsh->setCell(r, c, m_cells[k]);
Shinya Kitaoka 120a6e
      k++;
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  app->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::eachCells(int each) {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo = new EachUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1,
Shinya Kitaoka 120a6e
                             m_range.m_c1, each);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Shinya Kitaoka 120a6e
  m_range.m_r1 = m_range.m_r0 + (m_range.m_r1 - m_range.m_r0 + each) / each - 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Reframe command : 強制的にNコマ打ちにする
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ReframeUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_r1;
Shinya Kitaoka 120a6e
  int m_type;
Shinya Kitaoka 120a6e
  int m_nr;
shun-iwasawa aa65b8
  int m_withBlank;
Shinya Kitaoka 120a6e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  std::vector<int> m_newRows;</int>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<int> m_columnIndeces;</int>
Shinya Kitaoka 120a6e
shun-iwasawa aa65b8
  ReframeUndo(int r0, int r1, std::vector<int> columnIndeces, int type,</int>
shun-iwasawa aa65b8
              int withBlank = -1);
Shinya Kitaoka 120a6e
  ~ReframeUndo();
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 120a6e
  void repeat() const;
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override {
shun-iwasawa aa65b8
    if (m_withBlank == -1)
shun-iwasawa aa65b8
      return QObject::tr("Reframe to %1's").arg(QString::number(m_type));
shun-iwasawa aa65b8
    else
shun-iwasawa aa65b8
      return QObject::tr("Reframe to %1's with %2 blanks")
shun-iwasawa aa65b8
          .arg(QString::number(m_type))
shun-iwasawa aa65b8
          .arg(QString::number(m_withBlank));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ReframeUndo::ReframeUndo(int r0, int r1, std::vector<int> columnIndeces,</int>
shun-iwasawa aa65b8
                         int type, int withBlank)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_type(type)
Shinya Kitaoka 120a6e
    , m_nr(0)
shun-iwasawa aa65b8
    , m_columnIndeces(columnIndeces)
shun-iwasawa aa65b8
    , m_withBlank(withBlank) {
Shinya Kitaoka 120a6e
  m_nr = m_r1 - m_r0 + 1;
Shinya Kitaoka 120a6e
  assert(m_nr > 0);
Shinya Kitaoka 120a6e
  m_cells.reset(new TXshCell[m_nr * (int)m_columnIndeces.size()]);
Shinya Kitaoka 120a6e
  assert(m_cells);
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int r = r0; r <= r1; r++)
manongjohn f2da01
    for (int c     = 0; c < (int)m_columnIndeces.size(); c++)
Shinya Kitaoka 120a6e
      m_cells[k++] = TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(
Shinya Kitaoka 120a6e
          r, m_columnIndeces[c]);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_newRows.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
ReframeUndo::~ReframeUndo() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ReframeUndo::undo() const {
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
  int rowCount = m_r1 - m_r0;
Shinya Kitaoka 120a6e
  if (rowCount < 0 || m_columnIndeces.size() < 1) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int c = 0; c < m_columnIndeces.size(); c++) {
Shinya Kitaoka 120a6e
    /*-- コマンド後に縮んだカラムはその分引き伸ばす --*/
Shinya Kitaoka 120a6e
    if (m_newRows[c] < m_nr)
Shinya Kitaoka 120a6e
      xsh->insertCells(m_r0 + m_newRows[c], m_columnIndeces[c],
Shinya Kitaoka 120a6e
                       m_nr - m_newRows[c]);
Shinya Kitaoka 120a6e
    /*-- コマンド後に延びたカラムはその分縮める --*/
Shinya Kitaoka 120a6e
    else if (m_newRows[c] > m_nr)
Shinya Kitaoka 120a6e
      xsh->removeCells(m_r1 + 1, m_columnIndeces[c], m_newRows[c] - m_nr);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_cells) {
Shinya Kitaoka 120a6e
    int k = 0;
Shinya Kitaoka 120a6e
    for (int r = m_r0; r <= m_r1; r++)
Shinya Kitaoka 120a6e
      for (int c = 0; c < m_columnIndeces.size(); c++) {
Shinya Kitaoka 120a6e
        if (m_cells[k].isEmpty())
Shinya Kitaoka 120a6e
          xsh->clearCells(r, m_columnIndeces[c]);
Shinya Kitaoka 120a6e
        else
Shinya Kitaoka 120a6e
          xsh->setCell(r, m_columnIndeces[c], m_cells[k]);
Shinya Kitaoka 120a6e
        k++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ReframeUndo::redo() const {
Shinya Kitaoka 120a6e
  if (m_r1 - m_r0 < 0 || m_columnIndeces.size() < 1) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp *app = TApp::instance();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int c = 0; c < m_columnIndeces.size(); c++)
Shinya Kitaoka 120a6e
    app->getCurrentXsheet()->getXsheet()->reframeCells(
shun-iwasawa aa65b8
        m_r0, m_r1, m_columnIndeces[c], m_type, m_withBlank);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ReframeUndo::repeat() const {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::reframeCells(int count) {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::vector<int> colIndeces;</int>
Shinya Kitaoka 120a6e
  for (int c = m_range.m_c0; c <= m_range.m_c1; c++) colIndeces.push_back(c);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ReframeUndo *undo =
Shinya Kitaoka 120a6e
      new ReframeUndo(m_range.m_r0, m_range.m_r1, colIndeces, count);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int c = m_range.m_c0; c <= m_range.m_c1; c++) {
Shinya Kitaoka 120a6e
    int nrows = TApp::instance()->getCurrentXsheet()->getXsheet()->reframeCells(
Shinya Kitaoka 120a6e
        m_range.m_r0, m_range.m_r1, c, count);
Shinya Kitaoka 120a6e
    undo->m_newRows.push_back(nrows);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TColumnSelection::reframeCells(int count) {
Shinya Kitaoka 120a6e
  if (isEmpty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int rowCount =
Shinya Kitaoka 120a6e
      TApp::instance()->getCurrentXsheet()->getXsheet()->getFrameCount();
Shinya Kitaoka 120a6e
  std::vector<int> colIndeces;</int>
Shinya Kitaoka 120a6e
  std::set<int>::const_iterator it;</int>
Shinya Kitaoka 120a6e
  for (it = m_indices.begin(); it != m_indices.end(); it++)
Shinya Kitaoka 120a6e
    colIndeces.push_back(*it);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ReframeUndo *undo = new ReframeUndo(0, rowCount - 1, colIndeces, count);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  for (int c = 0; c < (int)colIndeces.size(); c++) {
Shinya Kitaoka 120a6e
    int nrows = TApp::instance()->getCurrentXsheet()->getXsheet()->reframeCells(
Shinya Kitaoka 120a6e
        0, rowCount - 1, colIndeces[c], count);
Shinya Kitaoka 120a6e
    undo->m_newRows.push_back(nrows);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa aa65b8
//=============================================================================
shun-iwasawa aa65b8
shun-iwasawa aa65b8
void TCellSelection::reframeWithEmptyInbetweens() {
shun-iwasawa aa65b8
  if (isEmpty() || areAllColSelectedLocked()) return;
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  std::vector<int> colIndeces;</int>
shun-iwasawa aa65b8
  for (int c = m_range.m_c0; c <= m_range.m_c1; c++) colIndeces.push_back(c);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  // destruction of m_reframePopup will be done along with the main window
shun-iwasawa aa65b8
  if (!m_reframePopup) m_reframePopup = new ReframePopup();
manongjohn f2da01
  int ret                             = m_reframePopup->exec();
shun-iwasawa aa65b8
  if (ret == QDialog::Rejected) return;
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  int step, blank;
shun-iwasawa aa65b8
  m_reframePopup->getValues(step, blank);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  ReframeUndo *undo =
shun-iwasawa aa65b8
      new ReframeUndo(m_range.m_r0, m_range.m_r1, colIndeces, step, blank);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  int maximumRow = 0;
shun-iwasawa aa65b8
  for (int c = m_range.m_c0; c <= m_range.m_c1; c++) {
shun-iwasawa aa65b8
    int nrows = TApp::instance()->getCurrentXsheet()->getXsheet()->reframeCells(
shun-iwasawa aa65b8
        m_range.m_r0, m_range.m_r1, c, step, blank);
shun-iwasawa aa65b8
    undo->m_newRows.push_back(nrows);
shun-iwasawa aa65b8
    if (maximumRow < nrows) maximumRow = nrows;
shun-iwasawa aa65b8
  }
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  if (maximumRow == 0) {
shun-iwasawa aa65b8
    delete undo;
shun-iwasawa aa65b8
    return;
shun-iwasawa aa65b8
  }
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  TUndoManager::manager()->add(undo);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  // select reframed range
shun-iwasawa aa65b8
  selectCells(m_range.m_r0, m_range.m_c0, m_range.m_r0 + maximumRow - 1,
shun-iwasawa aa65b8
              m_range.m_c1);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
shun-iwasawa aa65b8
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
shun-iwasawa aa65b8
}
shun-iwasawa aa65b8
shun-iwasawa aa65b8
void TColumnSelection::reframeWithEmptyInbetweens() {
shun-iwasawa aa65b8
  if (isEmpty()) return;
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  int rowCount =
shun-iwasawa aa65b8
      TApp::instance()->getCurrentXsheet()->getXsheet()->getFrameCount();
shun-iwasawa aa65b8
  std::vector<int> colIndeces;</int>
shun-iwasawa aa65b8
  std::set<int>::const_iterator it;</int>
shun-iwasawa aa65b8
  for (it = m_indices.begin(); it != m_indices.end(); it++)
shun-iwasawa aa65b8
    colIndeces.push_back(*it);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  if (!m_reframePopup) m_reframePopup = new ReframePopup();
manongjohn f2da01
  int ret                             = m_reframePopup->exec();
shun-iwasawa aa65b8
  if (ret == QDialog::Rejected) return;
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  int step, blank;
shun-iwasawa aa65b8
  m_reframePopup->getValues(step, blank);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  ReframeUndo *undo = new ReframeUndo(0, rowCount - 1, colIndeces, step, blank);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  bool commandExecuted = false;
shun-iwasawa aa65b8
  for (int c = 0; c < (int)colIndeces.size(); c++) {
shun-iwasawa aa65b8
    int nrows = TApp::instance()->getCurrentXsheet()->getXsheet()->reframeCells(
shun-iwasawa aa65b8
        0, rowCount - 1, colIndeces[c], step, blank);
shun-iwasawa aa65b8
    undo->m_newRows.push_back(nrows);
shun-iwasawa aa65b8
    if (nrows > 0) commandExecuted = true;
shun-iwasawa aa65b8
  }
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  if (!commandExecuted) {
shun-iwasawa aa65b8
    delete undo;
shun-iwasawa aa65b8
    return;
shun-iwasawa aa65b8
  }
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  TUndoManager::manager()->add(undo);
shun-iwasawa aa65b8
shun-iwasawa aa65b8
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
shun-iwasawa aa65b8
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
shun-iwasawa aa65b8
}
shun-iwasawa aa65b8
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Reset Step Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class ResetStepUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  int m_rowsCount, m_colsCount;
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Shinya Kitaoka 120a6e
  QMap<int, int=""> m_insertedCells;  //!< Count of inserted cells, by column</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ResetStepUndo(int r0, int c0, int r1, int c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ResetStepUndo::ResetStepUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_c0(c0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_c1(c1)
Shinya Kitaoka 120a6e
    , m_rowsCount(m_r1 - m_r0 + 1)
Shinya Kitaoka 120a6e
    , m_colsCount(m_c1 - m_c0 + 1)
Shinya Kitaoka 120a6e
    , m_cells(new TXshCell[m_rowsCount * m_colsCount]) {
Shinya Kitaoka 120a6e
  assert(m_rowsCount > 0 && m_colsCount > 0);
otakuto e28b5e
  assert(m_cells);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TApp *app = TApp::instance();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = c0; c <= c1; ++c) {
Shinya Kitaoka 120a6e
    TXshCell prevCell;
Shinya Kitaoka 120a6e
    m_insertedCells[c] = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int r = r0; r <= r1; ++r) {
Shinya Kitaoka 120a6e
      const TXshCell &cell =
Shinya Kitaoka 120a6e
          app->getCurrentXsheet()->getXsheet()->getCell(r, c);
Shinya Kitaoka 120a6e
      m_cells[k++] = cell;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (prevCell != cell) {
Shinya Kitaoka 120a6e
        prevCell = cell;
Shinya Kitaoka 120a6e
        m_insertedCells[c]++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ResetStepUndo::redo() const {
Shinya Kitaoka 120a6e
  TCG_ASSERT(m_rowsCount > 0 && m_colsCount > 0, return );
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->resetStepCells(m_r0, m_c0,
Shinya Kitaoka 120a6e
                                                                    m_r1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void ResetStepUndo::undo() const {
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) {
Shinya Kitaoka 120a6e
    xsh->removeCells(m_r0, c, m_insertedCells[c]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    xsh->insertCells(m_r0, c, m_rowsCount);
Shinya Kitaoka 120a6e
    for (int r = m_r0; r <= m_r1; ++r) xsh->setCell(r, c, m_cells[k++]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::resetStepCells() {
Shinya Kitaoka 120a6e
  if (isEmpty() || areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new ResetStepUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Increase Step Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class IncreaseStepUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  int m_rowsCount, m_colsCount;
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Shinya Kitaoka 120a6e
  QMap<int, int=""> m_insertedCells;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable int m_newR1;  //!< r1 updated by TXsheet::increaseStepCells()
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  IncreaseStepUndo(int r0, int c0, int r1, int c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
IncreaseStepUndo::IncreaseStepUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_c0(c0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_c1(c1)
Shinya Kitaoka 120a6e
    , m_rowsCount(m_r1 - m_r0 + 1)
Shinya Kitaoka 120a6e
    , m_colsCount(m_c1 - m_c0 + 1)
Shinya Kitaoka 120a6e
    , m_cells(new TXshCell[m_rowsCount * m_colsCount])
Shinya Kitaoka 120a6e
    , m_newR1(m_r1) {
otakuto e28b5e
  assert(m_cells);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = c0; c <= c1; ++c) {
Shinya Kitaoka 120a6e
    TXshCell prevCell;
Shinya Kitaoka 120a6e
    m_insertedCells[c] = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int r = r0; r <= r1; ++r) {
Shinya Kitaoka 120a6e
      const TXshCell &cell =
Shinya Kitaoka 120a6e
          TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
Shinya Kitaoka 120a6e
      m_cells[k++] = cell;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (prevCell != cell) {
Shinya Kitaoka 120a6e
        prevCell = cell;
Shinya Kitaoka 120a6e
        m_insertedCells[c]++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void IncreaseStepUndo::redo() const {
Shinya Kitaoka 120a6e
  m_newR1 = m_r1;
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->increaseStepCells(
Shinya Kitaoka 120a6e
      m_r0, m_c0, m_newR1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void IncreaseStepUndo::undo() const {
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) {
Shinya Kitaoka 120a6e
    xsh->removeCells(m_r0, c, m_rowsCount + m_insertedCells[c]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    xsh->insertCells(m_r0, c, m_rowsCount);
Shinya Kitaoka 120a6e
    for (int r = m_r0; r <= m_r1; ++r) xsh->setCell(r, c, m_cells[k++]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::increaseStepCells() {
Jeremy Bullock 1cf798
  if (isEmpty()) {
Jeremy Bullock 1cf798
    int row = TTool::getApplication()->getCurrentFrame()->getFrame();
Jeremy Bullock 1cf798
    int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex();
Jeremy Bullock 1cf798
    TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Jeremy Bullock 1cf798
    m_range.m_r0 = row;
Jeremy Bullock 1cf798
    m_range.m_r1 = row;
Jeremy Bullock 1cf798
    m_range.m_c0 = col;
Jeremy Bullock 1cf798
    m_range.m_c1 = col;
Jeremy Bullock 1cf798
    TXshCell cell;
Jeremy Bullock 1cf798
    cell = xsh->getCell(row, col);
Jeremy Bullock 1cf798
    if (cell.isEmpty()) return;
Jeremy Bullock 1cf798
  }
Jeremy Bullock 1cf798
  if (areAllColSelectedLocked()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  IncreaseStepUndo *undo = new IncreaseStepUndo(m_range.m_r0, m_range.m_c0,
Shinya Kitaoka 120a6e
                                                m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (undo->m_newR1 != m_range.m_r1) {
Shinya Kitaoka 120a6e
    m_range.m_r1 = undo->m_newR1;
Shinya Kitaoka 120a6e
    TApp::instance()->getCurrentSelection()->notifySelectionChanged();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Decrease Step Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class DecreaseStepUndo final : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Shinya Kitaoka 120a6e
  int m_rowsCount, m_colsCount;
Toshihiro Shimizu 890ddd
otakuto e28b5e
  std::unique_ptr<txshcell[]> m_cells;</txshcell[]>
Shinya Kitaoka 120a6e
  QMap<int, int=""> m_removedCells;</int,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable int m_newR1;  //!< r1 updated by TXsheet::decreaseStepCells()
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  DecreaseStepUndo(int r0, int c0, int r1, int c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
DecreaseStepUndo::DecreaseStepUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
    : m_r0(r0)
Shinya Kitaoka 120a6e
    , m_c0(c0)
Shinya Kitaoka 120a6e
    , m_r1(r1)
Shinya Kitaoka 120a6e
    , m_c1(c1)
Shinya Kitaoka 120a6e
    , m_rowsCount(m_r1 - m_r0 + 1)
Shinya Kitaoka 120a6e
    , m_colsCount(m_c1 - m_c0 + 1)
Shinya Kitaoka 120a6e
    , m_cells(new TXshCell[m_rowsCount * m_colsCount])
Shinya Kitaoka 120a6e
    , m_newR1(m_r1) {
otakuto e28b5e
  assert(m_cells);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = c0; c <= c1; ++c) {
Shinya Kitaoka 120a6e
    TXshCell prevCell =
Shinya Kitaoka 120a6e
        TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r0, c);
Shinya Kitaoka 120a6e
    m_removedCells[c] = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool removed = false;
Shinya Kitaoka 120a6e
    m_cells[k++] = prevCell;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (int r = r0 + 1; r <= r1; ++r) {
Shinya Kitaoka 120a6e
      const TXshCell &cell =
Shinya Kitaoka 120a6e
          TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(r, c);
Shinya Kitaoka 120a6e
      m_cells[k++] = cell;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (prevCell == cell) {
Shinya Kitaoka 120a6e
        if (!removed) {
Shinya Kitaoka 120a6e
          removed = true;
Shinya Kitaoka 120a6e
          m_removedCells[c]++;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        removed  = false;
Shinya Kitaoka 120a6e
        prevCell = cell;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DecreaseStepUndo::redo() const {
Shinya Kitaoka 120a6e
  m_newR1 = m_r1;
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->getXsheet()->decreaseStepCells(
Shinya Kitaoka 120a6e
      m_r0, m_c0, m_newR1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void DecreaseStepUndo::undo() const {
Shinya Kitaoka 120a6e
  TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
  TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int k = 0;
Shinya Kitaoka 120a6e
  for (int c = m_c0; c <= m_c1; ++c) {
Shinya Kitaoka 120a6e
    xsh->removeCells(m_r0, c, m_rowsCount - m_removedCells[c]);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    xsh->insertCells(m_r0, c, m_rowsCount);
Shinya Kitaoka 120a6e
    for (int r = m_r0; r <= m_r1; ++r) xsh->setCell(r, c, m_cells[k++]);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  app->getCurrentScene()->setDirtyFlag(true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::decreaseStepCells() {
Jeremy Bullock 1cf798
  if (isEmpty()) {
Jeremy Bullock 1cf798
    int row = TTool::getApplication()->getCurrentFrame()->getFrame();
Jeremy Bullock 1cf798
    int col = TTool::getApplication()->getCurrentColumn()->getColumnIndex();
Jeremy Bullock 1cf798
    int r1  = row;
Jeremy Bullock 1cf798
    TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Jeremy Bullock 1cf798
    TXshCell cell;
Jeremy Bullock 1cf798
    TXshCell nextCell;
Jeremy Bullock 1cf798
    bool sameCells = true;
Jeremy Bullock 1cf798
    cell           = xsh->getCell(row, col);
Jeremy Bullock 1cf798
    if (cell.isEmpty()) return;
Jeremy Bullock 1cf798
Jeremy Bullock 1cf798
    for (int i = 1; sameCells; i++) {
Jeremy Bullock 1cf798
      nextCell = xsh->getCell(row + i, col);
Jeremy Bullock 1cf798
      if (nextCell.m_frameId == cell.m_frameId &&
Jeremy Bullock 1cf798
          nextCell.m_level == cell.m_level) {
Jeremy Bullock 1cf798
        r1 = row + i;
Jeremy Bullock 1cf798
      } else
Jeremy Bullock 1cf798
        sameCells = false;
Jeremy Bullock 1cf798
    }
Jeremy Bullock 1cf798
    m_range.m_r0 = row;
Jeremy Bullock 1cf798
    m_range.m_r1 = r1;
Jeremy Bullock 1cf798
    m_range.m_c0 = col;
Jeremy Bullock 1cf798
    m_range.m_c1 = col;
Jeremy Bullock 1cf798
    TApp::instance()->getCurrentSelection()->notifySelectionChanged();
Jeremy Bullock 1cf798
  }
Shinya Kitaoka 120a6e
  DecreaseStepUndo *undo = new DecreaseStepUndo(m_range.m_r0, m_range.m_c0,
Shinya Kitaoka 120a6e
                                                m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (undo->m_newR1 != m_range.m_r1) {
Shinya Kitaoka 120a6e
    m_range.m_r1 = undo->m_newR1;
Shinya Kitaoka 120a6e
    TApp::instance()->getCurrentSelection()->notifySelectionChanged();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Rollup Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class RollupUndo : public TUndo {
Shinya Kitaoka 120a6e
  int m_r0, m_c0, m_r1, m_c1;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RollupUndo(int r0, int c0, int r1, int c1)
Shinya Kitaoka 120a6e
      : m_r0(r0), m_c0(c0), m_r1(r1), m_c1(c1) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override {
Shinya Kitaoka 120a6e
    TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
    TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    xsh->rollupCells(m_r0, m_c0, m_r1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    app->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void undo() const override {
Shinya Kitaoka 120a6e
    TApp *app    = TApp::instance();
Shinya Kitaoka 120a6e
    TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    xsh->rolldownCells(m_r0, m_c0, m_r1, m_c1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
    app->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  int getSize() const override { return sizeof(*this); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Roll Up"); }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::rollupCells() {
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new RollupUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Rolldown Cells  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class RolldownUndo final : public RollupUndo {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  RolldownUndo(int r0, int c0, int r1, int c1) : RollupUndo(r0, c0, r1, c1) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  void redo() const override { RollupUndo::undo(); }
Shinya Kitaoka 473e70
  void undo() const override { RollupUndo::redo(); }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  QString getHistoryString() override { return QObject::tr("Roll Down"); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::rolldownCells() {
Shinya Kitaoka 120a6e
  TUndo *undo =
Shinya Kitaoka 120a6e
      new RolldownUndo(m_range.m_r0, m_range.m_c0, m_range.m_r1, m_range.m_c1);
Shinya Kitaoka 120a6e
  TUndoManager::manager()->add(undo);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  undo->redo();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Set Keyframes  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::setKeyframes() {
Shinya Kitaoka 120a6e
  if (isEmpty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Preliminary data-fetching
Shinya Kitaoka 120a6e
  TApp *app = TApp::instance();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXsheetHandle *xshHandle = app->getCurrentXsheet();
Shinya Kitaoka 120a6e
  TXsheet *xsh             = xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int row = m_range.m_r0, col = m_range.m_c0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TXshCell &cell = xsh->getCell(row, col);
Shinya Kitaoka 120a6e
  if (cell.getSoundLevel() || cell.getSoundTextLevel()) return;
Toshihiro Shimizu 890ddd
John Dancel 421acd
  const TStageObjectId &id =
John Dancel c323ac
      col >= 0 ? TStageObjectId::ColumnId(col)
John Dancel c323ac
               : TStageObjectId::CameraId(xsh->getCameraColumnIndex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObject *obj = xsh->getStageObject(id);
Shinya Kitaoka 120a6e
  if (!obj) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Command body
Shinya Kitaoka 120a6e
  if (obj->isFullKeyframe(row)) {
Shinya Kitaoka 120a6e
    const TStageObject::Keyframe &key = obj->getKeyframe(row);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    UndoRemoveKeyFrame *undo = new UndoRemoveKeyFrame(id, row, key, xshHandle);
Shinya Kitaoka 120a6e
    undo->setObjectHandle(app->getCurrentObject());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(undo);
Shinya Kitaoka 120a6e
    undo->redo();
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    UndoSetKeyFrame *undo = new UndoSetKeyFrame(id, row, xshHandle);
Shinya Kitaoka 120a6e
    undo->setObjectHandle(app->getCurrentObject());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TUndoManager::manager()->add(undo);
Shinya Kitaoka 120a6e
    undo->redo();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TApp::instance()->getCurrentScene()->setDirtyFlag(
Shinya Kitaoka 120a6e
      true);  // Should be moved inside the undos!
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
//    Clone Level  command
Toshihiro Shimizu 890ddd
//*********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class CloneLevelUndo final : public TUndo {
Shinya Kitaoka 120a6e
  typedef std::map<txshsimplelevel *,="" txshlevelp=""> InsertedLevelsMap;</txshsimplelevel>
Shinya Kitaoka 120a6e
  typedef std::set<int> InsertedColumnsSet;</int>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  struct ExistsFunc;
Shinya Kitaoka 120a6e
  class LevelNamePopup;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  TCellSelection::Range m_range;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  mutable InsertedLevelsMap m_insertedLevels;
Shinya Kitaoka 120a6e
  mutable InsertedColumnsSet m_insertedColumns;
Shinya Kitaoka 120a6e
  mutable bool m_clonedLevels;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  mutable bool m_ok;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  CloneLevelUndo(const TCellSelection::Range &range)
Shinya Kitaoka 120a6e
      : m_range(range), m_clonedLevels(false), m_ok(false) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  void redo() const override;
Shinya Kitaoka 473e70
  void undo() const override;
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  int getSize() const override {
manongjohn f2da01
    return sizeof *this +
manongjohn f2da01
           (sizeof(TXshLevelP) + sizeof(TXshSimpleLevel *)) *
manongjohn f2da01
               m_insertedLevels.size();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString getHistoryString() override {
Shinya Kitaoka 120a6e
    if (m_insertedLevels.empty()) return QString();
Shinya Kitaoka 120a6e
    QString str;
Shinya Kitaoka 120a6e
    if (m_insertedLevels.size() == 1) {
Shinya Kitaoka 120a6e
      str = QObject::tr("Clone  Level : %1 > %2")
Shinya Kitaoka 120a6e
                .arg(QString::fromStdWString(
Shinya Kitaoka 120a6e
                    m_insertedLevels.begin()->first->getName()))
Shinya Kitaoka 120a6e
                .arg(QString::fromStdWString(
Shinya Kitaoka 120a6e
                    m_insertedLevels.begin()->second->getName()));
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      str = QObject::tr("Clone  Levels : ");
Shinya Kitaoka 120a6e
      std::map<txshsimplelevel *,="" txshlevelp="">::const_iterator it =</txshsimplelevel>
Shinya Kitaoka 120a6e
          m_insertedLevels.begin();
Shinya Kitaoka 120a6e
      for (; it != m_insertedLevels.end(); ++it) {
Shinya Kitaoka 120a6e
        str += QString("%1 > %2, ")
Shinya Kitaoka 120a6e
                   .arg(QString::fromStdWString(it->first->getName()))
Shinya Kitaoka 120a6e
                   .arg(QString::fromStdWString(it->second->getName()));
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    return str;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 473e70
  int getHistoryType() override { return HistoryType::Xsheet; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  TXshSimpleLevel *cloneLevel(const TXshSimpleLevel *srcSl,
Shinya Kitaoka 120a6e
                              const TFilePath &dstPath,
Shinya Kitaoka 120a6e
                              const std::set<tframeid> &frames) const;</tframeid>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool chooseLevelName(TFilePath &fp) const;
Shinya Kitaoka 120a6e
  bool chooseOverwrite(OverwriteDialog *dialog, TFilePath &dstPath,
Shinya Kitaoka 120a6e
                       TXshSimpleLevel *&dstSl) const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  void cloneLevels() const;
Shinya Kitaoka 120a6e
  void insertLevels() const;
Shinya Kitaoka 120a6e
  void insertCells() const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
struct CloneLevelUndo::ExistsFunc final : public OverwriteDialog::ExistsFunc {
Shinya Kitaoka 120a6e
  ToonzScene *m_scene;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ExistsFunc(ToonzScene *scene) : m_scene(scene) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  QString conflictString(const TFilePath &fp) const override {
Shinya Kitaoka 120a6e
    return OverwriteDialog::tr(
Shinya Kitaoka 120a6e
               "Level \"%1\" already exists.\n\nWhat do you want to do?")
Shinya Kitaoka 120a6e
        .arg(QString::fromStdWString(fp.withoutParentDir().getWideString()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
  bool operator()(const TFilePath &fp) const override {
Shinya Kitaoka 120a6e
    return TSystem::doesExistFileOrLevel(fp) ||
Shinya Kitaoka 120a6e
           m_scene->getLevelSet()->getLevel(*m_scene, fp);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class CloneLevelUndo::LevelNamePopup final : public DVGui::Dialog {
Shinya Kitaoka 120a6e
  DVGui::LineEdit *m_name;
Shinya Kitaoka 120a6e
  QPushButton *m_ok, *m_cancel;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  LevelNamePopup(const std::wstring &defaultLevelName)
Shinya Kitaoka 120a6e
      : DVGui::Dialog(TApp::instance()->getMainWindow(), true, true,
Shinya Kitaoka 120a6e
                      "Clone Level") {
shun-iwasawa 199e29
    setWindowTitle(
shun-iwasawa 199e29
        QObject::tr("Clone Level", "CloneLevelUndo::LevelNamePopup"));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    beginHLayout();
Toshihiro Shimizu 890ddd
shun-iwasawa 199e29
    QLabel *label = new QLabel(
shun-iwasawa 199e29
        QObject::tr("Level Name:", "CloneLevelUndo::LevelNamePopup"));
Shinya Kitaoka 120a6e
    addWidget(label);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_name = new DVGui::LineEdit;
Shinya Kitaoka 120a6e
    addWidget(m_name);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_name->setText(QString::fromStdWString(defaultLevelName));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    endHLayout();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_ok     = new QPushButton(QObject::tr("Ok"));
Shinya Kitaoka 120a6e
    m_cancel = new QPushButton(QObject::tr("Cancel"));
Shinya Kitaoka 120a6e
    addButtonBarWidget(m_ok, m_cancel);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    m_ok->setDefault(true);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    connect(m_ok, SIGNAL(clicked()), this, SLOT(accept()));
Shinya Kitaoka 120a6e
    connect(m_cancel, SIGNAL(clicked()), this, SLOT(reject()));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QString getName() const { return m_name->text(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshSimpleLevel *CloneLevelUndo::cloneLevel(
Shinya Kitaoka 120a6e
    const TXshSimpleLevel *srcSl, const TFilePath &dstPath,
Shinya Kitaoka 120a6e
    const std::set<tframeid> &frames) const {</tframeid>
Shinya Kitaoka 120a6e
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int levelType = srcSl->getType();
Shinya Kitaoka 120a6e
  assert(levelType > 0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const std::wstring &dstName = dstPath.getWideName();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *dstSl =
Shinya Kitaoka 120a6e
      scene->createNewLevel(levelType, dstName)->getSimpleLevel();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(dstSl);
Shinya Kitaoka 120a6e
  dstSl->setPath(scene->codeFilePath(dstPath));
Shinya Kitaoka 120a6e
  dstSl->setName(dstName);
Shinya Kitaoka 120a6e
  dstSl->clonePropertiesFrom(srcSl);
Shinya Kitaoka 120a6e
  *dstSl->getHookSet() = *srcSl->getHookSet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (levelType == TZP_XSHLEVEL || levelType == PLI_XSHLEVEL) {
Shinya Kitaoka 120a6e
    TPalette *palette = srcSl->getPalette();
Shinya Kitaoka 120a6e
    assert(palette);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    dstSl->setPalette(palette->clone());
shun_iwasawa 3fc880
    dstSl->getPalette()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // The level clone shell was created. Now, clone the associated frames found
Shinya Kitaoka 120a6e
  // in the selection
Shinya Kitaoka 120a6e
  std::set<tframeid>::const_iterator ft, fEnd(frames.end());</tframeid>
Shinya Kitaoka 120a6e
  for (ft = frames.begin(); ft != fEnd; ++ft) {
Shinya Kitaoka 120a6e
    const TFrameId &fid = *ft;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    TImageP img = srcSl->getFullsampledFrame(*ft, ImageManager::dontPutInCache);
Shinya Kitaoka 120a6e
    if (!img) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    dstSl->setFrame(*ft, img->cloneImage());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
shun_iwasawa 3fc880
  dstSl->setDirtyFlag(true);
shun_iwasawa 3fc880
Shinya Kitaoka 120a6e
  return dstSl;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool CloneLevelUndo::chooseLevelName(TFilePath &fp) const {
Shinya Kitaoka 2a7129
  std::unique_ptr<levelnamepopup> levelNamePopup(</levelnamepopup>
Shinya Kitaoka 120a6e
      new LevelNamePopup(fp.getWideName()));
Shinya Kitaoka 120a6e
  if (levelNamePopup->exec() == QDialog::Accepted) {
Shinya Kitaoka 120a6e
    const QString &levelName = levelNamePopup->getName();
Toshihiro Shimizu 890ddd
manongjohn 7f3150
    if (isValidFileName_message(levelName) &&
manongjohn 7f3150
        !isReservedFileName_message(levelName)) {
Shinya Kitaoka 120a6e
      fp = fp.withName(levelName.toStdWString());
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool CloneLevelUndo::chooseOverwrite(OverwriteDialog *dialog,
Shinya Kitaoka 120a6e
                                     TFilePath &dstPath,
Shinya Kitaoka 120a6e
                                     TXshSimpleLevel *&dstSl) const {
Shinya Kitaoka 120a6e
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
Shinya Kitaoka 120a6e
  ExistsFunc exists(scene);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  OverwriteDialog::Resolution acceptedRes = OverwriteDialog::ALL_RESOLUTIONS;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshLevel *xl = scene->getLevelSet()->getLevel(*scene, dstPath);
Shinya Kitaoka 120a6e
  if (xl)
Shinya Kitaoka 120a6e
    acceptedRes =
Shinya Kitaoka 120a6e
        OverwriteDialog::Resolution(acceptedRes & ~OverwriteDialog::OVERWRITE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Apply user's decision
Shinya Kitaoka 120a6e
  switch (dialog->execute(dstPath, exists, acceptedRes,
Shinya Kitaoka 120a6e
                          OverwriteDialog::APPLY_TO_ALL_FLAG)) {
Shinya Kitaoka 120a6e
  default:
Shinya Kitaoka 120a6e
    return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  case OverwriteDialog::KEEP_OLD:
Shinya Kitaoka 120a6e
    // Load the level at the preferred clone path
Shinya Kitaoka 120a6e
    if (!xl) xl = scene->loadLevel(dstPath);  // Hard load - from disk
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    assert(xl);
Shinya Kitaoka 120a6e
    dstSl = xl->getSimpleLevel();
Shinya Kitaoka 120a6e
    break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  case OverwriteDialog::OVERWRITE:
Shinya Kitaoka 120a6e
    assert(!xl);
Shinya Kitaoka 120a6e
    break;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  case OverwriteDialog::RENAME:
Shinya Kitaoka 120a6e
    break;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CloneLevelUndo::cloneLevels() const {
Shinya Kitaoka 120a6e
  TApp *app         = TApp::instance();
Shinya Kitaoka 120a6e
  ToonzScene *scene = app->getCurrentScene()->getScene();
Shinya Kitaoka 120a6e
  TXsheet *xsh      = app->getCurrentXsheet()->getXsheet();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the simple levels and associated frames in the specified range
Shinya Kitaoka 120a6e
  typedef std::set<tframeid> FramesSet;</tframeid>
Shinya Kitaoka 120a6e
  typedef std::map<txshsimplelevel *,="" framesset=""> LevelsMap;</txshsimplelevel>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  LevelsMap levels;
Shinya Kitaoka 120a6e
  getSelectedFrames(*xsh, m_range.m_r0, m_range.m_c0, m_range.m_r1,
Shinya Kitaoka 120a6e
                    m_range.m_c1, levels);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (!levels.empty()) {
Shinya Kitaoka 120a6e
    bool askCloneName = (levels.size() == 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Now, try to clone every found level in the associated range
Shinya Kitaoka 2a7129
    std::unique_ptr<overwritedialog> dialog;</overwritedialog>
Shinya Kitaoka 120a6e
    ExistsFunc exists(scene);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    LevelsMap::iterator lt, lEnd(levels.end());
Shinya Kitaoka 120a6e
    for (lt = levels.begin(); lt != lEnd; ++lt) {
Shinya Kitaoka 120a6e
      assert(lt->first && !lt->second.empty());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      TXshSimpleLevel *srcSl = lt->first;
justburner b375f4
      if (srcSl->getPath().isUneditable())
manongjohn f2da01
        continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      const TFilePath &srcPath = srcSl->getPath();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Build the destination level data
Shinya Kitaoka 120a6e
      TXshSimpleLevel *dstSl = 0;
Shinya Kitaoka 120a6e
      TFilePath dstPath      = scene->decodeFilePath(
Shinya Kitaoka 120a6e
          srcPath.withName(srcPath.getWideName() + L"_clone"));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Ask user to suggest an appropriate level name
Shinya Kitaoka 120a6e
      if (askCloneName && !chooseLevelName(dstPath)) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // Get a unique level path
Shinya Kitaoka 120a6e
      if (exists(dstPath)) {
Shinya Kitaoka 120a6e
        // Ask user for action
Shinya Kitaoka 120a6e
        if (!dialog.get()) dialog.reset(new OverwriteDialog);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        if (!chooseOverwrite(dialog.get(), dstPath, dstSl)) continue;
Shinya Kitaoka 120a6e
      }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      // If the destination level was not retained from existing data, it must
Shinya Kitaoka 120a6e
      // be created and cloned
Shinya Kitaoka 120a6e
      if (!dstSl) dstSl = cloneLevel(srcSl, dstPath, lt->second);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      assert(dstSl);
Shinya Kitaoka 120a6e
      m_insertedLevels[srcSl] = dstSl;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CloneLevelUndo::insertLevels() const {
Shinya Kitaoka 120a6e
  ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  InsertedLevelsMap::iterator lt, lEnd = m_insertedLevels.end();
Shinya Kitaoka 120a6e
  for (lt = m_insertedLevels.begin(); lt != lEnd; ++lt)
Shinya Kitaoka 120a6e
    scene->getLevelSet()->insertLevel(lt->second.getPointer());
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CloneLevelUndo::insertCells() const {
Shinya Kitaoka 120a6e
  TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_insertedColumns.clear();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If necessary, insert blank columns AFTER the columns range.
Shinya Kitaoka 120a6e
  // Remember the indices of inserted columns, too.
Shinya Kitaoka 120a6e
  for (int c = 1; c <= m_range.getColCount(); ++c) {
Shinya Kitaoka 120a6e
    int colIndex = m_range.m_c1 + c;
Shinya Kitaoka 120a6e
    if (xsh->isColumnEmpty(
Shinya Kitaoka 120a6e
            colIndex))  // If there already is a hole, no need to insert -
Shinya Kitaoka 120a6e
      continue;         // we'll just use it.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    xsh->insertColumn(colIndex);
Shinya Kitaoka 120a6e
    m_insertedColumns.insert(colIndex);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, re-traverse the selected range, and add corresponding cells
Shinya Kitaoka 120a6e
  // in the destination range
Shinya Kitaoka 120a6e
  for (int c = m_range.m_c0; c <= m_range.m_c1; ++c) {
Shinya Kitaoka 120a6e
    for (int r = m_range.m_r0; r <= m_range.m_r1; ++r) {
Shinya Kitaoka 120a6e
      const TXshCell &srcCell = xsh->getCell(r, c);
Shinya Kitaoka 120a6e
      if (TXshSimpleLevel *srcSl = srcCell.getSimpleLevel()) {
Shinya Kitaoka 120a6e
        std::map<txshsimplelevel *,="" txshlevelp="">::iterator lt =</txshsimplelevel>
Shinya Kitaoka 120a6e
            m_insertedLevels.find(srcSl);
Shinya Kitaoka 120a6e
        if (lt != m_insertedLevels.end()) {
Shinya Kitaoka 120a6e
          TXshCell dstCell(lt->second, srcCell.getFrameId());
Shinya Kitaoka 120a6e
          xsh->setCell(r, c + m_range.getColCount(), dstCell);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CloneLevelUndo::redo() const {
Shinya Kitaoka 120a6e
  if (m_clonedLevels)
Shinya Kitaoka 120a6e
    insertLevels();
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    m_clonedLevels = true;
Shinya Kitaoka 120a6e
    cloneLevels();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_insertedLevels.empty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Command succeeded, let's deal with the xsheet
Shinya Kitaoka 120a6e
  m_ok = true;
Shinya Kitaoka 120a6e
  insertCells();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Finally, emit notifications
Shinya Kitaoka 120a6e
  TApp *app = TApp::instance();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  app->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  app->getCurrentScene()->notifyCastChange();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void CloneLevelUndo::undo() const {
Shinya Kitaoka 120a6e
  assert(!m_insertedLevels.empty());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TApp *app         = TApp::instance();
Shinya Kitaoka 120a6e
  ToonzScene *scene = app->getCurrentScene()->getScene();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXsheet *xsh    = scene->getXsheet();
Shinya Kitaoka 120a6e
  TXsheet *topXsh = scene->getChildStack()->getTopXsheet();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Erase inserted columns from the xsheet
Shinya Kitaoka 120a6e
  for (int i = m_range.getColCount(); i > 0; --i) {
Shinya Kitaoka 120a6e
    int index                        = m_range.m_c1 + i;
Shinya Kitaoka 120a6e
    std::set<int>::const_iterator it = m_insertedColumns.find(index);</int>
Shinya Kitaoka 120a6e
    xsh->removeColumn(index);
Shinya Kitaoka 120a6e
    if (it == m_insertedColumns.end()) xsh->insertColumn(index);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Attempt removal of inserted columns from the cast
Shinya Kitaoka 120a6e
  // NOTE: Cloned levels who were KEEP_OLD'd may have already been present in
Shinya Kitaoka 120a6e
  // the cast
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<txshsimplelevel *,="" txshlevelp="">::const_iterator lt,</txshsimplelevel>
Shinya Kitaoka 120a6e
      lEnd = m_insertedLevels.end();
Shinya Kitaoka 120a6e
  for (lt = m_insertedLevels.begin(); lt != lEnd; ++lt) {
Shinya Kitaoka 120a6e
    if (!topXsh->isLevelUsed(lt->second.getPointer()))
Shinya Kitaoka 120a6e
      scene->getLevelSet()->removeLevel(lt->second.getPointer());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  app->getCurrentXsheet()->notifyXsheetChanged();
Shinya Kitaoka 120a6e
  app->getCurrentScene()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  app->getCurrentScene()->notifyCastChange();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCellSelection::cloneLevel() {
Shinya Kitaoka 2a7129
  std::unique_ptr<clonelevelundo> undo(new CloneLevelUndo(m_range));</clonelevelundo>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (undo->redo(), undo->m_ok) TUndoManager::manager()->add(undo.release());
Toshihiro Shimizu 890ddd
}
manongjohn b248d8
manongjohn b248d8
//=============================================================================
manongjohn b248d8
manongjohn b248d8
void TCellSelection::shiftKeyframes(int direction) {
manongjohn b248d8
  if (isEmpty() || areAllColSelectedLocked()) return;
manongjohn b248d8
manongjohn b248d8
  int shift = m_range.getRowCount() * direction;
manongjohn b248d8
  if (!shift) return;
manongjohn b248d8
manongjohn b248d8
  TXsheetHandle *xsheet = TApp::instance()->getCurrentXsheet();
manongjohn b248d8
  TXsheet *xsh          = xsheet->getXsheet();
manongjohn b248d8
  TCellKeyframeSelection *cellKeyframeSelection = new TCellKeyframeSelection(
manongjohn b248d8
      new TCellSelection(), new TKeyframeSelection());
manongjohn b248d8
manongjohn b248d8
  cellKeyframeSelection->setXsheetHandle(xsheet);
manongjohn b248d8
manongjohn b248d8
  TUndoManager::manager()->beginBlock();
manongjohn b248d8
  for (int col = m_range.m_c0; col <= m_range.m_c1; col++) {
manongjohn b248d8
    TXshColumn *column = xsh->getColumn(col);
manongjohn b248d8
    if (!column || column->isLocked()) continue;
manongjohn b248d8
manongjohn b248d8
    TStageObjectId colId =
manongjohn b248d8
        col < 0 ? TStageObjectId::ColumnId(xsh->getCameraColumnIndex())
manongjohn b248d8
                : TStageObjectId::ColumnId(col);
manongjohn b248d8
    TStageObject *colObj = xsh->getStageObject(colId);
manongjohn b248d8
    TStageObject::KeyframeMap keyframes;
manongjohn b248d8
    colObj->getKeyframes(keyframes);
manongjohn b248d8
    if (!keyframes.size()) continue;
manongjohn b248d8
    int row = m_range.m_r0;
manongjohn b248d8
    for (TStageObject::KeyframeMap::iterator it = keyframes.begin();
manongjohn b248d8
         it != keyframes.end(); it++) {
manongjohn b248d8
      if (it->first < m_range.m_r0) continue;
manongjohn b248d8
      row = it->first;
manongjohn b248d8
      cellKeyframeSelection->selectCellsKeyframes(row, col,
manongjohn b248d8
                                                  xsh->getFrameCount(), col);
manongjohn b248d8
      cellKeyframeSelection->getKeyframeSelection()->shiftKeyframes(
manongjohn b248d8
          row, row + shift, col, col);
manongjohn b248d8
      break;
manongjohn b248d8
    }
manongjohn b248d8
  }
manongjohn b248d8
  TUndoManager::manager()->endBlock();
manongjohn b248d8
manongjohn b248d8
  delete cellKeyframeSelection;
manongjohn b248d8
}