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/implbase1.hxx>
33 #include <osl/mutex.hxx>
34 #include <unotools/charclass.hxx>
35 #include <unotools/collatorwrapper.hxx>
36 #include <osl/thread.hxx>
42 * class FmSearchThread
45 class SAL_WARN_UNUSED FmSearchThread
: public ::osl::Thread
47 FmSearchEngine
* m_pEngine
;
48 Link
<> m_aTerminationHdl
;
50 virtual void SAL_CALL
run() SAL_OVERRIDE
;
51 virtual void SAL_CALL
onTerminated() SAL_OVERRIDE
;
54 FmSearchThread(FmSearchEngine
* pEngine
) : m_pEngine(pEngine
) { }
55 void setTerminationHandler(Link
<> aHdl
) { m_aTerminationHdl
= aHdl
; }
59 * struct FmSearchProgress - the owner of SearchEngine receives this structure for status updates
60 * (at the end of the search)
62 struct FmSearchProgress
64 enum STATE
{ STATE_PROGRESS
, STATE_PROGRESS_COUNTING
, STATE_CANCELED
, STATE_SUCCESSFULL
, STATE_NOTHINGFOUND
, STATE_ERROR
};
65 // (move to new record; progress during counting of records; cancelled; record found; nothing found;
66 // any non-processable error)
69 // current record - always valid (e.g. of interest for continuing search in case of cancellation)
70 sal_uInt32 nCurrentRecord
;
71 // Overflow - only valid in case of STATE_PROGRESS
74 // the position of the search cursor - valid in case of STATE_SUCCESSFULL, STATE_CANCELED and STATE_NOTHING_FOUND
75 ::com::sun::star::uno::Any aBookmark
;
76 // the field, in which the text was found - valid in case of STATE_SUCCESSFULL
77 sal_Int32 nFieldIndex
;
81 * class FmRecordCountListener - utility class for FmSearchEngine, listens at a certain cursor and provides
82 * the differences in RecordCount
84 class SAL_WARN_UNUSED FmRecordCountListener
: public ::cppu::WeakImplHelper1
< ::com::sun::star::beans::XPropertyChangeListener
>
87 Link
<> m_lnkWhoWantsToKnow
;
88 ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertySet
> m_xListening
;
92 Link
<> SetPropChangeHandler(const Link
<>& lnk
);
96 FmRecordCountListener(const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XResultSet
>& dbcCursor
);
97 // the set has to support the sdb::ResultSet service
98 virtual ~FmRecordCountListener();
100 // DECLARE_UNO3_AGG_DEFAULTS(FmPropertyListener, UsrObject)
101 // virtual sal_Bool queryInterface(::com::sun::star::uno::Uik aUik, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rOut);
103 // ::com::sun::star::lang::XEventListener
104 virtual void SAL_CALL
disposing(const ::com::sun::star::lang::EventObject
& Source
) throw(::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
106 // ::com::sun::star::beans::XPropertyChangeListener
107 virtual void SAL_CALL
propertyChange(const ::com::sun::star::beans::PropertyChangeEvent
& evt
) throw(::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
112 void NotifyCurrentCount();
117 * class FmSearchEngine - Impl class for FmSearchDialog
120 // We have three possible control types we may search in, determined by the supported interfaces : ::com::sun::star::awt::XTextComponent,
121 // ::com::sun::star::awt::XListBox, ::com::sun::star::awt::XCheckBox.
122 // While searching we don't want to do this distinction for every control in every round. So we need some helpers.
123 class SAL_WARN_UNUSED ControlTextWrapper
126 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> m_xControl
;
129 ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> getControl() const{ return m_xControl
; }
131 ControlTextWrapper(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _xControl
) { m_xControl
= _xControl
; }
132 virtual ~ControlTextWrapper() { }
134 virtual OUString
getCurrentText() const = 0;
137 class SAL_WARN_UNUSED SimpleTextWrapper
: public ControlTextWrapper
139 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XTextComponent
> m_xText
;
141 SimpleTextWrapper(const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XTextComponent
>& _xText
);
142 virtual OUString
getCurrentText() const SAL_OVERRIDE
;
145 class SAL_WARN_UNUSED ListBoxWrapper
: public ControlTextWrapper
147 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XListBox
> m_xBox
;
149 ListBoxWrapper(const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XListBox
>& _xBox
);
150 virtual OUString
getCurrentText() const SAL_OVERRIDE
;
153 class SAL_WARN_UNUSED CheckBoxWrapper
: public ControlTextWrapper
155 ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XCheckBox
> m_xBox
;
157 CheckBoxWrapper(const ::com::sun::star::uno::Reference
< ::com::sun::star::awt::XCheckBox
>& _xBox
);
158 virtual OUString
getCurrentText() const SAL_OVERRIDE
;
162 enum FMSEARCH_MODE
{ SM_BRUTE
, SM_ALLOWSCHEDULE
, SM_USETHREAD
};
164 typedef std::vector
< ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
> > InterfaceArray
;
166 class SVX_DLLPUBLIC SAL_WARN_UNUSED FmSearchEngine
168 friend class FmSearchThread
;
170 enum SEARCH_RESULT
{ SR_FOUND
, SR_NOTFOUND
, SR_ERROR
, SR_CANCELED
};
171 enum SEARCHFOR_TYPE
{ SEARCHFOR_STRING
, SEARCHFOR_NULL
, SEARCHFOR_NOTNULL
};
173 CursorWrapper m_xSearchCursor
;
174 std::deque
<sal_Int32
> m_arrFieldMapping
;
175 // Since the iterator could have more columns, as managed here (in this field listbox),
176 // a mapping of this ::com::sun::star::form keys on the indices of the respective columns is kept in the iterator
179 ::com::sun::star::uno::Reference
< ::com::sun::star::util::XNumberFormatsSupplier
> m_xFormatSupplier
;
180 ::com::sun::star::uno::Reference
< ::com::sun::star::util::XNumberFormatter
> m_xFormatter
;
182 CharClass m_aCharacterClassficator
;
183 CollatorWrapper m_aStringCompare
;
185 // the collection of all interesting fields (or their ::com::sun::star::data::XDatabaseVariant interfaces and FormatKeys)
188 ::com::sun::star::uno::Reference
< ::com::sun::star::sdb::XColumn
> xContents
;
189 sal_uInt32 nFormatKey
;
190 bool bDoubleHandling
;
193 typedef std::vector
<FieldInfo
> FieldCollection
;
194 FieldCollection m_arrUsedFields
;
195 sal_Int32 m_nCurrentFieldIndex
; // the last parameter of RebuildUsedFields, it allows checks in FormatField
197 typedef std::vector
<svxform::ControlTextWrapper
*> ControlTextSuppliers
;
198 ControlTextSuppliers m_aControlTexts
;
200 bool m_bUsingTextComponents
;
201 CursorWrapper m_xOriginalIterator
;
202 CursorWrapper m_xClonedIterator
;
204 // Data for the decision in which field a "Found" is accepted
205 ::com::sun::star::uno::Any m_aPreviousLocBookmark
; // position of the last finding
206 FieldCollection::iterator m_iterPreviousLocField
; // field of the last finding
208 // Communication with the thread that does the actual searching
209 OUString m_strSearchExpression
; // forward direction
210 SEARCHFOR_TYPE m_eSearchForType
; // ditto
211 SEARCH_RESULT m_srResult
; // backward direction
213 // The link we broadcast the progress and the result to
214 Link
<> m_aProgressHandler
;
215 bool m_bSearchingCurrently
: 1; // is an (asynchronous) search running?
216 bool m_bCancelAsynchRequest
: 1; // should be cancelled?
217 ::osl::Mutex m_aCancelAsynchAccess
; // access to_bCancelAsynchRequest (technically only
218 // relevant for m_eMode == SM_USETHREAD)
219 FMSEARCH_MODE m_eMode
; // current mode
221 // parameters for the search
222 bool m_bFormatter
: 1; // use field formatting
223 bool m_bForward
: 1; // direction
224 bool m_bWildcard
: 1; // wildcard search
225 bool m_bRegular
: 1; // regular expression
226 bool m_bLevenshtein
: 1; // Levenshtein search
227 bool m_bTransliteration
: 1; // Levenshtein search
229 bool m_bLevRelaxed
: 1; // parameters for Levenshtein search
230 sal_uInt16 m_nLevOther
;
231 sal_uInt16 m_nLevShorter
;
232 sal_uInt16 m_nLevLonger
;
234 sal_uInt16 m_nPosition
; // if not regular or levenshtein, then one of the MATCHING_... values
236 sal_Int32 m_nTransliterationFlags
;
241 SVX_DLLPRIVATE
bool CancelRequested(); // provides a through m_aCancelAsynchAccess backed interpretation of m_bCancelAsynchRequest
244 void SetCaseSensitive(bool bSet
);
245 bool GetCaseSensitive() const;
247 void SetFormatterUsing(bool bSet
); // this is somewhat more extensive, so no inline ... here
248 bool GetFormatterUsing() const { return m_bFormatter
; }
250 void SetDirection(bool bForward
) { m_bForward
= bForward
; }
251 bool GetDirection() const { return m_bForward
; }
253 void SetWildcard(bool bSet
) { m_bWildcard
= bSet
; }
254 bool GetWildcard() const { return m_bWildcard
; }
256 void SetRegular(bool bSet
) { m_bRegular
= bSet
; }
257 bool GetRegular() const { return m_bRegular
; }
259 void SetLevenshtein(bool bSet
) { m_bLevenshtein
= bSet
; }
260 bool GetLevenshtein() const { return m_bLevenshtein
; }
262 void SetIgnoreWidthCJK(bool bSet
);
263 bool GetIgnoreWidthCJK() const;
265 void SetTransliteration(bool bSet
) { m_bTransliteration
= bSet
; }
266 bool GetTransliteration() const { return m_bTransliteration
; }
268 void SetLevRelaxed(bool bSet
) { m_bLevRelaxed
= bSet
; }
269 bool GetLevRelaxed() const { return m_bLevRelaxed
; }
270 void SetLevOther(sal_uInt16 nHowMuch
) { m_nLevOther
= nHowMuch
; }
271 sal_uInt16
GetLevOther() const { return m_nLevOther
; }
272 void SetLevShorter(sal_uInt16 nHowMuch
) { m_nLevShorter
= nHowMuch
; }
273 sal_uInt16
GetLevShorter() const { return m_nLevShorter
; }
274 void SetLevLonger(sal_uInt16 nHowMuch
) { m_nLevLonger
= nHowMuch
; }
275 sal_uInt16
GetLevLonger() const { return m_nLevLonger
; }
276 // all Lev. values will only be considered in case of m_bLevenshtein==sal_True
278 void SetTransliterationFlags(sal_Int32 _nFlags
) { m_nTransliterationFlags
= _nFlags
; }
279 sal_Int32
GetTransliterationFlags() const { return m_nTransliterationFlags
; }
281 void SetPosition(sal_uInt16 nValue
) { m_nPosition
= nValue
; }
282 sal_uInt16
GetPosition() const { return m_nPosition
; }
283 // position will be ignored in case of m_bWildCard==sal_True
285 FMSEARCH_MODE
GetSearchMode() const { return m_eMode
; }
288 /** two constructs, both analogical to FmSearchDialog, therefore look this up for explanations ....
289 xCursor has to implement ::com::sun::star::data::DatabaseCursor service each time.
290 If eMode == SM_USETHREAD, a ProgressHandler should be set, because in this case the result forwarding will be done
292 If eMode != SM_USETHREAD, SearchNext and StarOver won't return, until the search has finished (independently of its
293 success), only then the result can be requested. If additionally the ProgressHandler is set, it will be called for
294 every record as well as at the end of the search.
297 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _rxContext
,
298 const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XResultSet
>& xCursor
,
299 const OUString
& strVisibleFields
,
300 const ::com::sun::star::uno::Reference
< ::com::sun::star::util::XNumberFormatsSupplier
>& xFormat
,
301 FMSEARCH_MODE eMode
);
303 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& _rxContext
,
304 const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XResultSet
>& xCursor
,
305 const OUString
& strVisibleFields
,
306 const InterfaceArray
& arrFields
,
307 FMSEARCH_MODE eMode
);
309 virtual ~FmSearchEngine();
311 /** the link will be called on every record and after the completion of the search, the parameter is a pointer to
312 a FmSearchProgress structure
313 the handler should be in any case thread-safe
315 void SetProgressHandler(Link
<> aHdl
) { m_aProgressHandler
= aHdl
; }
317 /// search for the next appearance (for nDirection values check DIRECTION_*-defines)
318 void SearchNext(const OUString
& strExpression
);
319 /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
320 void SearchNextSpecial(bool _bSearchForNull
);
321 /// search for the next appearance, dependent on nDirection from the start or end
322 void StartOver(const OUString
& strExpression
);
323 /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
324 void StartOverSpecial(bool _bSearchForNull
);
325 /// invalidate previous search reference
326 void InvalidatePreviousLoc();
328 /** rebuilds m_arrUsedFields (nFieldIndex==-1 means all fields, otherwise it specifies the field index)
329 if bForce is not set, nothing will happen in case of nFieldIndex == m_nCurrentFieldIndex
330 (calls InvalidatePreviousLoc)
332 void RebuildUsedFields(sal_Int32 nFieldIndex
, bool bForce
= false);
333 OUString
FormatField(sal_Int32 nWhich
);
335 /// returns directly; once it was really aborted, ProgressHandler is called with STATE_CANCELED
338 /** only valid, if not an (asynchronous) search is running, the next search will then be executed
339 on top of the new iterator with the new parameter
341 bool SwitchToContext(const ::com::sun::star::uno::Reference
< ::com::sun::star::sdbc::XResultSet
>& xCursor
, const OUString
& strVisibleFields
, const InterfaceArray
& arrFields
,
342 sal_Int32 nFieldIndex
);
345 void Init(const OUString
& strVisibleFields
);
347 void SearchNextImpl();
348 // this Impl method is running in SearchThread
350 // start a thread-search (or call SearchNextImpl directly, depending on the search mode)
351 void ImplStartNextSearch();
354 SVX_DLLPRIVATE
void clearControlTexts();
355 SVX_DLLPRIVATE
void fillControlTexts(const InterfaceArray
& arrFields
);
357 // three methods implementing a complete search loop (null/not null, wildcard, SearchText)
358 // (they all have some code in common, but with this solution we have to do a distinction only once per search (before
359 // starting the loop), not in every loop step
360 SVX_DLLPRIVATE SEARCH_RESULT
SearchSpecial(bool _bSearchForNull
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
361 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
362 SVX_DLLPRIVATE SEARCH_RESULT
SearchWildcard(const OUString
& strExpression
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
363 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
364 SVX_DLLPRIVATE SEARCH_RESULT
SearchRegularApprox(const OUString
& strExpression
, sal_Int32
& nFieldPos
, FieldCollection::iterator
& iterFieldLoop
,
365 const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
367 SVX_DLLPRIVATE
void PropagateProgress(bool _bDontPropagateOverflow
);
368 // call the ProgressHandler with STATE_PROGRESS and the current position of the search iterator
370 // helpers, that are needed several times
371 SVX_DLLPRIVATE
bool MoveCursor();
372 // moves m_xSearchIterator with respect to direction/overflow cursor
373 SVX_DLLPRIVATE
bool MoveField(sal_Int32
& nPos
, FieldCollection::iterator
& iter
, const FieldCollection::iterator
& iterBegin
, const FieldCollection::iterator
& iterEnd
);
374 // moves the iterator with respect to the direction/overflow iterator/overflow cursor
375 SVX_DLLPRIVATE
void BuildAndInsertFieldInfo(const ::com::sun::star::uno::Reference
< ::com::sun::star::container::XIndexAccess
>& xAllFields
, sal_Int32 nField
);
376 // builds a FieldInfo in relation to field number nField (in xAllFields) and adds it to m_arrUsedFields
377 // xAllFields needs to support the DatabaseRecord service
378 SVX_DLLPRIVATE OUString
FormatField(const FieldInfo
& rField
);
379 // formats the field with the NumberFormatter
381 SVX_DLLPRIVATE
bool HasPreviousLoc() { return m_aPreviousLocBookmark
.hasValue(); }
383 DECL_LINK(OnSearchTerminated
, FmSearchThread
*);
384 // is used by SearchThread, after the return from this handler the thread removes itself
385 DECL_LINK(OnNewRecordCount
, void*);
388 #endif // INCLUDED_SVX_FMSRCIMP_HXX
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */