1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SVX_FMSRCIMP_HXX
21 #define INCLUDED_SVX_FMSRCIMP_HXX
23 #include <svx/fmtools.hxx>
24 #include <svx/svxdllapi.h>
26 #include <com/sun/star/awt/XCheckBox.hpp>
27 #include <com/sun/star/awt/XListBox.hpp>
28 #include <com/sun/star/awt/XTextComponent.hpp>
29 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
30 #include <com/sun/star/util/XNumberFormatter.hpp>
32 #include <cppuhelper/implbase.hxx>
33 #include <osl/mutex.hxx>
34 #include <unotools/charclass.hxx>
35 #include <unotools/collatorwrapper.hxx>
36 #include <osl/thread.hxx>
41 enum class TransliterationFlags
;
44 * struct FmSearchProgress - the owner of SearchEngine receives this structure for status updates
45 * (at the end of the search)
47 struct FmSearchProgress
49 enum class State
{ Progress
, ProgressCounting
, Canceled
, Successful
, NothingFound
, Error
};
50 // (move to new record; progress during counting of records; cancelled; record found; nothing found;
51 // any non-processable error)
54 // current record - always valid (e.g. of interest for continuing search in case of cancellation)
55 sal_uInt32 nCurrentRecord
;
56 // Overflow - only valid in case of STATE_PROGRESS
59 // the position of the search cursor - valid in case of STATE_SUCCESSFULL, STATE_CANCELED and STATE_NOTHING_FOUND
60 css::uno::Any aBookmark
;
61 // the field, in which the text was found - valid in case of STATE_SUCCESSFULL
62 sal_Int32 nFieldIndex
;
66 * class FmRecordCountListener - utility class for FmSearchEngine, listens at a certain cursor and provides
67 * the differences in RecordCount
69 class SAL_WARN_UNUSED FmRecordCountListener
: public cppu::WeakImplHelper
< css::beans::XPropertyChangeListener
>
72 Link
<sal_Int32
,void> m_lnkWhoWantsToKnow
;
73 css::uno::Reference
< css::beans::XPropertySet
> m_xListening
;
77 void SetPropChangeHandler(const Link
<sal_Int32
,void>& lnk
);
81 FmRecordCountListener(const css::uno::Reference
< css::sdbc::XResultSet
>& dbcCursor
);
82 // the set has to support the sdb::ResultSet service
83 virtual ~FmRecordCountListener() override
;
85 // DECLARE_UNO3_AGG_DEFAULTS(FmPropertyListener, UsrObject)
86 // virtual sal_Bool queryInterface(css::uno::Uik aUik, css::uno::Reference< css::uno::XInterface >& rOut);
88 // css::lang::XEventListener
89 virtual void SAL_CALL
disposing(const css::lang::EventObject
& Source
) override
;
91 // css::beans::XPropertyChangeListener
92 virtual void SAL_CALL
propertyChange(const css::beans::PropertyChangeEvent
& evt
) override
;
97 void NotifyCurrentCount();
102 * class FmSearchEngine - Impl class for FmSearchDialog
105 // We have three possible control types we may search in, determined by the supported interfaces : css::awt::XTextComponent,
106 // css::awt::XListBox, css::awt::XCheckBox.
107 // While searching we don't want to do this distinction for every control in every round. So we need some helpers.
108 class SAL_WARN_UNUSED ControlTextWrapper
111 css::uno::Reference
< css::uno::XInterface
> m_xControl
;
114 const css::uno::Reference
< css::uno::XInterface
>& getControl() const{ return m_xControl
; }
116 ControlTextWrapper(const css::uno::Reference
< css::uno::XInterface
>& _xControl
) { m_xControl
= _xControl
; }
117 virtual ~ControlTextWrapper() { }
119 virtual OUString
getCurrentText() const = 0;
122 class SAL_WARN_UNUSED SimpleTextWrapper
: public ControlTextWrapper
124 css::uno::Reference
< css::awt::XTextComponent
> m_xText
;
126 SimpleTextWrapper(const css::uno::Reference
< css::awt::XTextComponent
>& _xText
);
127 virtual OUString
getCurrentText() const override
;
130 class SAL_WARN_UNUSED ListBoxWrapper
: public ControlTextWrapper
132 css::uno::Reference
< css::awt::XListBox
> m_xBox
;
134 ListBoxWrapper(const css::uno::Reference
< css::awt::XListBox
>& _xBox
);
135 virtual OUString
getCurrentText() const override
;
138 class SAL_WARN_UNUSED CheckBoxWrapper
: public ControlTextWrapper
140 css::uno::Reference
< css::awt::XCheckBox
> m_xBox
;
142 CheckBoxWrapper(const css::uno::Reference
< css::awt::XCheckBox
>& _xBox
);
143 virtual OUString
getCurrentText() const override
;
147 typedef std::vector
< css::uno::Reference
< css::uno::XInterface
> > InterfaceArray
;
149 class SAL_WARN_UNUSED SVX_DLLPUBLIC FmSearchEngine final
151 friend class FmSearchThread
;
153 enum class SearchResult
{ Found
, NotFound
, Error
, Cancelled
};
154 enum class SearchFor
{ String
, Null
, NotNull
};
156 CursorWrapper m_xSearchCursor
;
157 std::deque
<sal_Int32
> m_arrFieldMapping
;
158 // Since the iterator could have more columns, as managed here (in this field listbox),
159 // a mapping of this css::form keys on the indices of the respective columns is kept in the iterator
162 css::uno::Reference
< css::util::XNumberFormatsSupplier
> m_xFormatSupplier
;
164 CharClass m_aCharacterClassficator
;
165 CollatorWrapper m_aStringCompare
;
167 // the collection of all interesting fields (or their css::data::XDatabaseVariant interfaces and FormatKeys)
170 css::uno::Reference
< css::sdb::XColumn
> xContents
;
171 sal_uInt32 nFormatKey
;
172 bool bDoubleHandling
;
175 typedef std::vector
<FieldInfo
> FieldCollection
;
176 FieldCollection m_arrUsedFields
;
177 sal_Int32 m_nCurrentFieldIndex
; // the last parameter of RebuildUsedFields, it allows checks in FormatField
179 typedef std::vector
<svxform::ControlTextWrapper
*> ControlTextSuppliers
;
180 ControlTextSuppliers m_aControlTexts
;
182 CursorWrapper m_xOriginalIterator
;
183 CursorWrapper m_xClonedIterator
;
185 // Data for the decision in which field a "Found" is accepted
186 css::uno::Any m_aPreviousLocBookmark
; // position of the last finding
187 FieldCollection::iterator m_iterPreviousLocField
; // field of the last finding
189 // Communication with the thread that does the actual searching
190 OUString m_strSearchExpression
; // forward direction
191 SearchFor m_eSearchForType
; // ditto
192 SearchResult m_srResult
; // backward direction
194 // The link we broadcast the progress and the result to
195 Link
<const FmSearchProgress
*,void> m_aProgressHandler
;
196 bool m_bSearchingCurrently
: 1; // is an (asynchronous) search running?
197 bool m_bCancelAsynchRequest
: 1; // should be cancelled?
198 ::osl::Mutex m_aCancelAsynchAccess
; // access to_bCancelAsynchRequest (technically only
199 // relevant for m_eMode == SM_USETHREAD)
201 // parameters for the search
202 bool m_bFormatter
: 1; // use field formatting
203 bool m_bForward
: 1; // direction
204 bool m_bWildcard
: 1; // wildcard search
205 bool m_bRegular
: 1; // regular expression
206 bool m_bLevenshtein
: 1; // Levenshtein search
207 bool m_bTransliteration
: 1; // Levenshtein search
209 bool m_bLevRelaxed
: 1; // parameters for Levenshtein search
210 sal_uInt16 m_nLevOther
;
211 sal_uInt16 m_nLevShorter
;
212 sal_uInt16 m_nLevLonger
;
214 sal_uInt16 m_nPosition
; // if not regular or levenshtein, then one of the MATCHING_... values
216 TransliterationFlags m_nTransliterationFlags
;
221 SVX_DLLPRIVATE
bool CancelRequested(); // provides a through m_aCancelAsynchAccess backed interpretation of m_bCancelAsynchRequest
224 void SetCaseSensitive(bool bSet
);
225 bool GetCaseSensitive() const;
227 void SetFormatterUsing(bool bSet
); // this is somewhat more extensive, so no inline ... here
228 bool GetFormatterUsing() const { return m_bFormatter
; }
230 void SetDirection(bool bForward
) { m_bForward
= bForward
; }
231 bool GetDirection() const { return m_bForward
; }
233 void SetWildcard(bool bSet
) { m_bWildcard
= bSet
; }
234 bool GetWildcard() const { return m_bWildcard
; }
236 void SetRegular(bool bSet
) { m_bRegular
= bSet
; }
237 bool GetRegular() const { return m_bRegular
; }
239 void SetLevenshtein(bool bSet
) { m_bLevenshtein
= bSet
; }
240 bool GetLevenshtein() const { return m_bLevenshtein
; }
242 void SetIgnoreWidthCJK(bool bSet
);
243 bool GetIgnoreWidthCJK() const;
245 void SetTransliteration(bool bSet
) { m_bTransliteration
= bSet
; }
246 bool GetTransliteration() const { return m_bTransliteration
; }
248 void SetLevRelaxed(bool bSet
) { m_bLevRelaxed
= bSet
; }
249 bool GetLevRelaxed() const { return m_bLevRelaxed
; }
250 void SetLevOther(sal_uInt16 nHowMuch
) { m_nLevOther
= nHowMuch
; }
251 sal_uInt16
GetLevOther() const { return m_nLevOther
; }
252 void SetLevShorter(sal_uInt16 nHowMuch
) { m_nLevShorter
= nHowMuch
; }
253 sal_uInt16
GetLevShorter() const { return m_nLevShorter
; }
254 void SetLevLonger(sal_uInt16 nHowMuch
) { m_nLevLonger
= nHowMuch
; }
255 sal_uInt16
GetLevLonger() const { return m_nLevLonger
; }
256 // all Lev. values will only be considered in case of m_bLevenshtein==sal_True
258 void SetTransliterationFlags(TransliterationFlags _nFlags
) { m_nTransliterationFlags
= _nFlags
; }
260 GetTransliterationFlags() const { return m_nTransliterationFlags
; }
262 void SetPosition(sal_uInt16 nValue
) { m_nPosition
= nValue
; }
263 sal_uInt16
GetPosition() const { return m_nPosition
; }
264 // position will be ignored in case of m_bWildCard==sal_True
267 /** two constructs, both analogical to FmSearchDialog, therefore look this up for explanations ....
268 xCursor has to implement css::data::DatabaseCursor service each time.
269 If eMode == SM_USETHREAD, a ProgressHandler should be set, because in this case the result forwarding will be done
271 If eMode != SM_USETHREAD, SearchNext and StarOver won't return, until the search has finished (independently of its
272 success), only then the result can be requested. If additionally the ProgressHandler is set, it will be called for
273 every record as well as at the end of the search.
276 const css::uno::Reference
< css::uno::XComponentContext
>& _rxContext
,
277 const css::uno::Reference
< css::sdbc::XResultSet
>& xCursor
,
278 const OUString
& strVisibleFields
,
279 const InterfaceArray
& arrFields
);
283 /** the link will be called on every record and after the completion of the search, the parameter is a pointer to
284 a FmSearchProgress structure
285 the handler should be in any case thread-safe
287 void SetProgressHandler(Link
<const FmSearchProgress
*,void> aHdl
) { m_aProgressHandler
= aHdl
; }
289 /// search for the next appearance (for nDirection values check DIRECTION_*-defines)
290 void SearchNext(const OUString
& strExpression
);
291 /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
292 void SearchNextSpecial(bool _bSearchForNull
);
293 /// search for the next appearance, dependent on nDirection from the start or end
294 void StartOver(const OUString
& strExpression
);
295 /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
296 void StartOverSpecial(bool _bSearchForNull
);
297 /// invalidate previous search reference
298 void InvalidatePreviousLoc();
300 /** rebuilds m_arrUsedFields (nFieldIndex==-1 means all fields, otherwise it specifies the field index)
301 if bForce is not set, nothing will happen in case of nFieldIndex == m_nCurrentFieldIndex
302 (calls InvalidatePreviousLoc)
304 void RebuildUsedFields(sal_Int32 nFieldIndex
, bool bForce
= false);
305 OUString
FormatField(sal_Int32 nWhich
);
307 /// returns directly; once it was really aborted, ProgressHandler is called with STATE_CANCELED
310 /** only valid, if not an (asynchronous) search is running, the next search will then be executed
311 on top of the new iterator with the new parameter
313 void SwitchToContext(const css::uno::Reference
< css::sdbc::XResultSet
>& xCursor
, const OUString
& strVisibleFields
, const InterfaceArray
& arrFields
,
314 sal_Int32 nFieldIndex
);
317 void Init(const OUString
& strVisibleFields
);
319 void SearchNextImpl();
320 // this Impl method is running in SearchThread
322 // start a thread-search (or call SearchNextImpl directly, depending on the search mode)
323 void ImplStartNextSearch();
325 SVX_DLLPRIVATE
void clearControlTexts();
326 SVX_DLLPRIVATE
void fillControlTexts(const InterfaceArray
& arrFields
);
328 // three methods implementing a complete search loop (null/not null, wildcard, SearchText)
329 // (they all have some code in common, but with this solution we have to do a distinction only once per search (before
330 // starting the loop), not in every loop step
331 SVX_DLLPRIVATE SearchResult
SearchSpecial(bool _bSearchForNull
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
332 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
333 SVX_DLLPRIVATE SearchResult
SearchWildcard(const OUString
& strExpression
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
334 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
335 SVX_DLLPRIVATE SearchResult
SearchRegularApprox(const OUString
& strExpression
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
336 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
338 SVX_DLLPRIVATE
void PropagateProgress(bool _bDontPropagateOverflow
);
339 // call the ProgressHandler with STATE_PROGRESS and the current position of the search iterator
341 // helpers, that are needed several times
342 SVX_DLLPRIVATE
bool MoveCursor();
343 // moves m_xSearchIterator with respect to direction/overflow cursor
344 SVX_DLLPRIVATE
bool MoveField(sal_Int32
& nPos
, FieldCollection::iterator
& iter
, const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
345 // moves the iterator with respect to the direction/overflow iterator/overflow cursor
346 SVX_DLLPRIVATE
void BuildAndInsertFieldInfo(const css::uno::Reference
< css::container::XIndexAccess
>& xAllFields
, sal_Int32 nField
);
348 void OnSearchTerminated();
349 // is used by SearchThread, after the return from this handler the thread removes itself
350 DECL_LINK(OnNewRecordCount
, sal_Int32
, void);
353 #endif // INCLUDED_SVX_FMSRCIMP_HXX
355 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */