Created
March 12, 2025 15:21
-
-
Save varshneydevansh/92e98a7a14cb90289ba77c97fd7e899c to your computer and use it in GitHub Desktop.
cui/source/dialogs/cuifmsearch.cxx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tools/debug.hxx> | |
#include <vcl/stdtext.hxx> | |
#include <vcl/svapp.hxx> | |
#include <vcl/weld.hxx> | |
#include <dialmgr.hxx> | |
#include <sfx2/app.hxx> | |
#include <svx/fmsrccfg.hxx> | |
#include <svx/fmsrcimp.hxx> | |
#include <strings.hrc> | |
#include <cuifmsearch.hxx> | |
#include <svl/cjkoptions.hxx> | |
#include <comphelper/processfactory.hxx> | |
#include <comphelper/string.hxx> | |
#include <svx/svxdlg.hxx> | |
#include <o3tl/string_view.hxx> | |
using namespace css::uno; | |
using namespace ::svxform; | |
using namespace css::sdbc; | |
#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 | |
if (!SvtCJKOptions::IsJapaneseFindEnabled()) | |
{ | |
// hide the options for the japanese search | |
m_pSoundsLikeCJK->hide(); | |
m_pSoundsLikeCJKSettings->hide(); | |
} | |
if (!SvtCJKOptions::IsCJKFontEnabled()) | |
{ | |
m_pHalfFullFormsCJK->hide(); | |
// never ignore the width (ignoring is expensive) if the option is not available at all | |
m_pSearchEngine->SetIgnoreWidthCJK( false ); | |
} | |
// some initial record texts | |
m_pftRecord->set_label( OUString::number(_rxCursor->getRow()) ); | |
m_pbClose->set_tooltip_text(OUString()); | |
} | |
FmSearchDialog::FmSearchDialog(weld::Window* pParent, const OUString& sInitialText, const std::vector< OUString >& _rContexts, sal_Int16 nInitialContext, | |
const Link<FmSearchContext&,sal_uInt32>& lnkContextSupplier) | |
: GenericDialogController(pParent, u"cui/ui/fmsearchdialog.ui"_ustr, u"RecordSearchDialog"_ustr) | |
, m_sCancel( GetStandardText( StandardButtonType::Cancel ) ) | |
, m_lnkContextSupplier(lnkContextSupplier) | |
, m_prbSearchForText(m_xBuilder->weld_radio_button("rbSearchForText")) | |
, m_prbSearchForNull(m_xBuilder->weld_radio_button("rbSearchForNull")) | |
, m_prbSearchForNotNull(m_xBuilder->weld_radio_button("rbSearchForNotNull")) | |
, m_pcmbSearchText(m_xBuilder->weld_combo_box("cmbSearchText")) | |
, m_pftForm(m_xBuilder->weld_label("ftForm")) | |
, m_plbForm(m_xBuilder->weld_combo_box("lbForm")) | |
, m_prbAllFields(m_xBuilder->weld_radio_button("rbAllFields")) | |
, m_prbSingleField(m_xBuilder->weld_radio_button("rbSingleField")) | |
, m_plbField(m_xBuilder->weld_combo_box("lbField")) | |
, m_pftPosition(m_xBuilder->weld_label("ftPosition")) | |
, m_plbPosition(m_xBuilder->weld_combo_box("lbPosition")) | |
, m_pcbUseFormat(m_xBuilder->weld_check_button("cbUseFormat")) | |
, m_pcbCase(m_xBuilder->weld_check_button("cbCase")) | |
, m_pcbBackwards(m_xBuilder->weld_check_button("cbBackwards")) | |
, m_pcbStartOver(m_xBuilder->weld_check_button("cbStartOver")) | |
, m_pcbWildCard(m_xBuilder->weld_check_button("cbWildCard")) | |
, m_pcbRegular(m_xBuilder->weld_check_button("cbRegular")) | |
, m_pcbApprox(m_xBuilder->weld_check_button("cbApprox")) | |
, m_ppbApproxSettings(m_xBuilder->weld_button("pbApproxSettings")) | |
, m_pHalfFullFormsCJK(m_xBuilder->weld_check_button("HalfFullFormsCJK")) | |
, m_pSoundsLikeCJK(m_xBuilder->weld_check_button("SoundsLikeCJK")) | |
, m_pSoundsLikeCJKSettings(m_xBuilder->weld_button("SoundsLikeCJKSettings")) | |
, m_pftRecord(m_xBuilder->weld_label("ftRecord")) | |
, m_pftHint(m_xBuilder->weld_label("ftHint")) | |
, m_pbSearchAgain(m_xBuilder->weld_button("pbSearchAgain")) | |
, m_pbClose(m_xBuilder->weld_button("close")) | |
, m_prbReplaceWithText(m_xBuilder->weld_radio_button("rbReplaceWithText")) | |
, m_prbSetToNull(m_xBuilder->weld_radio_button("rbSetToNull")) | |
, m_pcmbReplaceText(m_xBuilder->weld_combo_box("cmbReplaceText")) | |
, m_pbReplace(m_xBuilder->weld_button("pbReplace")) | |
, m_pbReplaceAll(m_xBuilder->weld_button("pbReplaceAll")) | |
, m_sReplaceAll(CuiResId(RID_STR_REPLACE_ALL)) | |
{ | |
m_pcmbSearchText->set_size_request(m_pcmbSearchText->get_approximate_digit_width() * 38, -1); | |
m_plbForm->set_size_request(m_plbForm->get_approximate_digit_width() * 38, -1); | |
m_sSearch = m_pbSearchAgain->get_label(); | |
DBG_ASSERT(m_lnkContextSupplier.IsSet(), "FmSearchDialog::FmSearchDialog : have no ContextSupplier !"); | |
FmSearchContext fmscInitial; | |
fmscInitial.nContext = nInitialContext; | |
m_lnkContextSupplier.Call(fmscInitial); | |
DBG_ASSERT(fmscInitial.xCursor.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !"); | |
DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial.strUsedFields, ';') == static_cast<sal_Int32>(fmscInitial.arrFields.size()), | |
"FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplied !"); | |
#if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL | |
for (const Reference<XInterface> & arrField : fmscInitial.arrFields) | |
{ | |
DBG_ASSERT(arrField.is(), "FmSearchDialog::FmSearchDialog : invalid data supplied by ContextSupplier !"); | |
} | |
#endif // (OSL_DEBUG_LEVEL > 1) || DBG_UTIL | |
for ( std::vector< OUString >::const_iterator context = _rContexts.begin(); | |
context != _rContexts.end(); | |
++context | |
) | |
{ | |
m_arrContextFields.emplace_back(); | |
m_plbForm->append_text(*context); | |
} | |
m_plbForm->set_active(nInitialContext); | |
m_plbForm->connect_changed(LINK(this, FmSearchDialog, OnContextSelection)); | |
if (m_arrContextFields.size() == 1) | |
{ | |
// hide dispensable controls | |
m_pftForm->hide(); | |
m_plbForm->hide(); | |
} | |
m_pSearchEngine.reset( new FmSearchEngine( | |
::comphelper::getProcessComponentContext(), fmscInitial.xCursor, fmscInitial.strUsedFields, fmscInitial.arrFields ) ); | |
initCommon( fmscInitial.xCursor ); | |
if ( !fmscInitial.sFieldDisplayNames.isEmpty() ) | |
{ // use the display names if supplied | |
DBG_ASSERT(comphelper::string::getTokenCount(fmscInitial.sFieldDisplayNames, ';') == comphelper::string::getTokenCount(fmscInitial.strUsedFields, ';'), | |
"FmSearchDialog::FmSearchDialog : invalid initial context description !"); | |
Init(fmscInitial.sFieldDisplayNames, sInitialText); | |
} | |
else | |
Init(fmscInitial.strUsedFields, sInitialText); | |
} | |
FmSearchDialog::~FmSearchDialog() | |
{ | |
SaveParams(); | |
m_pConfig.reset(); | |
m_pSearchEngine.reset(); | |
} | |
void FmSearchDialog::Init(std::u16string_view strVisibleFields, const OUString& sInitialText) | |
{ | |
//the initialization of all the Controls | |
m_prbSearchForText->connect_toggled(LINK(this, FmSearchDialog, OnToggledSearchRadio)); | |
m_prbSearchForNull->connect_toggled(LINK(this, FmSearchDialog, OnToggledSearchRadio)); | |
m_prbSearchForNotNull->connect_toggled(LINK(this, FmSearchDialog, OnToggledSearchRadio)); | |
m_prbAllFields->connect_toggled(LINK(this, FmSearchDialog, OnToggledFieldRadios)); | |
m_prbSingleField->connect_toggled(LINK(this, FmSearchDialog, OnToggledFieldRadios)); | |
m_pbSearchAgain->connect_clicked(LINK(this, FmSearchDialog, OnClickedSearchAgain)); | |
m_ppbApproxSettings->connect_clicked(LINK(this, FmSearchDialog, OnClickedSpecialSettings)); | |
m_pSoundsLikeCJKSettings->connect_clicked(LINK(this, FmSearchDialog, OnClickedSpecialSettings)); | |
m_pbReplace->connect_clicked(LINK(this, FmSearchDialog, OnClickedReplace)); | |
m_pbReplaceAll->connect_clicked(LINK(this, FmSearchDialog, OnClickedReplaceAll)); | |
m_plbPosition->connect_changed(LINK(this, FmSearchDialog, OnPositionSelected)); | |
m_plbField->connect_changed(LINK(this, FmSearchDialog, OnFieldSelected)); | |
m_pcmbSearchText->connect_changed(LINK(this, FmSearchDialog, OnSearchTextModified)); | |
m_pcmbReplaceText->connect_changed(LINK(this, FmSearchDialog, OnReplaceTextModified)); | |
m_pcmbSearchText->set_entry_completion(false); | |
m_pcmbSearchText->connect_focus_in(LINK(this, FmSearchDialog, OnFocusGrabbed)); | |
m_pcbUseFormat->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbBackwards->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbStartOver->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbCase->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbWildCard->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbRegular->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pcbApprox->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pHalfFullFormsCJK->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pSoundsLikeCJK->connect_toggled(LINK(this, FmSearchDialog, OnCheckBoxToggled)); | |
m_pbReplaceAll->set_label(m_sReplaceAll); | |
// fill the listboxes | |
// method of field comparison | |
const TranslateId aResIds[] = { | |
RID_STR_SEARCH_ANYWHERE, | |
RID_STR_SEARCH_BEGINNING, | |
RID_STR_SEARCH_END, | |
RID_STR_SEARCH_WHOLE | |
}; | |
for (auto const & pResId : aResIds) | |
m_plbPosition->append_text(CuiResId(pResId)); | |
m_plbPosition->set_active(MATCHING_ANYWHERE); | |
// the field listbox | |
if (!strVisibleFields.empty()) | |
{ | |
sal_Int32 nPos {0}; | |
do { | |
m_plbField->append_text(OUString(o3tl::getToken(strVisibleFields, 0, ';', nPos))); | |
} while (nPos>=0); | |
} | |
m_pConfig.reset( new FmSearchConfigItem ); | |
LoadParams(); | |
m_pcmbSearchText->set_entry_text(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 OUString. | |
OUString sRealSetText = m_pcmbSearchText->get_active_text(); | |
if (sRealSetText != sInitialText) | |
m_pcmbSearchText->set_entry_text(OUString()); | |
OnSearchTextModified(*m_pcmbSearchText); | |
// initial | |
EnableSearchUI(true); | |
if ( m_prbSearchForText->get_active() ) | |
m_pcmbSearchText->grab_focus(); | |
} | |
bool FmSearchEngine::ReplaceNext(const OUString& aSearchText, const OUString& aReplaceText) | |
{ | |
if (aSearchText.isEmpty() || m_strSearchExpression != aSearchText) | |
{ | |
// If the search text has changed, start a new search | |
m_strSearchExpression = aSearchText; | |
m_eSearchForType = SearchFor::String; | |
SearchNext(m_strSearchExpression); | |
} | |
if (m_srResult == SearchResult::Found) | |
{ | |
// Replace the found text with the replace text | |
FieldCollection::iterator iterField = m_arrUsedFields.begin() + m_nCurrentFieldIndex; | |
css::uno::Reference<css::sdb::XColumn> xColumn = iterField->xContents; | |
css::uno::Reference<css::beans::XPropertySet> xColumnProps(xColumn, css::uno::UNO_QUERY); | |
if (xColumnProps.is()) | |
{ | |
OUString sCurrentValue; | |
xColumnProps->getPropertyValue("Value") >>= sCurrentValue; | |
OUString sNewValue = sCurrentValue.replaceFirst(aSearchText, aReplaceText); | |
xColumnProps->setPropertyValue("Value", css::uno::Any(sNewValue)); | |
// Update the control text | |
m_aControlTexts[m_nCurrentFieldIndex]->SetText(sNewValue); | |
// Move to the next position | |
SearchNext(m_strSearchExpression); | |
return true; | |
} | |
} | |
return false; | |
} | |
sal_Int32 FmSearchEngine::ReplaceAll(const OUString& aSearchText, const OUString& aReplaceText) | |
{ | |
sal_Int32 nReplacedCount = 0; | |
m_strSearchExpression = aSearchText; | |
m_eSearchForType = SearchFor::String; | |
// Start searching from the beginning | |
StartOver(m_strSearchExpression); | |
while (m_srResult == SearchResult::Found) | |
{ | |
// Replace the found text with the replace text | |
FieldCollection::iterator iterField = m_arrUsedFields.begin() + m_nCurrentFieldIndex; | |
css::uno::Reference<css::sdb::XColumn> xColumn = iterField->xContents; | |
css::uno::Reference<css::beans::XPropertySet> xColumnProps(xColumn, css::uno::UNO_QUERY); | |
if (xColumnProps.is()) | |
{ | |
OUString sCurrentValue; | |
xColumnProps->getPropertyValue("Value") >>= sCurrentValue; | |
OUString sNewValue = sCurrentValue.replaceAll(aSearchText, aReplaceText); | |
xColumnProps->setPropertyValue("Value", css::uno::Any(sNewValue)); | |
// Update the control text | |
m_aControlTexts[m_nCurrentFieldIndex]->SetText(sNewValue); | |
++nReplacedCount; | |
} | |
// Move to the next position | |
SearchNext(m_strSearchExpression); | |
} | |
return nReplacedCount; | |
} | |
short FmSearchDialog::run() | |
{ | |
short nRet = weld::GenericDialogController::run(); | |
m_pSearchEngine->CancelSearch(); | |
return nRet; | |
} | |
IMPL_LINK(FmSearchDialog, OnToggledSearchRadio, weld::Toggleable&, rButton, void) | |
{ | |
if (!rButton.get_active()) | |
return; | |
EnableSearchForDependees(true); | |
} | |
IMPL_LINK(FmSearchDialog, OnToggledFieldRadios, weld::Toggleable&, rButton, void) | |
{ | |
if (!rButton.get_active()) | |
return; | |
// en- or disable field list box accordingly | |
if (m_prbSingleField->get_active()) | |
{ | |
m_plbField->set_sensitive(true); | |
m_pSearchEngine->RebuildUsedFields(m_plbField->get_active()); | |
} | |
else | |
{ | |
m_plbField->set_sensitive(false); | |
m_pSearchEngine->RebuildUsedFields(-1); | |
} | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnClickedSearchAgain, weld::Button&, void) | |
{ | |
if (m_pbClose->get_sensitive()) | |
{ // the button has the function 'search' | |
OUString strThisRoundText = m_pcmbSearchText->get_active_text(); | |
// to history | |
m_pcmbSearchText->remove_text(strThisRoundText); | |
m_pcmbSearchText->insert_text(0, strThisRoundText); | |
// the remove/insert makes sure that a) the OUString does not appear twice and | |
// that b) the last searched strings are at the beginning and limit the list length | |
while (m_pcmbSearchText->get_count() > MAX_HISTORY_ENTRIES) | |
m_pcmbSearchText->remove(m_pcmbSearchText->get_count()-1); | |
// take out the 'overflow' hint | |
m_pftHint->set_label(OUString()); | |
if (m_pcbStartOver->get_active()) | |
{ | |
m_pcbStartOver->set_active(false); | |
EnableSearchUI(false); | |
if (m_prbSearchForText->get_active()) | |
m_pSearchEngine->StartOver(strThisRoundText); | |
else | |
m_pSearchEngine->StartOverSpecial(m_prbSearchForNull->get_active()); | |
} | |
else | |
{ | |
EnableSearchUI(false); | |
if (m_prbSearchForText->get_active()) | |
m_pSearchEngine->SearchNext(strThisRoundText); | |
else | |
m_pSearchEngine->SearchNextSpecial(m_prbSearchForNull->get_active()); | |
} | |
} | |
else | |
{ // the button has the function 'cancel' | |
// the CancelButton is usually only disabled, when working in a thread or with reschedule | |
m_pSearchEngine->CancelSearch(); | |
// the ProgressHandler is called when it's really finished, here it's only a demand | |
} | |
} | |
IMPL_LINK(FmSearchDialog, OnClickedSpecialSettings, weld::Button&, rButton, void) | |
{ | |
if (m_ppbApproxSettings.get() == &rButton) | |
{ | |
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); | |
VclPtr<AbstractSvxSearchSimilarityDialog> pDlg(pFact->CreateSvxSearchSimilarityDialog(m_xDialog.get(), m_pSearchEngine->GetLevRelaxed(), m_pSearchEngine->GetLevOther(), | |
m_pSearchEngine->GetLevShorter(), m_pSearchEngine->GetLevLonger() )); | |
pDlg->StartExecuteAsync([pDlg, this](sal_Int32 nResult){ | |
if (nResult == RET_OK) | |
{ | |
m_pSearchEngine->SetLevRelaxed( pDlg->IsRelaxed() ); | |
m_pSearchEngine->SetLevOther( pDlg->GetOther() ); | |
m_pSearchEngine->SetLevShorter(pDlg->GetShorter() ); | |
m_pSearchEngine->SetLevLonger( pDlg->GetLonger() ); | |
} | |
pDlg->disposeOnce(); | |
}); | |
} | |
else if (m_pSoundsLikeCJKSettings.get() == &rButton) | |
{ | |
SfxItemSet aSet( SfxGetpApp()->GetPool() ); | |
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); | |
ScopedVclPtr<AbstractSvxJSearchOptionsDialog> aDlg(pFact->CreateSvxJSearchOptionsDialog(m_xDialog.get(), aSet, m_pSearchEngine->GetTransliterationFlags() )); | |
aDlg->Execute(); | |
TransliterationFlags nFlags = aDlg->GetTransliterationFlags(); | |
m_pSearchEngine->SetTransliterationFlags(nFlags); | |
m_pcbCase->set_active(m_pSearchEngine->GetCaseSensitive()); | |
OnCheckBoxToggled( *m_pcbCase ); | |
m_pHalfFullFormsCJK->set_active( !m_pSearchEngine->GetIgnoreWidthCJK() ); | |
OnCheckBoxToggled( *m_pHalfFullFormsCJK ); | |
} | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnClickedReplace, weld::Button&, void) | |
{ | |
bool bSearchingForText = m_prbSearchForText->get_active(); | |
bool bReplacingWithText = m_prbReplaceWithText->get_active(); | |
if (bSearchingForText && bReplacingWithText) | |
{ | |
OUString aSearchText = m_pcmbSearchText->get_active_text(); | |
OUString aReplaceText = m_pcmbReplaceText->get_active_text(); | |
if (!aSearchText.isEmpty() && !aReplaceText.isEmpty()) | |
{ | |
try | |
{ | |
bool bReplaced = m_pSearchEngine->ReplaceNext(aSearchText, aReplaceText); | |
if (bReplaced) | |
{ | |
// Update the UI to reflect the replacement | |
m_pftRecord->set_label(OUString::number(m_pSearchEngine->GetCurrentRecord())); | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACED)); | |
} | |
else | |
{ | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_NO_REPLACE)); | |
} | |
} | |
catch (const Exception& e) | |
{ | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACE_ERROR)); | |
SAL_WARN("cui.dialogs", "Error during replace: " << e); | |
} | |
} | |
} | |
else | |
{ | |
// Handle case when search or replace text is empty | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACE_INVALID)); | |
} | |
EnableReplace(m_pbSearchAgain->get_sensitive()); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnClickedReplaceAll, weld::Button&, void) | |
{ | |
bool bSearchingForText = m_prbSearchForText->get_active(); | |
bool bReplacingWithText = m_prbReplaceWithText->get_active(); | |
if (bSearchingForText && bReplacingWithText) | |
{ | |
OUString aSearchText = m_pcmbSearchText->get_active_text(); | |
OUString aReplaceText = m_pcmbReplaceText->get_active_text(); | |
if (!aSearchText.isEmpty() && !aReplaceText.isEmpty()) | |
{ | |
try | |
{ | |
sal_Int32 nReplacedCount = m_pSearchEngine->ReplaceAll(aSearchText, aReplaceText); | |
m_pftRecord->set_label(OUString::number(m_pSearchEngine->GetCurrentRecord())); | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACED_ALL) + OUString::number(nReplacedCount)); | |
} | |
catch (const Exception& e) | |
{ | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACE_ERROR)); | |
SAL_WARN("cui.dialogs", "Error during replace all: " << e); | |
} | |
} | |
} | |
else | |
{ | |
// Handle case when search or replace text is empty | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_REPLACE_INVALID)); | |
} | |
EnableReplace(m_pbSearchAgain->get_sensitive()); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnSearchTextModified, weld::ComboBox&, void) | |
{ | |
if ((!m_pcmbSearchText->get_active_text().isEmpty()) || !m_prbSearchForText->get_active()) | |
m_pbSearchAgain->set_sensitive(true); | |
else | |
m_pbSearchAgain->set_sensitive(false); | |
m_pSearchEngine->InvalidatePreviousLoc(); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnReplaceTextModified, weld::ComboBox&, void) | |
{ | |
EnableReplace(m_pbSearchAgain->get_sensitive()); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnFocusGrabbed, weld::Widget&, void) | |
{ | |
m_pcmbSearchText->select_entry_region(0, -1); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnPositionSelected, weld::ComboBox&, void) | |
{ | |
m_pSearchEngine->SetPosition(m_plbPosition->get_active()); | |
} | |
IMPL_LINK_NOARG(FmSearchDialog, OnFieldSelected, weld::ComboBox&, void) | |
{ | |
m_pSearchEngine->RebuildUsedFields(m_prbAllFields->get_active() ? -1 : m_plbField->get_active()); | |
// calls m_pSearchEngine->InvalidatePreviousLoc too | |
int nCurrentContext = m_plbForm->get_active(); | |
if (nCurrentContext != -1) | |
m_arrContextFields[nCurrentContext] = m_plbField->get_active_text(); | |
} | |
IMPL_LINK(FmSearchDialog, OnCheckBoxToggled, weld::Toggleable&, rBox, void) | |
{ | |
bool bChecked = rBox.get_active(); | |
// formatter or case -> pass on to the engine | |
if (&rBox == m_pcbUseFormat.get()) | |
m_pSearchEngine->SetFormatterUsing(bChecked); | |
else if (&rBox == m_pcbCase.get()) | |
m_pSearchEngine->SetCaseSensitive(bChecked); | |
// direction -> pass on and reset the checkbox-text for StartOver | |
else if (&rBox == m_pcbBackwards.get()) | |
{ | |
m_pcbStartOver->set_label( CuiResId( bChecked ? RID_STR_FROM_BOTTOM : RID_STR_FROM_TOP ) ); | |
m_pSearchEngine->SetDirection(!bChecked); | |
} | |
// similarity-search or regular expression | |
else if ((&rBox == m_pcbApprox.get()) || (&rBox == m_pcbRegular.get()) || (&rBox == m_pcbWildCard.get())) | |
{ | |
weld::CheckButton* pBoxes[] = { m_pcbWildCard.get(), m_pcbRegular.get(), m_pcbApprox.get() }; | |
for (weld::CheckButton* pBoxe : pBoxes) | |
{ | |
if (pBoxe != &rBox) | |
{ | |
if (bChecked) | |
pBoxe->set_sensitive(false); | |
else | |
pBoxe->set_sensitive(true); | |
} | |
} | |
// pass on to the engine | |
m_pSearchEngine->SetWildcard(m_pcbWildCard->get_sensitive() && m_pcbWildCard->get_active()); | |
m_pSearchEngine->SetRegular(m_pcbRegular->get_sensitive() && m_pcbRegular->get_active()); | |
m_pSearchEngine->SetLevenshtein(m_pcbApprox->get_sensitive() && m_pcbApprox->get_active()); | |
// (disabled boxes have to be passed to the engine as sal_False) | |
// adjust the Position-Listbox (which is not allowed during Wildcard-search) | |
if (&rBox == m_pcbWildCard.get()) | |
{ | |
if (bChecked) | |
{ | |
m_pftPosition->set_sensitive(false); | |
m_plbPosition->set_sensitive(false); | |
} | |
else | |
{ | |
m_pftPosition->set_sensitive(true); | |
m_plbPosition->set_sensitive(true); | |
} | |
} | |
// and the button for similarity-search | |
if (&rBox == m_pcbApprox.get()) | |
{ | |
if (bChecked) | |
m_ppbApproxSettings->set_sensitive(true); | |
else | |
m_ppbApproxSettings->set_sensitive(false); | |
} | |
} | |
else if (&rBox == m_pHalfFullFormsCJK.get()) | |
{ | |
// forward to the search engine | |
m_pSearchEngine->SetIgnoreWidthCJK( !bChecked ); | |
} | |
else if (&rBox == m_pSoundsLikeCJK.get()) | |
{ | |
m_pSoundsLikeCJKSettings->set_sensitive(bChecked); | |
// two other buttons which depend on this one | |
bool bEnable = ( m_prbSearchForText->get_active() | |
&& !m_pSoundsLikeCJK->get_active() | |
) | |
|| !SvtCJKOptions::IsJapaneseFindEnabled(); | |
m_pcbCase->set_sensitive(bEnable); | |
m_pHalfFullFormsCJK->set_sensitive(bEnable); | |
// forward to the search engine | |
m_pSearchEngine->SetTransliteration( bChecked ); | |
} | |
} | |
void FmSearchDialog::EnableReplace(bool bEnable) | |
{ | |
bool bReplacingWithText = m_prbReplaceWithText->get_active(); | |
bEnable = bEnable && (!bReplacingWithText || (!m_pcmbReplaceText->get_active_text().isEmpty())); | |
m_pbReplace->set_sensitive(bEnable); | |
m_pbReplaceAll->set_sensitive(bEnable); | |
} | |
void FmSearchDialog::InitContext(sal_Int16 nContext) | |
{ | |
FmSearchContext fmscContext; | |
fmscContext.nContext = nContext; | |
sal_uInt32 nResult = m_lnkContextSupplier.Call(fmscContext); | |
DBG_ASSERT(nResult > 0, "FmSearchDialog::InitContext : ContextSupplier didn't give me any controls !"); | |
// put the field names into the respective listbox | |
m_plbField->clear(); | |
if (!fmscContext.sFieldDisplayNames.isEmpty()) | |
{ | |
// use the display names if supplied | |
DBG_ASSERT(comphelper::string::getTokenCount(fmscContext.sFieldDisplayNames, ';') == comphelper::string::getTokenCount(fmscContext.strUsedFields, ';'), | |
"FmSearchDialog::InitContext : invalid context description supplied !"); | |
sal_Int32 nPos {0}; | |
do { | |
m_plbField->append_text(fmscContext.sFieldDisplayNames.getToken(0, ';', nPos)); | |
} while (nPos>=0); | |
} | |
else if (!fmscContext.strUsedFields.isEmpty()) | |
{ | |
// else use the field names | |
sal_Int32 nPos {0}; | |
do { | |
m_plbField->append_text(fmscContext.strUsedFields.getToken(0, ';', nPos)); | |
} while (nPos>=0); | |
} | |
if (nContext < static_cast<sal_Int32>(m_arrContextFields.size()) && !m_arrContextFields[nContext].isEmpty()) | |
{ | |
m_plbField->set_active_text(m_arrContextFields[nContext]); | |
} | |
else | |
{ | |
m_plbField->set_active(0); | |
if (m_prbSingleField->get_active() && (m_plbField->get_count() > 1)) | |
m_plbField->grab_focus(); | |
} | |
m_pSearchEngine->SwitchToContext(fmscContext.xCursor, fmscContext.strUsedFields, fmscContext.arrFields, | |
m_prbAllFields->get_active() ? -1 : 0); | |
m_pftRecord->set_label(OUString::number(fmscContext.xCursor->getRow())); | |
} | |
IMPL_LINK(FmSearchDialog, OnContextSelection, weld::ComboBox&, rBox, void) | |
{ | |
InitContext(rBox.get_active()); | |
} | |
void FmSearchDialog::EnableSearchUI(bool bEnable) | |
{ | |
// the search button has two functions -> adjust its text accordingly | |
OUString sButtonText( bEnable ? m_sSearch : m_sCancel ); | |
m_pbSearchAgain->set_label(sButtonText); | |
m_prbSearchForText->set_sensitive(bEnable); | |
m_prbSearchForNull->set_sensitive(bEnable); | |
m_prbSearchForNotNull->set_sensitive(bEnable); | |
m_plbForm->set_sensitive(bEnable); | |
m_prbAllFields->set_sensitive(bEnable); | |
m_prbSingleField->set_sensitive(bEnable); | |
m_plbField->set_sensitive(bEnable && m_prbSingleField->get_active()); | |
m_pcbBackwards->set_sensitive(bEnable); | |
m_pcbStartOver->set_sensitive(bEnable); | |
m_pbClose->set_sensitive(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->set_sensitive(true); | |
} | |
} | |
void FmSearchDialog::EnableSearchForDependees(bool bEnable) | |
{ | |
bool bSearchingForText = m_prbSearchForText->get_active(); | |
m_pbSearchAgain->set_sensitive(bEnable && (!bSearchingForText || (!m_pcmbSearchText->get_active_text().isEmpty()))); | |
bEnable = bEnable && bSearchingForText; | |
bool bEnableRedundants = !m_pSoundsLikeCJK->get_active() || !SvtCJKOptions::IsJapaneseFindEnabled(); | |
m_pcmbSearchText->set_sensitive(bEnable); | |
m_pftPosition->set_sensitive(bEnable && !m_pcbWildCard->get_active()); | |
m_pcbWildCard->set_sensitive(bEnable && !m_pcbRegular->get_active() && !m_pcbApprox->get_active()); | |
m_pcbRegular->set_sensitive(bEnable && !m_pcbWildCard->get_active() && !m_pcbApprox->get_active()); | |
m_pcbApprox->set_sensitive(bEnable && !m_pcbWildCard->get_active() && !m_pcbRegular->get_active()); | |
m_ppbApproxSettings->set_sensitive(bEnable && m_pcbApprox->get_active()); | |
m_pHalfFullFormsCJK->set_sensitive(bEnable && bEnableRedundants); | |
m_pSoundsLikeCJK->set_sensitive(bEnable); | |
m_pSoundsLikeCJKSettings->set_sensitive(bEnable && m_pSoundsLikeCJK->get_active()); | |
m_plbPosition->set_sensitive(bEnable && !m_pcbWildCard->get_active()); | |
m_pcbUseFormat->set_sensitive(bEnable); | |
m_pcbCase->set_sensitive(bEnable && bEnableRedundants); | |
EnableReplace(bEnable); | |
} | |
void FmSearchDialog::OnFound(const css::uno::Any& aCursorPos, sal_Int16 nFieldPos) | |
{ | |
FmFoundRecordInformation friInfo; | |
friInfo.nContext = m_plbForm->get_active(); | |
// if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway | |
friInfo.aPosition = aCursorPos; | |
if (m_prbAllFields->get_active()) | |
friInfo.nFieldPos = nFieldPos; | |
else | |
friInfo.nFieldPos = m_plbField->get_active(); | |
// this of course implies that I have really searched in the field that is selected in the listbox, | |
// which is made sure in RebuildUsedFields | |
m_lnkFoundHandler.Call(friInfo); | |
m_pcmbSearchText->grab_focus(); | |
} | |
IMPL_LINK(FmSearchDialog, OnSearchProgress, const FmSearchProgress*, pProgress, void) | |
{ | |
SolarMutexGuard aGuard; | |
// make this single method thread-safe (it's an overkill to block the whole application for this, | |
// but we don't have another safety concept at the moment) | |
switch (pProgress->aSearchState) | |
{ | |
case FmSearchProgress::State::Progress: | |
if (pProgress->bOverflow) | |
{ | |
OUString sHint( CuiResId( m_pcbBackwards->get_active() ? RID_STR_OVERFLOW_BACKWARD : RID_STR_OVERFLOW_FORWARD ) ); | |
m_pftHint->set_label( sHint ); | |
} | |
m_pftRecord->set_label(OUString::number(1 + pProgress->nCurrentRecord)); | |
break; | |
case FmSearchProgress::State::ProgressCounting: | |
m_pftHint->set_label(CuiResId(RID_STR_SEARCH_COUNTING)); | |
m_pftRecord->set_label(OUString::number(pProgress->nCurrentRecord)); | |
break; | |
case FmSearchProgress::State::Successful: | |
OnFound(pProgress->aBookmark, static_cast<sal_Int16>(pProgress->nFieldIndex)); | |
EnableSearchUI(true); | |
break; | |
case FmSearchProgress::State::Error: | |
case FmSearchProgress::State::NothingFound: | |
{ | |
TranslateId pErrorId = (FmSearchProgress::State::Error == pProgress->aSearchState) | |
? RID_STR_SEARCH_GENERAL_ERROR | |
: RID_STR_SEARCH_NORECORD; | |
std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(), | |
VclMessageType::Warning, VclButtonsType::Ok, CuiResId(pErrorId))); | |
xBox->run(); | |
[[fallthrough]]; | |
} | |
case FmSearchProgress::State::Canceled: | |
EnableSearchUI(true); | |
if (m_lnkCanceledNotFoundHdl.IsSet()) | |
{ | |
FmFoundRecordInformation friInfo; | |
friInfo.nContext = m_plbForm->get_active(); | |
// if I don't do a search in a context, this has an invalid value - but then it doesn't matter anyway | |
friInfo.aPosition = pProgress->aBookmark; | |
m_lnkCanceledNotFoundHdl.Call(friInfo); | |
} | |
break; | |
} | |
m_pftRecord->set_label(OUString::number(1 + pProgress->nCurrentRecord)); | |
} | |
void FmSearchDialog::LoadParams() | |
{ | |
FmSearchParams aParams(m_pConfig->getParams()); | |
for (auto& historystr : aParams.aHistory) | |
m_pcmbSearchText->append_text(historystr); | |
// I do the settings at my UI-elements and then I simply call the respective change-handler, | |
// that way the data is handed on to the SearchEngine and all dependent settings are done | |
// current field | |
int nInitialField = m_plbField->find_text( aParams.sSingleSearchField ); | |
if (nInitialField == -1) | |
nInitialField = 0; | |
m_plbField->set_active(nInitialField); | |
OnFieldSelected(*m_plbField); | |
// all fields/single field (AFTER selecting the field because OnToggledFieldRadios expects a valid value there) | |
if (aParams.bAllFields) | |
{ | |
m_prbSingleField->set_active(false); | |
m_prbAllFields->set_active(true); | |
OnToggledFieldRadios(*m_prbAllFields); | |
// OnToggledFieldRadios also calls to RebuildUsedFields | |
} | |
else | |
{ | |
m_prbAllFields->set_active(false); | |
m_prbSingleField->set_active(true); | |
OnToggledFieldRadios(*m_prbSingleField); | |
} | |
m_plbPosition->set_active(aParams.nPosition); | |
OnPositionSelected(*m_plbPosition); | |
// field formatting/case sensitivity/direction | |
m_pcbUseFormat->set_active(aParams.bUseFormatter); | |
m_pcbCase->set_active( aParams.isCaseSensitive() ); | |
m_pcbBackwards->set_active(aParams.bBackwards); | |
OnCheckBoxToggled(*m_pcbUseFormat); | |
OnCheckBoxToggled(*m_pcbCase); | |
OnCheckBoxToggled(*m_pcbBackwards); | |
m_pHalfFullFormsCJK->set_active( !aParams.isIgnoreWidthCJK( ) ); // BEWARE: this checkbox has an inverse semantics! | |
m_pSoundsLikeCJK->set_active( aParams.bSoundsLikeCJK ); | |
OnCheckBoxToggled(*m_pHalfFullFormsCJK); | |
OnCheckBoxToggled(*m_pSoundsLikeCJK); | |
m_pcbWildCard->set_active(false); | |
m_pcbRegular->set_active(false); | |
m_pcbApprox->set_active(false); | |
OnCheckBoxToggled(*m_pcbWildCard); | |
OnCheckBoxToggled(*m_pcbRegular); | |
OnCheckBoxToggled(*m_pcbApprox); | |
weld::CheckButton* pToCheck = nullptr; | |
if (aParams.bWildcard) | |
pToCheck = m_pcbWildCard.get(); | |
if (aParams.bRegular) | |
pToCheck = m_pcbRegular.get(); | |
if (aParams.bApproxSearch) | |
pToCheck = m_pcbApprox.get(); | |
if (aParams.bSoundsLikeCJK) | |
pToCheck = m_pSoundsLikeCJK.get(); | |
if (pToCheck) | |
{ | |
pToCheck->set_active(true); | |
OnCheckBoxToggled(*pToCheck); | |
} | |
// set Levenshtein-parameters directly at the SearchEngine | |
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_prbSearchForText->set_active(false); | |
m_prbSearchForNull->set_active(false); | |
m_prbSearchForNotNull->set_active(false); | |
switch (aParams.nSearchForType) | |
{ | |
case 1: m_prbSearchForNull->set_active(true); break; | |
case 2: m_prbSearchForNotNull->set_active(true); break; | |
default: m_prbSearchForText->set_active(true); break; | |
} | |
OnToggledFieldRadios(*m_prbSearchForText); | |
} | |
void FmSearchDialog::SaveParams() const | |
{ | |
if (!m_pConfig) | |
return; | |
FmSearchParams aCurrentSettings; | |
int nCount = m_pcmbSearchText->get_count(); | |
aCurrentSettings.aHistory.realloc(nCount); | |
OUString* pHistory = aCurrentSettings.aHistory.getArray(); | |
for (int i = 0; i < nCount; ++i, ++pHistory) | |
*pHistory = m_pcmbSearchText->get_text(i); | |
aCurrentSettings.sSingleSearchField = m_plbField->get_active_text(); | |
aCurrentSettings.bAllFields = m_prbAllFields->get_active(); | |
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_prbSearchForNull->get_active()) | |
aCurrentSettings.nSearchForType = 1; | |
else if (m_prbSearchForNotNull->get_active()) | |
aCurrentSettings.nSearchForType = 2; | |
else | |
aCurrentSettings.nSearchForType = 0; | |
m_pConfig->setParams( aCurrentSettings ); | |
} | |
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment