tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / filter / xml / xmlcvali.cxx
blobec7a1ea70b3d852759e1a445a2ebddc5c5d6bfa6
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 #include "xmlcvali.hxx"
21 #include "xmlimprt.hxx"
22 #include "xmlconti.hxx"
23 #include <document.hxx>
24 #include "XMLConverter.hxx"
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <xmloff/XMLEventsImportContext.hxx>
29 #include <com/sun/star/sheet/TableValidationVisibility.hpp>
31 using namespace com::sun::star;
32 using namespace xmloff::token;
33 using namespace ::formula;
35 namespace {
37 class ScXMLContentValidationContext : public ScXMLImportContext
39 OUString sName;
40 OUString sHelpTitle;
41 OUString sHelpMessage;
42 OUString sErrorTitle;
43 OUString sErrorMessage;
44 OUString sErrorMessageType;
45 OUString sBaseCellAddress;
46 OUString sCondition;
47 sal_Int16 nShowList;
48 bool bAllowEmptyCell;
49 bool bIsCaseSensitive;
50 bool bDisplayHelp;
51 bool bDisplayError;
53 rtl::Reference<XMLEventsImportContext> xEventContext;
55 css::sheet::ValidationAlertStyle GetAlertStyle() const;
56 void SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
57 const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const;
58 void GetCondition( ScMyImportValidation& rValidation ) const;
60 public:
62 ScXMLContentValidationContext( ScXMLImport& rImport,
63 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList );
65 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
66 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
68 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
70 void SetHelpMessage(const OUString& sTitle, const OUString& sMessage, const bool bDisplay);
71 void SetErrorMessage(const OUString& sTitle, const OUString& sMessage, const OUString& sMessageType, const bool bDisplay);
72 void SetErrorMacro(const bool bExecute);
75 class ScXMLHelpMessageContext : public ScXMLImportContext
77 OUString sTitle;
78 OUStringBuffer sMessage;
79 sal_Int32 nParagraphCount;
80 bool bDisplay;
82 ScXMLContentValidationContext* pValidationContext;
84 public:
86 ScXMLHelpMessageContext( ScXMLImport& rImport,
87 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
88 ScXMLContentValidationContext* pValidationContext);
90 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
91 sal_Int32 nElement,
92 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
94 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
97 class ScXMLErrorMessageContext : public ScXMLImportContext
99 OUString sTitle;
100 OUStringBuffer sMessage;
101 OUString sMessageType;
102 sal_Int32 nParagraphCount;
103 bool bDisplay;
105 ScXMLContentValidationContext* pValidationContext;
107 public:
109 ScXMLErrorMessageContext( ScXMLImport& rImport,
110 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
111 ScXMLContentValidationContext* pValidationContext);
113 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
114 sal_Int32 nElement,
115 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
117 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
120 class ScXMLErrorMacroContext : public ScXMLImportContext
122 bool bExecute;
123 ScXMLContentValidationContext* pValidationContext;
125 public:
127 ScXMLErrorMacroContext( ScXMLImport& rImport,
128 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
129 ScXMLContentValidationContext* pValidationContext);
131 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
132 sal_Int32 nElement,
133 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override;
134 virtual void SAL_CALL endFastElement( sal_Int32 nElement ) override;
139 ScXMLContentValidationsContext::ScXMLContentValidationsContext( ScXMLImport& rImport ) :
140 ScXMLImportContext( rImport )
142 // here are no attributes
145 ScXMLContentValidationsContext::~ScXMLContentValidationsContext()
149 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLContentValidationsContext::createFastChildContext(
150 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
152 SvXMLImportContext *pContext = nullptr;
153 sax_fastparser::FastAttributeList *pAttribList =
154 &sax_fastparser::castToFastAttributeList( xAttrList );
156 switch (nElement)
158 case XML_ELEMENT( TABLE, XML_CONTENT_VALIDATION ):
159 pContext = new ScXMLContentValidationContext( GetScImport(), pAttribList );
160 break;
163 return pContext;
166 ScXMLContentValidationContext::ScXMLContentValidationContext( ScXMLImport& rImport,
167 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList ) :
168 ScXMLImportContext( rImport ),
169 nShowList(sheet::TableValidationVisibility::UNSORTED),
170 bAllowEmptyCell(true),
171 bIsCaseSensitive(false),
172 bDisplayHelp(false),
173 bDisplayError(false)
175 if ( !rAttrList.is() )
176 return;
178 for (auto &aIter : *rAttrList)
180 switch (aIter.getToken())
182 case XML_ELEMENT( TABLE, XML_NAME ):
183 sName = aIter.toString();
184 break;
185 case XML_ELEMENT( TABLE, XML_CONDITION ):
186 sCondition = aIter.toString();
187 break;
188 case XML_ELEMENT( TABLE, XML_BASE_CELL_ADDRESS ):
189 sBaseCellAddress = aIter.toString();
190 break;
191 case XML_ELEMENT( TABLE, XML_ALLOW_EMPTY_CELL ):
192 if (IsXMLToken(aIter, XML_FALSE))
193 bAllowEmptyCell = false;
194 break;
195 case XML_ELEMENT( TABLE, XML_CASE_SENSITIVE ):
196 if (IsXMLToken(aIter, XML_TRUE))
197 bIsCaseSensitive = true;
198 break;
199 case XML_ELEMENT( TABLE, XML_DISPLAY_LIST ):
200 if (IsXMLToken(aIter, XML_NO))
202 nShowList = sheet::TableValidationVisibility::INVISIBLE;
204 else if (IsXMLToken(aIter, XML_UNSORTED))
206 nShowList = sheet::TableValidationVisibility::UNSORTED;
208 else if (IsXMLToken(aIter, XML_SORT_ASCENDING))
210 nShowList = sheet::TableValidationVisibility::SORTEDASCENDING;
212 else if (IsXMLToken(aIter, XML_SORTED_ASCENDING))
214 // Read old wrong value, fdo#72548
215 nShowList = sheet::TableValidationVisibility::SORTEDASCENDING;
217 break;
222 uno::Reference< xml::sax::XFastContextHandler > SAL_CALL ScXMLContentValidationContext::createFastChildContext(
223 sal_Int32 nElement, const uno::Reference< xml::sax::XFastAttributeList >& xAttrList )
225 SvXMLImportContext *pContext = nullptr;
226 sax_fastparser::FastAttributeList *pAttribList =
227 &sax_fastparser::castToFastAttributeList( xAttrList );
229 switch (nElement)
231 case XML_ELEMENT( TABLE, XML_HELP_MESSAGE ):
232 pContext = new ScXMLHelpMessageContext( GetScImport(), pAttribList, this);
233 break;
234 case XML_ELEMENT( TABLE, XML_ERROR_MESSAGE ):
235 pContext = new ScXMLErrorMessageContext( GetScImport(), pAttribList, this);
236 break;
237 case XML_ELEMENT( TABLE, XML_ERROR_MACRO ):
238 pContext = new ScXMLErrorMacroContext( GetScImport(), pAttribList, this);
239 break;
240 case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
241 xEventContext = new XMLEventsImportContext( GetImport() );
242 pContext = xEventContext.get();
245 return pContext;
248 sheet::ValidationAlertStyle ScXMLContentValidationContext::GetAlertStyle() const
250 if (IsXMLToken(sErrorMessageType, XML_MACRO))
251 return sheet::ValidationAlertStyle_MACRO;
252 if (IsXMLToken(sErrorMessageType, XML_STOP))
253 return sheet::ValidationAlertStyle_STOP;
254 if (IsXMLToken(sErrorMessageType, XML_WARNING))
255 return sheet::ValidationAlertStyle_WARNING;
256 if (IsXMLToken(sErrorMessageType, XML_INFORMATION))
257 return sheet::ValidationAlertStyle_INFO;
258 // default for unknown
259 return sheet::ValidationAlertStyle_STOP;
262 void ScXMLContentValidationContext::SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar,
263 const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const
265 reGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
266 if( bHasNmsp )
268 // the entire attribute contains a namespace: internal namespace not allowed
269 rFormula = rCondition;
270 rFormulaNmsp = rGlobNmsp;
271 reGrammar = eGlobGrammar;
273 else
275 // the attribute does not contain a namespace: try to find a namespace of an external grammar
276 GetScImport().ExtractFormulaNamespaceGrammar( rFormula, rFormulaNmsp, reGrammar, rCondition, true );
277 if( reGrammar != FormulaGrammar::GRAM_EXTERNAL )
278 reGrammar = eGlobGrammar;
282 void ScXMLContentValidationContext::GetCondition( ScMyImportValidation& rValidation ) const
284 rValidation.aValidationType = sheet::ValidationType_ANY; // default if no condition is given
285 rValidation.aOperator = sheet::ConditionOperator_NONE;
287 if( sCondition.isEmpty() )
288 return;
290 // extract leading namespace from condition string
291 OUString aCondition, aConditionNmsp;
292 FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED;
293 GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, sCondition );
294 bool bHasNmsp = aCondition.getLength() < sCondition.getLength();
296 // parse a condition from the attribute string
297 ScXMLConditionParseResult aParseResult;
298 ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 );
300 /* Check the result. A valid value in aParseResult.meToken implies
301 that the other members of aParseResult are filled with valid data
302 for that token. */
303 bool bSecondaryPart = false;
304 switch( aParseResult.meToken )
306 case XML_COND_TEXTLENGTH: // condition is 'cell-content-text-length()<operator><expression>'
307 case XML_COND_TEXTLENGTH_ISBETWEEN: // condition is 'cell-content-text-length-is-between(<expression1>,<expression2>)'
308 case XML_COND_TEXTLENGTH_ISNOTBETWEEN: // condition is 'cell-content-text-length-is-not-between(<expression1>,<expression2>)'
309 case XML_COND_ISINLIST: // condition is 'cell-content-is-in-list(<expression>)'
310 case XML_COND_ISTRUEFORMULA: // condition is 'is-true-formula(<expression>)'
311 rValidation.aValidationType = aParseResult.meValidation;
312 rValidation.aOperator = aParseResult.meOperator;
313 break;
315 case XML_COND_ISWHOLENUMBER: // condition is 'cell-content-is-whole-number() and <condition>'
316 case XML_COND_ISDECIMALNUMBER: // condition is 'cell-content-is-decimal-number() and <condition>'
317 case XML_COND_ISDATE: // condition is 'cell-content-is-date() and <condition>'
318 case XML_COND_ISTIME: // condition is 'cell-content-is-time() and <condition>'
319 rValidation.aValidationType = aParseResult.meValidation;
320 bSecondaryPart = true;
321 break;
323 default:; // unacceptable or unknown condition
326 /* Parse the following 'and <condition>' part of some conditions. This
327 updates the members of aParseResult that will contain the operands
328 and comparison operator then. */
329 if( bSecondaryPart )
331 ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex );
332 if( aParseResult.meToken == XML_COND_AND )
334 ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex );
335 switch( aParseResult.meToken )
337 case XML_COND_CELLCONTENT: // condition is 'and cell-content()<operator><expression>'
338 case XML_COND_ISBETWEEN: // condition is 'and cell-content-is-between(<expression1>,<expression2>)'
339 case XML_COND_ISNOTBETWEEN: // condition is 'and cell-content-is-not-between(<expression1>,<expression2>)'
340 rValidation.aOperator = aParseResult.meOperator;
341 break;
342 default:; // unacceptable or unknown condition
347 // a validation type (date, integer) without a condition isn't possible
348 if( rValidation.aOperator == sheet::ConditionOperator_NONE )
349 rValidation.aValidationType = sheet::ValidationType_ANY;
351 // parse the formulas
352 if( rValidation.aValidationType != sheet::ValidationType_ANY )
354 SetFormula( rValidation.sFormula1, rValidation.sFormulaNmsp1, rValidation.eGrammar1,
355 aParseResult.maOperand1, aConditionNmsp, eGrammar, bHasNmsp );
356 SetFormula( rValidation.sFormula2, rValidation.sFormulaNmsp2, rValidation.eGrammar2,
357 aParseResult.maOperand2, aConditionNmsp, eGrammar, bHasNmsp );
361 void SAL_CALL ScXMLContentValidationContext::endFastElement( sal_Int32 /*nElement*/ )
363 // #i36650# event-listeners element moved up one level
364 if (xEventContext.is())
366 uno::Sequence<beans::PropertyValue> aValues;
367 xEventContext->GetEventSequence( u"OnError"_ustr, aValues );
369 auto pValue = std::find_if(std::cbegin(aValues), std::cend(aValues),
370 [](const beans::PropertyValue& rValue) {
371 return rValue.Name == "MacroName" || rValue.Name == "Script"; });
372 if (pValue != std::cend(aValues))
373 pValue->Value >>= sErrorTitle;
376 ScMyImportValidation aValidation;
377 if (ScDocument* pDoc = GetScImport().GetDocument())
378 aValidation.eGrammar1 = aValidation.eGrammar2 = pDoc->GetStorageGrammar();
379 aValidation.sName = sName;
380 aValidation.sBaseCellAddress = sBaseCellAddress;
381 aValidation.sInputTitle = sHelpTitle;
382 aValidation.sInputMessage = sHelpMessage;
383 aValidation.sErrorTitle = sErrorTitle;
384 aValidation.sErrorMessage = sErrorMessage;
385 GetCondition( aValidation );
386 aValidation.aAlertStyle = GetAlertStyle();
387 aValidation.bShowErrorMessage = bDisplayError;
388 aValidation.bShowInputMessage = bDisplayHelp;
389 aValidation.bIgnoreBlanks = bAllowEmptyCell;
390 aValidation.bCaseSensitive = bIsCaseSensitive;
391 aValidation.nShowList = nShowList;
392 GetScImport().AddValidation(aValidation);
395 void ScXMLContentValidationContext::SetHelpMessage(const OUString& sTitle, const OUString& sMessage, const bool bDisplay)
397 sHelpTitle = sTitle;
398 sHelpMessage = sMessage;
399 bDisplayHelp = bDisplay;
402 void ScXMLContentValidationContext::SetErrorMessage(const OUString& sTitle, const OUString& sMessage,
403 const OUString& sMessageType, const bool bDisplay)
405 sErrorTitle = sTitle;
406 sErrorMessage = sMessage;
407 sErrorMessageType = sMessageType;
408 bDisplayError = bDisplay;
411 void ScXMLContentValidationContext::SetErrorMacro(const bool bExecute)
413 sErrorMessageType = "macro";
414 bDisplayError = bExecute;
417 ScXMLHelpMessageContext::ScXMLHelpMessageContext( ScXMLImport& rImport,
418 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
419 ScXMLContentValidationContext* pTempValidationContext) :
420 ScXMLImportContext( rImport ),
421 nParagraphCount(0),
422 bDisplay(false)
424 pValidationContext = pTempValidationContext;
425 if ( !rAttrList.is() )
426 return;
428 for (auto &aIter : *rAttrList)
430 switch (aIter.getToken())
432 case XML_ELEMENT( TABLE, XML_TITLE ):
433 sTitle = aIter.toString();
434 break;
435 case XML_ELEMENT( TABLE, XML_DISPLAY ):
436 bDisplay = IsXMLToken(aIter, XML_TRUE);
437 break;
442 css::uno::Reference< css::xml::sax::XFastContextHandler > ScXMLHelpMessageContext::createFastChildContext(
443 sal_Int32 nElement,
444 const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
446 SvXMLImportContext *pContext = nullptr;
448 switch( nElement )
450 case XML_ELEMENT(TEXT, XML_P):
452 if(nParagraphCount)
453 sMessage.append('\n');
454 ++nParagraphCount;
455 pContext = new ScXMLContentContext( GetScImport(), sMessage );
457 break;
460 return pContext;
463 void SAL_CALL ScXMLHelpMessageContext::endFastElement( sal_Int32 /*nElement*/ )
465 pValidationContext->SetHelpMessage(sTitle, sMessage.makeStringAndClear(), bDisplay);
468 ScXMLErrorMessageContext::ScXMLErrorMessageContext( ScXMLImport& rImport,
469 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
470 ScXMLContentValidationContext* pTempValidationContext) :
471 ScXMLImportContext( rImport ),
472 nParagraphCount(0),
473 bDisplay(false)
475 pValidationContext = pTempValidationContext;
476 if ( !rAttrList.is() )
477 return;
479 for (auto &aIter : *rAttrList)
481 switch (aIter.getToken())
483 case XML_ELEMENT( TABLE, XML_TITLE ):
484 sTitle = aIter.toString();
485 break;
486 case XML_ELEMENT( TABLE, XML_MESSAGE_TYPE ):
487 sMessageType = aIter.toString();
488 break;
489 case XML_ELEMENT( TABLE, XML_DISPLAY ):
490 bDisplay = IsXMLToken(aIter, XML_TRUE);
491 break;
496 css::uno::Reference< css::xml::sax::XFastContextHandler > ScXMLErrorMessageContext::createFastChildContext(
497 sal_Int32 nElement,
498 const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
500 SvXMLImportContext *pContext = nullptr;
502 switch( nElement )
504 case XML_ELEMENT(TEXT, XML_P):
506 if(nParagraphCount)
507 sMessage.append('\n');
508 ++nParagraphCount;
509 pContext = new ScXMLContentContext( GetScImport(), sMessage);
511 break;
514 return pContext;
517 void SAL_CALL ScXMLErrorMessageContext::endFastElement( sal_Int32 /*nElement*/ )
519 pValidationContext->SetErrorMessage(sTitle, sMessage.makeStringAndClear(), sMessageType, bDisplay);
522 ScXMLErrorMacroContext::ScXMLErrorMacroContext( ScXMLImport& rImport,
523 const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList,
524 ScXMLContentValidationContext* pTempValidationContext) :
525 ScXMLImportContext( rImport ),
526 bExecute(false)
528 pValidationContext = pTempValidationContext;
529 if ( !rAttrList.is() )
530 return;
532 for (auto &aIter : *rAttrList)
534 switch (aIter.getToken())
536 case XML_ELEMENT( TABLE, XML_NAME ):
537 break;
538 case XML_ELEMENT( TABLE, XML_EXECUTE ):
539 bExecute = IsXMLToken(aIter, XML_TRUE);
540 break;
545 css::uno::Reference< css::xml::sax::XFastContextHandler > ScXMLErrorMacroContext::createFastChildContext(
546 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& /*xAttrList*/ )
548 SvXMLImportContext *pContext = nullptr;
550 if (nElement == XML_ELEMENT(SCRIPT, XML_EVENTS))
552 pContext = new XMLEventsImportContext(GetImport());
555 return pContext;
558 void SAL_CALL ScXMLErrorMacroContext::endFastElement( sal_Int32 /*nElement*/ )
560 pValidationContext->SetErrorMacro( bExecute );
563 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */