diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2021-05-03 16:17:05 +0530 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2021-05-12 10:51:49 +0200 |
commit | 31ab160dddf8d551dad8730fd3e1776986a64333 (patch) | |
tree | 6c061f244832f5fbd7f6e2c0a12347eb7ef0cb25 | |
parent | 8d1415a70c40d63d4b7873e608a386744276c2e0 (diff) |
autocomplete from superblock of str/edittext
Change-Id: Ibf73284971652c5cbd9874d81ded4a1f0cbb4e94
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115131
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-rw-r--r-- | sc/inc/column.hxx | 1 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/table.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column3.cxx | 108 | ||||
-rw-r--r-- | sc/source/core/data/documen3.cxx | 24 | ||||
-rw-r--r-- | sc/source/core/data/table3.cxx | 5 | ||||
-rw-r--r-- | sc/source/ui/app/inputhdl.cxx | 4 |
7 files changed, 142 insertions, 4 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 64485ccd5f2c..bbf9bce9be73 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -537,6 +537,7 @@ public: sc::ColumnBlockConstPosition& rBlockPos, SCROW nStartRow, SCROW nEndRow, ScFilterEntries& rFilterEntries ); + bool GetStringBlockEntries(SCROW nCursorRow, std::set<ScTypedStrData>& rStrings) const; bool GetDataEntries( SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit ) const; void UpdateInsertTabAbs(SCTAB nNewPos); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 4d385e97d0c9..aefdd253467c 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -2060,6 +2060,8 @@ public: SCTAB nTab, bool bCaseSens, ScFilterEntries& rFilterEntries ); + void GetStringBlockEntries( SCCOL nCursorCol, SCROW nCursorRow, SCTAB nTab, + std::vector<ScTypedStrData>& rStrings) const; void GetDataEntries( SCCOL nCol, SCROW nRow, SCTAB nTab, std::vector<ScTypedStrData>& rStrings, bool bLimit = false ); void GetFormulaEntries( ScTypedCaseStrSet& rStrings ); diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 8fa962081a05..437ee058f640 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -948,6 +948,8 @@ public: void GetFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, ScFilterEntries& rFilterEntries ); void GetFilteredFilterEntries(SCCOL nCol, SCROW nRow1, SCROW nRow2, const ScQueryParam& rParam, ScFilterEntries& rFilterEntries ); [[nodiscard]] + bool GetStringBlockEntries(SCCOL nCursorCol, SCROW nCursorRow, std::set<ScTypedStrData>& rStrings) const; + [[nodiscard]] bool GetDataEntries(SCCOL nCol, SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit); bool HasColHeader( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow ) const; diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index 90a0dcec43aa..4d21dd698beb 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -2525,6 +2525,7 @@ namespace { */ class StrCellIterator { +protected: typedef std::pair<sc::CellStoreType::const_iterator,size_t> PosType; PosType maPos; sc::CellStoreType::const_iterator const miBeg; @@ -2641,6 +2642,113 @@ public: } }; +/** + * Iterate over only over the super-block of string and edit-text blocks. + */ +class StrCellBlockIterator: public StrCellIterator +{ +public: + StrCellBlockIterator(const sc::CellStoreType& rCells, SCROW nStart, const ScDocument* pDoc) : + StrCellIterator(rCells, nStart, pDoc) + { + } + + bool prev() + { + // Don't go up anymore as we're on non-string block. + if (!has()) + return false; + + // We are in a string block. + if (maPos.second > 0) + { + // Move back one cell in the same block. + --maPos.second; + } + else + { + if (maPos.first == miBeg) + return false; + + // Move to the last cell of the previous block. + --maPos.first; + maPos.second = maPos.first->size - 1; + // Reached non-string block. + if (!has()) + return false; + } + return true; + } + + bool next() + { + // Don't go down anymore as we're on non-string block. + if (!has()) + return false; + + // We are in a string block. + ++maPos.second; + if (maPos.second >= maPos.first->size) + { + // Move to the next block. + ++maPos.first; + if (maPos.first == miEnd) + return false; + + maPos.second = 0; + // Reached non-string block. + if (!has()) + return false; + } + return true; + } + +}; + +} + +// Get a set of strings from super-block of string and edit-text blocks. +// This used for computing auto-complete entries in input handler. +bool ScColumn::GetStringBlockEntries(SCROW nCursorRow, std::set<ScTypedStrData>& rStrings) const +{ + // Start at the specified row position, and collect all string values + // going upward and downward directions in parallel. The cursor position + // cell must be skipped. + + StrCellBlockIterator aItrUp(maCells, nCursorRow-1, GetDoc()); + StrCellBlockIterator aItrDown(maCells, nCursorRow+1, GetDoc()); + + bool bMoveUp = aItrUp.valid() && aItrUp.has(); + bool bMoveDown = aItrDown.valid() && aItrDown.has(); + bool bFound = false; + OUString aStr; + + while (bMoveUp || bMoveDown) + { + if (bMoveUp) + { + aStr = aItrUp.get(); + if (!aStr.isEmpty()) + { + if (rStrings.insert(ScTypedStrData(aStr)).second) + bFound = true; + } + bMoveUp = aItrUp.prev(); + } + + if (bMoveDown) + { + aStr = aItrDown.get(); + if (!aStr.isEmpty()) + { + if (rStrings.insert(ScTypedStrData(aStr)).second) + bFound = true; + } + bMoveDown = aItrDown.next(); + } + } + + return bFound; } // GetDataEntries - Strings from continuous Section around nRow diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 783bac66f2fd..3a588b81fab7 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -1578,6 +1578,27 @@ void ScDocument::GetFilterEntriesArea( } /** + * Get entries for computing auto-complete entries in input handler (no numbers/formulas) + */ +void ScDocument::GetStringBlockEntries( + SCCOL nCursorCol, SCROW nCursorRow, SCTAB nTab, + std::vector<ScTypedStrData>& rStrings) const +{ + if (!ValidTab(nTab) || nTab >= static_cast<SCTAB>(maTabs.size())) + return; + + if (!maTabs[nTab]) + return; + + std::set<ScTypedStrData> aStrings; + if (maTabs[nTab]->GetStringBlockEntries(nCursorCol, nCursorRow, aStrings)) + { + rStrings.insert(rStrings.end(), aStrings.begin(), aStrings.end()); + sortAndRemoveDuplicates(rStrings, true/*bCaseSens*/); + } +} + +/** * Entries for selection list listbox (no numbers/formulas) */ void ScDocument::GetDataEntries( @@ -1587,8 +1608,7 @@ void ScDocument::GetDataEntries( if( !bLimit ) { /* Try to generate the list from list validation. This part is skipped, - if bLimit==true, because in that case this function is called to get - cell values for auto completion on input. */ + if bLimit==true. */ sal_uInt32 nValidation = GetAttr( nCol, nRow, nTab, ATTR_VALIDDATA )->GetValue(); if( nValidation ) { diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index c27c73fb88e1..926429e90fc1 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -3477,6 +3477,11 @@ void ScTable::GetFilteredFilterEntries( } } +bool ScTable::GetStringBlockEntries(SCCOL nCursorCol, SCROW nCursorRow, std::set<ScTypedStrData>& rStrings) const +{ + return aCol[nCursorCol].GetStringBlockEntries(nCursorRow, rStrings); +} + bool ScTable::GetDataEntries(SCCOL nCol, SCROW nRow, std::set<ScTypedStrData>& rStrings, bool bLimit) { return aCol[nCol].GetDataEntries( nRow, rStrings, bLimit ); diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index e7c68c0ad302..1df722b95c9f 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -1913,8 +1913,8 @@ void ScInputHandler::GetColData() pColumnData.reset( new ScTypedCaseStrSet ); std::vector<ScTypedStrData> aEntries; - rDoc.GetDataEntries( - aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aEntries, true); + rDoc.GetStringBlockEntries( + aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aEntries); if (!aEntries.empty()) pColumnData->insert(aEntries.begin(), aEntries.end()); |