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 #include <tools/debug.hxx>
21 #include <vcl/msgbox.hxx>
22 #include <vcl/svapp.hxx>
23 #include <tools/shl.hxx>
24 #include <dialmgr.hxx>
25 #include <sfx2/tabdlg.hxx>
26 #include <osl/mutex.hxx>
27 #include <sfx2/app.hxx>
29 #include <svl/filerec.hxx>
30 #include <svx/fmsrccfg.hxx>
31 #include <svx/fmsrcimp.hxx>
32 #include "fmsearch.hrc"
33 #include "cuifmsearch.hxx"
34 #include <svx/srchdlg.hxx>
35 #include <svl/cjkoptions.hxx>
36 #include <com/sun/star/i18n/TransliterationModules.hpp>
37 #include <comphelper/processfactory.hxx>
38 #include <comphelper/string.hxx>
39 #include <svx/svxdlg.hxx>
40 #include <sal/macros.h>
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::i18n
;
44 using namespace ::svxform
;
45 using namespace ::com::sun::star::sdbc
;
46 using namespace ::com::sun::star::util
;
48 #define MAX_HISTORY_ENTRIES 50
50 //------------------------------------------------------------------------
51 void FmSearchDialog::initCommon( const Reference
< XResultSet
>& _rxCursor
)
54 DBG_ASSERT( m_pSearchEngine
, "FmSearchDialog::initCommon: have no engine!" );
55 m_pSearchEngine
->SetProgressHandler(LINK(this, FmSearchDialog
, OnSearchProgress
));
57 // some layout changes according to available CJK options
58 SvtCJKOptions aCJKOptions
;
59 if (!aCJKOptions
.IsJapaneseFindEnabled())
61 sal_Int32 nUpper
= m_cbApprox
.GetPosPixel().Y();
62 sal_Int32 nDifference
= m_aSoundsLikeCJKSettings
.GetPosPixel().Y() - nUpper
;
64 // hide the options for the japanese search
65 Control
* pFieldsToMove
[] = { &m_flState
, &m_ftRecordLabel
, &m_ftRecord
, &m_ftHint
};
66 implMoveControls(pFieldsToMove
, SAL_N_ELEMENTS(pFieldsToMove
), nDifference
, &m_flOptions
);
68 m_aSoundsLikeCJK
.Hide();
69 m_aSoundsLikeCJKSettings
.Hide();
72 if (!aCJKOptions
.IsCJKFontEnabled())
74 m_aHalfFullFormsCJK
.Hide();
76 // never ignore the width (ignoring is expensive) if the option is not available at all
77 m_pSearchEngine
->SetIgnoreWidthCJK( sal_False
);
80 // some initial record texts
81 m_ftRecord
.SetText( OUString::number(_rxCursor
->getRow()) );
82 m_pbClose
.SetHelpText(String());
85 //------------------------------------------------------------------------
86 FmSearchDialog::FmSearchDialog(Window
* pParent
, const OUString
& sInitialText
, const ::std::vector
< OUString
>& _rContexts
, sal_Int16 nInitialContext
,
87 const Link
& lnkContextSupplier
)
88 :ModalDialog(pParent
, CUI_RES(RID_SVXDLG_SEARCHFORM
))
89 ,m_flSearchFor (this, CUI_RES(FL_SEARCHFOR
))
90 ,m_rbSearchForText (this, CUI_RES(RB_SEARCHFORTEXT
))
91 ,m_rbSearchForNull (this, CUI_RES(RB_SEARCHFORNULL
))
92 ,m_rbSearchForNotNull (this, CUI_RES(RB_SEARCHFORNOTNULL
))
93 ,m_cmbSearchText (this, CUI_RES(CMB_SEARCHTEXT
))
94 ,m_flWhere (this, CUI_RES(FL_WHERE
))
95 ,m_ftForm (this, CUI_RES(FT_FORM
))
96 ,m_lbForm (this, CUI_RES(LB_FORM
))
97 ,m_rbAllFields (this, CUI_RES(RB_ALLFIELDS
))
98 ,m_rbSingleField (this, CUI_RES(RB_SINGLEFIELD
))
99 ,m_lbField (this, CUI_RES(LB_FIELD
))
100 ,m_flOptions (this, CUI_RES(FL_OPTIONS
))
101 ,m_ftPosition (this, CUI_RES(FT_POSITION
))
102 ,m_lbPosition (this, CUI_RES(LB_POSITION
))
103 ,m_cbUseFormat (this, CUI_RES(CB_USEFORMATTER
))
104 ,m_cbCase (this, CUI_RES(CB_CASE
))
105 ,m_cbBackwards (this, CUI_RES(CB_BACKWARD
))
106 ,m_cbStartOver (this, CUI_RES(CB_STARTOVER
))
107 ,m_cbWildCard (this, CUI_RES(CB_WILDCARD
))
108 ,m_cbRegular (this, CUI_RES(CB_REGULAR
))
109 ,m_cbApprox (this, CUI_RES(CB_APPROX
))
110 ,m_pbApproxSettings (this, CUI_RES(PB_APPROXSETTINGS
))
111 ,m_aHalfFullFormsCJK (this, CUI_RES(CB_HALFFULLFORMS
))
112 ,m_aSoundsLikeCJK (this, CUI_RES(CB_SOUNDSLIKECJK
))
113 ,m_aSoundsLikeCJKSettings (this, CUI_RES(PB_SOUNDSLIKESETTINGS
))
114 ,m_flState (this, CUI_RES(FL_STATE
))
115 ,m_ftRecordLabel (this, CUI_RES(FT_RECORDLABEL
))
116 ,m_ftRecord (this, CUI_RES(FT_RECORD
))
117 ,m_ftHint (this, CUI_RES(FT_HINT
))
118 ,m_pbSearchAgain (this, CUI_RES(PB_SEARCH
))
119 ,m_pbClose (this, CUI_RES(1))
120 ,m_pbHelp (this, CUI_RES(1))
121 ,m_sSearch ( m_pbSearchAgain
.GetText() )
122 ,m_sCancel ( Button::GetStandardText( BUTTON_CANCEL
) )
123 ,m_pPreSearchFocus( NULL
)
124 ,m_lnkContextSupplier(lnkContextSupplier
)
127 DBG_ASSERT(m_lnkContextSupplier
.IsSet(), "FmSearchDialog::FmSearchDialog : have no ContextSupplier !");
129 FmSearchContext fmscInitial
;
130 fmscInitial
.nContext
= nInitialContext
;
131 m_lnkContextSupplier
.Call(&fmscInitial
);
132 DBG_ASSERT(fmscInitial
.xCursor
.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
133 DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial
.strUsedFields
, ';') == (xub_StrLen
)fmscInitial
.arrFields
.size(),
134 "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplied !");
135 #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
136 for (sal_Int32 i
=0; i
<(sal_Int32
)fmscInitial
.arrFields
.size(); ++i
)
137 DBG_ASSERT(fmscInitial
.arrFields
.at(i
).is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
138 #endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL
140 for ( ::std::vector
< OUString
>::const_iterator context
= _rContexts
.begin();
141 context
!= _rContexts
.end();
145 m_arrContextFields
.push_back(OUString());
146 m_lbForm
.InsertEntry(*context
);
148 m_lbForm
.SelectEntryPos(nInitialContext
);
150 m_lbForm
.SetSelectHdl(LINK(this, FmSearchDialog
, OnContextSelection
));
152 if (m_arrContextFields
.size() == 1)
153 { // remove the context selection listbox and rearrange the controls accordingly
154 sal_Int32 nUpper
= m_lbForm
.GetPosPixel().Y();
155 sal_Int32 nDifference
= m_rbAllFields
.GetPosPixel().Y() - nUpper
;
157 // move all controls below the affected ones up
158 Control
* pFieldsToMove
[] = { &m_rbAllFields
, &m_rbSingleField
, &m_lbField
, &m_flOptions
, &m_ftPosition
, &m_lbPosition
,
159 &m_cbUseFormat
, &m_cbCase
, &m_cbBackwards
, &m_cbStartOver
, &m_cbWildCard
, &m_cbRegular
, &m_cbApprox
,
160 &m_pbApproxSettings
, &m_aHalfFullFormsCJK
, &m_aSoundsLikeCJK
, &m_aSoundsLikeCJKSettings
,
161 &m_flState
, &m_ftRecordLabel
, &m_ftRecord
, &m_ftHint
};
163 implMoveControls(pFieldsToMove
, SAL_N_ELEMENTS(pFieldsToMove
), nDifference
, &m_flWhere
);
165 Point pt
= m_rbAllFields
.GetPosPixel();
166 pt
.X() = m_ftForm
.GetPosPixel().X();
167 m_rbAllFields
.SetPosPixel( pt
);
168 pt
= m_rbSingleField
.GetPosPixel();
169 pt
.X() = m_ftForm
.GetPosPixel().X();
170 m_rbSingleField
.SetPosPixel( pt
);
172 // hide dispensable controls
177 m_pSearchEngine
= new FmSearchEngine(
178 ::comphelper::getProcessComponentContext(), fmscInitial
.xCursor
, fmscInitial
.strUsedFields
, fmscInitial
.arrFields
, SM_ALLOWSCHEDULE
);
179 initCommon( fmscInitial
.xCursor
);
181 if (fmscInitial
.sFieldDisplayNames
.Len() != 0)
182 { // use the display names if supplied
183 DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial
.sFieldDisplayNames
, ';') == comphelper::string::getTokenCount(fmscInitial
.strUsedFields
, ';'),
184 "FmSearchDialog::FmSearchDialog : invalid initial context description !");
185 Init(fmscInitial
.sFieldDisplayNames
, sInitialText
);
188 Init(fmscInitial
.strUsedFields
, sInitialText
);
191 //------------------------------------------------------------------------
192 void FmSearchDialog::implMoveControls(
193 Control
** _ppControls
,
194 sal_Int32 _nControls
,
196 Control
* /*_pToResize*/)
198 for (sal_Int32 i
=0; i
<_nControls
; ++i
)
200 Point pt
= _ppControls
[i
]->GetPosPixel();
202 _ppControls
[i
]->SetPosPixel(pt
);
206 Size sz
= GetSizePixel();
211 //------------------------------------------------------------------------
212 FmSearchDialog::~FmSearchDialog()
214 if (m_aDelayedPaint
.IsActive())
215 m_aDelayedPaint
.Stop();
225 delete m_pSearchEngine
;
228 //------------------------------------------------------------------------
229 void FmSearchDialog::Init(const OUString
& strVisibleFields
, const OUString
& sInitialText
)
231 //the initialization of all the Controls
232 m_rbSearchForText
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedFieldRadios
));
233 m_rbSearchForNull
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedFieldRadios
));
234 m_rbSearchForNotNull
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedFieldRadios
));
236 m_rbAllFields
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedFieldRadios
));
237 m_rbSingleField
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedFieldRadios
));
239 m_pbSearchAgain
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedSearchAgain
));
240 m_pbApproxSettings
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedSpecialSettings
));
241 m_aSoundsLikeCJKSettings
.SetClickHdl(LINK(this, FmSearchDialog
, OnClickedSpecialSettings
));
243 m_lbPosition
.SetSelectHdl(LINK(this, FmSearchDialog
, OnPositionSelected
));
244 m_lbField
.SetSelectHdl(LINK(this, FmSearchDialog
, OnFieldSelected
));
246 m_cmbSearchText
.SetModifyHdl(LINK(this, FmSearchDialog
, OnSearchTextModified
));
247 m_cmbSearchText
.EnableAutocomplete(sal_False
);
249 m_cbUseFormat
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
250 m_cbBackwards
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
251 m_cbStartOver
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
252 m_cbCase
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
253 m_cbWildCard
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
254 m_cbRegular
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
255 m_cbApprox
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
256 m_aHalfFullFormsCJK
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
257 m_aSoundsLikeCJK
.SetToggleHdl(LINK(this, FmSearchDialog
, OnCheckBoxToggled
));
259 // fill the listboxes
260 // method of field comparison
261 sal_uInt16 nResIds
[] = {
262 RID_STR_SEARCH_ANYWHERE
,
263 RID_STR_SEARCH_BEGINNING
,
267 for ( size_t i
=0; i
<SAL_N_ELEMENTS(nResIds
); ++i
)
268 m_lbPosition
.InsertEntry( String( CUI_RES( nResIds
[i
] ) ) );
269 m_lbPosition
.SelectEntryPos(MATCHING_ANYWHERE
);
272 for (sal_Int32 i
=0; i
< comphelper::string::getTokenCount(strVisibleFields
, ';'); ++i
)
273 m_lbField
.InsertEntry(comphelper::string::getToken(strVisibleFields
, i
, ';'));
276 m_pConfig
= new FmSearchConfigItem
;
279 m_cmbSearchText
.SetText(sInitialText
);
280 // if the Edit-line has changed the text (e.g. because it contains
281 // control characters, as can be the case with memo fields), I use
282 // an empty OUString.
283 OUString sRealSetText
= m_cmbSearchText
.GetText();
284 if (!sRealSetText
.equals(sInitialText
))
285 m_cmbSearchText
.SetText(OUString());
286 LINK(this, FmSearchDialog
, OnSearchTextModified
).Call(&m_cmbSearchText
);
289 m_aDelayedPaint
.SetTimeoutHdl(LINK(this, FmSearchDialog
, OnDelayedPaint
));
290 m_aDelayedPaint
.SetTimeout(500);
291 EnableSearchUI(sal_True
);
293 if ( m_rbSearchForText
.IsChecked() )
294 m_cmbSearchText
.GrabFocus();
299 //------------------------------------------------------------------------
300 sal_Bool
FmSearchDialog::Close()
302 // If the close button is disabled and ESC is pressed in a dialog,
303 // then Frame will call Close anyway, which I don't want to happen
304 // while I'm in the middle of a search (maybe one that's running
305 // in its own thread)
306 if (!m_pbClose
.IsEnabled())
308 return ModalDialog::Close();
311 //------------------------------------------------------------------------
312 IMPL_LINK(FmSearchDialog
, OnClickedFieldRadios
, Button
*, pButton
)
314 if ((pButton
== &m_rbSearchForText
) || (pButton
== &m_rbSearchForNull
) || (pButton
== &m_rbSearchForNotNull
))
316 EnableSearchForDependees(sal_True
);
319 // en- or disable field list box accordingly
320 if (pButton
== &m_rbSingleField
)
323 m_pSearchEngine
->RebuildUsedFields(m_lbField
.GetSelectEntryPos());
328 m_pSearchEngine
->RebuildUsedFields(-1);
334 //------------------------------------------------------------------------
335 IMPL_LINK_NOARG(FmSearchDialog
, OnClickedSearchAgain
)
337 if (m_pbClose
.IsEnabled())
338 { // the button has the function 'search'
339 OUString strThisRoundText
= m_cmbSearchText
.GetText();
341 m_cmbSearchText
.RemoveEntry(strThisRoundText
);
342 m_cmbSearchText
.InsertEntry(strThisRoundText
, 0);
343 // the remove/insert makes sure that a) the OUString does not appear twice and
344 // that b) the last searched strings are at the beginning and limit the list length
345 while (m_cmbSearchText
.GetEntryCount() > MAX_HISTORY_ENTRIES
)
346 m_cmbSearchText
.RemoveEntry(m_cmbSearchText
.GetEntryCount()-1);
348 // take out the 'overflow' hint
349 m_ftHint
.SetText(OUString());
350 m_ftHint
.Invalidate();
352 if (m_cbStartOver
.IsChecked())
354 m_cbStartOver
.Check(sal_False
);
355 EnableSearchUI(sal_False
);
356 if (m_rbSearchForText
.IsChecked())
357 m_pSearchEngine
->StartOver(strThisRoundText
);
359 m_pSearchEngine
->StartOverSpecial(m_rbSearchForNull
.IsChecked());
363 EnableSearchUI(sal_False
);
364 if (m_rbSearchForText
.IsChecked())
365 m_pSearchEngine
->SearchNext(strThisRoundText
);
367 m_pSearchEngine
->SearchNextSpecial(m_rbSearchForNull
.IsChecked());
371 { // the button has the function 'cancel'
372 DBG_ASSERT(m_pSearchEngine
->GetSearchMode() != SM_BRUTE
, "FmSearchDialog, OnClickedSearchAgain : falscher Modus !");
373 // the CancelButton is usually only disabled, when working in a thread or with reschedule
374 m_pSearchEngine
->CancelSearch();
375 // the ProgressHandler is called when it's really finished, here it's only a demand
380 //------------------------------------------------------------------------
381 IMPL_LINK(FmSearchDialog
, OnClickedSpecialSettings
, Button
*, pButton
)
383 if (&m_pbApproxSettings
== pButton
)
385 AbstractSvxSearchSimilarityDialog
* pDlg
= NULL
;
387 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
389 pDlg
= pFact
->CreateSvxSearchSimilarityDialog( this, m_pSearchEngine
->GetLevRelaxed(), m_pSearchEngine
->GetLevOther(),
390 m_pSearchEngine
->GetLevShorter(), m_pSearchEngine
->GetLevLonger() );
391 DBG_ASSERT( pDlg
, "FmSearchDialog, OnClickedSpecialSettings: could not load the dialog!" );
393 if ( pDlg
&& pDlg
->Execute() == RET_OK
)
395 m_pSearchEngine
->SetLevRelaxed( pDlg
->IsRelaxed() );
396 m_pSearchEngine
->SetLevOther( pDlg
->GetOther() );
397 m_pSearchEngine
->SetLevShorter(pDlg
->GetShorter() );
398 m_pSearchEngine
->SetLevLonger( pDlg
->GetLonger() );
402 else if (&m_aSoundsLikeCJKSettings
== pButton
)
404 SfxItemSet
aSet( SFX_APP()->GetPool() );
405 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
408 AbstractSvxJSearchOptionsDialog
* aDlg
= pFact
->CreateSvxJSearchOptionsDialog( this, aSet
, m_pSearchEngine
->GetTransliterationFlags() );
409 DBG_ASSERT(aDlg
, "Dialogdiet fail!");
413 sal_Int32 nFlags
= aDlg
->GetTransliterationFlags();
414 m_pSearchEngine
->SetTransliterationFlags(nFlags
);
416 m_cbCase
.Check(m_pSearchEngine
->GetCaseSensitive());
417 OnCheckBoxToggled( &m_cbCase
);
418 m_aHalfFullFormsCJK
.Check( !m_pSearchEngine
->GetIgnoreWidthCJK() );
419 OnCheckBoxToggled( &m_aHalfFullFormsCJK
);
427 //------------------------------------------------------------------------
428 IMPL_LINK_NOARG(FmSearchDialog
, OnSearchTextModified
)
430 if ((!m_cmbSearchText
.GetText().isEmpty()) || !m_rbSearchForText
.IsChecked())
431 m_pbSearchAgain
.Enable();
433 m_pbSearchAgain
.Disable();
435 m_pSearchEngine
->InvalidatePreviousLoc();
439 //------------------------------------------------------------------------
440 IMPL_LINK(FmSearchDialog
, OnPositionSelected
, ListBox
*, pBox
)
442 (void) pBox
; // avoid warning
443 DBG_ASSERT(pBox
->GetSelectEntryCount() == 1, "FmSearchDialog::OnMethodSelected : unerwartet : nicht genau ein Eintrag selektiert !");
445 m_pSearchEngine
->SetPosition(m_lbPosition
.GetSelectEntryPos());
449 //------------------------------------------------------------------------
450 IMPL_LINK(FmSearchDialog
, OnFieldSelected
, ListBox
*, pBox
)
452 (void) pBox
; // avoid warning
453 DBG_ASSERT(pBox
->GetSelectEntryCount() == 1, "FmSearchDialog::OnFieldSelected : unerwartet : nicht genau ein Eintrag selektiert !");
455 m_pSearchEngine
->RebuildUsedFields(m_rbAllFields
.IsChecked() ? -1 : (sal_Int16
)m_lbField
.GetSelectEntryPos());
456 // calls m_pSearchEngine->InvalidatePreviousLoc too
458 sal_Int32 nCurrentContext
= m_lbForm
.GetSelectEntryPos();
459 if (nCurrentContext
!= LISTBOX_ENTRY_NOTFOUND
)
460 m_arrContextFields
[nCurrentContext
] = OUString(m_lbField
.GetSelectEntry());
464 //------------------------------------------------------------------------
465 IMPL_LINK(FmSearchDialog
, OnCheckBoxToggled
, CheckBox
*, pBox
)
467 sal_Bool bChecked
= pBox
->IsChecked();
469 // formatter or case -> pass on to the engine
470 if (pBox
== &m_cbUseFormat
)
471 m_pSearchEngine
->SetFormatterUsing(bChecked
);
472 else if (pBox
== &m_cbCase
)
473 m_pSearchEngine
->SetCaseSensitive(bChecked
);
474 // direction -> pass on and reset the checkbox-text for StartOver
475 else if (pBox
== &m_cbBackwards
)
477 m_cbStartOver
.SetText( OUString( CUI_RES( bChecked
? RID_STR_FROM_BOTTOM
: RID_STR_FROM_TOP
) ) );
478 m_pSearchEngine
->SetDirection(!bChecked
);
480 // similarity-search or regular expression
481 else if ((pBox
== &m_cbApprox
) || (pBox
== &m_cbRegular
) || (pBox
== &m_cbWildCard
))
483 CheckBox
* pBoxes
[] = { &m_cbWildCard
, &m_cbRegular
, &m_cbApprox
};
484 for (sal_uInt32 i
=0; i
< SAL_N_ELEMENTS(pBoxes
); ++i
)
486 if (pBoxes
[i
] != pBox
)
489 pBoxes
[i
]->Disable();
495 // pass on to the engine
496 m_pSearchEngine
->SetWildcard(m_cbWildCard
.IsEnabled() ? m_cbWildCard
.IsChecked() : sal_False
);
497 m_pSearchEngine
->SetRegular(m_cbRegular
.IsEnabled() ? m_cbRegular
.IsChecked() : sal_False
);
498 m_pSearchEngine
->SetLevenshtein(m_cbApprox
.IsEnabled() ? m_cbApprox
.IsChecked() : sal_False
);
499 // (disabled boxes have to be passed to the engine as sal_False)
501 // adjust the Position-Listbox (which is not allowed during Wildcard-search)
502 if (pBox
== &m_cbWildCard
)
506 m_ftPosition
.Disable();
507 m_lbPosition
.Disable();
511 m_ftPosition
.Enable();
512 m_lbPosition
.Enable();
516 // and the button for similarity-search
517 if (pBox
== &m_cbApprox
)
520 m_pbApproxSettings
.Enable();
522 m_pbApproxSettings
.Disable();
525 else if (pBox
== &m_aHalfFullFormsCJK
)
527 // forward to the search engine
528 m_pSearchEngine
->SetIgnoreWidthCJK( !bChecked
);
530 else if (pBox
== &m_aSoundsLikeCJK
)
532 m_aSoundsLikeCJKSettings
.Enable(bChecked
);
534 // two other buttons which depend on this one
535 sal_Bool bEnable
= ( m_rbSearchForText
.IsChecked()
536 && !m_aSoundsLikeCJK
.IsChecked()
538 || !SvtCJKOptions().IsJapaneseFindEnabled();
539 m_cbCase
.Enable(bEnable
);
540 m_aHalfFullFormsCJK
.Enable(bEnable
);
542 // forward to the search engine
543 m_pSearchEngine
->SetTransliteration( bChecked
);
549 //------------------------------------------------------------------------
550 void FmSearchDialog::InitContext(sal_Int16 nContext
)
552 FmSearchContext fmscContext
;
553 fmscContext
.nContext
= nContext
;
558 m_lnkContextSupplier
.Call(&fmscContext
);
559 DBG_ASSERT(nResult
> 0, "FmSearchDialog::InitContext : ContextSupplier didn't give me any controls !");
561 // put the field names into the respective listbox
564 if (fmscContext
.sFieldDisplayNames
.Len() != 0)
566 // use the display names if supplied
567 DBG_ASSERT(comphelper::string::getTokenCount(fmscContext
.sFieldDisplayNames
, ';') == comphelper::string::getTokenCount(fmscContext
.strUsedFields
, ';'),
568 "FmSearchDialog::InitContext : invalid context description supplied !");
569 for (sal_Int32 i
=0; i
< comphelper::string::getTokenCount(fmscContext
.sFieldDisplayNames
, ';'); ++i
)
570 m_lbField
.InsertEntry(comphelper::string::getToken(fmscContext
.sFieldDisplayNames
, i
, ';'));
574 // else use the field names
575 for (sal_Int32 i
=0; i
< comphelper::string::getTokenCount(fmscContext
.strUsedFields
, ';'); ++i
)
576 m_lbField
.InsertEntry(comphelper::string::getToken(fmscContext
.strUsedFields
, i
, ';'));
579 if (nContext
< (sal_Int32
)m_arrContextFields
.size() && m_arrContextFields
[nContext
].Len())
581 m_lbField
.SelectEntry(m_arrContextFields
[nContext
]);
585 m_lbField
.SelectEntryPos(0);
586 if (m_rbSingleField
.IsChecked() && (m_lbField
.GetEntryCount() > 1))
587 m_lbField
.GrabFocus();
590 m_pSearchEngine
->SwitchToContext(fmscContext
.xCursor
, fmscContext
.strUsedFields
, fmscContext
.arrFields
,
591 m_rbAllFields
.IsChecked() ? -1 : 0);
593 m_ftRecord
.SetText(OUString::number(fmscContext
.xCursor
->getRow()));
596 //------------------------------------------------------------------------
597 IMPL_LINK( FmSearchDialog
, OnContextSelection
, ListBox
*, pBox
)
599 InitContext(pBox
->GetSelectEntryPos());
603 //------------------------------------------------------------------------
604 void FmSearchDialog::EnableSearchUI(sal_Bool bEnable
)
606 // when the controls shall be disabled their paint is turned off and then turned on again after a delay
608 EnableControlPaint(sal_False
);
611 if (m_aDelayedPaint
.IsActive())
612 m_aDelayedPaint
.Stop();
614 // (the whole thing goes on below)
615 // this small intricateness hopfully leads to no flickering when turning the SearchUI off
616 // and on again shortly after (like it's the case during a short search process)
620 // if one of my children has the focus, remember it
621 Window
* pFocusWindow
= Application::GetFocusWindow( );
622 if ( pFocusWindow
&& IsChild( pFocusWindow
) )
623 m_pPreSearchFocus
= pFocusWindow
;
625 m_pPreSearchFocus
= NULL
;
628 // the search button has two functions -> adjust its text accordingly
629 OUString
sButtonText( bEnable
? m_sSearch
: m_sCancel
);
630 m_pbSearchAgain
.SetText( sButtonText
);
632 if (m_pSearchEngine
->GetSearchMode() != SM_BRUTE
)
634 m_flSearchFor
.Enable (bEnable
);
635 m_rbSearchForText
.Enable (bEnable
);
636 m_rbSearchForNull
.Enable (bEnable
);
637 m_rbSearchForNotNull
.Enable (bEnable
);
638 m_flWhere
.Enable (bEnable
);
639 m_ftForm
.Enable (bEnable
);
640 m_lbForm
.Enable (bEnable
);
641 m_rbAllFields
.Enable (bEnable
);
642 m_rbSingleField
.Enable (bEnable
);
643 m_lbField
.Enable (bEnable
&& m_rbSingleField
.IsChecked());
644 m_flOptions
.Enable (bEnable
);
645 m_cbBackwards
.Enable (bEnable
);
646 m_cbStartOver
.Enable (bEnable
);
647 m_pbClose
.Enable (bEnable
);
648 EnableSearchForDependees (bEnable
);
651 { // this means we're preparing for starting a search
652 // In this case, EnableSearchForDependees disabled the search button
653 // But as we're about to use it for cancelling the search, we really need to enable it, again
654 m_pbSearchAgain
.Enable( sal_True
);
659 m_aDelayedPaint
.Start();
661 EnableControlPaint(sal_True
);
665 if ( m_pPreSearchFocus
)
667 m_pPreSearchFocus
->GrabFocus();
668 if ( WINDOW_EDIT
== m_pPreSearchFocus
->GetType() )
670 Edit
* pEdit
= static_cast< Edit
* >( m_pPreSearchFocus
);
671 pEdit
->SetSelection( Selection( 0, pEdit
->GetText().getLength() ) );
674 m_pPreSearchFocus
= NULL
;
679 //------------------------------------------------------------------------
680 void FmSearchDialog::EnableSearchForDependees(sal_Bool bEnable
)
682 sal_Bool bSearchingForText
= m_rbSearchForText
.IsChecked();
683 m_pbSearchAgain
.Enable(bEnable
&& (!bSearchingForText
|| (!m_cmbSearchText
.GetText().isEmpty())));
685 bEnable
= bEnable
&& bSearchingForText
;
687 sal_Bool bEnableRedundants
= !m_aSoundsLikeCJK
.IsChecked() || !SvtCJKOptions().IsJapaneseFindEnabled();
689 m_cmbSearchText
.Enable (bEnable
);
690 m_ftPosition
.Enable (bEnable
&& !m_cbWildCard
.IsChecked());
691 m_cbWildCard
.Enable (bEnable
&& !m_cbRegular
.IsChecked() && !m_cbApprox
.IsChecked());
692 m_cbRegular
.Enable (bEnable
&& !m_cbWildCard
.IsChecked() && !m_cbApprox
.IsChecked());
693 m_cbApprox
.Enable (bEnable
&& !m_cbWildCard
.IsChecked() && !m_cbRegular
.IsChecked());
694 m_pbApproxSettings
.Enable (bEnable
&& m_cbApprox
.IsChecked());
695 m_aHalfFullFormsCJK
.Enable (bEnable
&& bEnableRedundants
);
696 m_aSoundsLikeCJK
.Enable (bEnable
);
697 m_aSoundsLikeCJKSettings
.Enable (bEnable
&& m_aSoundsLikeCJK
.IsChecked());
698 m_lbPosition
.Enable (bEnable
&& !m_cbWildCard
.IsChecked());
699 m_cbUseFormat
.Enable (bEnable
);
700 m_cbCase
.Enable (bEnable
&& bEnableRedundants
);
703 //------------------------------------------------------------------------
704 void FmSearchDialog::EnableControlPaint(sal_Bool bEnable
)
706 Control
* pAffectedControls
[] = { &m_flSearchFor
, &m_rbSearchForText
, &m_cmbSearchText
, &m_rbSearchForNull
, &m_rbSearchForNotNull
,
707 &m_rbSearchForText
, &m_flWhere
, &m_rbAllFields
, &m_rbSingleField
, &m_lbField
, &m_flOptions
, &m_ftPosition
, &m_lbPosition
,
708 &m_cbUseFormat
, &m_cbCase
, &m_cbBackwards
, &m_cbStartOver
, &m_cbWildCard
, &m_cbRegular
, &m_cbApprox
, &m_pbApproxSettings
,
709 &m_pbSearchAgain
, &m_pbClose
};
712 for (sal_uInt32 i
=0; i
<SAL_N_ELEMENTS(pAffectedControls
); ++i
)
714 pAffectedControls
[i
]->SetUpdateMode(bEnable
);
715 pAffectedControls
[i
]->EnablePaint(bEnable
);
718 for (sal_uInt32 i
=0; i
<SAL_N_ELEMENTS(pAffectedControls
); ++i
)
720 pAffectedControls
[i
]->EnablePaint(bEnable
);
721 pAffectedControls
[i
]->SetUpdateMode(bEnable
);
725 //------------------------------------------------------------------------
726 IMPL_LINK_NOARG(FmSearchDialog
, OnDelayedPaint
)
728 EnableControlPaint(sal_True
);
732 //------------------------------------------------------------------------
733 void FmSearchDialog::OnFound(const ::com::sun::star::uno::Any
& aCursorPos
, sal_Int16 nFieldPos
)
735 FmFoundRecordInformation friInfo
;
736 friInfo
.nContext
= m_lbForm
.GetSelectEntryPos();
737 // if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway
738 friInfo
.aPosition
= aCursorPos
;
739 if (m_rbAllFields
.IsChecked())
740 friInfo
.nFieldPos
= nFieldPos
;
742 friInfo
.nFieldPos
= m_lbField
.GetSelectEntryPos();
743 // this of course implies that I have really searched in the field that is selected in the listbox,
744 // which is made sure in RebuildUsedFields
746 m_lnkFoundHandler
.Call(&friInfo
);
748 m_cmbSearchText
.GrabFocus();
751 //------------------------------------------------------------------------
752 IMPL_LINK(FmSearchDialog
, OnSearchProgress
, FmSearchProgress
*, pProgress
)
754 SolarMutexGuard aGuard
;
755 // make this single method thread-safe (it's an overkill to block the whole application for this,
756 // but we don't have another safety concept at the moment)
758 switch (pProgress
->aSearchState
)
760 case FmSearchProgress::STATE_PROGRESS
:
761 if (pProgress
->bOverflow
)
763 OUString
sHint( CUI_RES( m_cbBackwards
.IsChecked() ? RID_STR_OVERFLOW_BACKWARD
: RID_STR_OVERFLOW_FORWARD
) );
764 m_ftHint
.SetText( sHint
);
765 m_ftHint
.Invalidate();
768 m_ftRecord
.SetText(OUString::number(1 + pProgress
->nCurrentRecord
));
769 m_ftRecord
.Invalidate();
772 case FmSearchProgress::STATE_PROGRESS_COUNTING
:
773 m_ftHint
.SetText(CUI_RESSTR(RID_STR_SEARCH_COUNTING
));
774 m_ftHint
.Invalidate();
776 m_ftRecord
.SetText(OUString::number(pProgress
->nCurrentRecord
));
777 m_ftRecord
.Invalidate();
780 case FmSearchProgress::STATE_SUCCESSFULL
:
781 OnFound(pProgress
->aBookmark
, (sal_Int16
)pProgress
->nFieldIndex
);
782 EnableSearchUI(sal_True
);
785 case FmSearchProgress::STATE_ERROR
:
786 case FmSearchProgress::STATE_NOTHINGFOUND
:
788 sal_uInt16 nErrorId
= (FmSearchProgress::STATE_ERROR
== pProgress
->aSearchState
)
789 ? RID_SVXERR_SEARCH_GENERAL_ERROR
790 : RID_SVXERR_SEARCH_NORECORD
;
791 ErrorBox(this, CUI_RES(nErrorId
)).Execute();
794 case FmSearchProgress::STATE_CANCELED
:
795 EnableSearchUI(sal_True
);
796 if (m_lnkCanceledNotFoundHdl
.IsSet())
798 FmFoundRecordInformation friInfo
;
799 friInfo
.nContext
= m_lbForm
.GetSelectEntryPos();
800 // if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway
801 friInfo
.aPosition
= pProgress
->aBookmark
;
802 m_lnkCanceledNotFoundHdl
.Call(&friInfo
);
807 m_ftRecord
.SetText(OUString::number(1 + pProgress
->nCurrentRecord
));
812 //------------------------------------------------------------------------
813 void FmSearchDialog::LoadParams()
815 FmSearchParams
aParams(m_pConfig
->getParams());
817 const OUString
* pHistory
= aParams
.aHistory
.getConstArray();
818 const OUString
* pHistoryEnd
= pHistory
+ aParams
.aHistory
.getLength();
819 for (; pHistory
!= pHistoryEnd
; ++pHistory
)
820 m_cmbSearchText
.InsertEntry( *pHistory
);
822 // I do the settings at my UI-elements and then I simply call the respective change-handler,
823 // that way the data is handed on to the SearchEngine and all dependent settings are done
826 sal_uInt16 nInitialField
= m_lbField
.GetEntryPos( String( aParams
.sSingleSearchField
) );
827 if (nInitialField
== COMBOBOX_ENTRY_NOTFOUND
)
829 m_lbField
.SelectEntryPos(nInitialField
);
830 LINK(this, FmSearchDialog
, OnFieldSelected
).Call(&m_lbField
);
831 // all fields/single field (AFTER selcting the field because OnClickedFieldRadios expects a valid value there)
832 if (aParams
.bAllFields
)
834 m_rbSingleField
.Check(sal_False
);
835 m_rbAllFields
.Check(sal_True
);
836 LINK(this, FmSearchDialog
, OnClickedFieldRadios
).Call(&m_rbAllFields
);
837 // OnClickedFieldRadios also calls to RebuildUsedFields
841 m_rbAllFields
.Check(sal_False
);
842 m_rbSingleField
.Check(sal_True
);
843 LINK(this, FmSearchDialog
, OnClickedFieldRadios
).Call(&m_rbSingleField
);
846 m_lbPosition
.SelectEntryPos(aParams
.nPosition
);
847 LINK(this, FmSearchDialog
, OnPositionSelected
).Call(&m_lbPosition
);
849 // field formatting/case sensitivity/direction
850 m_cbUseFormat
.Check(aParams
.bUseFormatter
);
851 m_cbCase
.Check( aParams
.isCaseSensitive() );
852 m_cbBackwards
.Check(aParams
.bBackwards
);
853 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbUseFormat
);
854 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbCase
);
855 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbBackwards
);
857 m_aHalfFullFormsCJK
.Check( !aParams
.isIgnoreWidthCJK( ) ); // BEWARE: this checkbox has a inverse semantics!
858 m_aSoundsLikeCJK
.Check( aParams
.bSoundsLikeCJK
);
859 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_aHalfFullFormsCJK
);
860 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_aSoundsLikeCJK
);
862 m_cbWildCard
.Check(sal_False
);
863 m_cbRegular
.Check(sal_False
);
864 m_cbApprox
.Check(sal_False
);
865 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbWildCard
);
866 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbRegular
);
867 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(&m_cbApprox
);
869 CheckBox
* pToCheck
= NULL
;
870 if (aParams
.bWildcard
)
871 pToCheck
= &m_cbWildCard
;
872 if (aParams
.bRegular
)
873 pToCheck
= &m_cbRegular
;
874 if (aParams
.bApproxSearch
)
875 pToCheck
= &m_cbApprox
;
876 if (aParams
.bSoundsLikeCJK
)
877 pToCheck
= &m_aSoundsLikeCJK
;
880 pToCheck
->Check(sal_True
);
881 LINK(this, FmSearchDialog
, OnCheckBoxToggled
).Call(pToCheck
);
884 // set Levenshtein-parameters directly at the SearchEngine
885 m_pSearchEngine
->SetLevRelaxed(aParams
.bLevRelaxed
);
886 m_pSearchEngine
->SetLevOther(aParams
.nLevOther
);
887 m_pSearchEngine
->SetLevShorter(aParams
.nLevShorter
);
888 m_pSearchEngine
->SetLevLonger(aParams
.nLevLonger
);
890 m_pSearchEngine
->SetTransliterationFlags( aParams
.getTransliterationFlags( ) );
892 m_rbSearchForText
.Check(sal_False
);
893 m_rbSearchForNull
.Check(sal_False
);
894 m_rbSearchForNotNull
.Check(sal_False
);
895 switch (aParams
.nSearchForType
)
897 case 1: m_rbSearchForNull
.Check(sal_True
); break;
898 case 2: m_rbSearchForNotNull
.Check(sal_True
); break;
899 default: m_rbSearchForText
.Check(sal_True
); break;
901 LINK(this, FmSearchDialog
, OnClickedFieldRadios
).Call(&m_rbSearchForText
);
904 //------------------------------------------------------------------------
905 void FmSearchDialog::SaveParams() const
910 FmSearchParams aCurrentSettings
;
912 aCurrentSettings
.aHistory
.realloc( m_cmbSearchText
.GetEntryCount() );
913 OUString
* pHistory
= aCurrentSettings
.aHistory
.getArray();
914 for (sal_uInt16 i
=0; i
<m_cmbSearchText
.GetEntryCount(); ++i
, ++pHistory
)
915 *pHistory
= m_cmbSearchText
.GetEntry(i
);
917 aCurrentSettings
.sSingleSearchField
= m_lbField
.GetSelectEntry();
918 aCurrentSettings
.bAllFields
= m_rbAllFields
.IsChecked();
919 aCurrentSettings
.nPosition
= m_pSearchEngine
->GetPosition();
920 aCurrentSettings
.bUseFormatter
= m_pSearchEngine
->GetFormatterUsing();
921 aCurrentSettings
.setCaseSensitive ( m_pSearchEngine
->GetCaseSensitive() );
922 aCurrentSettings
.bBackwards
= !m_pSearchEngine
->GetDirection();
923 aCurrentSettings
.bWildcard
= m_pSearchEngine
->GetWildcard();
924 aCurrentSettings
.bRegular
= m_pSearchEngine
->GetRegular();
925 aCurrentSettings
.bApproxSearch
= m_pSearchEngine
->GetLevenshtein();
926 aCurrentSettings
.bLevRelaxed
= m_pSearchEngine
->GetLevRelaxed();
927 aCurrentSettings
.nLevOther
= m_pSearchEngine
->GetLevOther();
928 aCurrentSettings
.nLevShorter
= m_pSearchEngine
->GetLevShorter();
929 aCurrentSettings
.nLevLonger
= m_pSearchEngine
->GetLevLonger();
931 aCurrentSettings
.bSoundsLikeCJK
= m_pSearchEngine
->GetTransliteration();
932 aCurrentSettings
.setTransliterationFlags ( m_pSearchEngine
->GetTransliterationFlags() );
934 if (m_rbSearchForNull
.IsChecked())
935 aCurrentSettings
.nSearchForType
= 1;
936 else if (m_rbSearchForNotNull
.IsChecked())
937 aCurrentSettings
.nSearchForType
= 2;
939 aCurrentSettings
.nSearchForType
= 0;
941 m_pConfig
->setParams( aCurrentSettings
);
944 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */