xref: /AOO41X/main/svx/inc/svx/fmsrcimp.hxx (revision 3334a7e6acdae9820fa1a6f556bb10129a8de6b2)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _FMSRCIMP_HXX
25 #define _FMSRCIMP_HXX
26 
27 #include <svx/fmtools.hxx>
28 #include "svx/svxdllapi.h"
29 
30 /** === begin UNO includes === **/
31 #include <com/sun/star/awt/XCheckBox.hpp>
32 #include <com/sun/star/awt/XListBox.hpp>
33 #include <com/sun/star/awt/XTextComponent.hpp>
34 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
35 #include <com/sun/star/util/XNumberFormatter.hpp>
36 /** === end UNO includes === **/
37 
38 #include <comphelper/stl_types.hxx>
39 #include <cppuhelper/implbase1.hxx>
40 #include <osl/mutex.hxx>
41 #include <unotools/charclass.hxx>
42 #include <unotools/collatorwrapper.hxx>
43 #include <vos/thread.hxx>
44 
45 #include <deque>
46 
47 // ===================================================================================================
48 // = class FmSearchThread - wie der Name schon sagt
49 // ===================================================================================================
50 
51 class FmSearchEngine;
52 class FmSearchThread : public ::vos::OThread
53 {
54     FmSearchEngine*     m_pEngine;
55     Link                m_aTerminationHdl;
56 
57     virtual void SAL_CALL run();
58     virtual void SAL_CALL onTerminated();
59 
60 public:
FmSearchThread(FmSearchEngine * pEngine)61     FmSearchThread(FmSearchEngine* pEngine) : m_pEngine(pEngine) { }
setTerminationHandler(Link aHdl)62     void setTerminationHandler(Link aHdl) { m_aTerminationHdl = aHdl; }
63 };
64 
65 // ===================================================================================================
66 // = struct FmSearchProgress - diese Struktur bekommt der Owner der SearchEngine fuer Status-Updates
67 // = (und am Ende der Suche)
68 // ===================================================================================================
69 
70 struct FmSearchProgress
71 {
72     enum STATE { STATE_PROGRESS, STATE_PROGRESS_COUNTING, STATE_CANCELED, STATE_SUCCESSFULL, STATE_NOTHINGFOUND, STATE_ERROR };
73         // (Bewegung auf neuen Datensatz; Fortschritt beim Zaehlen von Datensaetzen; abgebrochen; Datensatz gefunden;
74         // nichts gefunden, irgendein nicht zu handelnder Fehler)
75     STATE   aSearchState;
76 
77     // aktueller Datensatz - immer gueltig (ist zum Beispiel bei Abbrechen auch fuer das Weitersuchen interesant)
78     sal_uInt32  nCurrentRecord;
79     // Ueberlauf - nur gueltig bei STATE_PROGRESS
80     sal_Bool    bOverflow;
81 
82     // die Position des Such-Cursors - bei STATE_SUCCESSFULL, STATE_CANCELED und STATE_NOTHING_FOUND gueltig
83     ::com::sun::star::uno::Any  aBookmark;
84     // das Feld, in dem der Text gefunden wurde - bei STATE_SUCCESSFULL gueltig
85     sal_Int32   nFieldIndex;
86 };
87 
88 // ===================================================================================================
89 // = class FmRecordCountListener - Hilfsklasse fuer FmSearchEngine, lauscht an einem Cursor und teilt
90 // =                                Aenderungem im RecordCount mit
91 // ===================================================================================================
92 
93 class FmRecordCountListener : public ::cppu::WeakImplHelper1< ::com::sun::star::beans::XPropertyChangeListener>
94 {
95 // Atribute
96     Link            m_lnkWhoWantsToKnow;
97     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >   m_xListening;
98 
99 // Attribut-Zugriff
100 public:
101     Link SetPropChangeHandler(const Link& lnk);
102 
103 // Oprationen
104 public:
105     FmRecordCountListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& dbcCursor);
106         // the set has to support the sdb::ResultSet service
107     virtual ~FmRecordCountListener();
108 
109     //  DECLARE_UNO3_AGG_DEFAULTS(FmPropertyListener, UsrObject);
110     //  virtual sal_Bool queryInterface(::com::sun::star::uno::Uik aUik, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rOut);
111 
112 // ::com::sun::star::lang::XEventListener
113     virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw(::com::sun::star::uno::RuntimeException);
114 
115 // ::com::sun::star::beans::XPropertyChangeListener
116     virtual void SAL_CALL propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);
117 
118     void DisConnect();
119 
120 private:
121     void NotifyCurrentCount();
122 
123 };
124 
125 // ===================================================================================================
126 // = class FmSearchEngine - Impl-Klasse fuer FmSearchDialog
127 // ===================================================================================================
128 
129 namespace svxform {
130     // We have three possible control types we may search in, determined by the supported interfaces : ::com::sun::star::awt::XTextComponent, ::com::sun::star::awt::XListBox, ::com::sun::star::awt::XCheckBox.
131     // While searching we don't want to do this distinction for every control in every round. So we need some helpers.
132     class ControlTextWrapper
133     {
134         // attributes
135         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >   m_xControl;
136         // attribute access
137     public:
getControl() const138         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >  getControl() const{ return m_xControl; }
139     public:
ControlTextWrapper(const::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> & _xControl)140         ControlTextWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xControl) { m_xControl = _xControl; }
~ControlTextWrapper()141         virtual ~ControlTextWrapper() { }
142 
143         virtual ::rtl::OUString getCurrentText() const = 0;
144     };
145     class SimpleTextWrapper : public ControlTextWrapper
146     {
147         ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent >  m_xText;
148     public:
149         SimpleTextWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent >& _xText);
150         virtual ::rtl::OUString getCurrentText() const;
151     };
152     class ListBoxWrapper : public ControlTextWrapper
153     {
154         ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >  m_xBox;
155     public:
156         ListBoxWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >& _xBox);
157         virtual ::rtl::OUString getCurrentText() const;
158     };
159     class CheckBoxWrapper : public ControlTextWrapper
160     {
161         ::com::sun::star::uno::Reference< ::com::sun::star::awt::XCheckBox >  m_xBox;
162     public:
163         CheckBoxWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XCheckBox >& _xBox);
164         virtual ::rtl::OUString getCurrentText() const;
165     };
166 }
167 
168 enum FMSEARCH_MODE { SM_BRUTE, SM_ALLOWSCHEDULE, SM_USETHREAD };
169 
170 DECLARE_STL_VECTOR( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>, InterfaceArray);
171 
172 class SVX_DLLPUBLIC FmSearchEngine
173 {
174     friend class FmSearchThread;
175 
176     enum SEARCH_RESULT { SR_FOUND, SR_NOTFOUND, SR_ERROR, SR_CANCELED };
177     enum SEARCHFOR_TYPE { SEARCHFOR_STRING, SEARCHFOR_NULL, SEARCHFOR_NOTNULL };
178 
179     // zugrundeliegende Daten
180     CursorWrapper                   m_xSearchCursor;
181     std::deque<sal_Int32>           m_arrFieldMapping;
182         // da der Iterator durchaus mehr Spalten haben kann, als ich eigentlich verwalte (in meiner Feld-Listbox),
183         // muss ich mir hier ein Mapping dieser ::com::sun::star::form-Schluessel auf die Indizies der entsprechenden Spalten im Iterator halten
184 
185     // der Formatter
186     ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >  m_xFormatSupplier;
187     ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter >        m_xFormatter;
188 
189     CharClass               m_aCharacterClassficator;
190     CollatorWrapper         m_aStringCompare;
191 
192     // die Sammlung aller interesanten Felder (bzw. ihre ::com::sun::star::data::XDatabaseVariant-Interfaces und ihre FormatKeys)
193     struct FieldInfo
194     {
195         ::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumn >          xContents;
196         sal_uInt32              nFormatKey;
197         sal_Bool                bDoubleHandling;
198     };
199 
200     DECLARE_STL_VECTOR(FieldInfo, FieldCollection);
201     FieldCollection             m_arrUsedFields;
202     sal_Int32                   m_nCurrentFieldIndex;   // der letzte Parameter von RebuildUsedFields, ermoeglicht mir Checks in FormatField
203 
204     DECLARE_STL_VECTOR(svxform::ControlTextWrapper*, ControlTextSuppliers);
205     ControlTextSuppliers    m_aControlTexts;
206 
207     sal_Bool                m_bUsingTextComponents;
208     CursorWrapper           m_xOriginalIterator;
209     CursorWrapper           m_xClonedIterator;
210 
211     // Daten fuer Entscheidung, in welchem Feld ich ein "Found" akzeptiere
212     ::com::sun::star::uno::Any  m_aPreviousLocBookmark;             // Position, an der ich zuletzt fuendig war
213     FieldCollectionIterator     m_iterPreviousLocField;             // dito Feld
214 
215     // Kommunikation mit dem Thread, der die eigentliche Suche durchfuehrt
216     ::rtl::OUString             m_strSearchExpression;              // Hinrichtung
217     SEARCHFOR_TYPE      m_eSearchForType;                   // dito
218     SEARCH_RESULT       m_srResult;                         // Rueckrichtung
219 
220     // der Link, dem ich Fortschritte und Ergebnisse mitteile
221     Link                m_aProgressHandler;
222     sal_Bool            m_bSearchingCurrently : 1;      // laeuft gerade eine (asynchrone) Suche ?
223     sal_Bool            m_bCancelAsynchRequest : 1;     // soll abgebrochen werden ?
224     ::osl::Mutex        m_aCancelAsynchAccess;          // Zugriff auf m_bCancelAsynchRequest (eigentlich nur bei
225                                                         // m_eMode == SM_USETHREAD interesant)
226     FMSEARCH_MODE   m_eMode;        //CHINA001  FmSearchDialog::SEARCH_MODE m_eMode;                // der aktuelle Modus
227     // der aktuelle Modus
228 
229     // Parameter fuer die Suche
230     sal_Bool    m_bFormatter : 1;       // Feldformatierung benutzen
231     sal_Bool    m_bForward : 1;         // Richtung
232     sal_Bool    m_bWildcard : 1;        // Platzhalter-Suche ?
233     sal_Bool    m_bRegular : 1;         // regulaerer Ausdruck
234     sal_Bool    m_bLevenshtein : 1;     // Levenshtein-Suche
235     sal_Bool    m_bTransliteration : 1; // Levenshtein-Suche
236 
237     sal_Bool    m_bLevRelaxed : 1;      // Parameter fuer Levenshtein-Suche
238     sal_uInt16  m_nLevOther;
239     sal_uInt16  m_nLevShorter;
240     sal_uInt16  m_nLevLonger;
241 
242     sal_uInt16  m_nPosition;            // wenn nicht regulaer oder lev, dann einer der MATCHING_...-Werte
243 
244     sal_Int32   m_nTransliterationFlags;
245 
246 // -------------
247 // Memberzugriff
248 private:
249     SVX_DLLPRIVATE sal_Bool CancelRequested();      // liefert eine durch m_aCancelAsynchAccess gesicherte Auswertung von m_bCancelAsynchRequest
250 
251 public:
252     void        SetCaseSensitive(sal_Bool bSet);
253     sal_Bool    GetCaseSensitive() const;
254 
255     void        SetFormatterUsing(sal_Bool bSet);   // das ist etwas umfangreicher, deshalb kein hier inline ....
GetFormatterUsing() const256     sal_Bool    GetFormatterUsing() const           { return m_bFormatter; }
257 
SetDirection(sal_Bool bForward)258     void        SetDirection(sal_Bool bForward)     { m_bForward = bForward; }
GetDirection() const259     sal_Bool    GetDirection() const                { return m_bForward; }
260 
SetWildcard(sal_Bool bSet)261     void        SetWildcard(sal_Bool bSet)          { m_bWildcard = bSet; }
GetWildcard() const262     sal_Bool    GetWildcard() const                 { return m_bWildcard; }
263 
SetRegular(sal_Bool bSet)264     void        SetRegular(sal_Bool bSet)           { m_bRegular = bSet; }
GetRegular() const265     sal_Bool    GetRegular() const                  { return m_bRegular; }
266 
SetLevenshtein(sal_Bool bSet)267     void        SetLevenshtein(sal_Bool bSet)       { m_bLevenshtein = bSet; }
GetLevenshtein() const268     sal_Bool    GetLevenshtein() const              { return m_bLevenshtein; }
269 
270     void        SetIgnoreWidthCJK(sal_Bool bSet);
271     sal_Bool    GetIgnoreWidthCJK() const;
272 
SetTransliteration(sal_Bool bSet)273     void        SetTransliteration(sal_Bool bSet)   { m_bTransliteration = bSet; }
GetTransliteration() const274     sal_Bool    GetTransliteration() const          { return m_bTransliteration; }
275 
SetLevRelaxed(sal_Bool bSet)276     void        SetLevRelaxed(sal_Bool bSet)        { m_bLevRelaxed = bSet; }
GetLevRelaxed() const277     sal_Bool    GetLevRelaxed() const               { return m_bLevRelaxed; }
SetLevOther(sal_uInt16 nHowMuch)278     void        SetLevOther(sal_uInt16 nHowMuch)    { m_nLevOther = nHowMuch; }
GetLevOther() const279     sal_uInt16  GetLevOther() const                 { return m_nLevOther; }
SetLevShorter(sal_uInt16 nHowMuch)280     void        SetLevShorter(sal_uInt16 nHowMuch)  { m_nLevShorter = nHowMuch; }
GetLevShorter() const281     sal_uInt16  GetLevShorter() const               { return m_nLevShorter; }
SetLevLonger(sal_uInt16 nHowMuch)282     void        SetLevLonger(sal_uInt16 nHowMuch)   { m_nLevLonger = nHowMuch; }
GetLevLonger() const283     sal_uInt16  GetLevLonger() const                { return m_nLevLonger; }
284         // die ganzen Lev-Werte werden nur bei  m_bLevenshtein==sal_True beachtet
285 
SetTransliterationFlags(sal_Int32 _nFlags)286     void        SetTransliterationFlags(sal_Int32 _nFlags)  { m_nTransliterationFlags = _nFlags; }
GetTransliterationFlags() const287     sal_Int32   GetTransliterationFlags() const             { return m_nTransliterationFlags; }
288 
SetPosition(sal_uInt16 nValue)289     void    SetPosition(sal_uInt16 nValue)      { m_nPosition = nValue; }
GetPosition() const290     sal_uInt16  GetPosition() const             { return m_nPosition; }
291         // Position wird bei m_bWildCard==sal_True nicht beachtet
292 
GetSearchMode() const293     FMSEARCH_MODE GetSearchMode() const { return m_eMode; }
294 
295 public:
296     /** zwei Constructoren, beide analog zu denen des FmSearchDialog, Erklaerung siehe also dort ....
297         xCursor muss jeweils den ::com::sun::star::data::DatabaseCursor-Service implementieren.
298         wenn eMode == SM_USETHREAD, sollte ein ProgressHandler gesetzt sein, da dann die Ergebnisuebermittlung ueber diesen
299         Handler erfolgt.
300         Ist eMode != SM_USETHREAD, kehren SearchNext und StarOver nicht zurueck, bevor die Suche (erfolgreich oder nicht) beendet
301         wurde, dann kann man das Ergebnis danach abfragen. Ist zusaetzlich der ProgressHandler gesetzt, wird dieser fuer jeden neuen
302         Datensatz sowie am Ende der Suche aufgerufen.
303     */
304     FmSearchEngine(
305         const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
306         const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor,
307         const ::rtl::OUString& strVisibleFields,
308         const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xFormat,
309         FMSEARCH_MODE eMode);//CHINA001 FmSearchDialog::SEARCH_MODE eMode);
310     FmSearchEngine(
311         const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
312         const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor,
313         const ::rtl::OUString& strVisibleFields,
314         const InterfaceArray& arrFields,
315         FMSEARCH_MODE eMode); //CHINA001 FmSearchDialog::SEARCH_MODE eMode);
316 
317     virtual ~FmSearchEngine();
318 
319     /** der Link wird fuer jeden Datensatz und nach Beendigung der Suche aufgerufen, Parameter ist ein Zeiger auf
320         eine FmSearchProgress-Struktur
321         der Handler sollte auf jeden Fall Thread-sicher sein
322     */
SetProgressHandler(Link aHdl)323     void SetProgressHandler(Link aHdl) { m_aProgressHandler = aHdl; }
324 
325     /// das naechste Vorkommen suchen (Werte fuer nDirection siehe DIRECTION_*-defines)
326     void SearchNext(const ::rtl::OUString& strExpression);
327     /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
328     void SearchNextSpecial(sal_Bool _bSearchForNull);
329     /// das naechste Vorkommen suchen, abhaengig von nDirection wird dabei am Anfang oder am Ende neu begonnen
330     void StartOver(const ::rtl::OUString& strExpression);
331     /// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
332     void StartOverSpecial(sal_Bool _bSearchForNull);
333     /// die Angaben ueber letzte Fundstelle invalidieren
334     void InvalidatePreviousLoc();
335 
336     /** baut m_arrUsedFields neu auf (nFieldIndex==-1 bedeutet alle Felder, ansonsten gibt es den Feldindex an)
337         wenn bForce nicht gesetzt ist, passiert bei nFieldIndex == m_nCurrentFieldIndex nichts
338         (ruft InvalidatePreviousLoc auf)
339     */
340     void RebuildUsedFields(sal_Int32 nFieldIndex, sal_Bool bForce = sal_False);
341     ::rtl::OUString FormatField(sal_Int32 nWhich);
342 
343     /// kehrt sofort zurueck; nachdem wirklich abgebrochen wurde, wird der ProgressHandler mit STATE_CANCELED aufgerufen
344     void CancelSearch();
345 
346     /** nur gueltig, wenn nicht gerade eine (asynchrone) Suche laeuft, die naechste Suche wird dann auf dem neuen Iterator
347         mit den neuen Parametern durchgefuehrt
348     */
349     sal_Bool SwitchToContext(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor, const ::rtl::OUString& strVisibleFields, const InterfaceArray& arrFields,
350         sal_Int32 nFieldIndex);
351 
352 protected:
353     void Init(const ::rtl::OUString& strVisibleFields);
354 
355     void SearchNextImpl();
356         // diese Impl-Methode laeuft im SearchThread
357 
358     // start a thread-search (or call SearchNextImpl directly, depending on the search mode)
359     void ImplStartNextSearch();
360 
361 private:
362     SVX_DLLPRIVATE void clearControlTexts();
363     SVX_DLLPRIVATE void fillControlTexts(const InterfaceArray& arrFields);
364 
365     // three methods implementing a complete search loop (null/not null, wildcard, SearchText)
366     // (they all have some code in common, but with this solution we have do do a distinction only once per search (before
367     // starting the loop), not in every loop step
368     SVX_DLLPRIVATE SEARCH_RESULT SearchSpecial(sal_Bool _bSearchForNull, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
369         const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
370     SVX_DLLPRIVATE SEARCH_RESULT SearchWildcard(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
371         const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
372     SVX_DLLPRIVATE SEARCH_RESULT SearchRegularApprox(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
373         const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
374 
375     SVX_DLLPRIVATE void PropagateProgress(sal_Bool _bDontPropagateOverflow);
376         // ruft den ProgressHandler mit STATE_PROGRESS und der aktuellen Position des SearchIterators auf
377 
378     // helpers, die ich mehrmals brauche
379     SVX_DLLPRIVATE sal_Bool MoveCursor();
380         // bewegt m_xSearchIterator unter Beachtung von Richtung/Ueberlauf Cursor
381     SVX_DLLPRIVATE sal_Bool MoveField(sal_Int32& nPos, FieldCollectionIterator& iter, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
382         // bewegt den Iterator unter Beachtung von Richtung/Ueberlauf Iterator/Ueberlauf Cursor
383     SVX_DLLPRIVATE void BuildAndInsertFieldInfo(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& xAllFields, sal_Int32 nField);
384         // baut eine FieldInfo zum Feld Nummer nField (in xAllFields) auf und fuegt sie zu m_arrUsedFields hinzu
385         // xAllFields muss den DatabaseRecord-Service unterstuetzen
386     SVX_DLLPRIVATE ::rtl::OUString FormatField(const FieldInfo& rField);
387         // formatiert das Feld mit dem NumberFormatter
388 
HasPreviousLoc()389     SVX_DLLPRIVATE sal_Bool HasPreviousLoc() { return m_aPreviousLocBookmark.hasValue(); }
390 
391     DECL_LINK(OnSearchTerminated, FmSearchThread*);
392         // wird vom SuchThread benutzt, nach Rueckkehr aus diesem Handler loescht sich der Thread selber
393     DECL_LINK(OnNewRecordCount, void*);
394 };
395 
396 #endif // _FMSRCIMP_HXX
397 
398