diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/svx/fmsrcimp.hxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | include/svx/fmsrcimp.hxx | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/include/svx/fmsrcimp.hxx b/include/svx/fmsrcimp.hxx new file mode 100644 index 0000000000..fdcf12fa31 --- /dev/null +++ b/include/svx/fmsrcimp.hxx @@ -0,0 +1,350 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVX_FMSRCIMP_HXX +#define INCLUDED_SVX_FMSRCIMP_HXX + +#include <svx/fmtools.hxx> +#include <svx/svxdllapi.h> + +#include <com/sun/star/beans/XPropertyChangeListener.hpp> + +#include <cppuhelper/implbase.hxx> +#include <unotools/charclass.hxx> +#include <unotools/collatorwrapper.hxx> +#include <tools/link.hxx> + +#include <atomic> +#include <deque> +#include <memory> +#include <string_view> +#include <vector> + +namespace com::sun::star::awt { class XCheckBox; } +namespace com::sun::star::awt { class XListBox; } +namespace com::sun::star::awt { class XTextComponent; } +namespace com::sun::star::sdb { class XColumn; } + +enum class TransliterationFlags; + +/** + * struct FmSearchProgress - the owner of SearchEngine receives this structure for status updates + * (at the end of the search) + */ +struct FmSearchProgress +{ + enum class State { Progress, ProgressCounting, Canceled, Successful, NothingFound, Error }; + // (move to new record; progress during counting of records; cancelled; record found; nothing found; + // any non-processable error) + State aSearchState; + + // current record - always valid (e.g. of interest for continuing search in case of cancellation) + sal_uInt32 nCurrentRecord; + // Overflow - only valid in case of STATE_PROGRESS + bool bOverflow; + + // the position of the search cursor - valid in case of STATE_SUCCESSFUL, STATE_CANCELED and STATE_NOTHING_FOUND + css::uno::Any aBookmark; + // the field, in which the text was found - valid in case of STATE_SUCCESSFUL + sal_Int32 nFieldIndex; +}; + +/** + * class FmRecordCountListener - utility class for FmSearchEngine, listens at a certain cursor and provides + * the differences in RecordCount + */ +// workaround for incremental linking bugs in MSVC2019 +class SAL_DLLPUBLIC_TEMPLATE FmRecordCountListener_Base : public cppu::WeakImplHelper< css::beans::XPropertyChangeListener > {}; +class SAL_WARN_UNUSED FmRecordCountListener final : public FmRecordCountListener_Base +{ +// attribute + Link<sal_Int32,void> m_lnkWhoWantsToKnow; + css::uno::Reference< css::beans::XPropertySet > m_xListening; + +// attribute access +public: + void SetPropChangeHandler(const Link<sal_Int32,void>& lnk); + +// methods +public: + FmRecordCountListener(const css::uno::Reference< css::sdbc::XResultSet >& dbcCursor); + // the set has to support the sdb::ResultSet service + virtual ~FmRecordCountListener() override; + + // DECLARE_UNO3_AGG_DEFAULTS(FmPropertyListener, UsrObject) + // virtual sal_Bool queryInterface(css::uno::Uik aUik, css::uno::Reference< css::uno::XInterface >& rOut); + + // css::lang::XEventListener + virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override; + + // css::beans::XPropertyChangeListener + virtual void SAL_CALL propertyChange(const css::beans::PropertyChangeEvent& evt) override; + + void DisConnect(); + +private: + void NotifyCurrentCount(); + +}; + +/** + * class FmSearchEngine - Impl class for FmSearchDialog + */ +namespace svxform { + // We have three possible control types we may search in, determined by the supported interfaces : css::awt::XTextComponent, + // css::awt::XListBox, css::awt::XCheckBox. + // While searching we don't want to do this distinction for every control in every round. So we need some helpers. + class SAL_WARN_UNUSED ControlTextWrapper + { + // attributes + css::uno::Reference< css::uno::XInterface > m_xControl; + // attribute access + public: + const css::uno::Reference< css::uno::XInterface >& getControl() const{ return m_xControl; } + public: + ControlTextWrapper(const css::uno::Reference< css::uno::XInterface >& _xControl) { m_xControl = _xControl; } + virtual ~ControlTextWrapper() { } + + virtual OUString getCurrentText() const = 0; + }; + + class SAL_WARN_UNUSED SimpleTextWrapper final : public ControlTextWrapper + { + css::uno::Reference< css::awt::XTextComponent > m_xText; + public: + SimpleTextWrapper(const css::uno::Reference< css::awt::XTextComponent >& _xText); + virtual OUString getCurrentText() const override; + }; + + class SAL_WARN_UNUSED ListBoxWrapper final : public ControlTextWrapper + { + css::uno::Reference< css::awt::XListBox > m_xBox; + public: + ListBoxWrapper(const css::uno::Reference< css::awt::XListBox >& _xBox); + virtual OUString getCurrentText() const override; + }; + + class SAL_WARN_UNUSED CheckBoxWrapper final : public ControlTextWrapper + { + css::uno::Reference< css::awt::XCheckBox > m_xBox; + public: + CheckBoxWrapper(const css::uno::Reference< css::awt::XCheckBox >& _xBox); + virtual OUString getCurrentText() const override; + }; +} + +typedef std::vector< css::uno::Reference< css::uno::XInterface> > InterfaceArray; + +class SAL_WARN_UNUSED SVX_DLLPUBLIC FmSearchEngine final +{ + friend class FmSearchThread; + + enum class SearchResult { Found, NotFound, Error, Cancelled }; + enum class SearchFor { String, Null, NotNull }; + + CursorWrapper m_xSearchCursor; + std::deque<sal_Int32> m_arrFieldMapping; + // Since the iterator could have more columns, as managed here (in this field listbox), + // a mapping of this css::form keys on the indices of the respective columns is kept in the iterator + + CharClass m_aCharacterClassficator; + CollatorWrapper m_aStringCompare; + + // the collection of all interesting fields (or their css::data::XDatabaseVariant interfaces and FormatKeys) + struct FieldInfo + { + css::uno::Reference< css::sdb::XColumn > xContents; + }; + + typedef std::vector<FieldInfo> FieldCollection; + FieldCollection m_arrUsedFields; + sal_Int32 m_nCurrentFieldIndex; // the last parameter of RebuildUsedFields, it allows checks in FormatField + + std::vector<std::unique_ptr<svxform::ControlTextWrapper>> + m_aControlTexts; + + CursorWrapper m_xOriginalIterator; + CursorWrapper m_xClonedIterator; + + // Data for the decision in which field a "Found" is accepted + css::uno::Any m_aPreviousLocBookmark; // position of the last finding + FieldCollection::iterator m_iterPreviousLocField; // field of the last finding + + // Communication with the thread that does the actual searching + OUString m_strSearchExpression; // forward direction + SearchFor m_eSearchForType; // ditto + SearchResult m_srResult; // backward direction + + // The link we broadcast the progress and the result to + Link<const FmSearchProgress*,void> m_aProgressHandler; + std::atomic<bool> m_bCancelAsynchRequest; // should be cancelled? + + // parameters for the search + bool m_bSearchingCurrently : 1; // is an (asynchronous) search running? + bool m_bFormatter : 1; // use field formatting + bool m_bForward : 1; // direction + bool m_bWildcard : 1; // wildcard search + bool m_bRegular : 1; // regular expression + bool m_bLevenshtein : 1; // Levenshtein search + bool m_bTransliteration : 1; // Levenshtein search + + bool m_bLevRelaxed : 1; // parameters for Levenshtein search + sal_uInt16 m_nLevOther; + sal_uInt16 m_nLevShorter; + sal_uInt16 m_nLevLonger; + + sal_uInt16 m_nPosition; // if not regular or levenshtein, then one of the MATCHING_... values + + TransliterationFlags m_nTransliterationFlags; + + +// member access +private: + SVX_DLLPRIVATE bool CancelRequested(); // provides a through m_aCancelAsynchAccess backed interpretation of m_bCancelAsynchRequest + +public: + void SetCaseSensitive(bool bSet); + bool GetCaseSensitive() const; + + void SetFormatterUsing(bool bSet); // this is somewhat more extensive, so no inline ... here + bool GetFormatterUsing() const { return m_bFormatter; } + + void SetDirection(bool bForward) { m_bForward = bForward; } + bool GetDirection() const { return m_bForward; } + + void SetWildcard(bool bSet) { m_bWildcard = bSet; } + bool GetWildcard() const { return m_bWildcard; } + + void SetRegular(bool bSet) { m_bRegular = bSet; } + bool GetRegular() const { return m_bRegular; } + + void SetLevenshtein(bool bSet) { m_bLevenshtein = bSet; } + bool GetLevenshtein() const { return m_bLevenshtein; } + + void SetIgnoreWidthCJK(bool bSet); + bool GetIgnoreWidthCJK() const; + + void SetTransliteration(bool bSet) { m_bTransliteration = bSet; } + bool GetTransliteration() const { return m_bTransliteration; } + + void SetLevRelaxed(bool bSet) { m_bLevRelaxed = bSet; } + bool GetLevRelaxed() const { return m_bLevRelaxed; } + void SetLevOther(sal_uInt16 nHowMuch) { m_nLevOther = nHowMuch; } + sal_uInt16 GetLevOther() const { return m_nLevOther; } + void SetLevShorter(sal_uInt16 nHowMuch) { m_nLevShorter = nHowMuch; } + sal_uInt16 GetLevShorter() const { return m_nLevShorter; } + void SetLevLonger(sal_uInt16 nHowMuch) { m_nLevLonger = nHowMuch; } + sal_uInt16 GetLevLonger() const { return m_nLevLonger; } + // all Lev. values will only be considered in case of m_bLevenshtein==sal_True + + void SetTransliterationFlags(TransliterationFlags _nFlags) { m_nTransliterationFlags = _nFlags; } + TransliterationFlags + GetTransliterationFlags() const { return m_nTransliterationFlags; } + + void SetPosition(sal_uInt16 nValue) { m_nPosition = nValue; } + sal_uInt16 GetPosition() const { return m_nPosition; } + // position will be ignored in case of m_bWildCard==sal_True + +public: + /** two constructs, both analogical to FmSearchDialog, therefore look this up for explanations... + xCursor has to implement css::data::DatabaseCursor service each time. + If eMode == SM_USETHREAD, a ProgressHandler should be set, because in this case the result forwarding will be done + by this handler. + If eMode != SM_USETHREAD, SearchNext and StarOver won't return, until the search has finished (independently of its + success), only then the result can be requested. If additionally the ProgressHandler is set, it will be called for + every record as well as at the end of the search. + */ + FmSearchEngine( + const css::uno::Reference< css::uno::XComponentContext >& _rxContext, + const css::uno::Reference< css::sdbc::XResultSet >& xCursor, + std::u16string_view strVisibleFields, + const InterfaceArray& arrFields); + + /** the link will be called on every record and after the completion of the search, the parameter is a pointer to + a FmSearchProgress structure + the handler should be in any case thread-safe + */ + void SetProgressHandler(Link<const FmSearchProgress*,void> aHdl) { m_aProgressHandler = aHdl; } + + /// search for the next appearance (for nDirection values check DIRECTION_*-defines) + void SearchNext(const OUString& strExpression); + /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL" + void SearchNextSpecial(bool _bSearchForNull); + /// search for the next appearance, dependent on nDirection from the start or end + void StartOver(const OUString& strExpression); + /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL" + void StartOverSpecial(bool _bSearchForNull); + /// invalidate previous search reference + void InvalidatePreviousLoc(); + + /** rebuilds m_arrUsedFields (nFieldIndex==-1 means all fields, otherwise it specifies the field index) + if bForce is not set, nothing will happen in case of nFieldIndex == m_nCurrentFieldIndex + (calls InvalidatePreviousLoc) + */ + void RebuildUsedFields(sal_Int32 nFieldIndex, bool bForce = false); + OUString FormatField(sal_Int32 nWhich); + + /// returns directly; once it was really aborted, ProgressHandler is called with STATE_CANCELED + void CancelSearch(); + + /** only valid, if not an (asynchronous) search is running, the next search will then be executed + on top of the new iterator with the new parameter + */ + void SwitchToContext(const css::uno::Reference< css::sdbc::XResultSet >& xCursor, std::u16string_view strVisibleFields, const InterfaceArray& arrFields, + sal_Int32 nFieldIndex); + +private: + void Init(std::u16string_view strVisibleFields); + + void SearchNextImpl(); + // this Impl method is running in SearchThread + + // start a thread-search (or call SearchNextImpl directly, depending on the search mode) + void ImplStartNextSearch(); + + SVX_DLLPRIVATE void fillControlTexts(const InterfaceArray& arrFields); + + // three methods implementing a complete search loop (null/not null, wildcard, SearchText) + // (they all have some code in common, but with this solution we have to do a distinction only once per search (before + // starting the loop), not in every loop step + SVX_DLLPRIVATE SearchResult SearchSpecial(bool _bSearchForNull, sal_Int32& nFieldPos, FieldCollection::iterator& iterFieldLoop, + const FieldCollection::iterator& iterBegin, const FieldCollection::iterator& iterEnd); + SVX_DLLPRIVATE SearchResult SearchWildcard(std::u16string_view strExpression, sal_Int32& nFieldPos, FieldCollection::iterator& iterFieldLoop, + const FieldCollection::iterator& iterBegin, const FieldCollection::iterator& iterEnd); + SVX_DLLPRIVATE SearchResult SearchRegularApprox(const OUString& strExpression, sal_Int32& nFieldPos, FieldCollection::iterator& iterFieldLoop, + const FieldCollection::iterator& iterBegin, const FieldCollection::iterator& iterEnd); + + SVX_DLLPRIVATE void PropagateProgress(bool _bDontPropagateOverflow); + // call the ProgressHandler with STATE_PROGRESS and the current position of the search iterator + + // helpers, that are needed several times + SVX_DLLPRIVATE bool MoveCursor(); + // moves m_xSearchIterator with respect to direction/overflow cursor + SVX_DLLPRIVATE bool MoveField(sal_Int32& nPos, FieldCollection::iterator& iter, const FieldCollection::iterator& iterBegin, const FieldCollection::iterator& iterEnd); + // moves the iterator with respect to the direction/overflow iterator/overflow cursor + SVX_DLLPRIVATE void BuildAndInsertFieldInfo(const css::uno::Reference< css::container::XIndexAccess >& xAllFields, sal_Int32 nField); + + void OnSearchTerminated(); + // is used by SearchThread, after the return from this handler the thread removes itself + DECL_DLLPRIVATE_LINK(OnNewRecordCount, sal_Int32, void); +}; + +#endif // INCLUDED_SVX_FMSRCIMP_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |