Spreadsheet: fix range selection
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user