summaryrefslogtreecommitdiff
path: root/cui/source/dialogs/cuifmsearch.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'cui/source/dialogs/cuifmsearch.cxx')
-rw-r--r--cui/source/dialogs/cuifmsearch.cxx963
1 files changed, 963 insertions, 0 deletions
diff --git a/cui/source/dialogs/cuifmsearch.cxx b/cui/source/dialogs/cuifmsearch.cxx
new file mode 100644
index 000000000000..b4556cccdf3e
--- /dev/null
+++ b/cui/source/dialogs/cuifmsearch.cxx
@@ -0,0 +1,963 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <tools/debug.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/shl.hxx>
+#include <dialmgr.hxx>
+#include <sfx2/tabdlg.hxx>
+#include <osl/mutex.hxx>
+#include <sfx2/app.hxx>
+#include <cuires.hrc>
+#include <svl/filerec.hxx>
+#include <svx/fmsrccfg.hxx>
+#include <svx/fmsrcimp.hxx>
+#include "fmsearch.hrc"
+#include "cuifmsearch.hxx"
+#include <svx/srchdlg.hxx>
+#include <svl/cjkoptions.hxx>
+#include <com/sun/star/i18n/TransliterationModules.hpp>
+#include <comphelper/processfactory.hxx>
+#include <svx/svxdlg.hxx>
+#include <sal/macros.h>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::i18n;
+using namespace ::svxform;
+using namespace ::com::sun::star::sdbc;
+using namespace ::com::sun::star::util;
+
+#define MAX_HISTORY_ENTRIES 50
+
+//------------------------------------------------------------------------
+void FmSearchDialog::initCommon( const Reference< XResultSet >& _rxCursor )
+{
+ // init the engine
+ DBG_ASSERT( m_pSearchEngine, "FmSearchDialog::initCommon: have no engine!" );
+ m_pSearchEngine->SetProgressHandler(LINK(this, FmSearchDialog, OnSearchProgress));
+
+ // some layout changes according to available CJK options
+ SvtCJKOptions aCJKOptions;
+ if (!aCJKOptions.IsJapaneseFindEnabled())
+ {
+ sal_Int32 nUpper = m_cbApprox.GetPosPixel().Y();
+ sal_Int32 nDifference = m_aSoundsLikeCJKSettings.GetPosPixel().Y() - nUpper;
+
+ // hide the options for the japanese search
+ Control* pFieldsToMove[] = { &m_flState, &m_ftRecordLabel, &m_ftRecord, &m_ftHint };
+ implMoveControls(pFieldsToMove, SAL_N_ELEMENTS(pFieldsToMove), nDifference, &m_flOptions);
+
+ m_aSoundsLikeCJK.Hide();
+ m_aSoundsLikeCJKSettings.Hide();
+ }
+
+ if (!aCJKOptions.IsCJKFontEnabled())
+ {
+ m_aHalfFullFormsCJK.Hide();
+
+ // never ignore the width (ignoring is expensive) if the option is not available at all
+ m_pSearchEngine->SetIgnoreWidthCJK( sal_False );
+ }
+
+ // some initial record texts
+ m_ftRecord.SetText( String::CreateFromInt32( _rxCursor->getRow() ) );
+ m_pbClose.SetHelpText(String());
+}
+
+//------------------------------------------------------------------------
+FmSearchDialog::FmSearchDialog(Window* pParent, const UniString& sInitialText, const ::std::vector< String >& _rContexts, sal_Int16 nInitialContext,
+ const Link& lnkContextSupplier)
+ :ModalDialog(pParent, CUI_RES(RID_SVXDLG_SEARCHFORM))
+ ,m_flSearchFor (this, CUI_RES(FL_SEARCHFOR))
+ ,m_rbSearchForText (this, CUI_RES(RB_SEARCHFORTEXT))
+ ,m_rbSearchForNull (this, CUI_RES(RB_SEARCHFORNULL))
+ ,m_rbSearchForNotNull (this, CUI_RES(RB_SEARCHFORNOTNULL))
+ ,m_cmbSearchText (this, CUI_RES(CMB_SEARCHTEXT))
+ ,m_flWhere (this, CUI_RES(FL_WHERE))
+ ,m_ftForm (this, CUI_RES(FT_FORM))
+ ,m_lbForm (this, CUI_RES(LB_FORM))
+ ,m_rbAllFields (this, CUI_RES(RB_ALLFIELDS))
+ ,m_rbSingleField (this, CUI_RES(RB_SINGLEFIELD))
+ ,m_lbField (this, CUI_RES(LB_FIELD))
+ ,m_flOptions (this, CUI_RES(FL_OPTIONS))
+ ,m_ftPosition (this, CUI_RES(FT_POSITION))
+ ,m_lbPosition (this, CUI_RES(LB_POSITION))
+ ,m_cbUseFormat (this, CUI_RES(CB_USEFORMATTER))
+ ,m_cbCase (this, CUI_RES(CB_CASE))
+ ,m_cbBackwards (this, CUI_RES(CB_BACKWARD))
+ ,m_cbStartOver (this, CUI_RES(CB_STARTOVER))
+ ,m_cbWildCard (this, CUI_RES(CB_WILDCARD))
+ ,m_cbRegular (this, CUI_RES(CB_REGULAR))
+ ,m_cbApprox (this, CUI_RES(CB_APPROX))
+ ,m_pbApproxSettings (this, CUI_RES(PB_APPROXSETTINGS))
+ ,m_aHalfFullFormsCJK (this, CUI_RES(CB_HALFFULLFORMS))
+ ,m_aSoundsLikeCJK (this, CUI_RES(CB_SOUNDSLIKECJK))
+ ,m_aSoundsLikeCJKSettings (this, CUI_RES(PB_SOUNDSLIKESETTINGS))
+ ,m_flState (this, CUI_RES(FL_STATE))
+ ,m_ftRecordLabel (this, CUI_RES(FT_RECORDLABEL))
+ ,m_ftRecord (this, CUI_RES(FT_RECORD))
+ ,m_ftHint (this, CUI_RES(FT_HINT))
+ ,m_pbSearchAgain (this, CUI_RES(PB_SEARCH))
+ ,m_pbClose (this, CUI_RES(1))
+ ,m_pbHelp (this, CUI_RES(1))
+ ,m_sSearch ( m_pbSearchAgain.GetText() )
+ ,m_sCancel ( Button::GetStandardText( BUTTON_CANCEL ) )
+ ,m_pPreSearchFocus( NULL )
+ ,m_lnkContextSupplier(lnkContextSupplier)
+ ,m_pConfig( NULL )
+{
+ DBG_ASSERT(m_lnkContextSupplier.IsSet(), "FmSearchDialog::FmSearchDialog : have no ContextSupplier !");
+
+ // erst mal die Informationen fuer den initialen Kontext
+ FmSearchContext fmscInitial;
+ fmscInitial.nContext = nInitialContext;
+ m_lnkContextSupplier.Call(&fmscInitial);
+ DBG_ASSERT(fmscInitial.xCursor.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
+ DBG_ASSERT(fmscInitial.strUsedFields.GetTokenCount(';') == (xub_StrLen)fmscInitial.arrFields.size(),
+ "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplied !");
+#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
+ for (sal_Int32 i=0; i<(sal_Int32)fmscInitial.arrFields.size(); ++i)
+ DBG_ASSERT(fmscInitial.arrFields.at(i).is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !");
+#endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL
+
+ for ( ::std::vector< String >::const_iterator context = _rContexts.begin();
+ context != _rContexts.end();
+ ++context
+ )
+ {
+ m_arrContextFields.push_back(String());
+ m_lbForm.InsertEntry(*context);
+ }
+ m_lbForm.SelectEntryPos(nInitialContext);
+
+ m_lbForm.SetSelectHdl(LINK(this, FmSearchDialog, OnContextSelection));
+
+ if (m_arrContextFields.size() == 1)
+ { // remove the context selection listbox and rearrange the controls accordingly
+ sal_Int32 nUpper = m_lbForm.GetPosPixel().Y();
+ sal_Int32 nDifference = m_rbAllFields.GetPosPixel().Y() - nUpper;
+
+ // move all controls below the affected ones up
+ Control* pFieldsToMove[] = { &m_rbAllFields, &m_rbSingleField, &m_lbField, &m_flOptions, &m_ftPosition, &m_lbPosition,
+ &m_cbUseFormat, &m_cbCase, &m_cbBackwards, &m_cbStartOver, &m_cbWildCard, &m_cbRegular, &m_cbApprox,
+ &m_pbApproxSettings, &m_aHalfFullFormsCJK, &m_aSoundsLikeCJK, &m_aSoundsLikeCJKSettings,
+ &m_flState, &m_ftRecordLabel, &m_ftRecord, &m_ftHint };
+
+ implMoveControls(pFieldsToMove, SAL_N_ELEMENTS(pFieldsToMove), nDifference, &m_flWhere);
+
+ Point pt = m_rbAllFields.GetPosPixel();
+ pt.X() = m_ftForm.GetPosPixel().X();
+ m_rbAllFields.SetPosPixel( pt );
+ pt = m_rbSingleField.GetPosPixel();
+ pt.X() = m_ftForm.GetPosPixel().X();
+ m_rbSingleField.SetPosPixel( pt );
+
+ // hide dispensable controls
+ m_ftForm.Hide();
+ m_lbForm.Hide();
+ }
+
+ m_pSearchEngine = new FmSearchEngine(
+ ::comphelper::getProcessServiceFactory(), fmscInitial.xCursor, fmscInitial.strUsedFields, fmscInitial.arrFields, SM_ALLOWSCHEDULE );
+ initCommon( fmscInitial.xCursor );
+
+ if (fmscInitial.sFieldDisplayNames.Len() != 0)
+ { // use the display names if supplied
+ DBG_ASSERT(fmscInitial.sFieldDisplayNames.GetTokenCount() == fmscInitial.strUsedFields.GetTokenCount(),
+ "FmSearchDialog::FmSearchDialog : invalid initial context description !");
+ Init(fmscInitial.sFieldDisplayNames, sInitialText);
+ }
+ else
+ Init(fmscInitial.strUsedFields, sInitialText);
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::implMoveControls(
+ Control** _ppControls,
+ sal_Int32 _nControls,
+ sal_Int32 _nUp,
+ Control* /*_pToResize*/)
+{
+ for (sal_Int32 i=0; i<_nControls; ++i)
+ {
+ Point pt = _ppControls[i]->GetPosPixel();
+ pt.Y() -= _nUp;
+ _ppControls[i]->SetPosPixel(pt);
+ }
+
+ // resize myself
+ Size sz = GetSizePixel();
+ sz.Height() -= _nUp;
+ SetSizePixel(sz);
+}
+
+//------------------------------------------------------------------------
+FmSearchDialog::~FmSearchDialog()
+{
+ if (m_aDelayedPaint.IsActive())
+ m_aDelayedPaint.Stop();
+
+ SaveParams();
+
+ if (m_pConfig)
+ {
+ delete m_pConfig;
+ m_pConfig = NULL;
+ }
+
+ delete m_pSearchEngine;
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::Init(const UniString& strVisibleFields, const UniString& sInitialText)
+{
+ //the initialization of all the Controls
+ m_rbSearchForText.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
+ m_rbSearchForNull.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
+ m_rbSearchForNotNull.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
+
+ m_rbAllFields.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
+ m_rbSingleField.SetClickHdl(LINK(this, FmSearchDialog, OnClickedFieldRadios));
+
+ m_pbSearchAgain.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSearchAgain));
+ m_pbApproxSettings.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSpecialSettings));
+ m_aSoundsLikeCJKSettings.SetClickHdl(LINK(this, FmSearchDialog, OnClickedSpecialSettings));
+
+ m_lbPosition.SetSelectHdl(LINK(this, FmSearchDialog, OnPositionSelected));
+ m_lbField.SetSelectHdl(LINK(this, FmSearchDialog, OnFieldSelected));
+
+ m_cmbSearchText.SetModifyHdl(LINK(this, FmSearchDialog, OnSearchTextModified));
+ m_cmbSearchText.EnableAutocomplete(sal_False);
+
+ m_cbUseFormat.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbBackwards.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbStartOver.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbCase.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbWildCard.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbRegular.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_cbApprox.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_aHalfFullFormsCJK.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+ m_aSoundsLikeCJK.SetToggleHdl(LINK(this, FmSearchDialog, OnCheckBoxToggled));
+
+ // fill the listboxes
+ // method of field comparison
+ sal_uInt16 nResIds[] = {
+ RID_STR_SEARCH_ANYWHERE,
+ RID_STR_SEARCH_BEGINNING,
+ RID_STR_SEARCH_END,
+ RID_STR_SEARCH_WHOLE
+ };
+ for ( size_t i=0; i<SAL_N_ELEMENTS(nResIds); ++i )
+ m_lbPosition.InsertEntry( String( CUI_RES( nResIds[i] ) ) );
+ m_lbPosition.SelectEntryPos(MATCHING_ANYWHERE);
+
+ // the field listbox
+ for (sal_uInt16 i=0; i<strVisibleFields.GetTokenCount(';'); ++i)
+ m_lbField.InsertEntry(strVisibleFields.GetToken(i, ';'));
+
+
+ m_pConfig = new FmSearchConfigItem;
+ LoadParams();
+
+ m_cmbSearchText.SetText(sInitialText);
+ // if the Edit-line has changed the text (e.g. because it contains
+ // control characters, as can be the case with memo fields), I use
+ // an empty UniString.
+ UniString sRealSetText = m_cmbSearchText.GetText();
+ if (!sRealSetText.Equals(sInitialText))
+ m_cmbSearchText.SetText(UniString());
+ LINK(this, FmSearchDialog, OnSearchTextModified).Call(&m_cmbSearchText);
+
+ // initial
+ m_aDelayedPaint.SetTimeoutHdl(LINK(this, FmSearchDialog, OnDelayedPaint));
+ m_aDelayedPaint.SetTimeout(500);
+ EnableSearchUI(sal_True);
+
+ if ( m_rbSearchForText.IsChecked() )
+ m_cmbSearchText.GrabFocus();
+
+ FreeResource();
+}
+
+//------------------------------------------------------------------------
+sal_Bool FmSearchDialog::Close()
+{
+ // If the close button is disabled and ESC is pressed in a dialog,
+ // then Frame will call Close anyway, which I don't want to happen
+ // while I'm in the middle of a search (maybe one that's running
+ // in its own thread)
+ if (!m_pbClose.IsEnabled())
+ return sal_False;
+ return ModalDialog::Close();
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnClickedFieldRadios, Button*, pButton)
+{
+ if ((pButton == &m_rbSearchForText) || (pButton == &m_rbSearchForNull) || (pButton == &m_rbSearchForNotNull))
+ {
+ EnableSearchForDependees(sal_True);
+ }
+ else
+ // en- or disable field list box accordingly
+ if (pButton == &m_rbSingleField)
+ {
+ m_lbField.Enable();
+ m_pSearchEngine->RebuildUsedFields(m_lbField.GetSelectEntryPos());
+ }
+ else
+ {
+ m_lbField.Disable();
+ m_pSearchEngine->RebuildUsedFields(-1);
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnClickedSearchAgain, Button*, EMPTYARG)
+{
+ if (m_pbClose.IsEnabled())
+ { // der Button hat die Funktion 'Suchen'
+ UniString strThisRoundText = m_cmbSearchText.GetText();
+ // zur History dazu
+ m_cmbSearchText.RemoveEntry(strThisRoundText);
+ m_cmbSearchText.InsertEntry(strThisRoundText, 0);
+ // das Remove/Insert stellt a) sicher, dass der UniString nicht zweimal auftaucht, b), dass die zuletzt gesuchten Strings am
+ // Anfang stehen
+ // und die Listenlaenge beschraenken
+ while (m_cmbSearchText.GetEntryCount() > MAX_HISTORY_ENTRIES)
+ m_cmbSearchText.RemoveEntry(m_cmbSearchText.GetEntryCount()-1);
+
+ // den 'Ueberlauf'-Hint rausnehmen
+ m_ftHint.SetText(UniString());
+ m_ftHint.Invalidate();
+
+ if (m_cbStartOver.IsChecked())
+ {
+ m_cbStartOver.Check(sal_False);
+ EnableSearchUI(sal_False);
+ if (m_rbSearchForText.IsChecked())
+ m_pSearchEngine->StartOver(strThisRoundText);
+ else
+ m_pSearchEngine->StartOverSpecial(m_rbSearchForNull.IsChecked());
+ }
+ else
+ {
+ EnableSearchUI(sal_False);
+ if (m_rbSearchForText.IsChecked())
+ m_pSearchEngine->SearchNext(strThisRoundText);
+ else
+ m_pSearchEngine->SearchNextSpecial(m_rbSearchForNull.IsChecked());
+ }
+ }
+ else
+ { // der Button hat die Fukntion 'Abbrechen'
+ DBG_ASSERT(m_pSearchEngine->GetSearchMode() != SM_BRUTE, "FmSearchDialog, OnClickedSearchAgain : falscher Modus !");
+ // der CancelButton wird normalerweise nur disabled, wenn ich in einem Thread oder mit Reschedule arbeite
+ m_pSearchEngine->CancelSearch();
+ // mein ProgressHandler wird gerufen, wenn es wirklich zu Ende ist, das hier war nur eine Anforderung
+ }
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnClickedSpecialSettings, Button*, pButton )
+{
+ if (&m_pbApproxSettings == pButton)
+ {
+ AbstractSvxSearchSimilarityDialog* pDlg = NULL;
+
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ if ( pFact )
+ pDlg = pFact->CreateSvxSearchSimilarityDialog( this, m_pSearchEngine->GetLevRelaxed(), m_pSearchEngine->GetLevOther(),
+ m_pSearchEngine->GetLevShorter(), m_pSearchEngine->GetLevLonger() );
+ DBG_ASSERT( pDlg, "FmSearchDialog, OnClickedSpecialSettings: could not load the dialog!" );
+
+ if ( pDlg && pDlg->Execute() == RET_OK )
+ {
+ m_pSearchEngine->SetLevRelaxed( pDlg->IsRelaxed() );
+ m_pSearchEngine->SetLevOther( pDlg->GetOther() );
+ m_pSearchEngine->SetLevShorter(pDlg->GetShorter() );
+ m_pSearchEngine->SetLevLonger( pDlg->GetLonger() );
+ }
+ delete pDlg;
+ }
+ else if (&m_aSoundsLikeCJKSettings == pButton)
+ {
+ SfxItemSet aSet( SFX_APP()->GetPool() );
+ SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
+ if(pFact)
+ {
+ AbstractSvxJSearchOptionsDialog* aDlg = pFact->CreateSvxJSearchOptionsDialog( this, aSet, m_pSearchEngine->GetTransliterationFlags() );
+ DBG_ASSERT(aDlg, "Dialogdiet fail!");
+ aDlg->Execute();
+
+
+ sal_Int32 nFlags = aDlg->GetTransliterationFlags();
+ m_pSearchEngine->SetTransliterationFlags(nFlags);
+
+ m_cbCase.Check(m_pSearchEngine->GetCaseSensitive());
+ OnCheckBoxToggled( &m_cbCase );
+ m_aHalfFullFormsCJK.Check( !m_pSearchEngine->GetIgnoreWidthCJK() );
+ OnCheckBoxToggled( &m_aHalfFullFormsCJK );
+ delete aDlg;
+ }
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnSearchTextModified, ComboBox*, EMPTYARG)
+{
+ if ((m_cmbSearchText.GetText().Len() != 0) || !m_rbSearchForText.IsChecked())
+ m_pbSearchAgain.Enable();
+ else
+ m_pbSearchAgain.Disable();
+
+ m_pSearchEngine->InvalidatePreviousLoc();
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnPositionSelected, ListBox*, pBox)
+{
+ (void) pBox; // avoid warning
+ DBG_ASSERT(pBox->GetSelectEntryCount() == 1, "FmSearchDialog::OnMethodSelected : unerwartet : nicht genau ein Eintrag selektiert !");
+
+ m_pSearchEngine->SetPosition(m_lbPosition.GetSelectEntryPos());
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnFieldSelected, ListBox*, pBox)
+{
+ (void) pBox; // avoid warning
+ DBG_ASSERT(pBox->GetSelectEntryCount() == 1, "FmSearchDialog::OnFieldSelected : unerwartet : nicht genau ein Eintrag selektiert !");
+
+ m_pSearchEngine->RebuildUsedFields(m_rbAllFields.IsChecked() ? -1 : (sal_Int16)m_lbField.GetSelectEntryPos());
+ // ruft auch m_pSearchEngine->InvalidatePreviousLoc auf
+
+ sal_Int32 nCurrentContext = m_lbForm.GetSelectEntryPos();
+ if (nCurrentContext != LISTBOX_ENTRY_NOTFOUND)
+ m_arrContextFields[nCurrentContext] = UniString(m_lbField.GetSelectEntry());
+ return 0;
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnCheckBoxToggled, CheckBox*, pBox)
+{
+ sal_Bool bChecked = pBox->IsChecked();
+
+ // Formatter oder case -> an die Engine weiterreichen
+ if (pBox == &m_cbUseFormat)
+ m_pSearchEngine->SetFormatterUsing(bChecked);
+ else if (pBox == &m_cbCase)
+ m_pSearchEngine->SetCaseSensitive(bChecked);
+ // Richtung -> weiterreichen und Checkbox-Text fuer StartOver neu setzen
+ else if (pBox == &m_cbBackwards)
+ {
+ m_cbStartOver.SetText( String( CUI_RES( bChecked ? RID_STR_FROM_BOTTOM : RID_STR_FROM_TOP ) ) );
+ m_pSearchEngine->SetDirection(!bChecked);
+ }
+ // Aehnlichkeitssuche oder regulaerer Ausdruck
+ else if ((pBox == &m_cbApprox) || (pBox == &m_cbRegular) || (pBox == &m_cbWildCard))
+ {
+ // die beiden jeweils anderen Boxes disablen oder enablen
+ CheckBox* pBoxes[] = { &m_cbWildCard, &m_cbRegular, &m_cbApprox };
+ for (sal_uInt32 i=0; i< SAL_N_ELEMENTS(pBoxes); ++i)
+ {
+ if (pBoxes[i] != pBox)
+ {
+ if (bChecked)
+ pBoxes[i]->Disable();
+ else
+ pBoxes[i]->Enable();
+ }
+ }
+
+ // an die Engine weiterreichen
+ m_pSearchEngine->SetWildcard(m_cbWildCard.IsEnabled() ? m_cbWildCard.IsChecked() : sal_False);
+ m_pSearchEngine->SetRegular(m_cbRegular.IsEnabled() ? m_cbRegular.IsChecked() : sal_False);
+ m_pSearchEngine->SetLevenshtein(m_cbApprox.IsEnabled() ? m_cbApprox.IsChecked() : sal_False);
+ // (Boxes, die disabled sind, muessen als sal_False an die Engine gehen)
+
+ // die Position-Listbox anpassen (ist bei Wildcard-Suche nicht erlaubt)
+ if (pBox == &m_cbWildCard)
+ {
+ if (bChecked)
+ {
+ m_ftPosition.Disable();
+ m_lbPosition.Disable();
+ }
+ else
+ {
+ m_ftPosition.Enable();
+ m_lbPosition.Enable();
+ }
+ }
+
+ // und den Button fuer die Aehnlichkeitssuche
+ if (pBox == &m_cbApprox)
+ {
+ if (bChecked)
+ m_pbApproxSettings.Enable();
+ else
+ m_pbApproxSettings.Disable();
+ }
+ }
+ else if (pBox == &m_aHalfFullFormsCJK)
+ {
+ // forward to the search engine
+ m_pSearchEngine->SetIgnoreWidthCJK( !bChecked );
+ }
+ else if (pBox == &m_aSoundsLikeCJK)
+ {
+ m_aSoundsLikeCJKSettings.Enable(bChecked);
+
+ // two other buttons which depend on this one
+ sal_Bool bEnable = ( m_rbSearchForText.IsChecked()
+ && !m_aSoundsLikeCJK.IsChecked()
+ )
+ || !SvtCJKOptions().IsJapaneseFindEnabled();
+ m_cbCase.Enable(bEnable);
+ m_aHalfFullFormsCJK.Enable(bEnable);
+
+ // forward to the search engine
+ m_pSearchEngine->SetTransliteration( bChecked );
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::InitContext(sal_Int16 nContext)
+{
+ FmSearchContext fmscContext;
+ fmscContext.nContext = nContext;
+
+#ifdef DBG_UTIL
+ sal_uInt32 nResult =
+#endif
+ m_lnkContextSupplier.Call(&fmscContext);
+ DBG_ASSERT(nResult > 0, "FmSearchDialog::InitContext : ContextSupplier didn't give me any controls !");
+
+ // packen wir zuerst die Feld-Namen in die entsprechende Listbox
+ m_lbField.Clear();
+
+ if (fmscContext.sFieldDisplayNames.Len() != 0)
+ {
+ // use the display names if supplied
+ DBG_ASSERT(fmscContext.sFieldDisplayNames.GetTokenCount() == fmscContext.strUsedFields.GetTokenCount(),
+ "FmSearchDialog::InitContext : invalid context description supplied !");
+ for (xub_StrLen i=0; i<fmscContext.sFieldDisplayNames.GetTokenCount(); ++i)
+ m_lbField.InsertEntry(fmscContext.sFieldDisplayNames.GetToken(i));
+ }
+ else
+ // else use the field names
+ for (xub_StrLen i=0; i<fmscContext.strUsedFields.GetTokenCount(); ++i)
+ m_lbField.InsertEntry(fmscContext.strUsedFields.GetToken(i));
+
+ if (nContext < (sal_Int32)m_arrContextFields.size() && m_arrContextFields[nContext].Len())
+ {
+ m_lbField.SelectEntry(m_arrContextFields[nContext]);
+ }
+ else
+ {
+ m_lbField.SelectEntryPos(0);
+ if (m_rbSingleField.IsChecked() && (m_lbField.GetEntryCount() > 1))
+ m_lbField.GrabFocus();
+ }
+
+ // dann geben wir der Engine Bescheid
+ m_pSearchEngine->SwitchToContext(fmscContext.xCursor, fmscContext.strUsedFields, fmscContext.arrFields,
+ m_rbAllFields.IsChecked() ? -1 : 0);
+
+ // und die Position des neuen Cursors anzeigen
+ m_ftRecord.SetText(String::CreateFromInt32(fmscContext.xCursor->getRow()));
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK( FmSearchDialog, OnContextSelection, ListBox*, pBox)
+{
+ InitContext(pBox->GetSelectEntryPos());
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::EnableSearchUI(sal_Bool bEnable)
+{
+ // wenn die Controls disabled werden sollen, schalte ich mal eben kurz ihr Paint aus und verzoegert wieder an
+ if (!bEnable)
+ EnableControlPaint(sal_False);
+ else
+ { // beim Enablen teste ich, ob der Timer fuer das delayed paint aktiv ist und stoppe ihn wenn noetig
+ if (m_aDelayedPaint.IsActive())
+ m_aDelayedPaint.Stop();
+ }
+ // (das ganze geht unten noch weiter)
+ // diese kleine Verrenkung fuehrt hoffentlich dazu, dass es nicht flackert, wenn man die SearchUI schnell hintereinander
+ // aus- und wieder einschaltet (wie das bei einem kurzen Suchvorgang zwangslaeufig der Fall ist)
+
+ if ( !bEnable )
+ {
+ // if one of my children has the focus, remember it
+ Window* pFocusWindow = Application::GetFocusWindow( );
+ if ( pFocusWindow && IsChild( pFocusWindow ) )
+ m_pPreSearchFocus = pFocusWindow;
+ else
+ m_pPreSearchFocus = NULL;
+ }
+
+ // der Suchen-Button hat einen Doppelfunktion, seinen Text entsprechend anpassen
+ String sButtonText( bEnable ? m_sSearch : m_sCancel );
+ m_pbSearchAgain.SetText( sButtonText );
+
+ // jetzt Controls en- oder disablen
+ if (m_pSearchEngine->GetSearchMode() != SM_BRUTE)
+ {
+ m_flSearchFor.Enable (bEnable);
+ m_rbSearchForText.Enable (bEnable);
+ m_rbSearchForNull.Enable (bEnable);
+ m_rbSearchForNotNull.Enable (bEnable);
+ m_flWhere.Enable (bEnable);
+ m_ftForm.Enable (bEnable);
+ m_lbForm.Enable (bEnable);
+ m_rbAllFields.Enable (bEnable);
+ m_rbSingleField.Enable (bEnable);
+ m_lbField.Enable (bEnable && m_rbSingleField.IsChecked());
+ m_flOptions.Enable (bEnable);
+ m_cbBackwards.Enable (bEnable);
+ m_cbStartOver.Enable (bEnable);
+ m_pbClose.Enable (bEnable);
+ EnableSearchForDependees (bEnable);
+
+ if ( !bEnable )
+ { // this means we're preparing for starting a search
+ // In this case, EnableSearchForDependees disabled the search button
+ // But as we're about to use it for cancelling the search, we really need to enable it, again
+ m_pbSearchAgain.Enable( sal_True );
+ }
+ }
+
+ // und den Rest fuer das delayed paint
+ if (!bEnable)
+ m_aDelayedPaint.Start();
+ else
+ EnableControlPaint(sal_True);
+
+ if ( bEnable )
+ { // restore focus
+ if ( m_pPreSearchFocus )
+ {
+ m_pPreSearchFocus->GrabFocus();
+ if ( WINDOW_EDIT == m_pPreSearchFocus->GetType() )
+ {
+ Edit* pEdit = static_cast< Edit* >( m_pPreSearchFocus );
+ pEdit->SetSelection( Selection( 0, pEdit->GetText().Len() ) );
+ }
+ }
+ m_pPreSearchFocus = NULL;
+ }
+
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::EnableSearchForDependees(sal_Bool bEnable)
+{
+ sal_Bool bSearchingForText = m_rbSearchForText.IsChecked();
+ m_pbSearchAgain.Enable(bEnable && (!bSearchingForText || (m_cmbSearchText.GetText().Len() != 0)));
+
+ bEnable = bEnable && bSearchingForText;
+
+ sal_Bool bEnableRedundants = !m_aSoundsLikeCJK.IsChecked() || !SvtCJKOptions().IsJapaneseFindEnabled();
+
+ m_cmbSearchText.Enable (bEnable);
+ m_ftPosition.Enable (bEnable && !m_cbWildCard.IsChecked());
+ m_cbWildCard.Enable (bEnable && !m_cbRegular.IsChecked() && !m_cbApprox.IsChecked());
+ m_cbRegular.Enable (bEnable && !m_cbWildCard.IsChecked() && !m_cbApprox.IsChecked());
+ m_cbApprox.Enable (bEnable && !m_cbWildCard.IsChecked() && !m_cbRegular.IsChecked());
+ m_pbApproxSettings.Enable (bEnable && m_cbApprox.IsChecked());
+ m_aHalfFullFormsCJK.Enable (bEnable && bEnableRedundants);
+ m_aSoundsLikeCJK.Enable (bEnable);
+ m_aSoundsLikeCJKSettings.Enable (bEnable && m_aSoundsLikeCJK.IsChecked());
+ m_lbPosition.Enable (bEnable && !m_cbWildCard.IsChecked());
+ m_cbUseFormat.Enable (bEnable);
+ m_cbCase.Enable (bEnable && bEnableRedundants);
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::EnableControlPaint(sal_Bool bEnable)
+{
+ Control* pAffectedControls[] = { &m_flSearchFor, &m_rbSearchForText, &m_cmbSearchText, &m_rbSearchForNull, &m_rbSearchForNotNull,
+ &m_rbSearchForText, &m_flWhere, &m_rbAllFields, &m_rbSingleField, &m_lbField, &m_flOptions, &m_ftPosition, &m_lbPosition,
+ &m_cbUseFormat, &m_cbCase, &m_cbBackwards, &m_cbStartOver, &m_cbWildCard, &m_cbRegular, &m_cbApprox, &m_pbApproxSettings,
+ &m_pbSearchAgain, &m_pbClose };
+
+ if (!bEnable)
+ for (sal_uInt32 i=0; i<SAL_N_ELEMENTS(pAffectedControls); ++i)
+ {
+ pAffectedControls[i]->SetUpdateMode(bEnable);
+ pAffectedControls[i]->EnablePaint(bEnable);
+ }
+ else
+ for (sal_uInt32 i=0; i<SAL_N_ELEMENTS(pAffectedControls); ++i)
+ {
+ pAffectedControls[i]->EnablePaint(bEnable);
+ pAffectedControls[i]->SetUpdateMode(bEnable);
+ }
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnDelayedPaint, void*, EMPTYARG)
+{
+ EnableControlPaint(sal_True);
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::OnFound(const ::com::sun::star::uno::Any& aCursorPos, sal_Int16 nFieldPos)
+{
+ FmFoundRecordInformation friInfo;
+ friInfo.nContext = m_lbForm.GetSelectEntryPos();
+ // wenn ich keine Suche in Kontexten mache, steht hier was ungueltiges drin, aber dann ist es auch egal
+ friInfo.aPosition = aCursorPos;
+ if (m_rbAllFields.IsChecked())
+ friInfo.nFieldPos = nFieldPos;
+ else
+ friInfo.nFieldPos = m_lbField.GetSelectEntryPos();
+ // das setzt natuerlich voraus, dass ich wirklich in dem Feld gesucht habe, dass in der Listbox ausgewaehlt ist,
+ // genau das wird auch in RebuildUsedFields sichergestellt
+
+ // dem Handler Bescheid sagen
+ m_lnkFoundHandler.Call(&friInfo);
+
+ // und wieder Focus auf mich
+ m_cmbSearchText.GrabFocus();
+}
+
+//------------------------------------------------------------------------
+IMPL_LINK(FmSearchDialog, OnSearchProgress, FmSearchProgress*, pProgress)
+{
+ SolarMutexGuard aGuard;
+ // diese eine Methode Thread-sicher machen (das ist ein Overkill, die ganze restliche Applikation dafuer zu blockieren,
+ // aber im Augenblick haben wir kein anderes Sicherheitskonpzept)
+
+ switch (pProgress->aSearchState)
+ {
+ case FmSearchProgress::STATE_PROGRESS:
+ if (pProgress->bOverflow)
+ {
+ String sHint( CUI_RES( m_cbBackwards.IsChecked() ? RID_STR_OVERFLOW_BACKWARD : RID_STR_OVERFLOW_FORWARD ) );
+ m_ftHint.SetText( sHint );
+ m_ftHint.Invalidate();
+ }
+
+ m_ftRecord.SetText(String::CreateFromInt32(1 + pProgress->nCurrentRecord));
+ m_ftRecord.Invalidate();
+ break;
+
+ case FmSearchProgress::STATE_PROGRESS_COUNTING:
+ m_ftHint.SetText(CUI_RESSTR(RID_STR_SEARCH_COUNTING));
+ m_ftHint.Invalidate();
+
+ m_ftRecord.SetText(String::CreateFromInt32(pProgress->nCurrentRecord));
+ m_ftRecord.Invalidate();
+ break;
+
+ case FmSearchProgress::STATE_SUCCESSFULL:
+ OnFound(pProgress->aBookmark, (sal_Int16)pProgress->nFieldIndex);
+ EnableSearchUI(sal_True);
+ break;
+
+ case FmSearchProgress::STATE_ERROR:
+ case FmSearchProgress::STATE_NOTHINGFOUND:
+ {
+ sal_uInt16 nErrorId = (FmSearchProgress::STATE_ERROR == pProgress->aSearchState)
+ ? RID_SVXERR_SEARCH_GENERAL_ERROR
+ : RID_SVXERR_SEARCH_NORECORD;
+ ErrorBox(this, CUI_RES(nErrorId)).Execute();
+ }
+ // NO break !
+ case FmSearchProgress::STATE_CANCELED:
+ EnableSearchUI(sal_True);
+ if (m_lnkCanceledNotFoundHdl.IsSet())
+ {
+ FmFoundRecordInformation friInfo;
+ friInfo.nContext = m_lbForm.GetSelectEntryPos();
+ // wenn ich keine Suche in Kontexten mache, steht hier was ungueltiges drin, aber dann ist es auch egal
+ friInfo.aPosition = pProgress->aBookmark;
+ m_lnkCanceledNotFoundHdl.Call(&friInfo);
+ }
+ break;
+ }
+
+ m_ftRecord.SetText(String::CreateFromInt32(1 + pProgress->nCurrentRecord));
+
+ return 0L;
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::LoadParams()
+{
+ FmSearchParams aParams(m_pConfig->getParams());
+
+ const ::rtl::OUString* pHistory = aParams.aHistory.getConstArray();
+ const ::rtl::OUString* pHistoryEnd = pHistory + aParams.aHistory.getLength();
+ for (; pHistory != pHistoryEnd; ++pHistory)
+ m_cmbSearchText.InsertEntry( *pHistory );
+
+ // die Einstellungen nehme ich an meinen UI-Elementen vor und rufe dann einfach den entsprechenden Change-Handler auf,
+ // dadurch werden die Daten an die SearchEngine weitergereicht und alle abhaengigen Enstellungen vorgenommen
+
+ // aktuelles Feld
+ sal_uInt16 nInitialField = m_lbField.GetEntryPos( String( aParams.sSingleSearchField ) );
+ if (nInitialField == COMBOBOX_ENTRY_NOTFOUND)
+ nInitialField = 0;
+ m_lbField.SelectEntryPos(nInitialField);
+ LINK(this, FmSearchDialog, OnFieldSelected).Call(&m_lbField);
+ // alle/einzelnes Feld (NACH dem Selektieren des Feldes, da OnClickedFieldRadios dort einen gueltigen Eintrag erwartet)
+ if (aParams.bAllFields)
+ {
+ m_rbSingleField.Check(sal_False);
+ m_rbAllFields.Check(sal_True);
+ LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbAllFields);
+ // OnClickedFieldRadios ruft auch um RebuildUsedFields
+ }
+ else
+ {
+ m_rbAllFields.Check(sal_False);
+ m_rbSingleField.Check(sal_True);
+ LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbSingleField);
+ }
+
+ // Position im Feld
+ m_lbPosition.SelectEntryPos(aParams.nPosition);
+ LINK(this, FmSearchDialog, OnPositionSelected).Call(&m_lbPosition);
+
+ // Feld-Formatierung/Case-Sensitivitaet/Richtung
+ m_cbUseFormat.Check(aParams.bUseFormatter);
+ m_cbCase.Check( aParams.isCaseSensitive() );
+ m_cbBackwards.Check(aParams.bBackwards);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbUseFormat);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbCase);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbBackwards);
+
+ m_aHalfFullFormsCJK.Check( !aParams.isIgnoreWidthCJK( ) ); // BEWARE: this checkbox has a inverse semantics!
+ m_aSoundsLikeCJK.Check( aParams.bSoundsLikeCJK );
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_aHalfFullFormsCJK);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_aSoundsLikeCJK);
+
+ // die drei Checkboxen fuer spezielle Sucharten
+ // erst mal alle ruecksetzen
+ m_cbWildCard.Check(sal_False);
+ m_cbRegular.Check(sal_False);
+ m_cbApprox.Check(sal_False);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbWildCard);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbRegular);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(&m_cbApprox);
+
+ // dann die richtige setzen
+ CheckBox* pToCheck = NULL;
+ if (aParams.bWildcard)
+ pToCheck = &m_cbWildCard;
+ if (aParams.bRegular)
+ pToCheck = &m_cbRegular;
+ if (aParams.bApproxSearch)
+ pToCheck = &m_cbApprox;
+ if (aParams.bSoundsLikeCJK)
+ pToCheck = &m_aSoundsLikeCJK;
+ if (pToCheck)
+ {
+ pToCheck->Check(sal_True);
+ LINK(this, FmSearchDialog, OnCheckBoxToggled).Call(pToCheck);
+ }
+
+ // die Levenshtein-Parameter direkt an der SearchEngine setzen
+ m_pSearchEngine->SetLevRelaxed(aParams.bLevRelaxed);
+ m_pSearchEngine->SetLevOther(aParams.nLevOther);
+ m_pSearchEngine->SetLevShorter(aParams.nLevShorter);
+ m_pSearchEngine->SetLevLonger(aParams.nLevLonger);
+
+ m_pSearchEngine->SetTransliterationFlags( aParams.getTransliterationFlags( ) );
+
+ m_rbSearchForText.Check(sal_False);
+ m_rbSearchForNull.Check(sal_False);
+ m_rbSearchForNotNull.Check(sal_False);
+ switch (aParams.nSearchForType)
+ {
+ case 1: m_rbSearchForNull.Check(sal_True); break;
+ case 2: m_rbSearchForNotNull.Check(sal_True); break;
+ default: m_rbSearchForText.Check(sal_True); break;
+ }
+ LINK(this, FmSearchDialog, OnClickedFieldRadios).Call(&m_rbSearchForText);
+}
+
+//------------------------------------------------------------------------
+void FmSearchDialog::SaveParams() const
+{
+ if (!m_pConfig)
+ return;
+
+ FmSearchParams aCurrentSettings;
+
+ aCurrentSettings.aHistory.realloc( m_cmbSearchText.GetEntryCount() );
+ ::rtl::OUString* pHistory = aCurrentSettings.aHistory.getArray();
+ for (sal_uInt16 i=0; i<m_cmbSearchText.GetEntryCount(); ++i, ++pHistory)
+ *pHistory = m_cmbSearchText.GetEntry(i);
+
+ aCurrentSettings.sSingleSearchField = m_lbField.GetSelectEntry();
+ aCurrentSettings.bAllFields = m_rbAllFields.IsChecked();
+ aCurrentSettings.nPosition = m_pSearchEngine->GetPosition();
+ aCurrentSettings.bUseFormatter = m_pSearchEngine->GetFormatterUsing();
+ aCurrentSettings.setCaseSensitive ( m_pSearchEngine->GetCaseSensitive() );
+ aCurrentSettings.bBackwards = !m_pSearchEngine->GetDirection();
+ aCurrentSettings.bWildcard = m_pSearchEngine->GetWildcard();
+ aCurrentSettings.bRegular = m_pSearchEngine->GetRegular();
+ aCurrentSettings.bApproxSearch = m_pSearchEngine->GetLevenshtein();
+ aCurrentSettings.bLevRelaxed = m_pSearchEngine->GetLevRelaxed();
+ aCurrentSettings.nLevOther = m_pSearchEngine->GetLevOther();
+ aCurrentSettings.nLevShorter = m_pSearchEngine->GetLevShorter();
+ aCurrentSettings.nLevLonger = m_pSearchEngine->GetLevLonger();
+
+ aCurrentSettings.bSoundsLikeCJK = m_pSearchEngine->GetTransliteration();
+ aCurrentSettings.setTransliterationFlags ( m_pSearchEngine->GetTransliterationFlags() );
+
+ if (m_rbSearchForNull.IsChecked())
+ aCurrentSettings.nSearchForType = 1;
+ else if (m_rbSearchForNotNull.IsChecked())
+ aCurrentSettings.nSearchForType = 2;
+ else
+ aCurrentSettings.nSearchForType = 0;
+
+ m_pConfig->setParams( aCurrentSettings );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */