LibreOffice Module sc (master)  1
optsolver.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <rangelst.hxx>
21 #include <sfx2/bindings.hxx>
22 #include <svl/numformat.hxx>
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  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( std::move(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  auto xKeepAlive = shared_from_this();
511  if (&rBtn == m_xBtnSolve.get() || &rBtn == m_xBtnClose.get())
512  {
513  bool bSolve = ( &rBtn == m_xBtnSolve.get() );
514 
515  SetDispatcherLock( false );
516  SwitchToDocument();
517 
518  bool bClose = true;
519  if ( bSolve )
520  bClose = CallSolver();
521 
522  if ( bClose )
523  {
524  // Close: write dialog settings to DocShell for subsequent calls
525  ReadConditions();
526  std::unique_ptr<ScOptSolverSave> pSave( new ScOptSolverSave(
527  m_xEdObjectiveCell->GetText(), m_xRbMax->get_active(), m_xRbMin->get_active(), m_xRbValue->get_active(),
528  m_xEdTargetValue->GetText(), m_xEdVariableCells->GetText(), std::vector(maConditions), maEngine, maProperties ) );
529  mpDocShell->SetSolverSaveData( std::move(pSave) );
530  response(RET_CLOSE);
531  }
532  else
533  {
534  // no solution -> dialog is kept open
535  SetDispatcherLock( true );
536  }
537  }
538  else if (&rBtn == m_xBtnOpt.get())
539  {
541  m_xOptDlg = std::make_shared<ScSolverOptionsDialog>(m_xDialog.get(), maImplNames, maDescriptions, maEngine, maProperties);
542  weld::DialogController::runAsync(m_xOptDlg, [this](sal_Int32 nResult){
543  if (nResult == RET_OK)
544  {
545  maEngine = m_xOptDlg->GetEngine();
546  maProperties = m_xOptDlg->GetProperties();
547  }
548  m_xOptDlg.reset();
549  });
550  }
551  else if (&rBtn == m_xBtnResetAll.get())
552  {
553  OUString sEmpty;
554  m_xEdObjectiveCell->SetText(sEmpty);
555  m_xEdTargetValue->SetText(sEmpty);
556  m_xEdVariableCells->SetText(sEmpty);
557 
558  // Get default property values of solver implementations
559  maEngine = maImplNames[0];
561 
562  // Clear all conditions (Constraints)
563  maConditions.clear();
564  std::unique_ptr<ScOptSolverSave> pEmpty( new ScOptSolverSave(
565  sEmpty, true, false, false,
566  sEmpty, sEmpty, std::vector(maConditions), maEngine, maProperties ) );
567  mpDocShell->SetSolverSaveData( std::move(pEmpty) );
568  ShowConditions();
569 
570  m_xRbMax->set_active(true);
571  m_xEdObjectiveCell->GrabFocus();
572  mpEdActive = m_xEdObjectiveCell.get();
573  }
574 }
575 
576 IMPL_LINK( ScOptSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
577 {
578  formula::RefEdit* pEdit = nullptr;
579  mpEdActive = nullptr;
580 
581  if( &rCtrl == m_xEdObjectiveCell.get() )
582  pEdit = mpEdActive = m_xEdObjectiveCell.get();
583  else if( &rCtrl == m_xEdTargetValue.get() )
584  pEdit = mpEdActive = m_xEdTargetValue.get();
585  else if( &rCtrl == m_xEdVariableCells.get() )
586  pEdit = mpEdActive = m_xEdVariableCells.get();
587  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
588  {
589  if( &rCtrl == mpLeftEdit[nRow] )
590  pEdit = mpEdActive = mpLeftEdit[nRow];
591  else if( &rCtrl == mpRightEdit[nRow] )
592  pEdit = mpEdActive = mpRightEdit[nRow];
593  }
594 
595  if( pEdit )
596  pEdit->SelectAll();
597 }
598 
599 IMPL_LINK( ScOptSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
600 {
601  formula::RefEdit* pEdit = nullptr;
602  mpEdActive = nullptr;
603 
604  if( &rCtrl == m_xRBObjectiveCell.get() )
605  pEdit = mpEdActive = m_xEdObjectiveCell.get();
606  else if( &rCtrl == m_xRBTargetValue.get() )
607  pEdit = mpEdActive = m_xEdTargetValue.get();
608  else if( &rCtrl == m_xRBVariableCells.get() )
609  pEdit = mpEdActive = m_xEdVariableCells.get();
610  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
611  {
612  if( &rCtrl == mpLeftButton[nRow] )
613  pEdit = mpEdActive = mpLeftEdit[nRow];
614  else if( &rCtrl == mpRightButton[nRow] )
615  pEdit = mpEdActive = mpRightEdit[nRow];
616  }
617 
618  if( pEdit )
619  pEdit->SelectAll();
620 }
621 
622 
623 IMPL_LINK(ScOptSolverDlg, GetFocusHdl, weld::Widget&, rCtrl, void)
624 {
625  if( &rCtrl == m_xRbValue.get() ) // focus on "Value of" radio button
626  mpEdActive = m_xEdTargetValue.get(); // use value edit for ref input, but don't change selection
627  else
628  {
629  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
630  {
631  if( &rCtrl == mpOperator[nRow] ) // focus on "operator" list box
632  mpEdActive = mpRightEdit[nRow]; // use right edit for ref input, but don't change selection
633  }
634  }
635 }
636 
638 {
639  mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
640 }
641 
643 {
644  mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
645 }
646 
647 IMPL_LINK(ScOptSolverDlg, DelBtnHdl, weld::Button&, rBtn, void)
648 {
649  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
650  if (&rBtn == mpDelButton[nRow])
651  {
652  bool bHadFocus = rBtn.has_focus();
653 
654  ReadConditions();
655  tools::Long nVecPos = nScrollPos + nRow;
656  if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
657  {
658  maConditions.erase( maConditions.begin() + nVecPos );
659  ShowConditions();
660 
661  if ( bHadFocus && !rBtn.get_sensitive() )
662  {
663  // If the button is disabled, focus would normally move to the next control,
664  // (left edit of the next row). Move it to left edit of this row instead.
665 
666  mpEdActive = mpLeftEdit[nRow];
667  mpEdActive->GrabFocus();
668  }
669  }
670  }
671 }
672 
674 {
675  // modify handler for the target edit:
676  // select "Value of" if something is input into the edit
677  if ( !m_xEdTargetValue->GetText().isEmpty() )
678  m_xRbValue->set_active(true);
679 }
680 
682 {
683  // modify handler for the condition edits, just to enable/disable "delete" buttons
684  ReadConditions();
685  EnableButtons();
686 }
687 
689 {
690  // select handler for operator list boxes, just to enable/disable "delete" buttons
691  ReadConditions();
692  EnableButtons();
693 }
694 
696 {
697  ReadConditions();
698  nScrollPos = m_xScrollBar->vadjustment_get_value();
699  ShowConditions();
700  if( mpEdActive )
701  mpEdActive->SelectAll();
702 }
703 
704 IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit&, rEdit, void )
705 {
706  if ( &rEdit == mpLeftEdit[0] || &rEdit == mpRightEdit[0] )
707  {
708  if ( nScrollPos > 0 )
709  {
710  ReadConditions();
711  --nScrollPos;
712  ShowConditions();
713  if( mpEdActive )
714  mpEdActive->SelectAll();
715  }
716  }
717  else
718  {
719  formula::RefEdit* pFocus = nullptr;
720  for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow ) // second row or below: move focus
721  {
722  if ( &rEdit == mpLeftEdit[nRow] )
723  pFocus = mpLeftEdit[nRow-1];
724  else if ( &rEdit == mpRightEdit[nRow] )
725  pFocus = mpRightEdit[nRow-1];
726  }
727  if (pFocus)
728  {
729  mpEdActive = pFocus;
730  pFocus->GrabFocus();
731  }
732  }
733 }
734 
735 IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit&, rEdit, void )
736 {
737  if ( &rEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || &rEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
738  {
740  ReadConditions();
741  ++nScrollPos;
742  ShowConditions();
743  if( mpEdActive )
744  mpEdActive->SelectAll();
745  }
746  else
747  {
748  formula::RefEdit* pFocus = nullptr;
749  for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow ) // before last row: move focus
750  {
751  if ( &rEdit == mpLeftEdit[nRow] )
752  pFocus = mpLeftEdit[nRow+1];
753  else if ( &rEdit == mpRightEdit[nRow] )
754  pFocus = mpRightEdit[nRow+1];
755  }
756  if (pFocus)
757  {
758  mpEdActive = pFocus;
759  pFocus->GrabFocus();
760  }
761  }
762 }
763 
764 void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
765 {
766  OUString aMessage = bCondition ? maConditionError : maInputError;
767  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
768  VclMessageType::Warning, VclButtonsType::Ok,
769  aMessage));
770  xBox->run();
771  if (pFocus)
772  {
773  mpEdActive = pFocus;
774  pFocus->GrabFocus();
775  }
776 }
777 
778 bool ScOptSolverDlg::ParseRef( ScRange& rRange, const OUString& rInput, bool bAllowRange )
779 {
781  ScRefFlags nFlags = rRange.ParseAny( rInput, mrDoc, aDetails );
782  if ( nFlags & ScRefFlags::VALID )
783  {
784  if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO)
785  rRange.aStart.SetTab( mnCurTab );
786  if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO)
787  rRange.aEnd.SetTab( rRange.aStart.Tab() );
788  return ( bAllowRange || rRange.aStart == rRange.aEnd );
789  }
790  else if ( ScRangeUtil::MakeRangeFromName( rInput, mrDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
791  return ( bAllowRange || rRange.aStart == rRange.aEnd );
792 
793  return false; // not recognized
794 }
795 
796 bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
797 {
798  bool bFound = false;
799 
800  if ( !maProperties.hasElements() )
801  maProperties = ScSolverUtil::GetDefaults( maEngine ); // get property defaults from component
802 
803  sal_Int32 nPropCount = maProperties.getLength();
804  for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
805  {
806  const beans::PropertyValue& rValue = maProperties[nProp];
807  if ( rValue.Name == SC_UNONAME_TIMEOUT )
808  bFound = ( rValue.Value >>= rTimeout );
809  }
810  return bFound;
811 }
812 
813 bool ScOptSolverDlg::CallSolver() // return true -> close dialog after calling
814 {
815  // show progress dialog
816 
817  auto xProgress = std::make_shared<ScSolverProgressDialog>(m_xDialog.get());
818  sal_Int32 nTimeout = 0;
819  if ( FindTimeout( nTimeout ) )
820  xProgress->SetTimeLimit( nTimeout );
821  else
822  xProgress->HideTimeLimit();
823 
824  weld::DialogController::runAsync(xProgress, [](sal_Int32 /*nResult*/){});
825 
826  // try to make sure the progress dialog is painted before continuing
828 
829  // collect solver parameters
830 
831  ReadConditions();
832 
833  uno::Reference<sheet::XSpreadsheetDocument> xDocument( mpDocShell->GetModel(), uno::UNO_QUERY );
834 
835  ScRange aObjRange;
836  if ( !ParseRef( aObjRange, m_xEdObjectiveCell->GetText(), false ) )
837  {
838  ShowError( false, m_xEdObjectiveCell.get() );
839  return false;
840  }
841  table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
842 
843  // "changing cells" can be several ranges
844  ScRangeList aVarRanges;
845  if ( !ParseWithNames( aVarRanges, m_xEdVariableCells->GetText(), mrDoc ) )
846  {
847  ShowError( false, m_xEdVariableCells.get() );
848  return false;
849  }
850  uno::Sequence<table::CellAddress> aVariables;
851  sal_Int32 nVarPos = 0;
852 
853  for ( size_t nRangePos=0, nRange = aVarRanges.size(); nRangePos < nRange; ++nRangePos )
854  {
855  ScRange aRange( aVarRanges[ nRangePos ] );
856  aRange.PutInOrder();
857  SCTAB nTab = aRange.aStart.Tab();
858 
859  // resolve into single cells
860 
861  sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
862  ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
863  aVariables.realloc( nVarPos + nAdd );
864  auto pVariables = aVariables.getArray();
865 
866  for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
867  for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
868  pVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
869  }
870 
871  uno::Sequence<sheet::SolverConstraint> aConstraints;
872  sal_Int32 nConstrPos = 0;
873  for ( const auto& rConstr : maConditions )
874  {
875  if ( !rConstr.aLeftStr.isEmpty() )
876  {
877  sheet::SolverConstraint aConstraint;
878  // order of list box entries must match enum values
879  aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(rConstr.nOperator);
880 
881  ScRange aLeftRange;
882  if ( !ParseRef( aLeftRange, rConstr.aLeftStr, true ) )
883  {
884  ShowError( true, nullptr );
885  return false;
886  }
887 
888  bool bIsRange = false;
889  ScRange aRightRange;
890  if ( ParseRef( aRightRange, rConstr.aRightStr, true ) )
891  {
892  if ( aRightRange.aStart == aRightRange.aEnd )
893  aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
894  aRightRange.aStart.Col(), aRightRange.aStart.Row() );
895  else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
896  aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
897  bIsRange = true; // same size as "left" range, resolve into single cells
898  else
899  {
900  ShowError( true, nullptr );
901  return false;
902  }
903  }
904  else
905  {
906  sal_uInt32 nFormat = 0;
907  double fValue = 0.0;
908  if ( mrDoc.GetFormatTable()->IsNumberFormat( rConstr.aRightStr, nFormat, fValue ) )
909  aConstraint.Right <<= fValue;
910  else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
911  aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
912  {
913  ShowError( true, nullptr );
914  return false;
915  }
916  }
917 
918  // resolve into single cells
919 
920  sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
921  ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
922  aConstraints.realloc( nConstrPos + nAdd );
923  auto pConstraints = aConstraints.getArray();
924 
925  for (SCROW nRow = aLeftRange.aStart.Row(); nRow <= aLeftRange.aEnd.Row(); ++nRow)
926  for (SCCOL nCol = aLeftRange.aStart.Col(); nCol <= aLeftRange.aEnd.Col(); ++nCol)
927  {
928  aConstraint.Left = table::CellAddress( aLeftRange.aStart.Tab(), nCol, nRow );
929  if ( bIsRange )
930  aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
931  aRightRange.aStart.Col() + ( nCol - aLeftRange.aStart.Col() ),
932  aRightRange.aStart.Row() + ( nRow - aLeftRange.aStart.Row() ) );
933 
934  pConstraints[nConstrPos++] = aConstraint;
935  }
936  }
937  }
938 
939  bool bMaximize = m_xRbMax->get_active();
940  if ( m_xRbValue->get_active() )
941  {
942  // handle "value of" with an additional constraint (and then minimize)
943 
944  sheet::SolverConstraint aConstraint;
945  aConstraint.Left = aObjective;
946  aConstraint.Operator = sheet::SolverConstraintOperator_EQUAL;
947 
948  OUString aValStr = m_xEdTargetValue->GetText();
949  ScRange aRightRange;
950  if ( ParseRef( aRightRange, aValStr, false ) )
951  aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
952  aRightRange.aStart.Col(), aRightRange.aStart.Row() );
953  else
954  {
955  sal_uInt32 nFormat = 0;
956  double fValue = 0.0;
957  if ( mrDoc.GetFormatTable()->IsNumberFormat( aValStr, nFormat, fValue ) )
958  aConstraint.Right <<= fValue;
959  else
960  {
961  ShowError( false, m_xEdTargetValue.get() );
962  return false;
963  }
964  }
965 
966  aConstraints.realloc( nConstrPos + 1 );
967  aConstraints.getArray()[nConstrPos++] = aConstraint;
968  }
969 
970  // copy old document values
971 
972  sal_Int32 nVarCount = aVariables.getLength();
973  uno::Sequence<double> aOldValues( nVarCount );
974  std::transform(std::cbegin(aVariables), std::cend(aVariables), aOldValues.getArray(),
975  [this](const table::CellAddress& rVariable) -> double {
976  ScAddress aCellPos;
977  ScUnoConversion::FillScAddress( aCellPos, rVariable );
978  return mrDoc.GetValue( aCellPos );
979  });
980 
981  // create and initialize solver
982 
983  uno::Reference<sheet::XSolver> xSolver = ScSolverUtil::GetSolver( maEngine );
984  OSL_ENSURE( xSolver.is(), "can't get solver component" );
985  if ( !xSolver.is() )
986  return false;
987 
988  xSolver->setDocument( xDocument );
989  xSolver->setObjective( aObjective );
990  xSolver->setVariables( aVariables );
991  xSolver->setConstraints( aConstraints );
992  xSolver->setMaximize( bMaximize );
993 
994  // set options
995  uno::Reference<beans::XPropertySet> xOptProp(xSolver, uno::UNO_QUERY);
996  if ( xOptProp.is() )
997  {
998  for (const beans::PropertyValue& rValue : std::as_const(maProperties))
999  {
1000  try
1001  {
1002  xOptProp->setPropertyValue( rValue.Name, rValue.Value );
1003  }
1004  catch ( uno::Exception & )
1005  {
1006  OSL_FAIL("Exception in solver option property");
1007  }
1008  }
1009  }
1010 
1011  xSolver->solve();
1012  bool bSuccess = xSolver->getSuccess();
1013 
1014  xProgress->response(RET_CLOSE);
1015 
1016  bool bClose = false;
1017  bool bRestore = true; // restore old values unless a solution is accepted
1018  if ( bSuccess )
1019  {
1020  // put solution into document so it is visible when asking
1021  uno::Sequence<double> aSolution = xSolver->getSolution();
1022  if ( aSolution.getLength() == nVarCount )
1023  {
1024  mpDocShell->LockPaint();
1025  ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1026  for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1027  {
1028  ScAddress aCellPos;
1029  ScUnoConversion::FillScAddress( aCellPos, std::as_const(aVariables)[nVarPos] );
1030  rFunc.SetValueCell(aCellPos, aSolution[nVarPos], false);
1031  }
1032  mpDocShell->UnlockPaint();
1033  }
1035 
1036  // take formatted result from document (result value from component is ignored)
1037  OUString aResultStr = mrDoc.GetString(
1038  static_cast<SCCOL>(aObjective.Column), static_cast<SCROW>(aObjective.Row),
1039  static_cast<SCTAB>(aObjective.Sheet));
1040 
1041  ScSolverSuccessDialog aDialog(m_xDialog.get(), aResultStr);
1042  if (aDialog.run() == RET_OK)
1043  {
1044  // keep results and close dialog
1045  bRestore = false;
1046  bClose = true;
1047  }
1048  }
1049  else
1050  {
1051  OUString aError;
1052  uno::Reference<sheet::XSolverDescription> xDesc( xSolver, uno::UNO_QUERY );
1053  if ( xDesc.is() )
1054  aError = xDesc->getStatusDescription(); // error description from component
1055  ScSolverNoSolutionDialog aDialog(m_xDialog.get(), aError);
1056  aDialog.run();
1057  }
1058 
1059  if ( bRestore ) // restore old values
1060  {
1061  mpDocShell->LockPaint();
1062  ScDocFunc &rFunc = mpDocShell->GetDocFunc();
1063  for (nVarPos=0; nVarPos<nVarCount; ++nVarPos)
1064  {
1065  ScAddress aCellPos;
1066  ScUnoConversion::FillScAddress( aCellPos, aVariables[nVarPos] );
1067  rFunc.SetValueCell(aCellPos, std::as_const(aOldValues)[nVarPos], false);
1068  }
1069  mpDocShell->UnlockPaint();
1070  }
1071 
1072  return bClose;
1073 }
1074 
1075 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScRefFlags ParseAny(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1)
Definition: address.cxx:1733
std::unique_ptr< formula::RefButton > m_xRBRight1
Definition: optsolver.hxx:152
std::unique_ptr< formula::RefEdit > m_xEdVariableCells
Definition: optsolver.hxx:142
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
OUString aLeftStr
Definition: optsolver.hxx:50
void SetTimeLimit(sal_Int32 nSeconds)
Definition: optsolver.cxx:63
ScAddress aStart
Definition: address.hxx:497
ScDocShell * mpDocShell
Definition: optsolver.hxx:108
std::unique_ptr< weld::Label > m_xResultFT
Definition: optsolver.hxx:183
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
std::unique_ptr< weld::Label > m_xFtErrorText
Definition: optsolver.hxx:226
virtual void SetActive() override
Definition: optsolver.cxx:435
std::unique_ptr< formula::RefButton > m_xRBRight4
Definition: optsolver.hxx:173
static bool MakeRangeFromName(const OUString &rName, const ScDocument &rDoc, SCTAB nCurTab, ScRange &rRange, RutlNameScope eScope=RUTL_NAMES, ScAddress::Details const &rDetails=ScAddress::detailsOOOa1, bool bUseDetailsPos=false)
Definition: rangeutl.cxx:233
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: optsolver.cxx:450
SCROW Row() const
Definition: address.hxx:274
static const sal_uInt16 EDIT_ROW_COUNT
Definition: optsolver.hxx:121
formula::RefButton * mpRightButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:125
ScCursorRefEdit(std::unique_ptr< weld::Entry > xEntry)
Definition: optsolver.cxx:105
std::unique_ptr< weld::ScrolledWindow > m_xScrollBar
Definition: optsolver.hxx:176
Any maTarget
std::unique_ptr< ScCursorRefEdit > m_xEdLeft3
Definition: optsolver.hxx:162
IMPL_LINK_NOARG(ScOptSolverDlg, LoseEditFocusHdl, formula::RefEdit &, void)
Definition: optsolver.cxx:637
std::unique_ptr< formula::RefButton > m_xRBLeft2
Definition: optsolver.hxx:156
std::unique_ptr< formula::RefButton > m_xRBLeft1
Definition: optsolver.hxx:147
long Long
const OUString & GetObjective() const
Definition: optsolver.hxx:78
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
css::uno::Reference< css::frame::XModel3 > GetModel() const
const std::vector< ScOptConditionRow > & GetConditions() const
Definition: optsolver.hxx:84
css::uno::Sequence< OUString > maImplNames
Definition: optsolver.hxx:116
ScOptSolverSave(const OUString &rObjective, bool bMax, bool bMin, bool bValue, const OUString &rTarget, const OUString &rVariable, std::vector< ScOptConditionRow > &&rConditions, const OUString &rEngine, const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Definition: optsolver.cxx:134
std::unique_ptr< weld::ComboBox > m_xLbOp2
Definition: optsolver.hxx:157
void SetGetFocusHdl(const Link< RefButton &, void > &rLink)
bool GetMin() const
Definition: optsolver.hxx:80
std::unique_ptr< weld::Label > m_xFtObjectiveCell
Definition: optsolver.hxx:131
sal_uInt16 GetCode() const
Link< ScCursorRefEdit &, void > maCursorUpLink
Definition: optsolver.hxx:36
ScAddress aEnd
Definition: address.hxx:498
Link< ScCursorRefEdit &, void > maCursorDownLink
Definition: optsolver.hxx:37
bool IsDefault() const
Definition: optsolver.hxx:55
IMPL_LINK(ScSolverSuccessDialog, ClickHdl, weld::Button &, rBtn, void)
Definition: optsolver.cxx:97
std::unique_ptr< formula::RefButton > m_xRBVariableCells
Definition: optsolver.hxx:143
void SetSelection(const Selection &rSelection)
virtual int get_active() const =0
OUString aRightStr
Definition: optsolver.hxx:52
const SCTAB mnCurTab
Definition: optsolver.hxx:110
std::unique_ptr< weld::RadioButton > m_xRbMin
Definition: optsolver.hxx:136
void SetLoseFocusHdl(const Link< RefEdit &, void > &rLink)
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
void SetLoseFocusHdl(const Link< RefButton &, void > &rLink)
std::unique_ptr< ScCursorRefEdit > m_xEdLeft2
Definition: optsolver.hxx:155
constexpr sal_uInt16 KEY_UP
std::unique_ptr< weld::Button > m_xBtnOpt
Definition: optsolver.hxx:178
std::unique_ptr< formula::RefEdit > m_xEdObjectiveCell
Definition: optsolver.hxx:132
virtual bool IsRefInputMode() const override
Definition: optsolver.cxx:501
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
ScDocument & mrDoc
Definition: optsolver.hxx:109
std::unique_ptr< formula::RefButton > m_xRBLeft4
Definition: optsolver.hxx:170
std::unique_ptr< ScCursorRefEdit > m_xEdRight4
Definition: optsolver.hxx:172
ScCursorRefEdit * mpRightEdit[EDIT_ROW_COUNT]
Definition: optsolver.hxx:124
css::uno::Sequence< OUString > maDescriptions
Definition: optsolver.hxx:117
const OUString sEmpty
sal_uInt16 nOperator
Definition: optsolver.hxx:51
Selection GetSelection() const
void SetGetFocusHdl(const Link< RefEdit &, void > &rLink)
std::unique_ptr< weld::Button > m_xBtnSolve
Definition: optsolver.hxx:180
SCTAB Tab() const
Definition: address.hxx:283
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:764
std::unique_ptr< ScCursorRefEdit > m_xEdLeft1
Definition: optsolver.hxx:146
void Init(const ScAddress &rCursorPos)
Definition: optsolver.cxx:267
std::unique_ptr< weld::ComboBox > m_xLbOp4
Definition: optsolver.hxx:171
void ShowConditions()
Definition: optsolver.cxx:394
css::uno::Sequence< css::beans::PropertyValue > maProperties
Definition: optsolver.hxx:119
std::vector< ScOptConditionRow > maConditions
Definition: optsolver.hxx:113
bool GetMax() const
Definition: optsolver.hxx:79
constexpr sal_uInt16 KEY_DOWN
bool SetValueCell(const ScAddress &rPos, double fVal, bool bInteraction)
Definition: docfunc.cxx:867
void SetRefString(const OUString &rStr)
void SetTab(SCTAB nTabP)
Definition: address.hxx:295
void SetModifyHdl(const Link< RefEdit &, void > &rLink)
std::unique_ptr< weld::RadioButton > m_xRbMax
Definition: optsolver.hxx:135
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:459
void Justify()
std::unique_ptr< formula::RefEdit > m_xEdTargetValue
Definition: optsolver.hxx:138
static bool Reschedule(bool bHandleAllCurrentEvents=false)
void ReadConditions()
Definition: optsolver.cxx:370
std::unique_ptr< weld::Widget > m_xContents
Definition: optsolver.hxx:184
std::unique_ptr< weld::Button > m_xBtnDel1
Definition: optsolver.hxx:153
void connect_changed(const Link< ComboBox &, void > &rLink)
The dialog's content for a row, not yet parsed.
Definition: optsolver.hxx:48
#define SC_UNONAME_TIMEOUT
Definition: unonames.hxx:693
sal_Int16 SCCOL
Definition: types.hxx:21
std::unique_ptr< ScCursorRefEdit > m_xEdRight3
Definition: optsolver.hxx:165
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:179
OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2170
void SetCursorLinks(const Link< ScCursorRefEdit &, void > &rUp, const Link< ScCursorRefEdit &, void > &rDown)
Definition: optsolver.cxx:112
ScCursorRefEdit * mpLeftEdit[EDIT_ROW_COUNT]
Definition: optsolver.hxx:122
const OUString & GetTarget() const
Definition: optsolver.hxx:82
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:779
ScSolverNoSolutionDialog(weld::Window *pParent, const OUString &rErrorText)
Definition: optsolver.cxx:70
const OUString & GetEngine() const
Definition: optsolver.hxx:85
std::unique_ptr< weld::Label > m_xFtTime
Definition: optsolver.hxx:214
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:118
ScSolverSuccessDialog(weld::Window *pParent, std::u16string_view rSolution)
Definition: optsolver.cxx:81
std::unique_ptr< weld::Button > m_xBtnResetAll
Definition: optsolver.hxx:181
std::unique_ptr< formula::RefButton > m_xRBTargetValue
Definition: optsolver.hxx:139
bool GetValue() const
Definition: optsolver.hxx:81
static void FillScAddress(ScAddress &rScAddress, const css::table::CellAddress &rApiAddress)
Definition: convuno.hxx:63
std::unique_ptr< weld::ComboBox > m_xLbOp3
Definition: optsolver.hxx:164
SCCOL Col() const
Definition: address.hxx:279
void EnableButtons()
Definition: optsolver.cxx:418
std::unique_ptr< weld::RadioButton > m_xRbValue
Definition: optsolver.hxx:137
tools::Long Len() const
std::unique_ptr< weld::Label > m_xFtCellRef
Definition: optsolver.hxx:145
std::unique_ptr< formula::RefButton > m_xRBRight3
Definition: optsolver.hxx:166
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:17
void PutInOrder()
Definition: address.hxx:622
std::unique_ptr< weld::ComboBox > m_xLbOp1
Definition: optsolver.hxx:149
std::unique_ptr< weld::Button > m_xBtnDel2
Definition: optsolver.hxx:160
RET_CLOSE
tools::Long nScrollPos
Definition: optsolver.hxx:114
bool IsShift() const
bool FindTimeout(sal_Int32 &rTimeout)
Definition: optsolver.cxx:796
weld::Entry & rEdit
SfxBindings & GetBindings() const
std::unique_ptr< weld::Label > m_xFtConstraint
Definition: optsolver.hxx:150
const ScOptSolverSave * GetSolverSaveData() const
Definition: docsh.hxx:415
const OUString & GetVariable() const
Definition: optsolver.hxx:83
std::unique_ptr< formula::RefButton > m_xRBRight2
Definition: optsolver.hxx:159
All settings from the dialog, saved with the DocShell for the next call.
Definition: optsolver.hxx:59
weld::ComboBox * mpOperator[EDIT_ROW_COUNT]
Definition: optsolver.hxx:126
tools::Long Min() const
virtual ~ScSolverProgressDialog() override
Definition: optsolver.cxx:54
OUString aName
bool CallSolver()
Definition: optsolver.cxx:813
ScSolverProgressDialog(weld::Window *pParent)
Definition: optsolver.cxx:47
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
RET_OK
bool IsMod1() const
std::unique_ptr< weld::Label > m_xFtVariableCells
Definition: optsolver.hxx:141
Reference< XExecutableDialog > m_xDialog
weld::Button * mpDelButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:127
virtual short run()
OUString maConditionError
Definition: optsolver.hxx:106
virtual void Close() override
Definition: optsolver.cxx:427
formula::RefEdit * mpEdActive
Definition: optsolver.hxx:129
std::shared_ptr< ScSolverOptionsDialog > m_xOptDlg
Definition: optsolver.hxx:186
std::unique_ptr< ScCursorRefEdit > m_xEdRight1
Definition: optsolver.hxx:151
std::unique_ptr< weld::Button > m_xBtnDel4
Definition: optsolver.hxx:174
SC_DLLPUBLIC const ScRangeData * GetRangeAtBlock(const ScRange &rBlock, OUString &rName, bool *pSheetLocal=nullptr) const
Definition: documen3.cxx:238
OUString maInputError
Definition: optsolver.hxx:105
ScRefFlags
Definition: address.hxx:157
std::unique_ptr< formula::RefButton > m_xRBLeft3
Definition: optsolver.hxx:163
bool ParseWithNames(ScRangeList &rRanges, std::u16string_view rStr, const ScDocument &pDoc)
Definition: anyrefdg.cxx:759
std::unique_ptr< ScCursorRefEdit > m_xEdLeft4
Definition: optsolver.hxx:169
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:718
bool ParseRef(ScRange &rRange, const OUString &rInput, bool bAllowRange)
Definition: optsolver.cxx:778
const css::uno::Sequence< css::beans::PropertyValue > & GetProperties() const
Definition: optsolver.hxx:86
std::unique_ptr< ScCursorRefEdit > m_xEdRight2
Definition: optsolver.hxx:158
virtual ~ScSolverNoSolutionDialog() override
Definition: optsolver.cxx:77
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: optsolver.hxx:237
std::unique_ptr< formula::RefButton > m_xRBObjectiveCell
Definition: optsolver.hxx:133
std::unique_ptr< weld::Button > m_xBtnOk
Definition: optsolver.hxx:236
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:22
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:749
std::unique_ptr< weld::Label > m_xFtResult
Definition: optsolver.hxx:235
formula::RefButton * mpLeftButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:123
bool m_bDetectedRangeSegmentation false
virtual bool KeyInput(const KeyEvent &rKEvt)
bool IsMod2() const
std::unique_ptr< weld::Button > m_xBtnDel3
Definition: optsolver.hxx:167