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