diff --git a/src/Mod/Spreadsheet/App/PropertySheet.cpp b/src/Mod/Spreadsheet/App/PropertySheet.cpp index 7f73663540..cef6b26087 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.cpp +++ b/src/Mod/Spreadsheet/App/PropertySheet.cpp @@ -44,6 +44,7 @@ #include #include #include + FC_LOG_LEVEL_INIT("Spreadsheet", true, true) using namespace App; @@ -368,45 +369,124 @@ void PropertySheet::copyCells(Base::Writer& writer, const std::vector& ra writer.Stream() << "" << std::endl; } -void PropertySheet::pasteCells(XMLReader& reader, const CellAddress& addr) { - AtomicPropertyChange signaller(*this); - - bool first = true; - int roffset = 0, coffset = 0; - +void PropertySheet::pasteCells(XMLReader &reader, Range dstRange) { reader.readElement("Cells"); - for (int rangeCount = reader.getAttributeAsInteger("count"); rangeCount > 0; --rangeCount) { + int rangeCount = reader.getAttributeAsInteger("count"); + if(rangeCount<=0) + return; + + int dstRows = dstRange.rowCount(); + int dstCols = dstRange.colCount(); + CellAddress dstFrom = dstRange.from(); + + int roffset,coffset; + + AtomicPropertyChange signaller(*this); + for(int ri=0; ri < rangeCount; ++ri) { reader.readElement("Range"); CellAddress from(reader.getAttribute("from")); CellAddress to(reader.getAttribute("to")); - Range range(from, to); - for (int cellCount = reader.getAttributeAsInteger("count"); cellCount > 0; --cellCount) { - if (first) { - first = false; - roffset = addr.row() - from.row(); - coffset = addr.col() - from.col(); - } + int cellCount = reader.getAttributeAsInteger("count"); + + Range range(from,to); + + CellAddress addr(dstFrom); + if(!ri) { + roffset = addr.row() - from.row(); + coffset = addr.col() - from.col(); + } + + int rcount,ccount; + if(rangeCount>1) { + rcount = 1; + ccount = 1; + } else { + rcount = dstRows/range.rowCount(); + if(!rcount) + rcount = 1; + ccount = dstCols/range.colCount(); + if(!ccount) + ccount = 1; + } + for(int ci=0; ci < cellCount; ++ci) { reader.readElement("Cell"); CellAddress src(reader.getAttribute("address")); - CellAddress dst(src.row() + roffset, src.col() + coffset); - owner->clear(dst); - owner->cellUpdated(dst); - auto cell = owner->getNewCell(dst); - cell->setSpans(-1, -1); - cell->restore(reader, true); - int rows, cols; - if (cell->getSpans(rows, cols) && (rows > 1 || cols > 1)) - mergeCells(dst, CellAddress(dst.row() + rows - 1, dst.col() + cols - 1)); + if(ci) + range.next(); - if (roffset || coffset) { - OffsetCellsExpressionVisitor visitor(*this, roffset, coffset); - cell->visit(visitor); - if (visitor.changed()) - recomputeDependencies(dst); + while(src!=*range) { + for(int r=0; r < rcount; ++r) { + for(int c=0; c < ccount; ++c) { + CellAddress dst(range.row()+roffset+r*range.rowCount(), + range.column()+coffset+c*range.colCount()); + if(!dst.isValid()) + continue; + owner->clear(dst); + owner->cellUpdated(dst); + } + } + range.next(); } - dirty.insert(dst); - owner->cellUpdated(dst); + + CellAddress newCellAddr; + for(int r=0; r < rcount; ++r) { + for(int c=0; c < ccount; ++c) { + CellAddress dst(src.row()+roffset+r*range.rowCount(), + src.col()+coffset+c*range.colCount()); + if(!dst.isValid()) + continue; + + auto cell = owner->getNewCell(dst); + cell->setSpans(-1,-1); + + int roffset_cur, coffset_cur; + if(!newCellAddr.isValid()) { + roffset_cur = roffset; + coffset_cur = coffset; + newCellAddr = dst; + cell->restore(reader,true); + } else { + roffset_cur = r*range.rowCount(); + coffset_cur = c*range.colCount(); + auto newCell = owner->getCell(newCellAddr); + const Expression *expr; + if(!newCell || !(expr=newCell->getExpression(true))) { + FC_THROWM(Base::RuntimeError, "Failed to copy cell " + << getFullName() << '.' << dst.toString() + << " from " << newCellAddr.toString()); + } + cell->setExpression(ExpressionPtr(expr->copy())); + } + + int rows, cols; + if (cell->getSpans(rows, cols) && (rows > 1 || cols > 1)) + mergeCells(dst, CellAddress(dst.row() + rows - 1, dst.col() + cols - 1)); + + if(roffset_cur || coffset_cur) { + OffsetCellsExpressionVisitor visitor(*this, roffset_cur, coffset_cur); + cell->visit(visitor); + if(visitor.changed()) + recomputeDependencies(dst); + } + dirty.insert(dst); + owner->cellUpdated(dst); + } + } + } + if(!cellCount || range.next()) { + do { + for(int r=0; r < rcount; ++r) { + for(int c=0; c < ccount; ++c) { + CellAddress dst(range.row()+roffset+r*range.rowCount(), + range.column()+coffset+c*range.colCount()); + if(!dst.isValid()) + continue; + owner->clear(dst); + owner->cellUpdated(dst); + } + } + }while(range.next()); } } signaller.tryInvoke(); diff --git a/src/Mod/Spreadsheet/App/PropertySheet.h b/src/Mod/Spreadsheet/App/PropertySheet.h index 60694b85b5..a98fee3087 100644 --- a/src/Mod/Spreadsheet/App/PropertySheet.h +++ b/src/Mod/Spreadsheet/App/PropertySheet.h @@ -74,7 +74,7 @@ public: void copyCells(Base::Writer &writer, const std::vector &ranges) const; - void pasteCells(Base::XMLReader &reader, const App::CellAddress &addr); + void pasteCells(Base::XMLReader &reader, App::Range dstRange); Cell *createCell(App::CellAddress address); diff --git a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp index d5f079138e..b77e0d12a4 100644 --- a/src/Mod/Spreadsheet/Gui/SheetTableView.cpp +++ b/src/Mod/Spreadsheet/Gui/SheetTableView.cpp @@ -597,18 +597,16 @@ void SheetTableView::pasteClipboard() if(!mimeData || !mimeData->hasText()) return; - if(selectionModel()->selectedIndexes().size()>1) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Spreadsheet"), - QObject::tr("Spreadsheet does not support range selection when pasting.\n" - "Please select one cell only.")); + auto ranges = selectedRanges(); + if(ranges.empty()) return; - } - QModelIndex current = currentIndex(); + Range range = ranges.back(); App::AutoTransaction committer("Paste cell"); try { if (!mimeData->hasFormat(_SheetMime)) { + CellAddress current = range.from(); QStringList cells; QString text = mimeData->text(); int i=0; @@ -616,7 +614,7 @@ void SheetTableView::pasteClipboard() QStringList cols = it.split(QLatin1Char('\t')); int j=0; for (auto jt : cols) { - QModelIndex index = model()->index(current.row()+i, current.column()+j); + QModelIndex index = model()->index(current.row()+i, current.col()+j); model()->setData(index, jt); j++; } @@ -628,7 +626,7 @@ void SheetTableView::pasteClipboard() std::istream in(0); in.rdbuf(&buf); Base::XMLReader reader("", in); - sheet->getCells()->pasteCells(reader,CellAddress(current.row(),current.column())); + sheet->getCells()->pasteCells(reader,range); } GetApplication().getActiveDocument()->recompute(); @@ -637,7 +635,9 @@ void SheetTableView::pasteClipboard() e.ReportException(); QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Copy & Paste failed"), QString::fromLatin1(e.what())); + return; } + clearSelection(); } void SheetTableView::finishEditWithMove(int keyPressed, Qt::KeyboardModifiers modifiers, bool handleTabMotion)