tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / dbgui / validate.cxx
blobbacbe29e3af39850fb1e288f514f447c9b261ccc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #ifdef SC_DLLIMPLEMENTATION
21 #undef SC_DLLIMPLEMENTATION
22 #endif
24 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
25 #include <comphelper/string.hxx>
26 #include <svl/stritem.hxx>
27 #include <svl/eitem.hxx>
28 #include <svl/intitem.hxx>
29 #include <sfx2/app.hxx>
30 #include <o3tl/string_view.hxx>
32 #include <scresid.hxx>
33 #include <strings.hrc>
35 #include <stringutil.hxx>
36 #include <validat.hxx>
37 #include <validate.hxx>
38 #include <compiler.hxx>
39 #include <formula/opcode.hxx>
41 // cell range picker
42 #include <tabvwsh.hxx>
43 #include <sfx2/viewfrm.hxx>
44 #include <sfx2/childwin.hxx>
45 #include <reffact.hxx>
46 #include <comphelper/lok.hxx>
48 /* Position indexes for "Allow" list box.
49 They do not map directly to ScValidationMode and can safely be modified to
50 change the order of the list box entries. */
51 #define SC_VALIDDLG_ALLOW_ANY 0
52 #define SC_VALIDDLG_ALLOW_WHOLE 1
53 #define SC_VALIDDLG_ALLOW_DECIMAL 2
54 #define SC_VALIDDLG_ALLOW_DATE 3
55 #define SC_VALIDDLG_ALLOW_TIME 4
56 #define SC_VALIDDLG_ALLOW_RANGE 5
57 #define SC_VALIDDLG_ALLOW_LIST 6
58 #define SC_VALIDDLG_ALLOW_TEXTLEN 7
59 #define SC_VALIDDLG_ALLOW_CUSTOM 8
61 /* Position indexes for "Data" list box.
62 They do not map directly to ScConditionMode and can safely be modified to
63 change the order of the list box entries. */
64 #define SC_VALIDDLG_DATA_EQUAL 0
65 #define SC_VALIDDLG_DATA_LESS 1
66 #define SC_VALIDDLG_DATA_GREATER 2
67 #define SC_VALIDDLG_DATA_EQLESS 3
68 #define SC_VALIDDLG_DATA_EQGREATER 4
69 #define SC_VALIDDLG_DATA_NOTEQUAL 5
70 #define SC_VALIDDLG_DATA_VALIDRANGE 6
71 #define SC_VALIDDLG_DATA_INVALIDRANGE 7
72 #define SC_VALIDDLG_DATA_DIRECT 8
74 namespace ValidListType = css::sheet::TableValidationVisibility;
76 const WhichRangesContainer ScTPValidationValue::pValueRanges(svl::Items<
77 FID_VALID_LISTTYPE, FID_VALID_LISTTYPE,
78 FID_VALID_MODE, FID_VALID_ERRTEXT
79 >);
81 static bool isLOKMobilePhone()
83 if (!comphelper::LibreOfficeKit::isActive())
84 return false;
85 SfxViewShell* pViewShell = SfxViewShell::Current();
86 return pViewShell && pViewShell->isLOKMobilePhone();
89 ScValidationDlg::ScValidationDlg(weld::Window* pParent, const SfxItemSet* pArgSet,
90 ScTabViewShell *pTabViewSh)
91 : ScValidationDlgBase(pParent,
92 u"modules/scalc/ui/validationdialog.ui"_ustr, u"ValidationDialog"_ustr, pArgSet, nullptr)
93 , m_pTabVwSh(pTabViewSh)
94 , m_sValuePageId(u"criteria"_ustr)
95 , m_bOwnRefHdlr(false)
96 , m_bRefInputting(false)
97 , m_xHBox(m_xBuilder->weld_container(u"refinputbox"_ustr))
99 AddTabPage(m_sValuePageId, ScTPValidationValue::Create, nullptr);
100 AddTabPage(u"inputhelp"_ustr, ScTPValidationHelp::Create, nullptr);
101 AddTabPage(u"erroralert"_ustr, ScTPValidationError::Create, nullptr);
103 if (isLOKMobilePhone())
105 m_xBuilder->weld_button(u"cancel"_ustr)->hide();
106 m_xBuilder->weld_button(u"help"_ustr)->hide();
110 void ScValidationDlg::EndDialog(int nResponse)
112 // tdf#155708 - do not close, just hide validation window if we click in another sheet
113 if (nResponse == nCloseResponseToJustHide && getDialog()->get_visible())
115 getDialog()->hide();
116 return;
118 // tdf#137215 ensure original modality of true is restored before dialog loop ends
119 if (m_bOwnRefHdlr)
120 RemoveRefDlg(true);
121 ScValidationDlgBase::EndDialog(nResponse);
124 ScValidationDlg::~ScValidationDlg()
126 if (m_bOwnRefHdlr)
127 RemoveRefDlg(false);
130 void ScTPValidationValue::SetReferenceHdl( const ScRange&rRange , const ScDocument& rDoc )
132 if ( rRange.aStart != rRange.aEnd )
133 if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
134 if( m_pRefEdit )
135 pValidationDlg->RefInputStart( m_pRefEdit );
137 if ( m_pRefEdit )
139 OUString aStr(rRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D, rDoc.GetAddressConvention()));
140 m_pRefEdit->SetRefString( aStr );
144 void ScTPValidationValue:: SetActiveHdl()
146 if ( m_pRefEdit ) m_pRefEdit->GrabFocus();
148 if ( ScValidationDlg *pValidationDlg = GetValidationDlg() )
149 if( m_pRefEdit )
151 pValidationDlg->RefInputDone();
155 void ScTPValidationValue::RefInputStartPreHdl( formula::RefEdit* pEdit, const formula::RefButton* pButton )
157 ScValidationDlg *pValidationDlg = GetValidationDlg();
158 if (!pValidationDlg)
159 return;
161 weld::Container* pNewParent = pValidationDlg->get_refinput_shrink_parent();
162 if (pEdit == m_pRefEdit && pNewParent != m_pRefEditParent)
164 m_xRefGrid->move(m_pRefEdit->GetWidget(), pNewParent);
165 m_pRefEditParent = pNewParent;
168 if (pNewParent != m_pBtnRefParent)
170 // if Edit SetParent but button not, the tab order will be
171 // incorrect, so move button anyway, and restore
172 // parent later in order to restore the tab order. But
173 // hide it if it's moved but unwanted.
174 m_xRefGrid->move(m_xBtnRef->GetWidget(), pNewParent);
175 m_xBtnRef->GetWidget()->set_visible(pButton == m_xBtnRef.get());
176 m_pBtnRefParent = pNewParent;
179 pNewParent->show();
182 void ScTPValidationValue::RefInputDonePostHdl()
184 if (ScValidationDlg *pValidationDlg = GetValidationDlg())
186 weld::Container* pOldParent = pValidationDlg->get_refinput_shrink_parent();
188 if (m_pRefEdit && m_pRefEditParent != m_xRefGrid.get())
190 pOldParent->move(m_pRefEdit->GetWidget(), m_xRefGrid.get());
191 m_pRefEditParent = m_xRefGrid.get();
194 if (m_pBtnRefParent != m_xRefGrid.get())
196 pOldParent->move(m_xBtnRef->GetWidget(), m_xRefGrid.get());
197 m_xBtnRef->GetWidget()->show();
198 m_pBtnRefParent = m_xRefGrid.get();
201 pOldParent->hide();
202 ScViewData& rViewData = pValidationDlg->GetTabViewShell()->GetViewData();
203 SCTAB nCurTab = rViewData.GetTabNo();
204 SCTAB nRefTab = rViewData.GetRefTabNo();
205 // If RefInput switched to a different sheet from the data sheet,
206 // switch back: fdo#53920
207 if ( nCurTab != nRefTab )
209 rViewData.GetViewShell()->SetTabNo( nRefTab );
213 if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
214 m_pRefEdit->GrabFocus();
217 namespace {
219 /** Converts the passed ScValidationMode to the position in the list box. */
220 sal_uInt16 lclGetPosFromValMode( ScValidationMode eValMode )
222 sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
223 switch( eValMode )
225 case SC_VALID_ANY: nLbPos = SC_VALIDDLG_ALLOW_ANY; break;
226 case SC_VALID_WHOLE: nLbPos = SC_VALIDDLG_ALLOW_WHOLE; break;
227 case SC_VALID_DECIMAL: nLbPos = SC_VALIDDLG_ALLOW_DECIMAL; break;
228 case SC_VALID_DATE: nLbPos = SC_VALIDDLG_ALLOW_DATE; break;
229 case SC_VALID_TIME: nLbPos = SC_VALIDDLG_ALLOW_TIME; break;
230 case SC_VALID_TEXTLEN: nLbPos = SC_VALIDDLG_ALLOW_TEXTLEN; break;
231 case SC_VALID_LIST: nLbPos = SC_VALIDDLG_ALLOW_RANGE; break;
232 case SC_VALID_CUSTOM: nLbPos = SC_VALIDDLG_ALLOW_CUSTOM; break;
233 default: OSL_FAIL( "lclGetPosFromValMode - unknown validity mode" );
235 return nLbPos;
238 /** Converts the passed list box position to an ScValidationMode. */
239 ScValidationMode lclGetValModeFromPos( sal_uInt16 nLbPos )
241 ScValidationMode eValMode = SC_VALID_ANY;
242 switch( nLbPos )
244 case SC_VALIDDLG_ALLOW_ANY: eValMode = SC_VALID_ANY; break;
245 case SC_VALIDDLG_ALLOW_WHOLE: eValMode = SC_VALID_WHOLE; break;
246 case SC_VALIDDLG_ALLOW_DECIMAL: eValMode = SC_VALID_DECIMAL; break;
247 case SC_VALIDDLG_ALLOW_DATE: eValMode = SC_VALID_DATE; break;
248 case SC_VALIDDLG_ALLOW_TIME: eValMode = SC_VALID_TIME; break;
249 case SC_VALIDDLG_ALLOW_RANGE: eValMode = SC_VALID_LIST; break;
250 case SC_VALIDDLG_ALLOW_LIST: eValMode = SC_VALID_LIST; break;
251 case SC_VALIDDLG_ALLOW_TEXTLEN: eValMode = SC_VALID_TEXTLEN; break;
252 case SC_VALIDDLG_ALLOW_CUSTOM: eValMode = SC_VALID_CUSTOM; break;
253 default: OSL_FAIL( "lclGetValModeFromPos - invalid list box position" );
255 return eValMode;
258 /** Converts the passed ScConditionMode to the position in the list box. */
259 sal_uInt16 lclGetPosFromCondMode( ScConditionMode eCondMode )
261 sal_uInt16 nLbPos = SC_VALIDDLG_DATA_EQUAL;
262 switch( eCondMode )
264 case ScConditionMode::NONE: // may occur in old XML files after Excel import
265 case ScConditionMode::Equal: nLbPos = SC_VALIDDLG_DATA_EQUAL; break;
266 case ScConditionMode::Less: nLbPos = SC_VALIDDLG_DATA_LESS; break;
267 case ScConditionMode::Greater: nLbPos = SC_VALIDDLG_DATA_GREATER; break;
268 case ScConditionMode::EqLess: nLbPos = SC_VALIDDLG_DATA_EQLESS; break;
269 case ScConditionMode::EqGreater: nLbPos = SC_VALIDDLG_DATA_EQGREATER; break;
270 case ScConditionMode::NotEqual: nLbPos = SC_VALIDDLG_DATA_NOTEQUAL; break;
271 case ScConditionMode::Between: nLbPos = SC_VALIDDLG_DATA_VALIDRANGE; break;
272 case ScConditionMode::NotBetween: nLbPos = SC_VALIDDLG_DATA_INVALIDRANGE; break;
273 case ScConditionMode::Direct: nLbPos = SC_VALIDDLG_DATA_DIRECT; break;
274 default: OSL_FAIL( "lclGetPosFromCondMode - unknown condition mode" );
276 return nLbPos;
279 /** Converts the passed list box position to an ScConditionMode. */
280 ScConditionMode lclGetCondModeFromPos( sal_uInt16 nLbPos )
282 ScConditionMode eCondMode = ScConditionMode::Equal;
283 switch( nLbPos )
285 case SC_VALIDDLG_DATA_EQUAL: eCondMode = ScConditionMode::Equal; break;
286 case SC_VALIDDLG_DATA_LESS: eCondMode = ScConditionMode::Less; break;
287 case SC_VALIDDLG_DATA_GREATER: eCondMode = ScConditionMode::Greater; break;
288 case SC_VALIDDLG_DATA_EQLESS: eCondMode = ScConditionMode::EqLess; break;
289 case SC_VALIDDLG_DATA_EQGREATER: eCondMode = ScConditionMode::EqGreater; break;
290 case SC_VALIDDLG_DATA_NOTEQUAL: eCondMode = ScConditionMode::NotEqual; break;
291 case SC_VALIDDLG_DATA_VALIDRANGE: eCondMode = ScConditionMode::Between; break;
292 case SC_VALIDDLG_DATA_INVALIDRANGE: eCondMode = ScConditionMode::NotBetween; break;
293 case SC_VALIDDLG_DATA_DIRECT: eCondMode = ScConditionMode::Direct; break;
294 default: OSL_FAIL( "lclGetCondModeFromPos - invalid list box position" );
296 return eCondMode;
299 /** Converts line feed separated string to a formula with strings separated by semicolons.
300 @descr Keeps all empty strings.
301 Example: abc\ndef\n\nghi -> "abc";"def";"";"ghi".
302 @param rFmlaStr (out-param) The converted formula string. */
303 void lclGetFormulaFromStringList( OUString& rFmlaStr, std::u16string_view rStringList, sal_Unicode cFmlaSep )
305 rFmlaStr.clear();
306 if (!rStringList.empty())
308 sal_Int32 nIdx {0};
311 OUString aToken {o3tl::getToken(rStringList, 0, '\n', nIdx )};
312 ScGlobal::AddQuotes( aToken, '"' );
313 rFmlaStr = ScGlobal::addToken(rFmlaStr, aToken, cFmlaSep);
315 while (nIdx>0);
317 if( rFmlaStr.isEmpty() )
318 rFmlaStr = "\"\"";
321 /** Converts formula with strings separated by semicolons to line feed separated string.
322 @descr Keeps all empty strings. Ignores all empty tokens (multiple semicolons).
323 Example: "abc";;;"def";"";"ghi" -> abc\ndef\n\nghi.
324 @param rStringList (out-param) The converted line feed separated string list.
325 @return true = Conversion successful. */
326 bool lclGetStringListFromFormula( OUString& rStringList, const OUString& rFmlaStr, sal_Unicode cFmlaSep )
328 static constexpr OUStringLiteral aQuotes( u"\"\"" );
330 rStringList.clear();
331 bool bIsStringList = !rFmlaStr.isEmpty();
332 bool bTokenAdded = false;
334 for ( sal_Int32 nStringIx = 0; bIsStringList && nStringIx>=0; )
336 OUString aToken( ScStringUtil::GetQuotedToken(rFmlaStr, 0, aQuotes, cFmlaSep, nStringIx ) );
337 aToken = comphelper::string::strip(aToken, ' ');
338 if( !aToken.isEmpty() ) // ignore empty tokens, i.e. "a";;"b"
340 bIsStringList = ScGlobal::IsQuoted( aToken, '"' );
341 if( bIsStringList )
343 ScGlobal::EraseQuotes( aToken, '"' );
344 rStringList = ScGlobal::addToken(rStringList, aToken, '\n', 1, bTokenAdded);
345 bTokenAdded = true;
350 return bIsStringList;
353 } // namespace
355 ScTPValidationValue::ScTPValidationValue(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
356 : SfxTabPage(pPage, pController, u"modules/scalc/ui/validationcriteriapage.ui"_ustr,
357 u"ValidationCriteriaPage"_ustr, &rArgSet)
358 , maStrMin(ScResId(SCSTR_VALID_MINIMUM))
359 , maStrMax(ScResId(SCSTR_VALID_MAXIMUM))
360 , maStrValue(ScResId(SCSTR_VALID_VALUE))
361 , maStrFormula(ScResId(SCSTR_VALID_FORMULA))
362 , maStrRange(ScResId(SCSTR_VALID_RANGE))
363 , maStrList(ScResId(SCSTR_VALID_LIST))
364 , m_pRefEdit(nullptr)
365 , m_xLbAllow(m_xBuilder->weld_combo_box(u"allow"_ustr))
366 , m_xCbAllow(m_xBuilder->weld_check_button(u"allowempty"_ustr))
367 , m_xCbCaseSens(m_xBuilder->weld_check_button(u"casesens"_ustr))
368 , m_xCbShow(m_xBuilder->weld_check_button(u"showlist"_ustr))
369 , m_xCbSort(m_xBuilder->weld_check_button(u"sortascend"_ustr))
370 , m_xFtValue(m_xBuilder->weld_label(u"valueft"_ustr))
371 , m_xLbValue(m_xBuilder->weld_combo_box(u"data"_ustr))
372 , m_xFtMin(m_xBuilder->weld_label(u"minft"_ustr))
373 , m_xMinGrid(m_xBuilder->weld_widget(u"mingrid"_ustr))
374 , m_xEdMin(new formula::RefEdit(m_xBuilder->weld_entry(u"min"_ustr)))
375 , m_xEdList(m_xBuilder->weld_text_view(u"minlist"_ustr))
376 , m_xFtMax(m_xBuilder->weld_label(u"maxft"_ustr))
377 , m_xEdMax(new formula::RefEdit(m_xBuilder->weld_entry(u"max"_ustr)))
378 , m_xFtHint(m_xBuilder->weld_label(u"hintft"_ustr))
379 , m_xBtnRef(new formula::RefButton(m_xBuilder->weld_button(u"validref"_ustr)))
380 , m_xRefGrid(m_xBuilder->weld_container(u"refgrid"_ustr))
381 , m_pRefEditParent(m_xRefGrid.get())
382 , m_pBtnRefParent(m_xRefGrid.get())
384 m_xEdMin->SetReferences(nullptr, m_xFtMin.get());
386 Size aSize(m_xEdList->get_approximate_digit_width() * 40,
387 m_xEdList->get_height_rows(10));
388 m_xEdList->set_size_request(aSize.Width(), aSize.Height());
389 m_xEdMax->SetReferences(nullptr, m_xFtMax.get());
391 m_xBtnRef->SetClickHdl(LINK(this, ScTPValidationValue, ClickHdl));
393 //lock in the max size initial config
394 aSize = m_xContainer->get_preferred_size();
395 m_xContainer->set_size_request(aSize.Width(), aSize.Height());
397 Init();
399 // list separator in formulas
400 OUString aListSep = ::ScCompiler::GetNativeSymbol( ocSep );
401 OSL_ENSURE( aListSep.getLength() == 1, "ScTPValidationValue::ScTPValidationValue - list separator error" );
402 mcFmlaSep = aListSep.getLength() ? aListSep[0] : ';';
403 m_xBtnRef->GetWidget()->hide(); // cell range picker
406 ScTPValidationValue::~ScTPValidationValue()
408 m_xEdMin.reset();
409 m_xEdMax.reset();
410 m_xBtnRef.reset();
413 void ScTPValidationValue::Init()
415 m_xLbAllow->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
416 m_xLbValue->connect_changed( LINK( this, ScTPValidationValue, SelectHdl ) );
417 m_xCbShow->connect_toggled( LINK( this, ScTPValidationValue, CheckHdl ) );
419 // cell range picker
420 m_xEdMin->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
421 m_xEdMin->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
422 m_xEdMax->SetGetFocusHdl( LINK( this, ScTPValidationValue, EditSetFocusHdl ) );
423 m_xEdMax->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillEditFocusHdl ) );
424 m_xBtnRef->SetLoseFocusHdl( LINK( this, ScTPValidationValue, KillButtonFocusHdl ) );
426 m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_ANY );
427 m_xLbValue->set_active( SC_VALIDDLG_DATA_EQUAL );
429 SelectHdl( *m_xLbAllow );
430 CheckHdl( *m_xCbShow );
433 std::unique_ptr<SfxTabPage> ScTPValidationValue::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rArgSet)
435 return std::make_unique<ScTPValidationValue>(pPage, pController, *rArgSet);
438 void ScTPValidationValue::Reset( const SfxItemSet* rArgSet )
440 sal_uInt16 nLbPos = SC_VALIDDLG_ALLOW_ANY;
441 if( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_MODE ) )
442 nLbPos = lclGetPosFromValMode( static_cast< ScValidationMode >( pItem->GetValue() ) );
443 m_xLbAllow->set_active( nLbPos );
445 nLbPos = SC_VALIDDLG_DATA_EQUAL;
446 if( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_CONDMODE ) )
447 nLbPos = lclGetPosFromCondMode( static_cast< ScConditionMode >( pItem->GetValue() ) );
448 m_xLbValue->set_active( nLbPos );
450 // *** check boxes ***
451 bool bCheck = true;
452 if( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_BLANK ) )
453 bCheck = pItem->GetValue();
454 m_xCbAllow->set_active( bCheck );
456 bool bCaseSensetive = false;
457 if (const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_CASESENS ) )
458 bCaseSensetive = pItem->GetValue();
459 m_xCbCaseSens->set_active( bCaseSensetive );
461 sal_Int32 nListType = ValidListType::UNSORTED;
462 if( const SfxInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_LISTTYPE ) )
463 nListType = pItem->GetValue();
464 m_xCbShow->set_active( nListType != ValidListType::INVISIBLE );
465 m_xCbSort->set_active( nListType == ValidListType::SORTEDASCENDING );
467 // *** formulas ***
468 OUString aFmlaStr;
469 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_VALUE1 ) )
470 aFmlaStr = pItem->GetValue();
471 SetFirstFormula( aFmlaStr );
473 aFmlaStr.clear();
474 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_VALUE2 ) )
475 aFmlaStr = pItem->GetValue();
476 SetSecondFormula( aFmlaStr );
478 SelectHdl( *m_xLbAllow );
479 CheckHdl( *m_xCbShow );
482 bool ScTPValidationValue::FillItemSet( SfxItemSet* rArgSet )
484 sal_Int16 nListType = m_xCbShow->get_active() ?
485 (m_xCbSort->get_active() ? ValidListType::SORTEDASCENDING : ValidListType::UNSORTED) :
486 ValidListType::INVISIBLE;
488 const sal_Int32 nLbPos = m_xLbAllow->get_active();
489 bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
490 ScConditionMode eCondMode = bCustom ?
491 ScConditionMode::Direct : lclGetCondModeFromPos( m_xLbValue->get_active() );
493 rArgSet->Put( SfxUInt16Item( FID_VALID_MODE, sal::static_int_cast<sal_uInt16>(
494 lclGetValModeFromPos( nLbPos ) ) ) );
495 rArgSet->Put( SfxUInt16Item( FID_VALID_CONDMODE, sal::static_int_cast<sal_uInt16>( eCondMode ) ) );
496 rArgSet->Put( SfxStringItem( FID_VALID_VALUE1, GetFirstFormula() ) );
497 rArgSet->Put( SfxStringItem( FID_VALID_VALUE2, GetSecondFormula() ) );
498 rArgSet->Put( SfxBoolItem( FID_VALID_BLANK, m_xCbAllow->get_active() ) );
499 rArgSet->Put( SfxBoolItem( FID_VALID_CASESENS, m_xCbCaseSens->get_active() ) );
500 rArgSet->Put( SfxInt16Item( FID_VALID_LISTTYPE, nListType ) );
501 return true;
504 OUString ScTPValidationValue::GetFirstFormula() const
506 OUString aFmlaStr;
507 if( m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_LIST )
508 lclGetFormulaFromStringList( aFmlaStr, m_xEdList->get_text(), mcFmlaSep );
509 else
510 aFmlaStr = m_xEdMin->GetText();
511 return aFmlaStr;
514 OUString ScTPValidationValue::GetSecondFormula() const
516 return m_xEdMax->GetText();
519 void ScTPValidationValue::SetFirstFormula( const OUString& rFmlaStr )
521 // try if formula is a string list, validation mode must already be set
522 OUString aStringList;
523 if( (m_xLbAllow->get_active() == SC_VALIDDLG_ALLOW_RANGE) &&
524 lclGetStringListFromFormula( aStringList, rFmlaStr, mcFmlaSep ) )
526 m_xEdList->set_text( aStringList );
527 m_xEdMin->SetText( OUString() );
528 // change validation mode to string list
529 m_xLbAllow->set_active( SC_VALIDDLG_ALLOW_LIST );
531 else
533 m_xEdMin->SetText( rFmlaStr );
534 m_xEdList->set_text( OUString() );
538 void ScTPValidationValue::SetSecondFormula( const OUString& rFmlaStr )
540 m_xEdMax->SetText( rFmlaStr );
543 ScValidationDlg * ScTPValidationValue::GetValidationDlg()
545 return dynamic_cast<ScValidationDlg*>(GetDialogController());
548 void ScTPValidationValue::SetupRefDlg()
550 ScValidationDlg *pValidationDlg = GetValidationDlg();
551 if( !pValidationDlg )
552 return;
554 if( !pValidationDlg->SetupRefDlg() )
555 return;
557 pValidationDlg->SetHandler( this );
558 pValidationDlg->SetSetRefHdl( static_cast<ScRefHandlerHelper::PFUNCSETREFHDLTYPE>( &ScTPValidationValue::SetReferenceHdl ) );
559 pValidationDlg->SetSetActHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::SetActiveHdl ) );
560 pValidationDlg->SetRefInputStartPreHdl( static_cast<ScRefHandlerHelper::PINPUTSTARTDLTYPE>( &ScTPValidationValue::RefInputStartPreHdl ) );
561 pValidationDlg->SetRefInputDonePostHdl( static_cast<ScRefHandlerHelper::PCOMMONHDLTYPE>( &ScTPValidationValue::RefInputDonePostHdl ) );
563 weld::Label* pLabel = nullptr;
565 if (m_xEdMax->GetWidget()->get_visible())
567 m_pRefEdit = m_xEdMax.get();
568 pLabel = m_xFtMax.get();
570 else if (m_xEdMin->GetWidget()->get_visible())
572 m_pRefEdit = m_xEdMin.get();
573 pLabel = m_xFtMin.get();
576 if (m_pRefEdit && !m_pRefEdit->GetWidget()->has_focus())
577 m_pRefEdit->GrabFocus();
579 if( m_pRefEdit )
580 m_pRefEdit->SetReferences( pValidationDlg, pLabel );
582 m_xBtnRef->SetReferences( pValidationDlg, m_pRefEdit );
585 void ScTPValidationValue::RemoveRefDlg(bool bRestoreModal)
587 ScValidationDlg *pValidationDlg = GetValidationDlg();
588 if( !pValidationDlg )
589 return;
591 if( !pValidationDlg->RemoveRefDlg(bRestoreModal) )
592 return;
594 pValidationDlg->SetHandler( nullptr );
595 pValidationDlg->SetSetRefHdl( nullptr );
596 pValidationDlg->SetSetActHdl( nullptr );
597 pValidationDlg->SetRefInputStartPreHdl( nullptr );
598 pValidationDlg->SetRefInputDonePostHdl( nullptr );
600 if( m_pRefEdit )
601 m_pRefEdit->SetReferences( nullptr, nullptr );
602 m_pRefEdit = nullptr;
604 m_xBtnRef->SetReferences( nullptr, nullptr );
607 IMPL_LINK_NOARG(ScTPValidationValue, EditSetFocusHdl, formula::RefEdit&, void)
609 const sal_Int32 nPos = m_xLbAllow->get_active();
611 if ( nPos == SC_VALIDDLG_ALLOW_RANGE )
613 SetupRefDlg();
617 IMPL_LINK( ScTPValidationValue, KillEditFocusHdl, formula::RefEdit&, rWnd, void )
619 if (&rWnd != m_pRefEdit)
620 return;
621 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
623 if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
625 if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
627 RemoveRefDlg(true);
633 IMPL_LINK( ScTPValidationValue, KillButtonFocusHdl, formula::RefButton&, rWnd, void )
635 if( &rWnd != m_xBtnRef.get())
636 return;
637 if( ScValidationDlg *pValidationDlg = GetValidationDlg() )
638 if (pValidationDlg->IsChildFocus() && !pValidationDlg->IsRefInputting())
639 if( ( !m_pRefEdit || !m_pRefEdit->GetWidget()->has_focus()) && !m_xBtnRef->GetWidget()->has_focus() )
641 RemoveRefDlg(true);
645 IMPL_LINK_NOARG(ScTPValidationValue, SelectHdl, weld::ComboBox&, void)
647 const sal_Int32 nLbPos = m_xLbAllow->get_active();
648 bool bEnable = (nLbPos != SC_VALIDDLG_ALLOW_ANY);
649 bool bRange = (nLbPos == SC_VALIDDLG_ALLOW_RANGE);
650 bool bList = (nLbPos == SC_VALIDDLG_ALLOW_LIST);
651 bool bCustom = (nLbPos == SC_VALIDDLG_ALLOW_CUSTOM);
653 m_xCbAllow->set_sensitive( bEnable ); // Empty cell
654 m_xCbCaseSens->set_sensitive( bEnable &&
655 (bRange || bList || bCustom) ); // Case Sensitive
656 m_xFtValue->set_sensitive( bEnable );
657 m_xLbValue->set_sensitive( bEnable );
658 m_xFtMin->set_sensitive( bEnable );
659 m_xEdMin->GetWidget()->set_sensitive( bEnable );
660 m_xEdList->set_sensitive( bEnable );
661 m_xFtMax->set_sensitive( bEnable );
662 m_xEdMax->GetWidget()->set_sensitive( bEnable );
664 bool bShowMax = false;
666 if( bRange )
667 m_xFtMin->set_label( maStrRange );
668 else if( bList )
669 m_xFtMin->set_label( maStrList );
670 else if( bCustom )
671 m_xFtMin->set_label( maStrFormula );
672 else
674 switch( m_xLbValue->get_active() )
676 case SC_VALIDDLG_DATA_EQUAL:
677 case SC_VALIDDLG_DATA_NOTEQUAL: m_xFtMin->set_label( maStrValue ); break;
679 case SC_VALIDDLG_DATA_LESS:
680 case SC_VALIDDLG_DATA_EQLESS: m_xFtMin->set_label( maStrMax ); break;
682 case SC_VALIDDLG_DATA_VALIDRANGE:
683 case SC_VALIDDLG_DATA_INVALIDRANGE: bShowMax = true;
684 [[fallthrough]];
685 case SC_VALIDDLG_DATA_GREATER:
686 case SC_VALIDDLG_DATA_EQGREATER: m_xFtMin->set_label( maStrMin ); break;
688 default:
689 OSL_FAIL( "ScTPValidationValue::SelectHdl - unknown condition mode" );
693 m_xCbCaseSens->set_visible( bRange || bList || bCustom ); // Case Sensitive
694 m_xCbShow->set_visible( bRange || bList );
695 m_xCbSort->set_visible( bRange || bList );
696 m_xFtValue->set_visible( !bRange && !bList && !bCustom);
697 m_xLbValue->set_visible( !bRange && !bList && !bCustom );
698 m_xEdMin->GetWidget()->set_visible( !bList );
699 m_xEdList->set_visible( bList );
700 m_xMinGrid->set_vexpand( bList );
701 m_xFtMax->set_visible( bShowMax );
702 m_xEdMax->GetWidget()->set_visible( bShowMax );
703 m_xFtHint->set_visible( bRange );
704 m_xBtnRef->GetWidget()->set_visible( bRange ); // cell range picker
707 IMPL_LINK_NOARG(ScTPValidationValue, CheckHdl, weld::Toggleable&, void)
709 m_xCbSort->set_sensitive( m_xCbShow->get_active() );
712 // Input Help Page
714 ScTPValidationHelp::ScTPValidationHelp(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rArgSet)
715 : SfxTabPage(pPage, pController, u"modules/scalc/ui/validationhelptabpage.ui"_ustr, u"ValidationHelpTabPage"_ustr, &rArgSet)
716 , m_xTsbHelp(m_xBuilder->weld_check_button(u"tsbhelp"_ustr))
717 , m_xEdtTitle(m_xBuilder->weld_entry(u"title"_ustr))
718 , m_xEdInputHelp(m_xBuilder->weld_text_view(u"inputhelp_text"_ustr))
720 m_xEdInputHelp->set_size_request(m_xEdInputHelp->get_approximate_digit_width() * 40, m_xEdInputHelp->get_height_rows(13));
723 ScTPValidationHelp::~ScTPValidationHelp()
727 std::unique_ptr<SfxTabPage> ScTPValidationHelp::Create(weld::Container* pPage, weld::DialogController* pController,
728 const SfxItemSet* rArgSet)
730 return std::make_unique<ScTPValidationHelp>(pPage, pController, *rArgSet);
733 void ScTPValidationHelp::Reset( const SfxItemSet* rArgSet )
735 if ( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_SHOWHELP ) )
736 m_xTsbHelp->set_state( pItem->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
737 else
738 m_xTsbHelp->set_state( TRISTATE_FALSE );
740 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_HELPTITLE ) )
741 m_xEdtTitle->set_text( pItem->GetValue() );
742 else
743 m_xEdtTitle->set_text( OUString() );
745 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_HELPTEXT ) )
746 m_xEdInputHelp->set_text( pItem->GetValue() );
747 else
748 m_xEdInputHelp->set_text( OUString() );
751 bool ScTPValidationHelp::FillItemSet( SfxItemSet* rArgSet )
753 rArgSet->Put( SfxBoolItem( FID_VALID_SHOWHELP, m_xTsbHelp->get_state() == TRISTATE_TRUE ) );
754 rArgSet->Put( SfxStringItem( FID_VALID_HELPTITLE, m_xEdtTitle->get_text() ) );
755 rArgSet->Put( SfxStringItem( FID_VALID_HELPTEXT, m_xEdInputHelp->get_text() ) );
757 return true;
760 // Error Alert Page
762 ScTPValidationError::ScTPValidationError(weld::Container* pPage, weld::DialogController* pController,
763 const SfxItemSet& rArgSet)
765 : SfxTabPage ( pPage, pController,
766 u"modules/scalc/ui/erroralerttabpage.ui"_ustr, u"ErrorAlertTabPage"_ustr,
767 &rArgSet )
768 , m_xTsbShow(m_xBuilder->weld_check_button(u"tsbshow"_ustr))
769 , m_xLbAction(m_xBuilder->weld_combo_box(u"actionCB"_ustr))
770 , m_xBtnSearch(m_xBuilder->weld_button(u"browseBtn"_ustr))
771 , m_xEdtTitle(m_xBuilder->weld_entry(u"erroralert_title"_ustr))
772 , m_xFtError(m_xBuilder->weld_label(u"errormsg_label"_ustr))
773 , m_xEdError(m_xBuilder->weld_text_view(u"errorMsg"_ustr))
775 m_xEdError->set_size_request(m_xEdError->get_approximate_digit_width() * 40, m_xEdError->get_height_rows(12));
776 Init();
779 ScTPValidationError::~ScTPValidationError()
783 void ScTPValidationError::Init()
785 m_xLbAction->connect_changed(LINK(this, ScTPValidationError, SelectActionHdl));
786 m_xBtnSearch->connect_clicked(LINK( this, ScTPValidationError, ClickSearchHdl));
788 m_xLbAction->set_active(0);
790 SelectActionHdl(*m_xLbAction);
793 std::unique_ptr<SfxTabPage> ScTPValidationError::Create(weld::Container* pPage, weld::DialogController* pController,
794 const SfxItemSet* rArgSet)
796 return std::make_unique<ScTPValidationError>(pPage, pController, *rArgSet);
799 void ScTPValidationError::Reset( const SfxItemSet* rArgSet )
801 if ( const SfxBoolItem* pItem = rArgSet->GetItemIfSet( FID_VALID_SHOWERR ) )
802 m_xTsbShow->set_state( pItem->GetValue() ? TRISTATE_TRUE : TRISTATE_FALSE );
803 else
804 m_xTsbShow->set_state( TRISTATE_TRUE ); // check by default
806 if ( const SfxUInt16Item* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRSTYLE ) )
807 m_xLbAction->set_active( pItem->GetValue() );
808 else
809 m_xLbAction->set_active( 0 );
811 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRTITLE ) )
812 m_xEdtTitle->set_text( pItem->GetValue() );
813 else
814 m_xEdtTitle->set_text( OUString() );
816 if ( const SfxStringItem* pItem = rArgSet->GetItemIfSet( FID_VALID_ERRTEXT ) )
817 m_xEdError->set_text( pItem->GetValue() );
818 else
819 m_xEdError->set_text( OUString() );
821 SelectActionHdl(*m_xLbAction);
824 bool ScTPValidationError::FillItemSet( SfxItemSet* rArgSet )
826 rArgSet->Put( SfxBoolItem( FID_VALID_SHOWERR, m_xTsbShow->get_state() == TRISTATE_TRUE ) );
827 rArgSet->Put( SfxUInt16Item( FID_VALID_ERRSTYLE, m_xLbAction->get_active() ) );
828 rArgSet->Put( SfxStringItem( FID_VALID_ERRTITLE, m_xEdtTitle->get_text() ) );
829 rArgSet->Put( SfxStringItem( FID_VALID_ERRTEXT, m_xEdError->get_text() ) );
831 return true;
834 IMPL_LINK_NOARG(ScTPValidationError, SelectActionHdl, weld::ComboBox&, void)
836 ScValidErrorStyle eStyle = static_cast<ScValidErrorStyle>(m_xLbAction->get_active());
837 bool bMacro = ( eStyle == SC_VALERR_MACRO );
839 m_xBtnSearch->set_sensitive( bMacro );
840 m_xFtError->set_sensitive( !bMacro );
841 m_xEdError->set_sensitive( !bMacro );
844 IMPL_LINK_NOARG(ScTPValidationError, ClickSearchHdl, weld::Button&, void)
846 // Use static SfxApplication method to bring up selector dialog for
847 // choosing a script
848 OUString aScriptURL = SfxApplication::ChooseScript(GetFrameWeld());
850 if ( !aScriptURL.isEmpty() )
852 m_xEdtTitle->set_text( aScriptURL );
856 bool ScValidationDlg::EnterRefStatus()
858 ScTabViewShell *pTabViewShell = GetTabViewShell();
860 if( !pTabViewShell ) return false;
862 sal_uInt16 nId = SLOTID;
863 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
864 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
866 if (pWnd && pWnd->GetController().get() != this) pWnd = nullptr;
868 ScModule::get()->SetRefDialog(nId, pWnd == nullptr);
870 return true;
873 bool ScValidationDlg::LeaveRefStatus()
875 ScTabViewShell *pTabViewShell = GetTabViewShell();
877 if( !pTabViewShell ) return false;
879 sal_uInt16 nId = SLOTID;
880 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
881 if (rViewFrm.GetChildWindow(nId))
883 DoClose( nId );
885 return true;
888 bool ScValidationDlg::SetupRefDlg()
890 if ( m_bOwnRefHdlr ) return false;
891 if( EnterRefMode() )
893 SetModal( false );
894 m_bOwnRefHdlr = true;
895 return EnterRefStatus();
898 return false;
901 bool ScValidationDlg::RemoveRefDlg( bool bRestoreModal /* = true */ )
903 bool bVisLock = false;
904 bool bFreeWindowLock = false;
906 ScTabViewShell *pTabVwSh = GetTabViewShell();
908 if( !pTabVwSh ) return false;
910 if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame().GetChildWindow( SID_VALIDITY_REFERENCE ) )
912 bVisLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( true );
913 bFreeWindowLock = static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( true );
916 if ( !m_bOwnRefHdlr ) return false;
917 if( LeaveRefStatus() && LeaveRefMode() )
919 m_bOwnRefHdlr = false;
921 if( bRestoreModal )
923 SetModal( true );
927 if ( SfxChildWindow* pWnd = pTabVwSh->GetViewFrame().GetChildWindow( SID_VALIDITY_REFERENCE ) )
929 static_cast<ScValidityRefChildWin*>(pWnd)->LockVisible( bVisLock );
930 static_cast<ScValidityRefChildWin*>(pWnd)->LockFreeWindow( bFreeWindowLock );
933 return true;
936 IMPL_LINK_NOARG(ScTPValidationValue, ClickHdl, formula::RefButton&, void)
938 SetupRefDlg();
941 bool ScValidationDlg::IsChildFocus() const
943 return m_xDialog->has_toplevel_focus();
946 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */