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