31#include <com/sun/star/awt/XTextComponent.hpp>
32#include <com/sun/star/awt/XListBox.hpp>
33#include <com/sun/star/awt/XCheckBox.hpp>
34#include <com/sun/star/beans/XPropertySet.hpp>
35#include <com/sun/star/container/XIndexAccess.hpp>
36#include <com/sun/star/util/SearchAlgorithms2.hpp>
37#include <com/sun/star/util/SearchFlags.hpp>
38#include <com/sun/star/lang/Locale.hpp>
39#include <com/sun/star/i18n/CollatorOptions.hpp>
41#include <com/sun/star/sdb/XColumn.hpp>
42#include <com/sun/star/sdbc/XConnection.hpp>
43#include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
44#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
53#define EQUAL_BOOKMARKS(a, b) a == b
55#define IFACECAST(c) static_cast<const Reference< XInterface >&>(c)
114 DBG_ASSERT(
m_xListening.is(),
"FmRecordCountListener::disposing should never have been called without a propset !");
138SimpleTextWrapper::SimpleTextWrapper(
const Reference< css::awt::XTextComponent > & _xText)
142 DBG_ASSERT(
m_xText.is(),
"FmSearchEngine::SimpleTextWrapper::SimpleTextWrapper : invalid argument !");
156 DBG_ASSERT(
m_xBox.is(),
"FmSearchEngine::ListBoxWrapper::ListBoxWrapper : invalid argument !");
162 return m_xBox->getSelectedItem();
170 DBG_ASSERT(
m_xBox.is(),
"FmSearchEngine::CheckBoxWrapper::CheckBoxWrapper : invalid argument !");
190 bool bSuccess =
true;
194 if (m_xSearchCursor.isLast())
195 m_xSearchCursor.first();
197 m_xSearchCursor.next();
199 if (m_xSearchCursor.isFirst())
204 m_xSearchCursor.last();
206 prclListener->DisConnect();
209 m_xSearchCursor.previous();
226bool FmSearchEngine::MoveField(sal_Int32& nPos, FieldCollection::iterator& iter,
const FieldCollection::iterator& iterBegin,
const FieldCollection::iterator& iterEnd)
235 bSuccess = MoveCursor();
241 if (iter == iterBegin)
243 bSuccess = MoveCursor();
245 nPos = iter-iterBegin;
256 DBG_ASSERT( xAllFields.is() && ( nField >= 0 ) && ( nField < xAllFields->getCount() ),
257 "FmSearchEngine::BuildAndInsertFieldInfo: invalid field descriptor!" );
260 Reference< XInterface > xCurrentField;
261 xAllFields->getByIndex(nField) >>= xCurrentField;
265 Reference< css::beans::XPropertySet > xProperties(xCurrentField, UNO_QUERY_THROW);
269 fiCurrent.
xContents.set(xCurrentField, UNO_QUERY);
272 m_arrUsedFields.insert(m_arrUsedFields.end(), fiCurrent);
279 DBG_ASSERT(m_aControlTexts[nWhich],
"FmSearchEngine::FormatField(sal_Int32) : invalid object in array !");
280 DBG_ASSERT(m_aControlTexts[nWhich]->getControl().is(),
"FmSearchEngine::FormatField : invalid control !");
282 if (m_nCurrentFieldIndex != -1)
284 DBG_ASSERT((nWhich == 0) || (nWhich == m_nCurrentFieldIndex),
"FmSearchEngine::FormatField : parameter nWhich is invalid");
286 nWhich = m_nCurrentFieldIndex;
290 "FmSearchEngine::FormatField : invalid argument nWhich !");
291 return m_aControlTexts[m_nCurrentFieldIndex == -1 ? nWhich : m_nCurrentFieldIndex]->getCurrentText();
296 FieldCollection::iterator& iterFieldLoop,
const FieldCollection::iterator& iterBegin,
const FieldCollection::iterator& iterEnd)
300 try { aStartMark = m_xSearchCursor.getBookmark(); }
302 FieldCollection::const_iterator iterInitialField = iterFieldLoop;
306 bool bMovedAround(
false);
312 iterFieldLoop->xContents->getString();
313 bFound = _bSearchForNull == bool(iterFieldLoop->xContents->wasNull());
318 if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
323 try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
325 m_iterPreviousLocField = iterFieldLoop;
327 return SearchResult::Error;
330 Any aCurrentBookmark;
331 try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
334 bMovedAround =
EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
338 PropagateProgress(bMovedAround);
343 if (CancelRequested())
344 return SearchResult::Cancelled;
346 }
while (!bMovedAround);
348 return bFound ? SearchResult::Found : SearchResult::NotFound;
353 FieldCollection::iterator& iterFieldLoop,
const FieldCollection::iterator& iterBegin,
const FieldCollection::iterator& iterEnd)
357 try { aStartMark = m_xSearchCursor.getBookmark(); }
359 FieldCollection::const_iterator iterInitialField = iterFieldLoop;
361 WildCard aSearchExpression(strExpression);
365 bool bMovedAround(
false);
371 OUString sCurrentCheck;
373 sCurrentCheck = FormatField(nFieldPos);
375 sCurrentCheck = iterFieldLoop->xContents->getString();
377 if (!GetCaseSensitive())
379 sCurrentCheck = m_aCharacterClassficator.lowercase(sCurrentCheck);
382 bFound = aSearchExpression.
Matches(sCurrentCheck);
388 if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
393 try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
395 m_iterPreviousLocField = iterFieldLoop;
397 return SearchResult::Error;
400 Any aCurrentBookmark;
401 try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
404 bMovedAround =
EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
408 PropagateProgress(bMovedAround);
413 if (CancelRequested())
414 return SearchResult::Cancelled;
416 }
while (!bMovedAround);
418 return bFound ? SearchResult::Found : SearchResult::NotFound;
423 FieldCollection::iterator& iterFieldLoop,
const FieldCollection::iterator& iterBegin,
const FieldCollection::iterator& iterEnd)
426 "FmSearchEngine::SearchRegularApprox : invalid search mode!");
428 "FmSearchEngine::SearchRegularApprox : cannot search for regular expressions and similarities at the same time!");
432 try { aStartMark = m_xSearchCursor.getBookmark(); }
434 FieldCollection::const_iterator iterInitialField = iterFieldLoop;
438 aParam.
AlgorithmType2 = m_bRegular ? SearchAlgorithms2::REGEXP : SearchAlgorithms2::APPROXIMATE;
441 if ( !GetTransliteration() )
443 aParam.
transliterateFlags &= TransliterationFlags::IGNORE_CASE | TransliterationFlags::IGNORE_WIDTH;
448 aParam.
searchFlag |= SearchFlags::LEV_RELAXED;
459 bool bMovedAround(
false);
465 OUString sCurrentCheck;
467 sCurrentCheck = FormatField(nFieldPos);
469 sCurrentCheck = iterFieldLoop->xContents->getString();
473 sal_Int32 nStart = 0, nEnd = sCurrentCheck.getLength();
474 bFound = aLocalEngine.
SearchForward(sCurrentCheck, &nStart, &nEnd);
485 if (nEnd != sCurrentCheck.getLength())
496 if (nEnd != sCurrentCheck.getLength())
506 if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd))
512 try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); }
514 m_iterPreviousLocField = iterFieldLoop;
516 return SearchResult::Error;
519 Any aCurrentBookmark;
520 try { aCurrentBookmark = m_xSearchCursor.getBookmark(); }
522 bMovedAround =
EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField);
526 PropagateProgress(bMovedAround);
531 if (CancelRequested())
532 return SearchResult::Cancelled;
534 }
while (!bMovedAround);
536 return bFound ? SearchResult::Found : SearchResult::NotFound;
541 const Reference< XResultSet > & xCursor, std::u16string_view sVisibleFields,
543 :m_xSearchCursor(xCursor)
544 ,m_aCharacterClassficator( _rxContext,
SvtSysLocale().GetLanguageTag() )
545 ,m_aStringCompare( _rxContext )
546 ,m_nCurrentFieldIndex(-2)
547 ,m_xOriginalIterator(xCursor)
548 ,m_xClonedIterator(m_xOriginalIterator, true)
551 ,m_bCancelAsynchRequest(false)
552 ,m_bSearchingCurrently(false)
557 ,m_bLevenshtein(false)
558 ,m_bTransliteration(false)
559 ,m_bLevRelaxed(false)
568 Init(sVisibleFields);
605 Reference< XInterface > xCurrent;
606 for (
const auto & rField : arrFields)
609 DBG_ASSERT(xCurrent.is(),
"FmSearchEngine::fillControlTexts : invalid field interface !");
611 Reference< css::awt::XTextComponent > xAsText(xCurrent, UNO_QUERY);
618 Reference< css::awt::XListBox > xAsListBox(xCurrent, UNO_QUERY);
625 Reference< css::awt::XCheckBox > xAsCheckBox(xCurrent, UNO_QUERY);
626 DBG_ASSERT(xAsCheckBox.is(),
"FmSearchEngine::fillControlTexts : invalid field interface (no supported type) !");
649 Reference< XConnection > xConn;
650 Reference< XDatabaseMetaData > xMeta;
652 if ( xCursorProps.is() )
661 xMeta = xConn->getMetaData();
662 OSL_ENSURE( xMeta.is(),
"FmSearchEngine::Init: very strange cursor (could not derive connection meta data from it)!" );
664 bool bCaseSensitiveIdentifiers =
true;
666 bCaseSensitiveIdentifiers = xMeta->supportsMixedCaseQuotedIdentifiers();
670 bCaseSensitiveIdentifiers ? 0 : css::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE );
676 DBG_ASSERT(xSupplyCols.is(),
"FmSearchEngine::Init : invalid cursor (no columns supplier) !");
677 Reference< css::container::XNameAccess > xAllFieldNames = xSupplyCols->getColumns();
678 const Sequence< OUString > seqFieldNames = xAllFieldNames->getElementNames();
680 OUString sCurrentField;
687 sal_Int32 nFoundIndex = -1;
688 auto pFieldName = std::find_if(seqFieldNames.begin(), seqFieldNames.end(),
689 [
this, &sCurrentField](
const OUString& rFieldName) {
690 return 0 == m_aStringCompare.compareString( rFieldName, sCurrentField ); });
691 if (pFieldName != seqFieldNames.end())
692 nFoundIndex =
static_cast<sal_Int32
>(std::distance(seqFieldNames.begin(), pFieldName));
693 DBG_ASSERT(nFoundIndex != -1,
"FmSearchEngine::Init : Invalid field name were given !");
767 "FmSearchEngine::SearchNextImpl : search parameters are mutually exclusive!");
783 OUString aTmp(strSearchExpression);
784 aTmp = aTmp.replaceAll(
"*",
"\\*");
785 aTmp = aTmp.replaceAll(
"?",
"\\?");
786 strSearchExpression = aTmp;
791 strSearchExpression =
"*" + strSearchExpression +
"*";
794 strSearchExpression +=
"*";
797 strSearchExpression =
"*" + strSearchExpression;
802 OSL_FAIL(
"FmSearchEngine::SearchNextImpl() : the methods listbox may contain only 4 entries ...");
810 FieldCollection::iterator iterFieldCheck;
817 "FmSearchEngine::SearchNextImpl : invalid position!");
820 nFieldPos = iterFieldCheck - iterBegin;
821 MoveField(nFieldPos, iterFieldCheck, iterBegin, iterEnd);
826 iterFieldCheck = iterBegin;
829 iterFieldCheck = iterEnd;
832 nFieldPos = iterFieldCheck - iterBegin;
840 srResult =
SearchWildcard(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd);
842 srResult =
SearchRegularApprox(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd);
907 if (!m_aProgressHandler.IsSet())
913 m_aProgressHandler.Call(&aProgress);
931 sal_Int32 nFieldIndex)
943 Init(sVisibleFields);
1028 ((nFieldIndex >= 0) &&
1030 "FmSearchEngine::RebuildUsedFields : nFieldIndex is invalid!");
1033 if (nFieldIndex == -1)
1035 Reference< css::container::XIndexAccess > xFields;
1039 DBG_ASSERT(xSupplyCols.is(),
"FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !");
1040 xFields.set(xSupplyCols->getColumns(), UNO_QUERY);
1046 Reference< css::container::XIndexAccess > xFields;
1048 DBG_ASSERT(xSupplyCols.is(),
"FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !");
1049 xFields.set (xSupplyCols->getColumns(), UNO_QUERY);
static bool Reschedule(bool bHandleAllCurrentEvents=false)
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
sal_Int32 loadDefaultCollator(const css::lang::Locale &rLocale, sal_Int32 nOption)
css::uno::Any getBookmark()
bool moveToBookmark(const css::uno::Any &bookmark)
virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent &evt) override
FmRecordCountListener(const css::uno::Reference< css::sdbc::XResultSet > &dbcCursor)
css::uno::Reference< css::beans::XPropertySet > m_xListening
Link< sal_Int32, void > m_lnkWhoWantsToKnow
virtual ~FmRecordCountListener() override
void NotifyCurrentCount()
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void SetPropChangeHandler(const Link< sal_Int32, void > &lnk)
bool GetIgnoreWidthCJK() const
SVX_DLLPRIVATE bool CancelRequested()
SVX_DLLPRIVATE void fillControlTexts(const InterfaceArray &arrFields)
std::vector< std::unique_ptr< svxform::ControlTextWrapper > > m_aControlTexts
void SetIgnoreWidthCJK(bool bSet)
Link< const FmSearchProgress *, void > m_aProgressHandler
FieldCollection m_arrUsedFields
OUString m_strSearchExpression
SearchFor m_eSearchForType
SVX_DLLPRIVATE SearchResult SearchRegularApprox(const OUString &strExpression, sal_Int32 &nFieldPos, FieldCollection::iterator &iterFieldLoop, const FieldCollection::iterator &iterBegin, const FieldCollection::iterator &iterEnd)
bool GetCaseSensitive() const
std::deque< sal_Int32 > m_arrFieldMapping
sal_Int32 m_nCurrentFieldIndex
css::uno::Any m_aPreviousLocBookmark
FieldCollection::iterator m_iterPreviousLocField
void CancelSearch()
returns directly; once it was really aborted, ProgressHandler is called with STATE_CANCELED
void InvalidatePreviousLoc()
invalidate previous search reference
void StartOverSpecial(bool _bSearchForNull)
analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
SVX_DLLPRIVATE SearchResult SearchSpecial(bool _bSearchForNull, sal_Int32 &nFieldPos, FieldCollection::iterator &iterFieldLoop, const FieldCollection::iterator &iterBegin, const FieldCollection::iterator &iterEnd)
CollatorWrapper m_aStringCompare
CursorWrapper m_xClonedIterator
SVX_DLLPRIVATE void PropagateProgress(bool _bDontPropagateOverflow)
void Init(std::u16string_view strVisibleFields)
bool m_bSearchingCurrently
void SearchNext(const OUString &strExpression)
search for the next appearance (for nDirection values check DIRECTION_*-defines)
OUString FormatField(sal_Int32 nWhich)
SVX_DLLPRIVATE bool MoveCursor()
void SetCaseSensitive(bool bSet)
SVX_DLLPRIVATE void BuildAndInsertFieldInfo(const css::uno::Reference< css::container::XIndexAccess > &xAllFields, sal_Int32 nField)
CharClass m_aCharacterClassficator
SVX_DLLPRIVATE SearchResult SearchWildcard(std::u16string_view strExpression, sal_Int32 &nFieldPos, FieldCollection::iterator &iterFieldLoop, const FieldCollection::iterator &iterBegin, const FieldCollection::iterator &iterEnd)
void OnSearchTerminated()
CursorWrapper m_xOriginalIterator
void SetFormatterUsing(bool bSet)
void RebuildUsedFields(sal_Int32 nFieldIndex, bool bForce=false)
rebuilds m_arrUsedFields (nFieldIndex==-1 means all fields, otherwise it specifies the field index) i...
void ImplStartNextSearch()
SVX_DLLPRIVATE bool MoveField(sal_Int32 &nPos, FieldCollection::iterator &iter, const FieldCollection::iterator &iterBegin, const FieldCollection::iterator &iterEnd)
std::atomic< bool > m_bCancelAsynchRequest
FmSearchEngine(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const css::uno::Reference< css::sdbc::XResultSet > &xCursor, std::u16string_view strVisibleFields, const InterfaceArray &arrFields)
two constructs, both analogical to FmSearchDialog, therefore look this up for explanations....
TransliterationFlags m_nTransliterationFlags
void SwitchToContext(const css::uno::Reference< css::sdbc::XResultSet > &xCursor, std::u16string_view strVisibleFields, const InterfaceArray &arrFields, sal_Int32 nFieldIndex)
only valid, if not an (asynchronous) search is running, the next search will then be executed on top ...
CursorWrapper m_xSearchCursor
void SearchNextSpecial(bool _bSearchForNull)
analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
void StartOver(const OUString &strExpression)
search for the next appearance, dependent on nDirection from the start or end
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
const LanguageTag & GetLanguageTag() const
bool Matches(std::u16string_view rStr) const
css::uno::Reference< css::awt::XTextComponent > m_xText
virtual OUString getCurrentText() const override
bool SearchForward(const OUString &rStr, sal_Int32 *pStart, sal_Int32 *pEnd, css::util::SearchResult *pRes=nullptr)
#define DBG_ASSERT(sCon, aError)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
virtual TransliterationFlags GetTransliterationFlags() const override
constexpr OUStringLiteral FM_PROP_ROWCOUNT
constexpr OUStringLiteral FM_PROP_ACTIVE_CONNECTION
constexpr OUStringLiteral FM_PROP_ROWCOUNTFINAL
#define MATCHING_BEGINNING
#define MATCHING_ANYWHERE
#define MATCHING_WHOLETEXT
#define EQUAL_BOOKMARKS(a, b)
IMPL_LINK(FmSearchEngine, OnNewRecordCount, sal_Int32, theCounter, void)
std::vector< css::uno::Reference< css::uno::XInterface > > InterfaceArray
#define LINK(Instance, Class, Member)
const LanguageTag & getLocale()
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
css::uno::Reference< css::sdb::XColumn > xContents
struct FmSearchProgress - the owner of SearchEngine receives this structure for status updates (at th...
sal_uInt32 nCurrentRecord
TransliterationFlags transliterateFlags