From 5e2a8ff2326c85e4a8eed8e9ff6c69dd6814922c Mon Sep 17 00:00:00 2001 From: shun-iwasawa Date: Aug 19 2016 09:31:00 +0000 Subject: Improvement of direct inputting feature in Xsheet (#722) * improve xsheet direct input * small fix --- diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 6774dcf..b73a4d4 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -15,6 +15,7 @@ // TnzTools includes #include "tools/toolutils.h" +#include "tools/toolhandle.h" // TnzQt includes #include "toonzqt/strokesdata.h" @@ -44,6 +45,7 @@ #include "toonz/toonzimageutils.h" #include "toonz/trasterimageutils.h" #include "toonz/levelset.h" +#include "toonz/tstageobjecttree.h" // TnzCore includes #include "timagecache.h" @@ -1030,6 +1032,94 @@ public: }; //----------------------------------------------------------------------------- +// if at least one of the cell in the range, return false +bool checkIfCellsHaveTheSameContent(int &r0, int &c0, int &r1, int &c1, + TXshCell &cell) { + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + for (int c = c0; c <= c1; c++) { + for (int r = r0; r <= r1; r++) { + if (cell != xsh->getCell(r, c)) return false; + } + } + return true; +} + +void renameCellsWithoutUndo(int &r0, int &c0, int &r1, int &c1, + const TXshCell &cell) { + TApp *app = TApp::instance(); + TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); + for (int c = c0; c <= c1; c++) { + for (int r = r0; r <= r1; r++) { + xsh->setCell(r, c, TXshCell(cell)); + } + } + app->getCurrentXsheet()->notifyXsheetChanged(); + int currentFrame = app->getCurrentFrame()->getFrame(); + if (r0 <= currentFrame && currentFrame <= r1) { + app->getCurrentTool()->onImageChanged( + (TImage::Type)app->getCurrentImageType()); + xsh->getStageObjectTree()->invalidateAll(); + } +} + +class RenameCellsUndo final : public TUndo { + TCellSelection *m_selection; + QMimeData *m_data; + TXshCell m_cell; + +public: + RenameCellsUndo(TCellSelection *selection, QMimeData *data, TXshCell &cell) + : m_data(data), m_cell(cell) { + int r0, c0, r1, c1; + selection->getSelectedCells(r0, c0, r1, c1); + m_selection = new TCellSelection(); + m_selection->selectCells(r0, c0, r1, c1); + } + + ~RenameCellsUndo() { + delete m_selection; + delete m_data; + } + + void undo() const override { + int r0, c0, r1, c1; + m_selection->getSelectedCells(r0, c0, r1, c1); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + for (int c = c0; c <= c1; c++) { + xsh->clearCells(r0, c, r1 - r0 + 1); + } + const TCellData *cellData = dynamic_cast(m_data); + pasteCellsWithoutUndo(cellData, r0, c0, r1, c1, false, false); + TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); + } + + void redo() const override { + int r0, c0, r1, c1; + m_selection->getSelectedCells(r0, c0, r1, c1); + renameCellsWithoutUndo(r0, c0, r1, c1, m_cell); + } + + int getSize() const override { return sizeof(*this); } + + QString getHistoryString() override { + int r0, c0, r1, c1; + m_selection->getSelectedCells(r0, c0, r1, c1); + QString colRange = QString::number(c0 + 1); + if (c0 != c1) + colRange.append(QString(" - %1").arg(QString::number(c1 + 1))); + QString frameRange = QString::number(r0 + 1); + if (r0 != r1) + frameRange.append(QString(" - %1").arg(QString::number(r1 + 1))); + + return QObject::tr("Rename Cell at Column %1 Frame %2") + .arg(colRange) + .arg(frameRange); + } + + int getHistoryType() override { return HistoryType::Xsheet; } +}; + +//----------------------------------------------------------------------------- } // namespace //----------------------------------------------------------------------------- @@ -1467,10 +1557,12 @@ void TCellSelection::pasteCells() { void TCellSelection::deleteCells() { if (isEmpty()) return; - TCellData *data = new TCellData(); - TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); int r0, c0, r1, c1; getSelectedCells(r0, c0, r1, c1); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + // if all the selected cells are already empty, then do nothing + if (xsh->isRectEmpty(r0, c0, r1, c1)) return; + TCellData *data = new TCellData(); data->setCells(xsh, r0, c0, r1, c1); DeleteCellsUndo *undo = new DeleteCellsUndo(new TCellSelection(m_range), data); @@ -1942,3 +2034,21 @@ void TCellSelection::overWritePasteCells() { } //----------------------------------------------------------------------------- +// called from RenameCellField::RenameCell + +void TCellSelection::renameCells(TXshCell &cell) { + if (isEmpty()) return; + int r0, c0, r1, c1; + getSelectedCells(r0, c0, r1, c1); + // register undo only if the cell is modified + if (checkIfCellsHaveTheSameContent(r0, c0, r1, c1, cell)) return; + TCellData *data = new TCellData(); + TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); + data->setCells(xsh, r0, c0, r1, c1); + RenameCellsUndo *undo = new RenameCellsUndo(this, data, cell); + undo->redo(); + + TUndoManager::manager()->add(undo); +} + +//----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/cellselection.h b/toonz/sources/toonz/cellselection.h index c410344..9b9091d 100644 --- a/toonz/sources/toonz/cellselection.h +++ b/toonz/sources/toonz/cellselection.h @@ -8,6 +8,7 @@ #include class TimeStretchPopup; +class TXshCell; //============================================================================= // TCellSelection @@ -97,6 +98,8 @@ public: void reframe2Cells() { reframeCells(2); } void reframe3Cells() { reframeCells(3); } void reframe4Cells() { reframeCells(4); } + + void renameCells(TXshCell &cell); }; #endif // TCELLSELECTION_H diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index a02b533..7f281d1 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -599,15 +599,20 @@ void RenameCellField::renameCell() { // rinomino in 2. Quindi devo prima verificare // che la cella corrente non sia vuota - TXshCell cell = xsheet->getCell(m_row, m_col); - if (cell.isEmpty() && m_row > 0) { - cell = xsheet->getCell(m_row - 1, m_col); + TXshCell cell; + int tmpRow = m_row; + while (1) { + cell = xsheet->getCell(tmpRow, m_col); + if (!cell.isEmpty() || tmpRow == 0) break; + tmpRow--; } xl = cell.m_level.getPointer(); if (!xl || (xl->getType() == OVL_XSHLEVEL && xl->getPath().getFrame() == TFrameId::NO_FRAME)) return; - if (fid == TFrameId::NO_FRAME) fid = cell.m_frameId; + // if the next upper cell is empty, then make this cell empty too + if (fid == TFrameId::NO_FRAME) + fid = (m_row - tmpRow <= 1) ? cell.m_frameId : TFrameId(0); } else { ToonzScene *scene = m_viewer->getXsheet()->getScene(); TLevelSet *levelSet = scene->getLevelSet(); @@ -625,29 +630,37 @@ void RenameCellField::renameCell() { } } if (!xl) return; + + TCellSelection *cellSelection = dynamic_cast( + TApp::instance()->getCurrentSelection()->getSelection()); + if (!cellSelection) return; + TXshCell cell(xl, fid); - // register undo only if the cell is modified - if (cell == xsheet->getCell(m_row, m_col)) return; - - RenameCellUndo *undo = - new RenameCellUndo(m_row, m_col, xsheet->getCell(m_row, m_col), cell); - xsheet->setCell(m_row, m_col, cell); - TUndoManager::manager()->add(undo); - TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); - TApp *app = TApp::instance(); - if (m_row == app->getCurrentFrame()->getFrame()) { - app->getCurrentTool()->onImageChanged( - (TImage::Type)app->getCurrentImageType()); - xsheet->getStageObjectTree()->invalidateAll(); - } + if (fid.getNumber() == 0) { + TCellSelection::Range range = cellSelection->getSelectedCells(); + cellSelection->deleteCells(); + // revert cell selection + cellSelection->selectCells(range.m_r0, range.m_c0, range.m_r1, range.m_c1); + } else + cellSelection->renameCells(cell); } //----------------------------------------------------------------------------- void RenameCellField::onReturnPressed() { renameCell(); - showInRowCol(m_row + 1, m_col); + + // move the cell selection + TCellSelection *cellSelection = dynamic_cast( + TApp::instance()->getCurrentSelection()->getSelection()); + if (!cellSelection) return; + TCellSelection::Range range = cellSelection->getSelectedCells(); + int offset = range.m_r1 - range.m_r0 + 1; + cellSelection->selectCells(range.m_r0 + offset, range.m_c0, + range.m_r1 + offset, range.m_c1); + TApp::instance()->getCurrentSelection()->notifySelectionChanged(); + showInRowCol(m_row + offset, m_col); } //----------------------------------------------------------------------------- @@ -661,14 +674,30 @@ void RenameCellField::focusOutEvent(QFocusEvent *e) { //----------------------------------------------------------------------------- void RenameCellField::keyPressEvent(QKeyEvent *event) { + // move the cell selection + TCellSelection *cellSelection = dynamic_cast( + TApp::instance()->getCurrentSelection()->getSelection()); + if (!cellSelection) { + QLineEdit::keyPressEvent(event); + return; + } + TCellSelection::Range range = cellSelection->getSelectedCells(); + int offset = range.m_r1 - range.m_r0 + 1; + if (event->key() == Qt::Key_Up && m_row > 0) { renameCell(); - showInRowCol(m_row - 1, m_col); + cellSelection->selectCells(range.m_r0 - offset, range.m_c0, + range.m_r1 - offset, range.m_c1); + showInRowCol(m_row - offset, m_col); + TApp::instance()->getCurrentSelection()->notifySelectionChanged(); } else if (event->key() == Qt::Key_Down) { renameCell(); - showInRowCol(m_row + 1, m_col); - } - QLineEdit::keyPressEvent(event); + cellSelection->selectCells(range.m_r0 + offset, range.m_c0, + range.m_r1 + offset, range.m_c1); + showInRowCol(m_row + offset, m_col); + TApp::instance()->getCurrentSelection()->notifySelectionChanged(); + } else + QLineEdit::keyPressEvent(event); } //============================================================================= diff --git a/toonz/sources/toonzlib/txsheet.cpp b/toonz/sources/toonzlib/txsheet.cpp index 114ed3e..607b77a 100644 --- a/toonz/sources/toonzlib/txsheet.cpp +++ b/toonz/sources/toonzlib/txsheet.cpp @@ -1567,3 +1567,14 @@ TRectD TXsheet::getBBox(int r) const { return bbox; } + +//----------------------------------------------------------------------- + +bool TXsheet::isRectEmpty(int r0, int c0, int r1, int c1) const { + for (int r = r0; r <= r1; r++) { + for (int c = c0; c <= c1; c++) { + if (!getCell(r, c).isEmpty()) return false; + } + } + return true; +} \ No newline at end of file