LibreOffice Module sc (master) 1
optsolver.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <rangelst.hxx>
21#include <sfx2/bindings.hxx>
22#include <svl/numformat.hxx>
23#include <utility>
25#include <vcl/weld.hxx>
26#include <vcl/svapp.hxx>
27
28#include <reffact.hxx>
29#include <docsh.hxx>
30#include <docfunc.hxx>
31#include <rangeutl.hxx>
32#include <convuno.hxx>
33#include <unonames.hxx>
34#include <solveroptions.hxx>
35#include <solverutil.hxx>
36#include <globstr.hrc>
37#include <scresid.hxx>
39#include <optsolver.hxx>
40#include <table.hxx>
41
42#include <com/sun/star/sheet/SolverConstraint.hpp>
43#include <com/sun/star/sheet/SolverConstraintOperator.hpp>
44#include <com/sun/star/sheet/XSolverDescription.hpp>
45#include <com/sun/star/sheet/XSolver.hpp>
46
47using namespace com::sun::star;
48
50 : GenericDialogController(pParent, "modules/scalc/ui/solverprogressdialog.ui",
51 "SolverProgressDialog")
52 , m_xFtTime(m_xBuilder->weld_label("progress"))
53{
54}
55
57{
58}
59
61{
62 m_xFtTime->hide();
63}
64
65void ScSolverProgressDialog::SetTimeLimit( sal_Int32 nSeconds )
66{
67 OUString aOld = m_xFtTime->get_label();
68 OUString aNew = aOld.replaceFirst("#", OUString::number(nSeconds));
69 m_xFtTime->set_label(aNew);
70}
71
73 : GenericDialogController(pParent, "modules/scalc/ui/nosolutiondialog.ui", "NoSolutionDialog")
74 , m_xFtErrorText(m_xBuilder->weld_label("error"))
75{
76 m_xFtErrorText->set_label(rErrorText);
77}
78
80{
81}
82
83ScSolverSuccessDialog::ScSolverSuccessDialog(weld::Window* pParent, std::u16string_view rSolution)
84 : GenericDialogController(pParent, "modules/scalc/ui/solversuccessdialog.ui", "SolverSuccessDialog")
85 , m_xFtResult(m_xBuilder->weld_label("result"))
86 , m_xBtnOk(m_xBuilder->weld_button("ok"))
87 , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
88{
89 m_xBtnOk->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
90 m_xBtnCancel->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
91 OUString aMessage = m_xFtResult->get_label() + " " + rSolution;
92 m_xFtResult->set_label(aMessage);
93}
94
96{
97}
98
100{
101 if (&rBtn == m_xBtnOk.get())
102 m_xDialog->response(RET_OK);
103 else
104 m_xDialog->response(RET_CANCEL);
105}
106
107ScCursorRefEdit::ScCursorRefEdit(std::unique_ptr<weld::Entry> xControl)
108 : formula::RefEdit(std::move(xControl))
109{
110 xEntry->connect_key_press(Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
111 xEntry->connect_key_press(LINK(this, ScCursorRefEdit, KeyInputHdl));
112}
113
115{
116 maCursorUpLink = rUp;
117 maCursorDownLink = rDown;
118}
119
120IMPL_LINK(ScCursorRefEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
121{
122 vcl::KeyCode aCode = rKEvt.GetKeyCode();
123 bool bUp = (aCode.GetCode() == KEY_UP);
124 bool bDown = (aCode.GetCode() == KEY_DOWN);
125 if ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() && ( bUp || bDown ) )
126 {
127 if ( bUp )
128 maCursorUpLink.Call( *this );
129 else
130 maCursorDownLink.Call( *this );
131 return true;
132 }
133 return formula::RefEdit::KeyInput(rKEvt);
134}
135
137 ScDocShell* pDocSh, const ScAddress& aCursorPos)
138 : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/solverdlg.ui", "SolverDialog")
139 , maInputError(ScResId(STR_INVALIDINPUT))
140 , maConditionError(ScResId(STR_INVALIDCONDITION))
141
142 , mpDocShell(pDocSh)
143 , mrDoc(pDocSh->GetDocument())
144 , mnCurTab(aCursorPos.Tab())
145 , mbDlgLostFocus(false)
146 , nScrollPos(0)
147 , mpEdActive(nullptr)
148 , m_xFtObjectiveCell(m_xBuilder->weld_label("targetlabel"))
149 , m_xEdObjectiveCell(new formula::RefEdit(m_xBuilder->weld_entry("targetedit")))
150 , m_xRBObjectiveCell(new formula::RefButton(m_xBuilder->weld_button("targetbutton")))
151 , m_xRbMax(m_xBuilder->weld_radio_button("max"))
152 , m_xRbMin(m_xBuilder->weld_radio_button("min"))
153 , m_xRbValue(m_xBuilder->weld_radio_button("value"))
154 , m_xEdTargetValue(new formula::RefEdit(m_xBuilder->weld_entry("valueedit")))
155 , m_xRBTargetValue(new formula::RefButton(m_xBuilder->weld_button("valuebutton")))
156 , m_xFtVariableCells(m_xBuilder->weld_label("changelabel"))
157 , m_xEdVariableCells(new formula::RefEdit(m_xBuilder->weld_entry("changeedit")))
158 , m_xRBVariableCells(new formula::RefButton(m_xBuilder->weld_button("changebutton")))
159 , m_xFtCellRef(m_xBuilder->weld_label("cellreflabel"))
160 , m_xEdLeft1(new ScCursorRefEdit(m_xBuilder->weld_entry("ref1edit")))
161 , m_xRBLeft1(new formula::RefButton(m_xBuilder->weld_button("ref1button")))
162 , m_xLbOp1(m_xBuilder->weld_combo_box("op1list"))
163 , m_xFtConstraint(m_xBuilder->weld_label("constraintlabel"))
164 , m_xEdRight1(new ScCursorRefEdit(m_xBuilder->weld_entry("val1edit")))
165 , m_xRBRight1(new formula::RefButton(m_xBuilder->weld_button("val1button")))
166 , m_xBtnDel1(m_xBuilder->weld_button("del1"))
167 , m_xEdLeft2(new ScCursorRefEdit(m_xBuilder->weld_entry("ref2edit")))
168 , m_xRBLeft2(new formula::RefButton(m_xBuilder->weld_button("ref2button")))
169 , m_xLbOp2(m_xBuilder->weld_combo_box("op2list"))
170 , m_xEdRight2(new ScCursorRefEdit(m_xBuilder->weld_entry("val2edit")))
171 , m_xRBRight2(new formula::RefButton(m_xBuilder->weld_button("val2button")))
172 , m_xBtnDel2(m_xBuilder->weld_button("del2"))
173 , m_xEdLeft3(new ScCursorRefEdit(m_xBuilder->weld_entry("ref3edit")))
174 , m_xRBLeft3(new formula::RefButton(m_xBuilder->weld_button("ref3button")))
175 , m_xLbOp3(m_xBuilder->weld_combo_box("op3list"))
176 , m_xEdRight3(new ScCursorRefEdit(m_xBuilder->weld_entry("val3edit")))
177 , m_xRBRight3(new formula::RefButton(m_xBuilder->weld_button("val3button")))
178 , m_xBtnDel3(m_xBuilder->weld_button("del3"))
179 , m_xEdLeft4(new ScCursorRefEdit(m_xBuilder->weld_entry("ref4edit")))
180 , m_xRBLeft4(new formula::RefButton(m_xBuilder->weld_button("ref4button")))
181 , m_xLbOp4(m_xBuilder->weld_combo_box("op4list"))
182 , m_xEdRight4(new ScCursorRefEdit(m_xBuilder->weld_entry("val4edit")))
183 , m_xRBRight4(new formula::RefButton(m_xBuilder->weld_button("val4button")))
184 , m_xBtnDel4(m_xBuilder->weld_button("del4"))
185 , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar", true))
186 , m_xBtnOpt(m_xBuilder->weld_button("options"))
187 , m_xBtnClose(m_xBuilder->weld_button("close"))
188 , m_xBtnSolve(m_xBuilder->weld_button("ok"))
189 , m_xBtnResetAll(m_xBuilder->weld_button("resetall"))
190 , m_xResultFT(m_xBuilder->weld_label("result"))
191 , m_xContents(m_xBuilder->weld_widget("grid"))
192 , m_pSolverSettings(mrDoc.FetchTable(mnCurTab)->GetSolverSettings())
193{
194 m_xEdObjectiveCell->SetReferences(this, m_xFtObjectiveCell.get());
195 m_xRBObjectiveCell->SetReferences(this, m_xEdObjectiveCell.get());
196 m_xEdTargetValue->SetReferences(this, m_xResultFT.get());
197 m_xRBTargetValue->SetReferences(this, m_xEdTargetValue.get());
198 m_xEdVariableCells->SetReferences(this, m_xFtVariableCells.get());
199 m_xRBVariableCells->SetReferences(this, m_xEdVariableCells.get());
200 m_xEdLeft1->SetReferences(this, m_xFtCellRef.get());
201 m_xRBLeft1->SetReferences(this, m_xEdLeft1.get());
202 m_xEdRight1->SetReferences(this, m_xFtConstraint.get());
203 m_xRBRight1->SetReferences(this, m_xEdRight1.get());
204 m_xEdLeft2->SetReferences(this, m_xFtCellRef.get());
205 m_xRBLeft2->SetReferences(this, m_xEdLeft2.get());
206 m_xEdRight2->SetReferences(this, m_xFtConstraint.get());
207 m_xRBRight2->SetReferences(this, m_xEdRight2.get());
208 m_xEdLeft3->SetReferences(this, m_xFtCellRef.get());
209 m_xRBLeft3->SetReferences(this, m_xEdLeft3.get());
210 m_xEdRight3->SetReferences(this, m_xFtConstraint.get());
211 m_xRBRight3->SetReferences(this, m_xEdRight3.get());
212 m_xEdLeft4->SetReferences(this, m_xFtCellRef.get());
213 m_xRBLeft4->SetReferences(this, m_xEdLeft4.get());
214 m_xEdRight4->SetReferences(this, m_xFtConstraint.get());
215 m_xRBRight4->SetReferences(this, m_xEdRight4.get());
216
217 mpLeftEdit[0] = m_xEdLeft1.get();
218 mpLeftButton[0] = m_xRBLeft1.get();
219 mpRightEdit[0] = m_xEdRight1.get();
220 mpRightButton[0] = m_xRBRight1.get();
221 mpOperator[0] = m_xLbOp1.get();
222 mpDelButton[0] = m_xBtnDel1.get();
223
224 mpLeftEdit[1] = m_xEdLeft2.get();
225 mpLeftButton[1] = m_xRBLeft2.get();
226 mpRightEdit[1] = m_xEdRight2.get();
227 mpRightButton[1] = m_xRBRight2.get();
228 mpOperator[1] = m_xLbOp2.get();
229 mpDelButton[1] = m_xBtnDel2.get();
230
231 mpLeftEdit[2] = m_xEdLeft3.get();
232 mpLeftButton[2] = m_xRBLeft3.get();
233 mpRightEdit[2] = m_xEdRight3.get();
234 mpRightButton[2] = m_xRBRight3.get();
235 mpOperator[2] = m_xLbOp3.get();
236 mpDelButton[2] = m_xBtnDel3.get();
237
238 mpLeftEdit[3] = m_xEdLeft4.get();
239 mpLeftButton[3] = m_xRBLeft4.get();
240 mpRightEdit[3] = m_xEdRight4.get();
241 mpRightButton[3] = m_xRBRight4.get();
242 mpOperator[3] = m_xLbOp4.get();
243 mpDelButton[3] = m_xBtnDel4.get();
244
245 Init( aCursorPos );
246}
247
249{
250}
251
252void ScOptSolverDlg::Init(const ScAddress& rCursorPos)
253{
254 uno::Reference<frame::XFrame> xFrame = GetBindings().GetActiveFrame();
255 auto xDelNm = vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:DeleteRows", xFrame);
256 for (weld::Button* pButton : mpDelButton)
257 pButton->set_image(xDelNm);
258
259 m_xBtnOpt->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
260 m_xBtnClose->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
261 m_xBtnSolve->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
262 m_xBtnResetAll->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
263
264 Link<formula::RefEdit&,void> aEditLink = LINK( this, ScOptSolverDlg, GetEditFocusHdl );
265 Link<formula::RefButton&,void> aButtonLink = LINK( this, ScOptSolverDlg, GetButtonFocusHdl );
266 m_xEdObjectiveCell->SetGetFocusHdl( aEditLink );
267 m_xRBObjectiveCell->SetGetFocusHdl( aButtonLink );
268 m_xEdTargetValue->SetGetFocusHdl( aEditLink );
269 m_xRBTargetValue->SetGetFocusHdl( aButtonLink );
270 m_xEdVariableCells->SetGetFocusHdl( aEditLink );
271 m_xRBVariableCells->SetGetFocusHdl( aButtonLink );
272 Link<weld::Widget&,void> aLink = LINK(this, ScOptSolverDlg, GetFocusHdl);
273 m_xRbValue->connect_focus_in(aLink);
274 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
275 {
276 mpLeftEdit[nRow]->SetGetFocusHdl( aEditLink );
277 mpLeftButton[nRow]->SetGetFocusHdl( aButtonLink );
278 mpRightEdit[nRow]->SetGetFocusHdl( aEditLink );
279 mpRightButton[nRow]->SetGetFocusHdl( aButtonLink );
280 mpOperator[nRow]->connect_focus_in(aLink);
281 }
282
283 aEditLink = LINK( this, ScOptSolverDlg, LoseEditFocusHdl );
284 aButtonLink = LINK( this, ScOptSolverDlg, LoseButtonFocusHdl );
285 m_xEdObjectiveCell->SetLoseFocusHdl( aEditLink );
286 m_xRBObjectiveCell->SetLoseFocusHdl( aButtonLink );
287 m_xEdTargetValue->SetLoseFocusHdl( aEditLink );
288 m_xRBTargetValue-> SetLoseFocusHdl( aButtonLink );
289 m_xEdVariableCells->SetLoseFocusHdl( aEditLink );
290 m_xRBVariableCells->SetLoseFocusHdl( aButtonLink );
291 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
292 {
293 mpLeftEdit[nRow]->SetLoseFocusHdl( aEditLink );
294 mpLeftButton[nRow]->SetLoseFocusHdl( aButtonLink );
295 mpRightEdit[nRow]->SetLoseFocusHdl( aEditLink );
296 mpRightButton[nRow]->SetLoseFocusHdl( aButtonLink );
297 }
298
299 Link<ScCursorRefEdit&,void> aCursorUp = LINK( this, ScOptSolverDlg, CursorUpHdl );
300 Link<ScCursorRefEdit&,void> aCursorDown = LINK( this, ScOptSolverDlg, CursorDownHdl );
301 Link<formula::RefEdit&,void> aCondModify = LINK( this, ScOptSolverDlg, CondModifyHdl );
302 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
303 {
304 mpLeftEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
305 mpRightEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
306 mpLeftEdit[nRow]->SetModifyHdl( aCondModify );
307 mpRightEdit[nRow]->SetModifyHdl( aCondModify );
308 mpDelButton[nRow]->connect_clicked( LINK( this, ScOptSolverDlg, DelBtnHdl ) );
309 mpOperator[nRow]->connect_changed( LINK( this, ScOptSolverDlg, SelectHdl ) );
310 }
311 m_xEdTargetValue->SetModifyHdl( LINK( this, ScOptSolverDlg, TargetModifyHdl ) );
312
313 Size aSize(m_xContents->get_preferred_size());
314 m_xContents->set_size_request(aSize.Width(), aSize.Height());
315 m_xScrollBar->connect_vadjustment_changed( LINK( this, ScOptSolverDlg, ScrollHdl ) );
316
317 m_xScrollBar->vadjustment_set_page_increment( EDIT_ROW_COUNT );
318 m_xScrollBar->vadjustment_set_page_size( EDIT_ROW_COUNT );
319 // Range is set in ShowConditions
320
321 // get available solver implementations
324
325 // Load existing settings stored in the tab
328
329 // If no objective cell has been loaded, then use the selected cell
330 if (m_xEdObjectiveCell->GetText().isEmpty())
331 {
332 OUString aCursorStr;
333 if (!mrDoc.GetRangeAtBlock(ScRange(rCursorPos), aCursorStr))
334 aCursorStr = rCursorPos.Format(ScRefFlags::ADDR_ABS, nullptr, mrDoc.GetAddressConvention());
335 m_xEdObjectiveCell->SetRefString(aCursorStr);
336 }
337
338 m_xEdObjectiveCell->GrabFocus();
340}
341
343{
344 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
345 {
346 sc::ModelConstraint aRowEntry;
347 aRowEntry.aLeftStr = mpLeftEdit[nRow]->GetText();
348 aRowEntry.aRightStr = mpRightEdit[nRow]->GetText();
349 aRowEntry.nOperator = OperatorIndexToConstraintOperator(mpOperator[nRow]->get_active());
350
351 tools::Long nVecPos = nScrollPos + nRow;
352 if ( nVecPos >= static_cast<tools::Long>(m_aConditions.size()) && !aRowEntry.IsDefault() )
353 m_aConditions.resize( nVecPos + 1 );
354
355 if ( nVecPos < static_cast<tools::Long>(m_aConditions.size()) )
356 m_aConditions[nVecPos] = aRowEntry;
357
358 // remove default entries at the end
359 size_t nSize = m_aConditions.size();
360 while ( nSize > 0 && m_aConditions[ nSize-1 ].IsDefault() )
361 --nSize;
362 m_aConditions.resize( nSize );
363 }
364}
365
367{
368 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
369 {
370 sc::ModelConstraint aRowEntry;
371
372 tools::Long nVecPos = nScrollPos + nRow;
373 if ( nVecPos < static_cast<tools::Long>(m_aConditions.size()) )
374 aRowEntry = m_aConditions[nVecPos];
375
376 mpLeftEdit[nRow]->SetRefString( aRowEntry.aLeftStr );
377 mpRightEdit[nRow]->SetRefString( aRowEntry.aRightStr );
378 mpOperator[nRow]->set_active( aRowEntry.nOperator - 1);
379 }
380
381 // allow to scroll one page behind the visible or stored rows
383 tools::Long nMax = std::max( nVisible, static_cast<tools::Long>(m_aConditions.size()) );
384 m_xScrollBar->vadjustment_configure(nScrollPos, 0, nMax + EDIT_ROW_COUNT, 1,
386
388}
389
391{
392 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
393 {
394 tools::Long nVecPos = nScrollPos + nRow;
395 mpDelButton[nRow]->set_sensitive(nVecPos < static_cast<tools::Long>(m_aConditions.size()));
396 }
397}
398
400{
401 if (m_xOptDlg)
402 m_xOptDlg->response(RET_CANCEL);
403 assert(!m_xOptDlg);
404 DoClose( ScOptSolverDlgWrapper::GetChildWindowId() );
405}
406
408{
409 if ( mbDlgLostFocus )
410 {
411 mbDlgLostFocus = false;
412 if( mpEdActive )
414 }
415 else
416 {
417 m_xDialog->grab_focus();
418 }
419 RefInputDone();
420}
421
423{
424 if( !mpEdActive )
425 return;
426
427 if ( rRef.aStart != rRef.aEnd )
429
430 // "target"/"value": single cell
431 bool bSingle = ( mpEdActive == m_xEdObjectiveCell.get() || mpEdActive == m_xEdTargetValue.get() );
432
433 OUString aStr;
434 ScAddress aAdr = rRef.aStart;
435 ScRange aNewRef( rRef );
436 if ( bSingle )
437 aNewRef.aEnd = aAdr;
438
439 OUString aName;
440 if ( rDocP.GetRangeAtBlock( aNewRef, aName ) ) // named range: show name
441 aStr = aName;
442 else // format cell/range reference
443 {
445 if ( bSingle )
446 aStr = aAdr.Format(nFmt, &rDocP, rDocP.GetAddressConvention());
447 else
448 aStr = rRef.Format(rDocP, nFmt | ScRefFlags::RANGE_ABS, rDocP.GetAddressConvention());
449 }
450
451 // variable cells can be several ranges, so only the selection is replaced
452 if ( mpEdActive == m_xEdVariableCells.get() )
453 {
454 OUString aVal = mpEdActive->GetText();
456 aSel.Normalize();
457 aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
458 Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
459 mpEdActive->SetRefString( aVal );
460 mpEdActive->SetSelection( aNewSel );
461 }
462 else
464
467
468 // select "Value of" if a ref is input into "target" edit
469 if ( mpEdActive == m_xEdTargetValue.get() )
470 m_xRbValue->set_active(true);
471}
472
474{
475 return mpEdActive != nullptr;
476}
477
478// Loads solver settings into the dialog
480{
481 m_xEdObjectiveCell->SetRefString(m_pSolverSettings->GetParameter(sc::SP_OBJ_CELL));
482 m_xEdTargetValue->SetRefString(m_pSolverSettings->GetParameter(sc::SP_OBJ_VAL));
483 m_xEdVariableCells->SetRefString(m_pSolverSettings->GetParameter(sc::SP_VAR_CELLS));
484
485 // Objective type
486 sc::ObjectiveType eType = m_pSolverSettings->GetObjectiveType();
487 switch (eType)
488 {
489 case sc::OT_MAXIMIZE : m_xRbMax->set_active(true); break;
490 case sc::OT_MINIMIZE : m_xRbMin->set_active(true); break;
491 case sc::OT_VALUE : m_xRbValue->set_active(true); break;
492 }
493
494 // Model constraints
495 m_aConditions = m_pSolverSettings->GetConstraints();
496
497 // Loads solver engine name
498 // If the solver engine in the current settings are not supported, use the first available
501 {
504 }
505
506 // Query current engine options
508 m_pSolverSettings->GetEngineOptions(maProperties);
509}
510
511// Set solver settings and save them
513{
514 m_pSolverSettings->SetParameter(sc::SP_OBJ_CELL, m_xEdObjectiveCell->GetText());
515 m_pSolverSettings->SetParameter(sc::SP_OBJ_VAL, m_xEdTargetValue->GetText());
516 m_pSolverSettings->SetParameter(sc::SP_VAR_CELLS, m_xEdVariableCells->GetText());
517
518 // Objective type
519 if (m_xRbMax->get_active())
520 m_pSolverSettings->SetObjectiveType(sc::OT_MAXIMIZE);
521 else if (m_xRbMin->get_active())
522 m_pSolverSettings->SetObjectiveType(sc::OT_MINIMIZE);
523 else if (m_xRbValue->get_active())
524 m_pSolverSettings->SetObjectiveType(sc::OT_VALUE);
525
526 // Model constraints
527 m_pSolverSettings->SetConstraints(m_aConditions);
528
529 // Solver engine name
531
532 // Solver engine options
533 m_pSolverSettings->SetEngineOptions(maProperties);
534
535 // Effectively save settings to file
536 m_pSolverSettings->SaveSolverSettings();
537}
538
539// Test if a LO engine implementation exists
540bool ScOptSolverDlg::IsEngineAvailable(std::u16string_view sEngineName)
541{
542 auto nIndex = comphelper::findValue(maImplNames, sEngineName);
543 return nIndex != -1;
544}
545
546// Handler:
547
549{
550 auto xKeepAlive = shared_from_this();
551 if (&rBtn == m_xBtnSolve.get() || &rBtn == m_xBtnClose.get())
552 {
553 bool bSolve = ( &rBtn == m_xBtnSolve.get() );
554
555 SetDispatcherLock( false );
556 SwitchToDocument();
557
558 bool bClose = true;
559 if ( bSolve )
560 bClose = CallSolver();
561
562 if ( bClose )
563 {
564 // Close: write dialog settings to DocShell for subsequent calls
565 ReadConditions();
566 SaveSolverSettings();
567 response(RET_CLOSE);
568 }
569 else
570 {
571 // no solution -> dialog is kept open
572 SetDispatcherLock( true );
573 }
574 }
575 else if (&rBtn == m_xBtnOpt.get())
576 {
578 m_xOptDlg = std::make_shared<ScSolverOptionsDialog>(m_xDialog.get(), maImplNames, maDescriptions, maEngine, maProperties);
579 weld::DialogController::runAsync(m_xOptDlg, [this](sal_Int32 nResult){
580 if (nResult == RET_OK)
581 {
582 maEngine = m_xOptDlg->GetEngine();
583 maProperties = m_xOptDlg->GetProperties();
584 }
585 m_xOptDlg.reset();
586 });
587 }
588 else if (&rBtn == m_xBtnResetAll.get())
589 {
590 OUString sEmpty;
591 m_xEdObjectiveCell->SetText(sEmpty);
592 m_xEdTargetValue->SetText(sEmpty);
593 m_xEdVariableCells->SetText(sEmpty);
594
595 // Get default property values of solver implementations
596 maEngine = maImplNames[0];
598
599 // Clear all conditions (Constraints)
600 m_aConditions.clear();
601 ShowConditions();
602
603 m_xRbMax->set_active(true);
604 m_xEdObjectiveCell->GrabFocus();
605 mpEdActive = m_xEdObjectiveCell.get();
606 }
607}
608
609IMPL_LINK( ScOptSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
610{
611 formula::RefEdit* pEdit = nullptr;
612 mpEdActive = nullptr;
613
614 if( &rCtrl == m_xEdObjectiveCell.get() )
615 pEdit = mpEdActive = m_xEdObjectiveCell.get();
616 else if( &rCtrl == m_xEdTargetValue.get() )
617 pEdit = mpEdActive = m_xEdTargetValue.get();
618 else if( &rCtrl == m_xEdVariableCells.get() )
619 pEdit = mpEdActive = m_xEdVariableCells.get();
620 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
621 {
622 if( &rCtrl == mpLeftEdit[nRow] )
623 pEdit = mpEdActive = mpLeftEdit[nRow];
624 else if( &rCtrl == mpRightEdit[nRow] )
625 pEdit = mpEdActive = mpRightEdit[nRow];
626 }
627
628 if( pEdit )
629 pEdit->SelectAll();
630}
631
632IMPL_LINK( ScOptSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
633{
634 formula::RefEdit* pEdit = nullptr;
635 mpEdActive = nullptr;
636
637 if( &rCtrl == m_xRBObjectiveCell.get() )
638 pEdit = mpEdActive = m_xEdObjectiveCell.get();
639 else if( &rCtrl == m_xRBTargetValue.get() )
640 pEdit = mpEdActive = m_xEdTargetValue.get();
641 else if( &rCtrl == m_xRBVariableCells.get() )
642 pEdit = mpEdActive = m_xEdVariableCells.get();
643 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
644 {
645 if( &rCtrl == mpLeftButton[nRow] )
646 pEdit = mpEdActive = mpLeftEdit[nRow];
647 else if( &rCtrl == mpRightButton[nRow] )
648 pEdit = mpEdActive = mpRightEdit[nRow];
649 }
650
651 if( pEdit )
652 pEdit->SelectAll();
653}
654
655
656IMPL_LINK(ScOptSolverDlg, GetFocusHdl, weld::Widget&, rCtrl, void)
657{
658 if( &rCtrl == m_xRbValue.get() ) // focus on "Value of" radio button
659 mpEdActive = m_xEdTargetValue.get(); // use value edit for ref input, but don't change selection
660 else
661 {
662 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
663 {
664 if( &rCtrl == mpOperator[nRow] ) // focus on "operator" list box
665 mpEdActive = mpRightEdit[nRow]; // use right edit for ref input, but don't change selection
666 }
667 }
668}
669
671{
672 mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
673}
674
676{
677 mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
678}
679
680IMPL_LINK(ScOptSolverDlg, DelBtnHdl, weld::Button&, rBtn, void)
681{
682 for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
683 if (&rBtn == mpDelButton[nRow])
684 {
685 bool bHadFocus = rBtn.has_focus();
686
687 ReadConditions();
688 tools::Long nVecPos = nScrollPos + nRow;
689 if ( nVecPos < static_cast<tools::Long>(m_aConditions.size()) )
690 {
691 m_aConditions.erase( m_aConditions.begin() + nVecPos );
692 ShowConditions();
693
694 if ( bHadFocus && !rBtn.get_sensitive() )
695 {
696 // If the button is disabled, focus would normally move to the next control,
697 // (left edit of the next row). Move it to left edit of this row instead.
698
699 mpEdActive = mpLeftEdit[nRow];
700 mpEdActive->GrabFocus();
701 }
702 }
703 }
704}
705
707{
708 // modify handler for the target edit:
709 // select "Value of" if something is input into the edit
710 if ( !m_xEdTargetValue->GetText().isEmpty() )
711 m_xRbValue->set_active(true);
712}
713
715{
716 // modify handler for the condition edits, just to enable/disable "delete" buttons
717 ReadConditions();
718 EnableButtons();
719}
720
722{
723 // select handler for operator list boxes, just to enable/disable "delete" buttons
724 ReadConditions();
725 EnableButtons();
726}
727
729{
730 ReadConditions();
731 nScrollPos = m_xScrollBar->vadjustment_get_value();
732 ShowConditions();
733 if( mpEdActive )
734 mpEdActive->SelectAll();
735}
736
737IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit&, rEdit, void )
738{
739 if ( &rEdit == mpLeftEdit[0] || &rEdit == mpRightEdit[0] )
740 {
741 if ( nScrollPos > 0 )
742 {
743 ReadConditions();
744 --nScrollPos;
745 ShowConditions();
746 if( mpEdActive )
747 mpEdActive->SelectAll();
748 }
749 }
750 else
751 {
752 formula::RefEdit* pFocus = nullptr;
753 for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow ) // second row or below: move focus
754 {
755 if ( &rEdit == mpLeftEdit[nRow] )
756 pFocus = mpLeftEdit[nRow-1];
757 else if ( &rEdit == mpRightEdit[nRow] )
758 pFocus = mpRightEdit[nRow-1];
759 }
760 if (pFocus)
761 {
762 mpEdActive = pFocus;
763 pFocus->GrabFocus();
764 }
765 }
766}
767
768IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit&, rEdit, void )
769{
770 if ( &rEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || &rEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
771 {
773 ReadConditions();
774 ++nScrollPos;
775 ShowConditions();
776 if( mpEdActive )
777 mpEdActive->SelectAll();
778 }
779 else
780 {
781 formula::RefEdit* pFocus = nullptr;
782 for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow ) // before last row: move focus
783 {
784 if ( &rEdit == mpLeftEdit[nRow] )
785 pFocus = mpLeftEdit[nRow+1];
786 else if ( &rEdit == mpRightEdit[nRow] )
787 pFocus = mpRightEdit[nRow+1];
788 }
789 if (pFocus)
790 {
791 mpEdActive = pFocus;
792 pFocus->GrabFocus();
793 }
794 }
795}
796
797// Converts the position of the operator in the dropdown menu to a ConstraintOperator type
799{
800 switch(nIndex)
801 {
802 case 0 : return sc::CO_LESS_EQUAL; break;
803 case 1 : return sc::CO_EQUAL; break;
804 case 2 : return sc::CO_GREATER_EQUAL; break;
805 case 3 : return sc::CO_INTEGER; break;
806 case 4 : return sc::CO_BINARY; break;
807 default : return sc::CO_LESS_EQUAL; break;
808 }
809}
810
811void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
812{
813 OUString aMessage = bCondition ? maConditionError : maInputError;
814 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
815 VclMessageType::Warning, VclButtonsType::Ok,
816 aMessage));
817 xBox->run();
818 if (pFocus)
819 {
820 mpEdActive = pFocus;
821 pFocus->GrabFocus();
822 }
823}
824
825bool ScOptSolverDlg::ParseRef( ScRange& rRange, const OUString& rInput, bool bAllowRange )
826{
828 ScRefFlags nFlags = rRange.ParseAny( rInput, mrDoc, aDetails );
829 if ( nFlags & ScRefFlags::VALID )
830 {
831 if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO)
832 rRange.aStart.SetTab( mnCurTab );
833 if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO)
834 rRange.aEnd.SetTab( rRange.aStart.Tab() );
835 return ( bAllowRange || rRange.aStart == rRange.aEnd );
836 }
837 else if ( ScRangeUtil::MakeRangeFromName( rInput, mrDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
838 return ( bAllowRange || rRange.aStart == rRange.aEnd );
839
840 return false; // not recognized
841}
842
843bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
844{
845 bool bFound = false;
846
847 if ( !maProperties.hasElements() )
848 maProperties = ScSolverUtil::GetDefaults( maEngine ); // get property defaults from component
849
850 sal_Int32 nPropCount = maProperties.getLength();
851 for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
852 {
853 const beans::PropertyValue& rValue = maProperties[nProp];
854 if ( rValue.Name == SC_UNONAME_TIMEOUT )
855 bFound = ( rValue.Value >>= rTimeout );
856 }
857 return bFound;
858}
859
860bool ScOptSolverDlg::CallSolver() // return true -> close dialog after calling
861{
862 // show progress dialog
863
864 auto xProgress = std::make_shared<ScSolverProgressDialog>(m_xDialog.get());
865 sal_Int32 nTimeout = 0;
866 if ( FindTimeout( nTimeout ) )
867 xProgress->SetTimeLimit( nTimeout );
868 else
869 xProgress->HideTimeLimit();
870
871 weld::DialogController::runAsync(xProgress, [](sal_Int32 /*nResult*/){});
872
873 // try to make sure the progress dialog is painted before continuing
875
876 // collect solver parameters
877
879
881
882 ScRange aObjRange;
883 if ( !ParseRef( aObjRange, m_xEdObjectiveCell->GetText(), false ) )
884 {
885 ShowError( false, m_xEdObjectiveCell.get() );
886 return false;
887 }
888 table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
889
890 // "changing cells" can be several ranges
891 ScRangeList aVarRanges;
892 if ( !ParseWithNames( aVarRanges, m_xEdVariableCells->GetText(), mrDoc ) )
893 {
894 ShowError( false, m_xEdVariableCells.get() );
895 return false;
896 }
897 uno::Sequence<table::CellAddress> aVariables;
898 sal_Int32 nVarPos = 0;
899
900 for ( size_t nRangePos=0, nRange = aVarRanges.size(); nRangePos < nRange; ++nRangePos )
901 {
902 ScRange aRange( aVarRanges[ nRangePos ] );
903 aRange.PutInOrder();
904 SCTAB nTab = aRange.aStart.Tab();
905
906 // resolve into single cells
907
908 sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
909 ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
910 aVariables.realloc( nVarPos + nAdd );
911 auto pVariables = aVariables.getArray();
912
913 for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
914 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
915 pVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
916 }
917
918 uno::Sequence<sheet::SolverConstraint> aConstraints;
919 sal_Int32 nConstrPos = 0;
920 for ( const auto& rConstr : m_aConditions )
921 {
922 if ( !rConstr.aLeftStr.isEmpty() )
923 {
924 sheet::SolverConstraint aConstraint;
925 // Order of list box entries must match enum values.
926 // The enum SolverConstraintOperator starts at zero, whereas ConstraintOperator starts at 1
927 // hence we need to subtract -1 here
928 aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(rConstr.nOperator - 1);
929
930 ScRange aLeftRange;
931 if ( !ParseRef( aLeftRange, rConstr.aLeftStr, true ) )
932 {
933 ShowError( true, nullptr );
934 return false;
935 }
936
937 bool bIsRange = false;
938 ScRange aRightRange;
939 if ( ParseRef( aRightRange, rConstr.aRightStr, true ) )
940 {
941 if ( aRightRange.aStart == aRightRange.aEnd )
942 aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
943 aRightRange.aStart.Col(), aRightRange.aStart.Row() );
944 else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
945 aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
946 bIsRange = true; // same size as "left" range, resolve into single cells
947 else
948 {
949 ShowError( true, nullptr );
950 return false;
951 }
952 }
953 else
954 {
955 sal_uInt32 nFormat = 0;
956 double fValue = 0.0;
957 if ( mrDoc.GetFormatTable()->IsNumberFormat( rConstr.aRightStr, nFormat, fValue ) )
958 aConstraint.Right <<= fValue;
959 else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
960 aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
961 {
962 ShowError( true, nullptr );
963 return false;
964 }
965 }
966
967 // resolve into single cells
968
969 sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
970 ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
971 aConstraints.realloc( nConstrPos + nAdd );
972 auto pConstraints = aConstraints.getArray();
973
974 for (SCROW nRow = aLeftRange.aStart.Row(); nRow <= aLeftRange.aEnd.Row(); ++nRow)
975 for (SCCOL nCol = aLeftRange.aStart.Col(); nCol <= aLeftRange.aEnd.Col(); ++nCol)
976 {
977 aConstraint.Left = table::CellAddress( aLeftRange.aStart.Tab(), nCol, nRow );
978 if ( bIsRange )
979 aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
980 aRightRange.aStart.Col() + ( nCol - aLeftRange.aStart.Col() ),
981 aRightRange.aStart.Row() + ( nRow - aLeftRange.aStart.Row() ) );
982
983 pConstraints[nConstrPos++] = aConstraint;
984 }
985 }
986 }
987
988 bool bMaximize = m_xRbMax->get_active();
989 if ( m_xRbValue->get_active() )
990 {
991 // handle "value of" with an additional constraint (and then minimize)
992
993 sheet::SolverConstraint aConstraint;
994 aConstraint.Left = aObjective;
995 aConstraint.Operator = sheet::SolverConstraintOperator_EQUAL;
996
997 OUString aValStr = m_xEdTargetValue->GetText();
998 ScRange aRightRange;
999 if ( ParseRef( aRightRange, aValStr, false ) )
1000 aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
1001 aRightRange.aStart.Col(), aRightRange.aStart.Row() );
1002 else
1003 {
1004 sal_uInt32 nFormat = 0;
1005 double fValue = 0.0;
1006 if ( mrDoc.GetFormatTable()->IsNumberFormat( aValStr, nFormat, fValue ) )
1007 aConstraint.Right <<= fValue;
1008 else
1009 {
1010 ShowError( false, m_xEdTargetValue.get() );
1011 return false;
1012 }
1013 }
1014
1015 aConstraints.realloc( nConstrPos + 1 );
1016 aConstraints.getArray()[nConstrPos++] = aConstraint;
1017 }
1018
1019 // copy old document values
1020
1021 sal_Int32 nVarCount = aVariables.getLength();
1022 uno::Sequence<double> aOldValues( nVarCount );
1023 std::transform(std::cbegin(aVariables), std::cend(aVariables), aOldValues.getArray(),
1024 [this](const table::CellAddress& rVariable) -> double {
1025 ScAddress aCellPos;
1026 ScUnoConversion::FillScAddress( aCellPos, rVariable );
1027 return mrDoc.GetValue( aCellPos );
1028 });
1029
1030 // create and initialize solver
1031
1032 uno::Reference<sheet::XSolver> xSolver = ScSolverUtil::GetSolver( maEngine );
1033 OSL_ENSURE( xSolver.is(), "can't get solver component" );
1034 if ( !xSolver.is() )
1035 return false;
1036
1037 xSolver->setDocument( xDocument );
1038 xSolver->setObjective( aObjective );
1039 xSolver->setVariables( aVariables );
1040 xSolver->setConstraints( aConstraints );
1041 xSolver->setMaximize( bMaximize );
1042
1043 // set options
1044 uno::Reference<beans::XPropertySet> xOptProp(xSolver, uno::UNO_QUERY);
1045 if ( xOptProp.is() )
1046 {
1047 for (const beans::PropertyValue& rValue : std::as_const(maProperties))
1048 {
1049 try
1050 {
1051 xOptProp->setPropertyValue( rValue.Name, rValue.Value );
1052 }
1053 catch ( uno::Exception & )
1054 {
1055 OSL_FAIL("Exception in solver option property");
1056 }
1057 }
1058 }
1059
1060 xSolver->solve();
1061 bool bSuccess = xSolver->getSuccess();
1062
1063 xProgress->response(RET_CLOSE);
1064
1065 bool bClose = false;
1066 bool bRestore = true; // restore old values unless a solution is accepted
1067 if ( bSuccess )
1068 {
1069 // put solution into document so it is visible when asking
1070 uno::Sequence<double> aSolution = xSolver->getSolution();
1071 if ( aSolution.getLength() == nVarCount )
1072 {
1074 ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1075 for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1076 {
1077 ScAddress aCellPos;
1078 ScUnoConversion::FillScAddress( aCellPos, std::as_const(aVariables)[nVarPos] );
1079 rFunc.SetValueCell(aCellPos, aSolution[nVarPos], false);
1080 }
1082 }
1084
1085 // take formatted result from document (result value from component is ignored)
1086 OUString aResultStr = mrDoc.GetString(
1087 static_cast<SCCOL>(aObjective.Column), static_cast<SCROW>(aObjective.Row),
1088 static_cast<SCTAB>(aObjective.Sheet));
1089
1090 ScSolverSuccessDialog aDialog(m_xDialog.get(), aResultStr);
1091 if (aDialog.run() == RET_OK)
1092 {
1093 // keep results and close dialog
1094 bRestore = false;
1095 bClose = true;
1096 }
1097 }
1098 else
1099 {
1100 OUString aError;
1101 uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
1102 if ( xDesc.is() )
1103 aError = xDesc->getStatusDescription(); // error description from component
1104 ScSolverNoSolutionDialog aDialog(m_xDialog.get(), aError);
1105 aDialog.run();
1106 }
1107
1108 if ( bRestore ) // restore old values
1109 {
1111 ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1112 for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1113 {
1114 ScAddress aCellPos;
1115 ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1116 rFunc.SetValueCell(aCellPos, std::as_const(aOldValues)[nVarPos], false);
1117 }
1119 }
1120
1121 return bClose;
1122}
1123
1124/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScRefFlags
Definition: address.hxx:158
Reference< XExecutableDialog > m_xDialog
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static bool Reschedule(bool bHandleAllCurrentEvents=false)
SCTAB Tab() const
Definition: address.hxx:283
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
SCROW Row() const
Definition: address.hxx:274
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
SCCOL Col() const
Definition: address.hxx:279
void SetCursorLinks(const Link< ScCursorRefEdit &, void > &rUp, const Link< ScCursorRefEdit &, void > &rDown)
Definition: optsolver.cxx:114
Link< ScCursorRefEdit &, void > maCursorDownLink
Definition: optsolver.hxx:38
ScCursorRefEdit(std::unique_ptr< weld::Entry > xEntry)
Definition: optsolver.cxx:107
Link< ScCursorRefEdit &, void > maCursorUpLink
Definition: optsolver.hxx:37
bool SetValueCell(const ScAddress &rPos, double fVal, bool bInteraction)
Definition: docfunc.cxx:867
void UnlockPaint()
Definition: docsh3.cxx:322
void LockPaint()
Definition: docsh3.cxx:317
ScModelObj * GetModel() const
Definition: docsh.hxx:432
ScDocFunc & GetDocFunc()
Definition: docsh.hxx:221
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:492
SC_DLLPUBLIC const ScRangeData * GetRangeAtBlock(const ScRange &rBlock, OUString &rName, bool *pSheetLocal=nullptr) const
Definition: documen3.cxx:238
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3505
std::shared_ptr< sc::SolverSettings > m_pSolverSettings
Definition: optsolver.hxx:144
bool CallSolver()
Definition: optsolver.cxx:860
std::unique_ptr< weld::Widget > m_xContents
Definition: optsolver.hxx:141
std::unique_ptr< formula::RefButton > m_xRBRight3
Definition: optsolver.hxx:123
std::unique_ptr< formula::RefButton > m_xRBRight1
Definition: optsolver.hxx:109
void Init(const ScAddress &rCursorPos)
Definition: optsolver.cxx:252
std::unique_ptr< ScCursorRefEdit > m_xEdLeft4
Definition: optsolver.hxx:126
virtual ~ScOptSolverDlg() override
Definition: optsolver.cxx:248
css::uno::Sequence< OUString > maDescriptions
Definition: optsolver.hxx:75
std::unique_ptr< ScCursorRefEdit > m_xEdLeft2
Definition: optsolver.hxx:112
void ShowError(bool bCondition, formula::RefEdit *pFocus)
Definition: optsolver.cxx:811
void LoadSolverSettings()
Definition: optsolver.cxx:479
std::unique_ptr< weld::RadioButton > m_xRbValue
Definition: optsolver.hxx:95
std::unique_ptr< weld::RadioButton > m_xRbMin
Definition: optsolver.hxx:94
std::unique_ptr< formula::RefButton > m_xRBTargetValue
Definition: optsolver.hxx:97
weld::ComboBox * mpOperator[EDIT_ROW_COUNT]
Definition: optsolver.hxx:84
tools::Long nScrollPos
Definition: optsolver.hxx:72
std::unique_ptr< weld::Button > m_xBtnResetAll
Definition: optsolver.hxx:138
std::unique_ptr< ScCursorRefEdit > m_xEdLeft3
Definition: optsolver.hxx:119
std::unique_ptr< formula::RefButton > m_xRBRight2
Definition: optsolver.hxx:116
std::unique_ptr< weld::Button > m_xBtnClose
Definition: optsolver.hxx:136
bool ParseRef(ScRange &rRange, const OUString &rInput, bool bAllowRange)
Definition: optsolver.cxx:825
ScDocument & mrDoc
Definition: optsolver.hxx:67
formula::RefEdit * mpEdActive
Definition: optsolver.hxx:87
std::unique_ptr< weld::ComboBox > m_xLbOp2
Definition: optsolver.hxx:114
std::unique_ptr< weld::RadioButton > m_xRbMax
Definition: optsolver.hxx:93
static const sal_uInt16 EDIT_ROW_COUNT
Definition: optsolver.hxx:79
std::unique_ptr< weld::Button > m_xBtnDel2
Definition: optsolver.hxx:117
std::unique_ptr< formula::RefEdit > m_xEdVariableCells
Definition: optsolver.hxx:100
std::unique_ptr< formula::RefEdit > m_xEdObjectiveCell
Definition: optsolver.hxx:90
bool FindTimeout(sal_Int32 &rTimeout)
Definition: optsolver.cxx:843
std::unique_ptr< formula::RefButton > m_xRBLeft1
Definition: optsolver.hxx:105
std::unique_ptr< weld::Button > m_xBtnDel3
Definition: optsolver.hxx:124
virtual void SetActive() override
Definition: optsolver.cxx:407
std::unique_ptr< weld::ComboBox > m_xLbOp1
Definition: optsolver.hxx:106
ScDocShell * mpDocShell
Definition: optsolver.hxx:66
ScCursorRefEdit * mpRightEdit[EDIT_ROW_COUNT]
Definition: optsolver.hxx:82
std::unique_ptr< weld::Button > m_xBtnDel4
Definition: optsolver.hxx:131
std::shared_ptr< ScSolverOptionsDialog > m_xOptDlg
Definition: optsolver.hxx:143
ScOptSolverDlg(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, ScDocShell *pDocSh, const ScAddress &aCursorPos)
Definition: optsolver.cxx:136
virtual bool IsRefInputMode() const override
Definition: optsolver.cxx:473
OUString maConditionError
Definition: optsolver.hxx:64
bool mbDlgLostFocus
Definition: optsolver.hxx:69
std::unique_ptr< formula::RefEdit > m_xEdTargetValue
Definition: optsolver.hxx:96
css::uno::Sequence< OUString > maImplNames
Definition: optsolver.hxx:74
virtual void Close() override
Definition: optsolver.cxx:399
std::unique_ptr< weld::Label > m_xFtVariableCells
Definition: optsolver.hxx:99
const SCTAB mnCurTab
Definition: optsolver.hxx:68
std::unique_ptr< weld::ComboBox > m_xLbOp4
Definition: optsolver.hxx:128
std::unique_ptr< weld::ScrolledWindow > m_xScrollBar
Definition: optsolver.hxx:133
std::unique_ptr< weld::ComboBox > m_xLbOp3
Definition: optsolver.hxx:121
formula::RefButton * mpLeftButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:81
void ReadConditions()
Definition: optsolver.cxx:342
void SaveSolverSettings()
Definition: optsolver.cxx:512
static sc::ConstraintOperator OperatorIndexToConstraintOperator(sal_Int32 nIndex)
Definition: optsolver.cxx:798
std::unique_ptr< formula::RefButton > m_xRBLeft4
Definition: optsolver.hxx:127
std::unique_ptr< formula::RefButton > m_xRBLeft2
Definition: optsolver.hxx:113
OUString maInputError
Definition: optsolver.hxx:63
ScCursorRefEdit * mpLeftEdit[EDIT_ROW_COUNT]
Definition: optsolver.hxx:80
std::unique_ptr< formula::RefButton > m_xRBRight4
Definition: optsolver.hxx:130
std::unique_ptr< weld::Label > m_xResultFT
Definition: optsolver.hxx:140
bool IsEngineAvailable(std::u16string_view sEngineName)
Definition: optsolver.cxx:540
std::unique_ptr< ScCursorRefEdit > m_xEdRight3
Definition: optsolver.hxx:122
weld::Button * mpDelButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:85
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: optsolver.cxx:422
std::unique_ptr< weld::Button > m_xBtnOpt
Definition: optsolver.hxx:135
std::unique_ptr< ScCursorRefEdit > m_xEdRight4
Definition: optsolver.hxx:129
std::unique_ptr< weld::Label > m_xFtObjectiveCell
Definition: optsolver.hxx:89
void EnableButtons()
Definition: optsolver.cxx:390
std::unique_ptr< formula::RefButton > m_xRBObjectiveCell
Definition: optsolver.hxx:91
std::unique_ptr< ScCursorRefEdit > m_xEdRight2
Definition: optsolver.hxx:115
std::unique_ptr< formula::RefButton > m_xRBVariableCells
Definition: optsolver.hxx:101
std::unique_ptr< weld::Button > m_xBtnSolve
Definition: optsolver.hxx:137
std::unique_ptr< formula::RefButton > m_xRBLeft3
Definition: optsolver.hxx:120
std::vector< sc::ModelConstraint > m_aConditions
Definition: optsolver.hxx:71
std::unique_ptr< weld::Label > m_xFtConstraint
Definition: optsolver.hxx:107
std::unique_ptr< weld::Button > m_xBtnDel1
Definition: optsolver.hxx:110
std::unique_ptr< ScCursorRefEdit > m_xEdRight1
Definition: optsolver.hxx:108
void ShowConditions()
Definition: optsolver.cxx:366
formula::RefButton * mpRightButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:83
OUString maEngine
Definition: optsolver.hxx:76
css::uno::Sequence< css::beans::PropertyValue > maProperties
Definition: optsolver.hxx:77
std::unique_ptr< weld::Label > m_xFtCellRef
Definition: optsolver.hxx:103
std::unique_ptr< ScCursorRefEdit > m_xEdLeft1
Definition: optsolver.hxx:104
size_t size() const
Definition: rangelst.hxx:89
static bool MakeRangeFromName(const OUString &rName, const ScDocument &rDoc, SCTAB nCurTab, ScRange &rRange, RutlNameScope eScope=RUTL_NAMES, ScAddress::Details const &rDetails=ScAddress::detailsOOOa1, bool bUseDetailsPos=false)
Definition: rangeutl.cxx:233
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2170
void PutInOrder()
Definition: address.hxx:622
ScAddress aEnd
Definition: address.hxx:498
ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1733
ScAddress aStart
Definition: address.hxx:497
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:745
bool ParseWithNames(ScRangeList &rRanges, std::u16string_view rStr, const ScDocument &pDoc)
Definition: anyrefdg.cxx:755
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:775
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:714
std::unique_ptr< weld::Label > m_xFtErrorText
Definition: optsolver.hxx:189
ScSolverNoSolutionDialog(weld::Window *pParent, const OUString &rErrorText)
Definition: optsolver.cxx:72
virtual ~ScSolverNoSolutionDialog() override
Definition: optsolver.cxx:79
virtual ~ScSolverProgressDialog() override
Definition: optsolver.cxx:56
std::unique_ptr< weld::Label > m_xFtTime
Definition: optsolver.hxx:177
ScSolverProgressDialog(weld::Window *pParent)
Definition: optsolver.cxx:49
void SetTimeLimit(sal_Int32 nSeconds)
Definition: optsolver.cxx:65
virtual ~ScSolverSuccessDialog() override
Definition: optsolver.cxx:95
ScSolverSuccessDialog(weld::Window *pParent, std::u16string_view rSolution)
Definition: optsolver.cxx:83
std::unique_ptr< weld::Label > m_xFtResult
Definition: optsolver.hxx:198
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: optsolver.hxx:200
std::unique_ptr< weld::Button > m_xBtnOk
Definition: optsolver.hxx:199
static void GetImplementations(css::uno::Sequence< OUString > &rImplNames, css::uno::Sequence< OUString > &rDescriptions)
Definition: solverutil.cxx:39
static css::uno::Sequence< css::beans::PropertyValue > GetDefaults(std::u16string_view rImplName)
Definition: solverutil.cxx:136
static css::uno::Reference< css::sheet::XSolver > GetSolver(std::u16string_view rImplName)
Definition: solverutil.cxx:98
static void FillScAddress(ScAddress &rScAddress, const css::table::CellAddress &rApiAddress)
Definition: convuno.hxx:63
tools::Long Min() const
tools::Long Len() const
void Normalize()
css::uno::Reference< css::frame::XFrame > GetActiveFrame() const
SfxBindings & GetBindings() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
void SetGetFocusHdl(const Link< RefButton &, void > &rLink)
void SetLoseFocusHdl(const Link< RefButton &, void > &rLink)
void SetSelection(const Selection &rSelection)
void SetLoseFocusHdl(const Link< RefEdit &, void > &rLink)
void SetModifyHdl(const Link< RefEdit &, void > &rLink)
std::unique_ptr< weld::Entry > xEntry
Selection GetSelection() const
void SetRefString(const OUString &rStr)
void SetGetFocusHdl(const Link< RefEdit &, void > &rLink)
virtual bool KeyInput(const KeyEvent &rKEvt)
OUString GetText() const
bool IsMod1() const
sal_uInt16 GetCode() const
bool IsShift() const
bool IsMod2() const
void connect_clicked(const Link< Button &, void > &rLink)
virtual void set_active(int pos)=0
void connect_changed(const Link< ComboBox &, void > &rLink)
virtual short run()
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
virtual void set_sensitive(bool sensitive)=0
virtual void connect_focus_in(const Link< Widget &, void > &rLink)
DocumentType eType
sal_Int32 nIndex
OUString aName
constexpr sal_uInt16 KEY_UP
constexpr sal_uInt16 KEY_DOWN
aStr
SvGenericNameContainerMapImpl maProperties
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
const OUString sEmpty
@ SP_OBJ_VAL
@ SP_OBJ_CELL
@ SP_LO_ENGINE
@ SP_VAR_CELLS
@ OT_VALUE
@ OT_MAXIMIZE
@ OT_MINIMIZE
ConstraintOperator
@ CO_EQUAL
@ CO_GREATER_EQUAL
@ CO_INTEGER
@ CO_LESS_EQUAL
@ CO_BINARY
long Long
Reference< graphic::XGraphic > GetXGraphicForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
IMPL_LINK_NOARG(ScOptSolverDlg, LoseEditFocusHdl, formula::RefEdit &, void)
Definition: optsolver.cxx:670
IMPL_LINK(ScSolverSuccessDialog, ClickHdl, weld::Button &, rBtn, void)
Definition: optsolver.cxx:99
@ RUTL_NAMES
Definition: rangeutl.hxx:38
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
bool IsDefault() const
ConstraintOperator nOperator
Reference< XFrame > xFrame
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
constexpr OUStringLiteral SC_UNONAME_TIMEOUT
Definition: unonames.hxx:702
RET_OK
RET_CLOSE
RET_CANCEL