Spreadsheet: fix range selection

This commit is contained in:
Zheng, Lei
2022-06-12 17:19:28 +08:00
committed by Uwe
parent 4e8dfb152d
commit 1c8c6a48af
3 changed files with 56 additions and 2 deletions

View File

@@ -1975,3 +1975,8 @@ const boost::any PropertySheet::getPathValue(const App::ObjectIdentifier & path)
return boost::any();
return path.getValue();
}
bool PropertySheet::hasSpan() const
{
return !mergedCells.empty();
}

View File

@@ -153,6 +153,8 @@ public:
void getSpans(App::CellAddress address, int &rows, int &cols) const;
bool hasSpan() const;
App::CellAddress getAnchor(App::CellAddress address) const;
bool isMergedCell(App::CellAddress address) const;

View File

@@ -250,8 +250,55 @@ void SheetTableView::cellProperties()
std::vector<Range> SheetTableView::selectedRanges() const
{
std::vector<Range> result;
for (const auto &sel : selectionModel()->selection())
result.emplace_back(sel.top(), sel.left(), sel.bottom(), sel.right());
if (!sheet->getCells()->hasSpan()) {
for (const auto &sel : selectionModel()->selection())
result.emplace_back(sel.top(), sel.left(), sel.bottom(), sel.right());
} else {
// If there is spanning cell, QItemSelection returned by
// QTableView::selection() does not merge selected indices into ranges.
// So we have to do it by ourselves. Qt records selection in the order
// of column first and then row.
//
// Note that there will always be ambiguous cases with the available
// information, where multiple user selected ranges are merged
// together. For example, consecutive single column selections that
// form a rectangle will be merged together, but single row selections
// will not be merged.
for (const auto &sel : selectionModel()->selection()) {
if (!result.empty() && sel.bottom() == sel.top() && sel.right() == sel.left()) {
auto &last = result.back();
if (last.colCount() == 1
&& last.from().col() == sel.left()
&& sel.top() == last.to().row() + 1)
{
// This is the case of rectangle selection. We keep
// accumulating the last column, and try to merge the
// column to previous range whenever possible.
last = Range(last.from(), CellAddress(sel.top(), sel.left()));
if (result.size() > 1) {
auto &secondLast = result[result.size()-2];
if (secondLast.to().col() + 1 == last.to().col()
&& secondLast.from().row() == last.from().row()
&& secondLast.rowCount() == last.rowCount()) {
secondLast = Range(secondLast.from(), last.to());
result.pop_back();
}
}
continue;
}
else if (last.rowCount() == 1
&& last.from().row() == sel.top()
&& last.to().col() + 1 == sel.left())
{
// This is the case of single row selection
last = Range(last.from(), CellAddress(sel.top(), sel.left()));
continue;
}
}
result.emplace_back(sel.top(), sel.left(), sel.bottom(), sel.right());
}
}
return result;
}