tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / core / data / SolverSettings.cxx
blobc7413bcb943ebe944596db7c469e72d9402507c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
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 */
11 #include <global.hxx>
12 #include <compiler.hxx>
13 #include <table.hxx>
14 #include <docsh.hxx>
15 #include <rtl/math.hxx>
16 #include <o3tl/string_view.hxx>
17 #include <solverutil.hxx>
18 #include <unotools/charclass.hxx>
19 #include <SolverSettings.hxx>
21 namespace sc
23 SolverSettings::SolverSettings(ScTable& rTable)
24 : m_rTable(rTable)
25 , m_rDoc(m_rTable.GetDoc())
26 , m_pDocShell(m_rDoc.GetDocumentShell())
28 // Get the named range manager for this tab
29 std::map<OUString, ScRangeName*> rRangeMap;
30 m_rDoc.GetRangeNameMap(rRangeMap);
31 m_pRangeName = rRangeMap.find(m_rTable.GetName())->second;
33 Initialize();
36 void SolverSettings::Initialize()
38 // Assign default values for the solver parameters
39 ResetToDefaults();
41 // Read the parameter values in the sheet
42 ReadParamValue(SP_OBJ_CELL, m_sObjCell);
43 ReadParamValue(SP_OBJ_VAL, m_sObjVal);
44 ReadParamValue(SP_VAR_CELLS, m_sVariableCells);
46 // Read the objective type
47 OUString sObjType;
48 if (ReadParamValue(SP_OBJ_TYPE, sObjType))
50 switch (sObjType.toInt32())
52 case 1:
53 m_eObjType = ObjectiveType::OT_MAXIMIZE;
54 break;
55 case 2:
56 m_eObjType = ObjectiveType::OT_MINIMIZE;
57 break;
58 case 3:
59 m_eObjType = ObjectiveType::OT_VALUE;
60 break;
61 default:
62 m_eObjType = ObjectiveType::OT_MAXIMIZE;
66 // Read all constraints in the tab
67 ReadConstraints();
69 // Read the solver engine being used
70 ReadEngine();
72 // Read engine options
73 ReadParamValue(SP_INTEGER, m_sInteger);
74 ReadParamValue(SP_NON_NEGATIVE, m_sNonNegative);
75 ReadParamValue(SP_EPSILON_LEVEL, m_sEpsilonLevel);
76 ReadParamValue(SP_LIMIT_BBDEPTH, m_sLimitBBDepth);
77 ReadParamValue(SP_TIMEOUT, m_sTimeout);
78 ReadParamValue(SP_ALGORITHM, m_sAlgorithm);
79 // Engine options common for DEPS and SCO
80 ReadParamValue(SP_SWARM_SIZE, m_sSwarmSize);
81 ReadParamValue(SP_LEARNING_CYCLES, m_sLearningCycles);
82 ReadParamValue(SP_GUESS_VARIABLE_RANGE, m_sGuessVariableRange);
83 ReadDoubleParamValue(SP_VARIABLE_RANGE_THRESHOLD, m_sVariableRangeThreshold);
84 ReadParamValue(SP_ACR_COMPARATOR, m_sUseACRComparator);
85 ReadParamValue(SP_RND_STARTING_POINT, m_sUseRandomStartingPoint);
86 ReadParamValue(SP_STRONGER_PRNG, m_sUseStrongerPRNG);
87 ReadParamValue(SP_STAGNATION_LIMIT, m_sStagnationLimit);
88 ReadDoubleParamValue(SP_STAGNATION_TOLERANCE, m_sTolerance);
89 ReadParamValue(SP_ENHANCED_STATUS, m_sEnhancedSolverStatus);
90 // DEPS Options
91 ReadDoubleParamValue(SP_AGENT_SWITCH_RATE, m_sAgentSwitchRate);
92 ReadDoubleParamValue(SP_SCALING_MIN, m_sScalingFactorMin);
93 ReadDoubleParamValue(SP_SCALING_MAX, m_sScalingFactorMax);
94 ReadDoubleParamValue(SP_CROSSOVER_PROB, m_sCrossoverProbability);
95 ReadDoubleParamValue(SP_COGNITIVE_CONST, m_sCognitiveConstant);
96 ReadDoubleParamValue(SP_SOCIAL_CONST, m_sSocialConstant);
97 ReadDoubleParamValue(SP_CONSTRICTION_COEFF, m_sConstrictionCoeff);
98 ReadDoubleParamValue(SP_MUTATION_PROB, m_sMutationProbability);
99 // SCO Options
100 ReadParamValue(SP_LIBRARY_SIZE, m_sLibrarySize);
103 // Returns the current value of the parameter in the object as a string
104 OUString SolverSettings::GetParameter(SolverParameter eParam)
106 switch (eParam)
108 case SP_OBJ_CELL:
109 return m_sObjCell;
110 break;
111 case SP_OBJ_TYPE:
112 return OUString::number(m_eObjType);
113 break;
114 case SP_OBJ_VAL:
115 return m_sObjVal;
116 break;
117 case SP_VAR_CELLS:
118 return m_sVariableCells;
119 break;
120 case SP_CONSTR_COUNT:
121 return OUString::number(m_aConstraints.size());
122 break;
123 case SP_LO_ENGINE:
124 return m_sLOEngineName;
125 break;
126 case SP_MS_ENGINE:
127 return m_sMSEngineId;
128 break;
129 case SP_INTEGER:
130 return m_sInteger;
131 break;
132 case SP_NON_NEGATIVE:
133 return m_sNonNegative;
134 break;
135 case SP_EPSILON_LEVEL:
136 return m_sEpsilonLevel;
137 break;
138 case SP_LIMIT_BBDEPTH:
139 return m_sLimitBBDepth;
140 break;
141 case SP_TIMEOUT:
142 return m_sTimeout;
143 break;
144 case SP_ALGORITHM:
145 return m_sAlgorithm;
146 break;
147 case SP_SWARM_SIZE:
148 return m_sSwarmSize;
149 break;
150 case SP_LEARNING_CYCLES:
151 return m_sLearningCycles;
152 break;
153 case SP_GUESS_VARIABLE_RANGE:
154 return m_sGuessVariableRange;
155 break;
156 case SP_VARIABLE_RANGE_THRESHOLD:
157 return m_sVariableRangeThreshold;
158 break;
159 case SP_ACR_COMPARATOR:
160 return m_sUseACRComparator;
161 break;
162 case SP_RND_STARTING_POINT:
163 return m_sUseRandomStartingPoint;
164 break;
165 case SP_STRONGER_PRNG:
166 return m_sUseStrongerPRNG;
167 break;
168 case SP_STAGNATION_LIMIT:
169 return m_sStagnationLimit;
170 break;
171 case SP_STAGNATION_TOLERANCE:
172 return m_sTolerance;
173 break;
174 case SP_ENHANCED_STATUS:
175 return m_sEnhancedSolverStatus;
176 break;
177 case SP_AGENT_SWITCH_RATE:
178 return m_sAgentSwitchRate;
179 break;
180 case SP_SCALING_MIN:
181 return m_sScalingFactorMin;
182 break;
183 case SP_SCALING_MAX:
184 return m_sScalingFactorMax;
185 break;
186 case SP_CROSSOVER_PROB:
187 return m_sCrossoverProbability;
188 break;
189 case SP_COGNITIVE_CONST:
190 return m_sCognitiveConstant;
191 break;
192 case SP_SOCIAL_CONST:
193 return m_sSocialConstant;
194 break;
195 case SP_CONSTRICTION_COEFF:
196 return m_sConstrictionCoeff;
197 break;
198 case SP_MUTATION_PROB:
199 return m_sMutationProbability;
200 break;
201 case SP_LIBRARY_SIZE:
202 return m_sLibrarySize;
203 break;
204 default:
205 return u""_ustr;
209 // Sets the value of a single solver parameter in the object
210 void SolverSettings::SetParameter(SolverParameter eParam, const OUString& sValue)
212 switch (eParam)
214 case SP_OBJ_CELL:
215 m_sObjCell = sValue;
216 break;
217 case SP_OBJ_TYPE:
219 sal_Int32 nObjType = sValue.toInt32();
220 switch (nObjType)
222 case OT_MAXIMIZE:
223 m_eObjType = ObjectiveType::OT_MAXIMIZE;
224 break;
225 case OT_MINIMIZE:
226 m_eObjType = ObjectiveType::OT_MINIMIZE;
227 break;
228 case OT_VALUE:
229 m_eObjType = ObjectiveType::OT_VALUE;
230 break;
231 default:
232 m_eObjType = ObjectiveType::OT_MAXIMIZE;
233 break;
235 break;
237 case SP_OBJ_VAL:
238 m_sObjVal = sValue;
239 break;
240 case SP_VAR_CELLS:
241 m_sVariableCells = sValue;
242 break;
243 case SP_LO_ENGINE:
244 m_sLOEngineName = sValue;
245 break;
246 case SP_INTEGER:
248 if (sValue == "0" || sValue == "1")
249 m_sInteger = sValue;
251 break;
252 case SP_NON_NEGATIVE:
254 if (sValue == "1" || sValue == "2")
255 m_sNonNegative = sValue;
257 break;
258 case SP_EPSILON_LEVEL:
259 m_sEpsilonLevel = sValue;
260 break;
261 case SP_LIMIT_BBDEPTH:
262 m_sLimitBBDepth = sValue;
263 break;
264 case SP_TIMEOUT:
265 m_sTimeout = sValue;
266 break;
267 case SP_ALGORITHM:
269 if (sValue == "1" || sValue == "2" || sValue == "3")
270 m_sAlgorithm = sValue;
272 break;
273 case SP_SWARM_SIZE:
274 m_sSwarmSize = sValue;
275 break;
276 case SP_LEARNING_CYCLES:
277 m_sLearningCycles = sValue;
278 break;
279 case SP_GUESS_VARIABLE_RANGE:
280 m_sGuessVariableRange = sValue;
281 break;
282 case SP_VARIABLE_RANGE_THRESHOLD:
283 m_sVariableRangeThreshold = sValue;
284 break;
285 case SP_ACR_COMPARATOR:
287 if (sValue == "0" || sValue == "1")
288 m_sUseACRComparator = sValue;
290 break;
291 case SP_RND_STARTING_POINT:
293 if (sValue == "0" || sValue == "1")
294 m_sUseRandomStartingPoint = sValue;
296 break;
297 case SP_STRONGER_PRNG:
299 if (sValue == "0" || sValue == "1")
300 m_sUseStrongerPRNG = sValue;
302 break;
303 case SP_STAGNATION_LIMIT:
304 m_sStagnationLimit = sValue;
305 break;
306 case SP_STAGNATION_TOLERANCE:
307 m_sTolerance = sValue;
308 break;
309 case SP_ENHANCED_STATUS:
311 if (sValue == "0" || sValue == "1")
312 m_sEnhancedSolverStatus = sValue;
314 break;
315 case SP_AGENT_SWITCH_RATE:
316 m_sAgentSwitchRate = sValue;
317 break;
318 case SP_SCALING_MIN:
319 m_sScalingFactorMin = sValue;
320 break;
321 case SP_SCALING_MAX:
322 m_sScalingFactorMax = sValue;
323 break;
324 case SP_CROSSOVER_PROB:
325 m_sCrossoverProbability = sValue;
326 break;
327 case SP_COGNITIVE_CONST:
328 m_sCognitiveConstant = sValue;
329 break;
330 case SP_SOCIAL_CONST:
331 m_sSocialConstant = sValue;
332 break;
333 case SP_CONSTRICTION_COEFF:
334 m_sConstrictionCoeff = sValue;
335 break;
336 case SP_MUTATION_PROB:
337 m_sMutationProbability = sValue;
338 break;
339 case SP_LIBRARY_SIZE:
340 m_sLibrarySize = sValue;
341 break;
342 default:
343 break;
347 void SolverSettings::SetObjectiveType(ObjectiveType eType) { m_eObjType = eType; }
349 // Loads all constraints in the tab
350 void SolverSettings::ReadConstraints()
352 // Condition indices start at 1 for MS compatibility
353 // The number of "lhs", "rel" and "rhs" entries will always be the same
354 tools::Long nConstraint = 1;
355 m_aConstraints.clear();
356 OUString sValue;
358 while (ReadConstraintPart(CP_LEFT_HAND_SIDE, nConstraint, sValue))
360 // Left hand side
361 ModelConstraint aNewCondition;
362 aNewCondition.aLeftStr = sValue;
364 // Right hand side
365 if (ReadConstraintPart(CP_RIGHT_HAND_SIDE, nConstraint, sValue))
366 aNewCondition.aRightStr = sValue;
368 // Relation (operator)
369 if (ReadConstraintPart(CP_OPERATOR, nConstraint, sValue))
370 aNewCondition.nOperator = static_cast<sc::ConstraintOperator>(sValue.toInt32());
372 m_aConstraints.push_back(aNewCondition);
373 nConstraint++;
377 // Writes all constraints to the file
378 void SolverSettings::WriteConstraints()
380 // Condition indices start at 1 for MS compatibility
381 tools::Long nConstraint = 1;
383 for (auto& aConstraint : m_aConstraints)
385 // Left hand side
386 WriteConstraintPart(CP_LEFT_HAND_SIDE, nConstraint, aConstraint.aLeftStr);
387 // Relation (operator)
388 WriteConstraintPart(CP_OPERATOR, nConstraint, OUString::number(aConstraint.nOperator));
389 // Right hand side
390 WriteConstraintPart(CP_RIGHT_HAND_SIDE, nConstraint, aConstraint.aRightStr);
391 nConstraint++;
395 // Write a single constraint part to the file
396 void SolverSettings::WriteConstraintPart(ConstraintPart ePart, tools::Long nIndex,
397 const OUString& sValue)
399 // Empty named ranges cannot be written to the file (this corrupts MS files)
400 if (sValue.isEmpty())
401 return;
403 OUString sRange = m_aConstraintParts[ePart] + OUString::number(nIndex);
404 ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sValue);
405 pNewEntry->AddType(ScRangeData::Type::Hidden);
406 m_pRangeName->insert(pNewEntry);
409 // Reads a single constraint part from its associated named range; returns false if the named
410 // range does not exist in the file
411 bool SolverSettings::ReadConstraintPart(ConstraintPart ePart, tools::Long nIndex, OUString& rValue)
413 OUString sRange = m_aConstraintParts[ePart] + OUString::number(nIndex);
414 ScRangeData* pRangeData
415 = m_pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(sRange));
416 if (pRangeData)
418 rValue = pRangeData->GetSymbol();
419 // tdf#156814 Remove sheet name if it is a range that refers to the same sheet
420 ScRange aRange;
421 ScRefFlags nFlags = aRange.ParseAny(rValue, m_rDoc);
422 bool bIsValidRange = (nFlags & ScRefFlags::VALID) == ScRefFlags::VALID;
423 if (bIsValidRange && m_rTable.GetTab() == aRange.aStart.Tab())
424 rValue = aRange.Format(m_rDoc, ScRefFlags::RANGE_ABS);
425 return true;
427 return false;
430 /* Reads the engine name parameter as informed in the file in the format used in LO.
431 * If only a MS engine is informed, then it is converted to a LO-equivalent engine
433 void SolverSettings::ReadEngine()
435 if (!ReadParamValue(SP_LO_ENGINE, m_sLOEngineName, true))
437 // If no engine is defined, use CoinMP solver as default
438 m_sLOEngineName = "com.sun.star.comp.Calc.CoinMPSolver";
441 if (SolverNamesToExcelEngines.count(m_sLOEngineName))
443 // Find equivalent MS engine code
444 m_sMSEngineId = SolverNamesToExcelEngines.find(m_sLOEngineName)->second;
448 // Write solver LO and MS-equivalent engine names
449 void SolverSettings::WriteEngine()
451 WriteParamValue(SP_LO_ENGINE, m_sLOEngineName, true);
452 // Find equivalent MS engine code
453 if (SolverNamesToExcelEngines.count(m_sLOEngineName))
455 m_sMSEngineId = SolverNamesToExcelEngines.find(m_sLOEngineName)->second;
456 WriteParamValue(SP_MS_ENGINE, m_sMSEngineId);
460 // Assigns a new constraints vector
461 void SolverSettings::SetConstraints(std::vector<ModelConstraint> aConstraints)
463 m_aConstraints = std::move(aConstraints);
466 // Saves all solver settings into the file
467 void SolverSettings::SaveSolverSettings()
469 // Before saving, remove all existing named ranges related to the solver
470 DeleteAllNamedRanges();
472 WriteParamValue(SP_OBJ_CELL, m_sObjCell);
473 WriteParamValue(SP_OBJ_TYPE, OUString::number(m_eObjType));
474 WriteParamValue(SP_OBJ_VAL, m_sObjVal);
475 WriteParamValue(SP_VAR_CELLS, m_sVariableCells);
477 WriteConstraints();
478 WriteEngine();
480 sal_Int32 nConstrCount = m_aConstraints.size();
481 WriteParamValue(SP_CONSTR_COUNT, OUString::number(nConstrCount));
483 // Solver engine options
484 WriteParamValue(SP_INTEGER, m_sInteger);
485 WriteParamValue(SP_NON_NEGATIVE, m_sNonNegative);
486 WriteParamValue(SP_EPSILON_LEVEL, m_sEpsilonLevel);
487 WriteParamValue(SP_LIMIT_BBDEPTH, m_sLimitBBDepth);
488 WriteParamValue(SP_TIMEOUT, m_sTimeout);
489 WriteParamValue(SP_ALGORITHM, m_sAlgorithm);
490 // Engine options common for DEPS and SCO
491 WriteParamValue(SP_SWARM_SIZE, m_sSwarmSize);
492 WriteParamValue(SP_LEARNING_CYCLES, m_sLearningCycles);
493 WriteParamValue(SP_GUESS_VARIABLE_RANGE, m_sGuessVariableRange);
494 WriteDoubleParamValue(SP_VARIABLE_RANGE_THRESHOLD, m_sVariableRangeThreshold);
495 WriteParamValue(SP_ACR_COMPARATOR, m_sUseACRComparator);
496 WriteParamValue(SP_RND_STARTING_POINT, m_sUseRandomStartingPoint);
497 WriteParamValue(SP_STRONGER_PRNG, m_sUseStrongerPRNG);
498 WriteParamValue(SP_STAGNATION_LIMIT, m_sStagnationLimit);
499 WriteDoubleParamValue(SP_STAGNATION_TOLERANCE, m_sTolerance);
500 WriteParamValue(SP_ENHANCED_STATUS, m_sEnhancedSolverStatus);
501 // DEPS Options
502 WriteDoubleParamValue(SP_AGENT_SWITCH_RATE, m_sAgentSwitchRate);
503 WriteDoubleParamValue(SP_SCALING_MIN, m_sScalingFactorMin);
504 WriteDoubleParamValue(SP_SCALING_MAX, m_sScalingFactorMax);
505 WriteDoubleParamValue(SP_CROSSOVER_PROB, m_sCrossoverProbability);
506 WriteDoubleParamValue(SP_COGNITIVE_CONST, m_sCognitiveConstant);
507 WriteDoubleParamValue(SP_SOCIAL_CONST, m_sSocialConstant);
508 WriteDoubleParamValue(SP_CONSTRICTION_COEFF, m_sConstrictionCoeff);
509 WriteDoubleParamValue(SP_MUTATION_PROB, m_sMutationProbability);
510 // SCO Options
511 WriteParamValue(SP_LIBRARY_SIZE, m_sLibrarySize);
513 if (m_pDocShell)
514 m_pDocShell->SetDocumentModified();
517 /* Reads the current value of the parameter in the named range into rValue
518 * If the value does not exist, the rValue is left unchanged
519 * This is private because it is only used during initialization
520 * Returns true if the value exits; returns false otherwise
522 bool SolverSettings::ReadParamValue(SolverParameter eParam, OUString& rValue, bool bRemoveQuotes)
524 const auto iter = m_mNamedRanges.find(eParam);
525 assert(iter != m_mNamedRanges.end());
526 OUString sRange = iter->second;
527 ScRangeData* pRangeData
528 = m_pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(sRange));
529 if (pRangeData)
531 rValue = pRangeData->GetSymbol();
532 if (bRemoveQuotes)
533 ScGlobal::EraseQuotes(rValue, '"');
535 // tdf#156814 Remove sheet name from the objective cell and value if they refer to the same sheet
536 if (eParam == SP_OBJ_CELL || eParam == SP_OBJ_VAL)
538 ScRange aRange;
539 ScRefFlags nFlags = aRange.ParseAny(rValue, m_rDoc);
540 bool bIsValidRange = ((nFlags & ScRefFlags::VALID) == ScRefFlags::VALID);
542 if (bIsValidRange && m_rTable.GetTab() == aRange.aStart.Tab())
543 rValue = aRange.Format(m_rDoc, ScRefFlags::RANGE_ABS);
545 else if (eParam == SP_VAR_CELLS)
547 // Variable cells may contain multiple ranges separated by ';'
548 sal_Int32 nIdx = 0;
549 OUString sNewValue;
550 bool bFirst = true;
551 // Delimiter character to separate ranges
552 sal_Unicode cDelimiter = ScCompiler::GetNativeSymbolChar(OpCode::ocSep);
556 OUString aRangeStr(o3tl::getToken(rValue, 0, cDelimiter, nIdx));
557 ScRange aRange;
558 ScRefFlags nFlags = aRange.ParseAny(aRangeStr, m_rDoc);
559 bool bIsValidRange = (nFlags & ScRefFlags::VALID) == ScRefFlags::VALID;
561 if (bIsValidRange && m_rTable.GetTab() == aRange.aStart.Tab())
562 aRangeStr = aRange.Format(m_rDoc, ScRefFlags::RANGE_ABS);
564 if (bFirst)
566 sNewValue = aRangeStr;
567 bFirst = false;
569 else
571 sNewValue += OUStringChar(cDelimiter) + aRangeStr;
573 } while (nIdx > 0);
575 rValue = sNewValue;
577 return true;
579 return false;
582 // Reads a parameter value of type 'double' from the named range and into rValue
583 bool SolverSettings::ReadDoubleParamValue(SolverParameter eParam, OUString& rValue)
585 const auto iter = m_mNamedRanges.find(eParam);
586 assert(iter != m_mNamedRanges.end());
587 OUString sRange = iter->second;
588 ScRangeData* pRangeData
589 = m_pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(sRange));
590 if (pRangeData)
592 OUString sLocalizedValue = pRangeData->GetSymbol();
593 double fValue = rtl::math::stringToDouble(sLocalizedValue,
594 ScGlobal::getLocaleData().getNumDecimalSep()[0],
595 ScGlobal::getLocaleData().getNumThousandSep()[0]);
596 rValue = OUString::number(fValue);
597 return true;
599 return false;
602 /* Writes a parameter value to the file as a named range.
603 * Argument bQuoted indicates whether the value should be enclosed with quotes or not (used
604 * for string expressions that must be enclosed with quotes)
606 void SolverSettings::WriteParamValue(SolverParameter eParam, OUString sValue, bool bQuoted)
608 // Empty parameters cannot be written to the file (this corrupts MS files)
609 // There's no problem if the parameter is missing both for LO and MS
610 if (sValue.isEmpty())
611 return;
613 if (bQuoted)
614 ScGlobal::AddQuotes(sValue, '"');
616 const auto iter = m_mNamedRanges.find(eParam);
617 assert(iter != m_mNamedRanges.end());
618 OUString sRange = iter->second;
619 ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sValue);
620 pNewEntry->AddType(ScRangeData::Type::Hidden);
621 m_pRangeName->insert(pNewEntry);
624 // Writes a parameter value of type 'double' to the file as a named range
625 // The argument 'sValue' uses dot as decimal separator and needs to be localized before
626 // being written to the file
627 void SolverSettings::WriteDoubleParamValue(SolverParameter eParam, std::u16string_view sValue)
629 const auto iter = m_mNamedRanges.find(eParam);
630 assert(iter != m_mNamedRanges.end());
631 OUString sRange = iter->second;
632 double fValue = rtl::math::stringToDouble(sValue, '.', ',');
633 OUString sLocalizedValue = rtl::math::doubleToUString(
634 fValue, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
635 ScGlobal::getLocaleData().getNumDecimalSep()[0], true);
636 ScRangeData* pNewEntry = new ScRangeData(m_rDoc, sRange, sLocalizedValue);
637 pNewEntry->AddType(ScRangeData::Type::Hidden);
638 m_pRangeName->insert(pNewEntry);
641 void SolverSettings::GetEngineOptions(css::uno::Sequence<css::beans::PropertyValue>& aOptions)
643 sal_Int32 nOptionsSize = aOptions.getLength();
644 auto pParamValues = aOptions.getArray();
646 for (auto i = 0; i < nOptionsSize; i++)
648 const css::beans::PropertyValue& aProp = aOptions[i];
649 OUString sLOParamName = aProp.Name;
650 // Only try to get the parameter value if it is an expected parameter name
651 if (SolverParamNames.count(sLOParamName))
653 TParamInfo aParamInfo;
654 aParamInfo = SolverParamNames.find(sLOParamName)->second;
655 SolverParameter eParamId = std::get<SolverParameter>(aParamInfo[0]);
656 OUString sParamType = std::get<OUString>(aParamInfo[2]);
657 OUString sParamValue = GetParameter(eParamId);
658 if (sParamType == "int")
660 css::uno::Any nValue(sParamValue.toInt32());
661 pParamValues[i] = css::beans::PropertyValue(sLOParamName, -1, nValue,
662 css::beans::PropertyState_DIRECT_VALUE);
664 if (sParamType == "double")
666 css::uno::Any fValue(sParamValue.toDouble());
667 pParamValues[i] = css::beans::PropertyValue(sLOParamName, -1, fValue,
668 css::beans::PropertyState_DIRECT_VALUE);
670 if (sParamType == "bool")
672 // The parameter NonNegative is a special case for MS compatibility
673 // It uses "1" for "true" and "2" for "false"
674 bool bTmpValue;
675 if (sLOParamName == "NonNegative")
676 bTmpValue = sParamValue == "1" ? true : false;
677 else
678 bTmpValue = sParamValue.toBoolean();
680 css::uno::Any bValue(bTmpValue);
681 pParamValues[i] = css::beans::PropertyValue(sLOParamName, -1, bValue,
682 css::beans::PropertyState_DIRECT_VALUE);
688 // Updates the object members related to solver engine options using aOptions info
689 void SolverSettings::SetEngineOptions(const css::uno::Sequence<css::beans::PropertyValue>& aOptions)
691 sal_Int32 nOptionsSize = aOptions.getLength();
693 for (auto i = 0; i < nOptionsSize; i++)
695 const css::beans::PropertyValue& aProp = aOptions[i];
696 OUString sLOParamName = aProp.Name;
697 // Only try to set the parameter value if it is an expected parameter name
698 if (SolverParamNames.count(sLOParamName))
700 TParamInfo aParamInfo;
701 aParamInfo = SolverParamNames.find(sLOParamName)->second;
702 SolverParameter eParamId = std::get<SolverParameter>(aParamInfo[0]);
703 OUString sParamType = std::get<OUString>(aParamInfo[2]);
704 if (sParamType == "int")
706 sal_Int32 nValue = 0;
707 aProp.Value >>= nValue;
708 SetParameter(eParamId, OUString::number(nValue));
710 if (sParamType == "double")
712 double fValue = 0;
713 aProp.Value >>= fValue;
714 SetParameter(eParamId, OUString::number(fValue));
716 if (sParamType == "bool")
718 bool bValue = false;
719 aProp.Value >>= bValue;
720 if (sLOParamName == "NonNegative")
722 // The parameter NonNegative is a special case for MS compatibility
723 // It uses "1" for "true" and "2" for "false"
724 if (bValue)
725 SetParameter(eParamId, OUString::number(1));
726 else
727 SetParameter(eParamId, OUString::number(2));
729 else
731 SetParameter(eParamId, OUString::number(sal_Int32(bValue)));
738 // Deletes all named ranges in the current tab that are related to the solver (i.e. start with "solver_")
739 void SolverSettings::DeleteAllNamedRanges()
741 std::vector<ScRangeData*> aItemsToErase;
743 // Indices in m_pRangeName start at 1
744 for (size_t i = 1; i <= m_pRangeName->size(); ++i)
746 ScRangeData* pData = m_pRangeName->findByIndex(i);
747 if (pData && pData->GetName().startsWith("solver_"))
748 aItemsToErase.push_back(pData);
751 for (auto pItem : aItemsToErase)
752 m_pRangeName->erase(*pItem);
755 /* Sets all solver parameters to their default values and clear all constraints.
756 * This method only resets the object properties, but does not save changes to the
757 * document. To save changes, call SaveSolverSettings().
759 void SolverSettings::ResetToDefaults()
761 m_sObjCell = "";
762 m_eObjType = ObjectiveType::OT_MAXIMIZE;
763 m_sObjVal = "";
764 m_sVariableCells = "";
765 m_sMSEngineId = "1";
767 css::uno::Sequence<OUString> aEngineNames;
768 css::uno::Sequence<OUString> aDescriptions;
769 ScSolverUtil::GetImplementations(aEngineNames, aDescriptions);
771 // tdf#162760 Set the parameters of all available solver engines to the default values
772 for (const auto& sEngine : aEngineNames)
774 css::uno::Sequence<css::beans::PropertyValue> aEngineProps
775 = ScSolverUtil::GetDefaults(sEngine);
776 SetEngineOptions(aEngineProps);
779 // The default solver engine is the first implementation available
780 m_sLOEngineName = aEngineNames[0];
782 // Clear all constraints
783 m_aConstraints.clear();
786 /* Returns true if the current sheet already has a solver model.
787 This is determined by checking if the current tab has the SP_OBJ_CELL named range
788 which is associated with solver models.
789 Note that the named ranges are only created after SaveSolverSettings is called,
790 so before it is called, no solver-related named ranges exist.
792 bool SolverSettings::TabHasSolverModel()
794 // Check if the named range for the objective value exists in the sheet
795 const auto iter = m_mNamedRanges.find(SP_OBJ_CELL);
796 if (iter == m_mNamedRanges.end())
797 return false;
798 OUString sRange = iter->second;
799 ScRangeData* pRangeData
800 = m_pRangeName->findByUpperName(ScGlobal::getCharClass().uppercase(sRange));
801 if (pRangeData)
802 return true;
803 return false;
806 } // namespace sc
808 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */