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