LibreOffice Module sc (master)  1
optsolver.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <rangelst.hxx>
21 #include <sfx2/bindings.hxx>
22 #include <svl/numformat.hxx>
23 #include <svl/zforlist.hxx>
25 #include <vcl/weld.hxx>
26 #include <vcl/svapp.hxx>
27 
28 #include <reffact.hxx>
29 #include <docsh.hxx>
30 #include <docfunc.hxx>
31 #include <rangeutl.hxx>
32 #include <convuno.hxx>
33 #include <unonames.hxx>
34 #include <solveroptions.hxx>
35 #include <solverutil.hxx>
36 #include <globstr.hrc>
37 #include <scresid.hxx>
38 
39 #include <optsolver.hxx>
40 
41 #include <com/sun/star/sheet/SolverConstraint.hpp>
42 #include <com/sun/star/sheet/SolverConstraintOperator.hpp>
43 #include <com/sun/star/sheet/XSolverDescription.hpp>
44 #include <com/sun/star/sheet/XSolver.hpp>
45 
46 using namespace com::sun::star;
47 
49  : GenericDialogController(pParent, "modules/scalc/ui/solverprogressdialog.ui",
50  "SolverProgressDialog")
51  , m_xFtTime(m_xBuilder->weld_label("progress"))
52 {
53 }
54 
56 {
57 }
58 
60 {
61  m_xFtTime->hide();
62 }
63 
64 void ScSolverProgressDialog::SetTimeLimit( sal_Int32 nSeconds )
65 {
66  OUString aOld = m_xFtTime->get_label();
67  OUString aNew = aOld.replaceFirst("#", OUString::number(nSeconds));
68  m_xFtTime->set_label(aNew);
69 }
70 
72  : GenericDialogController(pParent, "modules/scalc/ui/nosolutiondialog.ui", "NoSolutionDialog")
73  , m_xFtErrorText(m_xBuilder->weld_label("error"))
74 {
75  m_xFtErrorText->set_label(rErrorText);
76 }
77 
79 {
80 }
81 
82 ScSolverSuccessDialog::ScSolverSuccessDialog(weld::Window* pParent, std::u16string_view rSolution)
83  : GenericDialogController(pParent, "modules/scalc/ui/solversuccessdialog.ui", "SolverSuccessDialog")
84  , m_xFtResult(m_xBuilder->weld_label("result"))
85  , m_xBtnOk(m_xBuilder->weld_button("ok"))
86  , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
87 {
88  m_xBtnOk->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
89  m_xBtnCancel->connect_clicked(LINK(this, ScSolverSuccessDialog, ClickHdl));
90  OUString aMessage = m_xFtResult->get_label() + " " + rSolution;
91  m_xFtResult->set_label(aMessage);
92 }
93 
95 {
96 }
97 
99 {
100  if (&rBtn == m_xBtnOk.get())
101  m_xDialog->response(RET_OK);
102  else
103  m_xDialog->response(RET_CANCEL);
104 }
105 
106 ScCursorRefEdit::ScCursorRefEdit(std::unique_ptr<weld::Entry> xControl)
107  : formula::RefEdit(std::move(xControl))
108 {
109  xEntry->connect_key_press(Link<const KeyEvent&, bool>()); //acknowledge we first remove the old one
110  xEntry->connect_key_press(LINK(this, ScCursorRefEdit, KeyInputHdl));
111 }
112 
114 {
115  maCursorUpLink = rUp;
116  maCursorDownLink = rDown;
117 }
118 
119 IMPL_LINK(ScCursorRefEdit, KeyInputHdl, const KeyEvent&, rKEvt, bool)
120 {
121  vcl::KeyCode aCode = rKEvt.GetKeyCode();
122  bool bUp = (aCode.GetCode() == KEY_UP);
123  bool bDown = (aCode.GetCode() == KEY_DOWN);
124  if ( !aCode.IsShift() && !aCode.IsMod1() && !aCode.IsMod2() && ( bUp || bDown ) )
125  {
126  if ( bUp )
127  maCursorUpLink.Call( *this );
128  else
129  maCursorDownLink.Call( *this );
130  return true;
131  }
132  return formula::RefEdit::KeyInput(rKEvt);
133 }
134 
135 ScOptSolverSave::ScOptSolverSave( const OUString& rObjective, bool bMax, bool bMin, bool bValue,
136  const OUString& rTarget, const OUString& rVariable,
137  std::vector<ScOptConditionRow>&& rConditions,
138  const OUString& rEngine,
139  const uno::Sequence<beans::PropertyValue>& rProperties ) :
140  maObjective( rObjective ),
141  mbMax( bMax ),
142  mbMin( bMin ),
143  mbValue( bValue ),
144  maTarget( rTarget ),
145  maVariable( rVariable ),
146  maConditions( std::move(rConditions) ),
147  maEngine( rEngine ),
148  maProperties( rProperties )
149 {
150 }
151 
153  ScDocShell* pDocSh, const ScAddress& aCursorPos)
154  : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/solverdlg.ui", "SolverDialog")
155  , maInputError(ScResId(STR_INVALIDINPUT))
156  , maConditionError(ScResId(STR_INVALIDCONDITION))
157 
158  , mpDocShell(pDocSh)
159  , mrDoc(pDocSh->GetDocument())
160  , mnCurTab(aCursorPos.Tab())
161  , mbDlgLostFocus(false)
162  , nScrollPos(0)
163  , mpEdActive(nullptr)
164  , m_xFtObjectiveCell(m_xBuilder->weld_label("targetlabel"))
165  , m_xEdObjectiveCell(new formula::RefEdit(m_xBuilder->weld_entry("targetedit")))
166  , m_xRBObjectiveCell(new formula::RefButton(m_xBuilder->weld_button("targetbutton")))
167  , m_xRbMax(m_xBuilder->weld_radio_button("max"))
168  , m_xRbMin(m_xBuilder->weld_radio_button("min"))
169  , m_xRbValue(m_xBuilder->weld_radio_button("value"))
170  , m_xEdTargetValue(new formula::RefEdit(m_xBuilder->weld_entry("valueedit")))
171  , m_xRBTargetValue(new formula::RefButton(m_xBuilder->weld_button("valuebutton")))
172  , m_xFtVariableCells(m_xBuilder->weld_label("changelabel"))
173  , m_xEdVariableCells(new formula::RefEdit(m_xBuilder->weld_entry("changeedit")))
174  , m_xRBVariableCells(new formula::RefButton(m_xBuilder->weld_button("changebutton")))
175  , m_xFtCellRef(m_xBuilder->weld_label("cellreflabel"))
176  , m_xEdLeft1(new ScCursorRefEdit(m_xBuilder->weld_entry("ref1edit")))
177  , m_xRBLeft1(new formula::RefButton(m_xBuilder->weld_button("ref1button")))
178  , m_xFtOperator(m_xBuilder->weld_label("oplabel"))
179  , m_xLbOp1(m_xBuilder->weld_combo_box("op1list"))
180  , m_xFtConstraint(m_xBuilder->weld_label("constraintlabel"))
181  , m_xEdRight1(new ScCursorRefEdit(m_xBuilder->weld_entry("val1edit")))
182  , m_xRBRight1(new formula::RefButton(m_xBuilder->weld_button("val1button")))
183  , m_xBtnDel1(m_xBuilder->weld_button("del1"))
184  , m_xEdLeft2(new ScCursorRefEdit(m_xBuilder->weld_entry("ref2edit")))
185  , m_xRBLeft2(new formula::RefButton(m_xBuilder->weld_button("ref2button")))
186  , m_xLbOp2(m_xBuilder->weld_combo_box("op2list"))
187  , m_xEdRight2(new ScCursorRefEdit(m_xBuilder->weld_entry("val2edit")))
188  , m_xRBRight2(new formula::RefButton(m_xBuilder->weld_button("val2button")))
189  , m_xBtnDel2(m_xBuilder->weld_button("del2"))
190  , m_xEdLeft3(new ScCursorRefEdit(m_xBuilder->weld_entry("ref3edit")))
191  , m_xRBLeft3(new formula::RefButton(m_xBuilder->weld_button("ref3button")))
192  , m_xLbOp3(m_xBuilder->weld_combo_box("op3list"))
193  , m_xEdRight3(new ScCursorRefEdit(m_xBuilder->weld_entry("val3edit")))
194  , m_xRBRight3(new formula::RefButton(m_xBuilder->weld_button("val3button")))
195  , m_xBtnDel3(m_xBuilder->weld_button("del3"))
196  , m_xEdLeft4(new ScCursorRefEdit(m_xBuilder->weld_entry("ref4edit")))
197  , m_xRBLeft4(new formula::RefButton(m_xBuilder->weld_button("ref4button")))
198  , m_xLbOp4(m_xBuilder->weld_combo_box("op4list"))
199  , m_xEdRight4(new ScCursorRefEdit(m_xBuilder->weld_entry("val4edit")))
200  , m_xRBRight4(new formula::RefButton(m_xBuilder->weld_button("val4button")))
201  , m_xBtnDel4(m_xBuilder->weld_button("del4"))
202  , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar", true))
203  , m_xBtnOpt(m_xBuilder->weld_button("options"))
204  , m_xBtnClose(m_xBuilder->weld_button("close"))
205  , m_xBtnSolve(m_xBuilder->weld_button("ok"))
206  , m_xBtnResetAll(m_xBuilder->weld_button("resetall"))
207  , m_xResultFT(m_xBuilder->weld_label("result"))
208  , m_xContents(m_xBuilder->weld_widget("grid"))
209 {
210  m_xEdObjectiveCell->SetReferences(this, m_xFtObjectiveCell.get());
211  m_xRBObjectiveCell->SetReferences(this, m_xEdObjectiveCell.get());
212  m_xEdTargetValue->SetReferences(this, m_xResultFT.get());
213  m_xRBTargetValue->SetReferences(this, m_xEdTargetValue.get());
214  m_xEdVariableCells->SetReferences(this, m_xFtVariableCells.get());
215  m_xRBVariableCells->SetReferences(this, m_xEdVariableCells.get());
216  m_xEdLeft1->SetReferences(this, m_xFtCellRef.get());
217  m_xRBLeft1->SetReferences(this, m_xEdLeft1.get());
218  m_xEdRight1->SetReferences(this, m_xFtConstraint.get());
219  m_xRBRight1->SetReferences(this, m_xEdRight1.get());
220  m_xEdLeft2->SetReferences(this, m_xFtCellRef.get());
221  m_xRBLeft2->SetReferences(this, m_xEdLeft2.get());
222  m_xEdRight2->SetReferences(this, m_xFtConstraint.get());
223  m_xRBRight2->SetReferences(this, m_xEdRight2.get());
224  m_xEdLeft3->SetReferences(this, m_xFtCellRef.get());
225  m_xRBLeft3->SetReferences(this, m_xEdLeft3.get());
226  m_xEdRight3->SetReferences(this, m_xFtConstraint.get());
227  m_xRBRight3->SetReferences(this, m_xEdRight3.get());
228  m_xEdLeft4->SetReferences(this, m_xFtCellRef.get());
229  m_xRBLeft4->SetReferences(this, m_xEdLeft4.get());
230  m_xEdRight4->SetReferences(this, m_xFtConstraint.get());
231  m_xRBRight4->SetReferences(this, m_xEdRight4.get());
232 
233  mpLeftEdit[0] = m_xEdLeft1.get();
234  mpLeftButton[0] = m_xRBLeft1.get();
235  mpRightEdit[0] = m_xEdRight1.get();
236  mpRightButton[0] = m_xRBRight1.get();
237  mpOperator[0] = m_xLbOp1.get();
238  mpDelButton[0] = m_xBtnDel1.get();
239 
240  mpLeftEdit[1] = m_xEdLeft2.get();
241  mpLeftButton[1] = m_xRBLeft2.get();
242  mpRightEdit[1] = m_xEdRight2.get();
243  mpRightButton[1] = m_xRBRight2.get();
244  mpOperator[1] = m_xLbOp2.get();
245  mpDelButton[1] = m_xBtnDel2.get();
246 
247  mpLeftEdit[2] = m_xEdLeft3.get();
248  mpLeftButton[2] = m_xRBLeft3.get();
249  mpRightEdit[2] = m_xEdRight3.get();
250  mpRightButton[2] = m_xRBRight3.get();
251  mpOperator[2] = m_xLbOp3.get();
252  mpDelButton[2] = m_xBtnDel3.get();
253 
254  mpLeftEdit[3] = m_xEdLeft4.get();
255  mpLeftButton[3] = m_xRBLeft4.get();
256  mpRightEdit[3] = m_xEdRight4.get();
257  mpRightButton[3] = m_xRBRight4.get();
258  mpOperator[3] = m_xLbOp4.get();
259  mpDelButton[3] = m_xBtnDel4.get();
260 
261  Init( aCursorPos );
262 }
263 
265 {
266 }
267 
268 void ScOptSolverDlg::Init(const ScAddress& rCursorPos)
269 {
270  uno::Reference<frame::XFrame> xFrame = GetBindings().GetActiveFrame();
271  auto xDelNm = vcl::CommandInfoProvider::GetXGraphicForCommand(".uno:DeleteRows", xFrame);
272  for (weld::Button* pButton : mpDelButton)
273  pButton->set_image(xDelNm);
274 
275  m_xBtnOpt->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
276  m_xBtnClose->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
277  m_xBtnSolve->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
278  m_xBtnResetAll->connect_clicked( LINK( this, ScOptSolverDlg, BtnHdl ) );
279 
280  Link<formula::RefEdit&,void> aEditLink = LINK( this, ScOptSolverDlg, GetEditFocusHdl );
281  Link<formula::RefButton&,void> aButtonLink = LINK( this, ScOptSolverDlg, GetButtonFocusHdl );
282  m_xEdObjectiveCell->SetGetFocusHdl( aEditLink );
283  m_xRBObjectiveCell->SetGetFocusHdl( aButtonLink );
284  m_xEdTargetValue->SetGetFocusHdl( aEditLink );
285  m_xRBTargetValue->SetGetFocusHdl( aButtonLink );
286  m_xEdVariableCells->SetGetFocusHdl( aEditLink );
287  m_xRBVariableCells->SetGetFocusHdl( aButtonLink );
288  Link<weld::Widget&,void> aLink = LINK(this, ScOptSolverDlg, GetFocusHdl);
289  m_xRbValue->connect_focus_in(aLink);
290  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
291  {
292  mpLeftEdit[nRow]->SetGetFocusHdl( aEditLink );
293  mpLeftButton[nRow]->SetGetFocusHdl( aButtonLink );
294  mpRightEdit[nRow]->SetGetFocusHdl( aEditLink );
295  mpRightButton[nRow]->SetGetFocusHdl( aButtonLink );
296  mpOperator[nRow]->connect_focus_in(aLink);
297  }
298 
299  aEditLink = LINK( this, ScOptSolverDlg, LoseEditFocusHdl );
300  aButtonLink = LINK( this, ScOptSolverDlg, LoseButtonFocusHdl );
301  m_xEdObjectiveCell->SetLoseFocusHdl( aEditLink );
302  m_xRBObjectiveCell->SetLoseFocusHdl( aButtonLink );
303  m_xEdTargetValue->SetLoseFocusHdl( aEditLink );
304  m_xRBTargetValue-> SetLoseFocusHdl( aButtonLink );
305  m_xEdVariableCells->SetLoseFocusHdl( aEditLink );
306  m_xRBVariableCells->SetLoseFocusHdl( aButtonLink );
307  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
308  {
309  mpLeftEdit[nRow]->SetLoseFocusHdl( aEditLink );
310  mpLeftButton[nRow]->SetLoseFocusHdl( aButtonLink );
311  mpRightEdit[nRow]->SetLoseFocusHdl( aEditLink );
312  mpRightButton[nRow]->SetLoseFocusHdl( aButtonLink );
313  }
314 
315  Link<ScCursorRefEdit&,void> aCursorUp = LINK( this, ScOptSolverDlg, CursorUpHdl );
316  Link<ScCursorRefEdit&,void> aCursorDown = LINK( this, ScOptSolverDlg, CursorDownHdl );
317  Link<formula::RefEdit&,void> aCondModify = LINK( this, ScOptSolverDlg, CondModifyHdl );
318  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
319  {
320  mpLeftEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
321  mpRightEdit[nRow]->SetCursorLinks( aCursorUp, aCursorDown );
322  mpLeftEdit[nRow]->SetModifyHdl( aCondModify );
323  mpRightEdit[nRow]->SetModifyHdl( aCondModify );
324  mpDelButton[nRow]->connect_clicked( LINK( this, ScOptSolverDlg, DelBtnHdl ) );
325  mpOperator[nRow]->connect_changed( LINK( this, ScOptSolverDlg, SelectHdl ) );
326  }
327  m_xEdTargetValue->SetModifyHdl( LINK( this, ScOptSolverDlg, TargetModifyHdl ) );
328 
329  Size aSize(m_xContents->get_preferred_size());
330  m_xContents->set_size_request(aSize.Width(), aSize.Height());
331  m_xScrollBar->connect_vadjustment_changed( LINK( this, ScOptSolverDlg, ScrollHdl ) );
332 
333  m_xScrollBar->vadjustment_set_page_increment( EDIT_ROW_COUNT );
334  m_xScrollBar->vadjustment_set_page_size( EDIT_ROW_COUNT );
335  // Range is set in ShowConditions
336 
337  // get available solver implementations
340  bool bImplHasElements = maImplNames.hasElements();
341 
342  const ScOptSolverSave* pOldData = mpDocShell->GetSolverSaveData();
343  if ( pOldData )
344  {
345  m_xEdObjectiveCell->SetRefString( pOldData->GetObjective() );
346  m_xRbMax->set_active( pOldData->GetMax() );
347  m_xRbMin->set_active( pOldData->GetMin() );
348  m_xRbValue->set_active( pOldData->GetValue() );
349  m_xEdTargetValue->SetRefString( pOldData->GetTarget() );
350  m_xEdVariableCells->SetRefString( pOldData->GetVariable() );
351  maConditions = pOldData->GetConditions();
352  maEngine = pOldData->GetEngine();
353  maProperties = pOldData->GetProperties();
354  }
355  else
356  {
357  m_xRbMax->set_active(true);
358  OUString aCursorStr;
359  if ( !mrDoc.GetRangeAtBlock( ScRange(rCursorPos), aCursorStr ) )
360  aCursorStr = rCursorPos.Format(ScRefFlags::ADDR_ABS, nullptr, mrDoc.GetAddressConvention());
361  m_xEdObjectiveCell->SetRefString( aCursorStr );
362  if ( bImplHasElements )
363  maEngine = maImplNames[0]; // use first implementation
364  }
365  ShowConditions();
366 
367  m_xEdObjectiveCell->GrabFocus();
369 }
370 
372 {
373  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
374  {
375  ScOptConditionRow aRowEntry;
376  aRowEntry.aLeftStr = mpLeftEdit[nRow]->GetText();
377  aRowEntry.aRightStr = mpRightEdit[nRow]->GetText();
378  aRowEntry.nOperator = mpOperator[nRow]->get_active();
379 
380  tools::Long nVecPos = nScrollPos + nRow;
381  if ( nVecPos >= static_cast<tools::Long>(maConditions.size()) && !aRowEntry.IsDefault() )
382  maConditions.resize( nVecPos + 1 );
383 
384  if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
385  maConditions[nVecPos] = aRowEntry;
386 
387  // remove default entries at the end
388  size_t nSize = maConditions.size();
389  while ( nSize > 0 && maConditions[ nSize-1 ].IsDefault() )
390  --nSize;
391  maConditions.resize( nSize );
392  }
393 }
394 
396 {
397  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
398  {
399  ScOptConditionRow aRowEntry;
400 
401  tools::Long nVecPos = nScrollPos + nRow;
402  if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
403  aRowEntry = maConditions[nVecPos];
404 
405  mpLeftEdit[nRow]->SetRefString( aRowEntry.aLeftStr );
406  mpRightEdit[nRow]->SetRefString( aRowEntry.aRightStr );
407  mpOperator[nRow]->set_active( aRowEntry.nOperator );
408  }
409 
410  // allow to scroll one page behind the visible or stored rows
412  tools::Long nMax = std::max( nVisible, static_cast<tools::Long>(maConditions.size()) );
413  m_xScrollBar->vadjustment_configure(nScrollPos, 0, nMax + EDIT_ROW_COUNT, 1,
414  EDIT_ROW_COUNT - 1, EDIT_ROW_COUNT);
415 
416  EnableButtons();
417 }
418 
420 {
421  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
422  {
423  tools::Long nVecPos = nScrollPos + nRow;
424  mpDelButton[nRow]->set_sensitive(nVecPos < static_cast<tools::Long>(maConditions.size()));
425  }
426 }
427 
429 {
430  if (m_xOptDlg)
431  m_xOptDlg->response(RET_CANCEL);
432  assert(!m_xOptDlg);
433  DoClose( ScOptSolverDlgWrapper::GetChildWindowId() );
434 }
435 
437 {
438  if ( mbDlgLostFocus )
439  {
440  mbDlgLostFocus = false;
441  if( mpEdActive )
443  }
444  else
445  {
446  m_xDialog->grab_focus();
447  }
448  RefInputDone();
449 }
450 
452 {
453  if( !mpEdActive )
454  return;
455 
456  if ( rRef.aStart != rRef.aEnd )
458 
459  // "target"/"value": single cell
460  bool bSingle = ( mpEdActive == m_xEdObjectiveCell.get() || mpEdActive == m_xEdTargetValue.get() );
461 
462  OUString aStr;
463  ScAddress aAdr = rRef.aStart;
464  ScRange aNewRef( rRef );
465  if ( bSingle )
466  aNewRef.aEnd = aAdr;
467 
468  OUString aName;
469  if ( rDocP.GetRangeAtBlock( aNewRef, aName ) ) // named range: show name
470  aStr = aName;
471  else // format cell/range reference
472  {
474  if ( bSingle )
475  aStr = aAdr.Format(nFmt, &rDocP, rDocP.GetAddressConvention());
476  else
477  aStr = rRef.Format(rDocP, nFmt | ScRefFlags::RANGE_ABS, rDocP.GetAddressConvention());
478  }
479 
480  // variable cells can be several ranges, so only the selection is replaced
481  if ( mpEdActive == m_xEdVariableCells.get() )
482  {
483  OUString aVal = mpEdActive->GetText();
485  aSel.Justify();
486  aVal = aVal.replaceAt( aSel.Min(), aSel.Len(), aStr );
487  Selection aNewSel( aSel.Min(), aSel.Min()+aStr.getLength() );
488  mpEdActive->SetRefString( aVal );
489  mpEdActive->SetSelection( aNewSel );
490  }
491  else
492  mpEdActive->SetRefString( aStr );
493 
494  ReadConditions();
495  EnableButtons();
496 
497  // select "Value of" if a ref is input into "target" edit
498  if ( mpEdActive == m_xEdTargetValue.get() )
499  m_xRbValue->set_active(true);
500 }
501 
503 {
504  return mpEdActive != nullptr;
505 }
506 
507 // Handler:
508 
509 IMPL_LINK(ScOptSolverDlg, BtnHdl, weld::Button&, rBtn, void)
510 {
511  auto xKeepAlive = shared_from_this();
512  if (&rBtn == m_xBtnSolve.get() || &rBtn == m_xBtnClose.get())
513  {
514  bool bSolve = ( &rBtn == m_xBtnSolve.get() );
515 
516  SetDispatcherLock( false );
517  SwitchToDocument();
518 
519  bool bClose = true;
520  if ( bSolve )
521  bClose = CallSolver();
522 
523  if ( bClose )
524  {
525  // Close: write dialog settings to DocShell for subsequent calls
526  ReadConditions();
527  std::unique_ptr<ScOptSolverSave> pSave( new ScOptSolverSave(
528  m_xEdObjectiveCell->GetText(), m_xRbMax->get_active(), m_xRbMin->get_active(), m_xRbValue->get_active(),
529  m_xEdTargetValue->GetText(), m_xEdVariableCells->GetText(), std::vector(maConditions), maEngine, maProperties ) );
530  mpDocShell->SetSolverSaveData( std::move(pSave) );
531  response(RET_CLOSE);
532  }
533  else
534  {
535  // no solution -> dialog is kept open
536  SetDispatcherLock( true );
537  }
538  }
539  else if (&rBtn == m_xBtnOpt.get())
540  {
542  m_xOptDlg = std::make_shared<ScSolverOptionsDialog>(m_xDialog.get(), maImplNames, maDescriptions, maEngine, maProperties);
543  weld::DialogController::runAsync(m_xOptDlg, [this](sal_Int32 nResult){
544  if (nResult == RET_OK)
545  {
546  maEngine = m_xOptDlg->GetEngine();
547  maProperties = m_xOptDlg->GetProperties();
548  }
549  m_xOptDlg.reset();
550  });
551  }
552  else if (&rBtn == m_xBtnResetAll.get())
553  {
554  OUString sEmpty;
555  m_xEdObjectiveCell->SetText(sEmpty);
556  m_xEdTargetValue->SetText(sEmpty);
557  m_xEdVariableCells->SetText(sEmpty);
558 
559  // Get default property values of solver implementations
560  maEngine = maImplNames[0];
562 
563  // Clear all conditions (Constraints)
564  maConditions.clear();
565  std::unique_ptr<ScOptSolverSave> pEmpty( new ScOptSolverSave(
566  sEmpty, true, false, false,
567  sEmpty, sEmpty, std::vector(maConditions), maEngine, maProperties ) );
568  mpDocShell->SetSolverSaveData( std::move(pEmpty) );
569  ShowConditions();
570 
571  m_xRbMax->set_active(true);
572  m_xEdObjectiveCell->GrabFocus();
573  mpEdActive = m_xEdObjectiveCell.get();
574  }
575 }
576 
577 IMPL_LINK( ScOptSolverDlg, GetEditFocusHdl, formula::RefEdit&, rCtrl, void )
578 {
579  formula::RefEdit* pEdit = nullptr;
580  mpEdActive = nullptr;
581 
582  if( &rCtrl == m_xEdObjectiveCell.get() )
583  pEdit = mpEdActive = m_xEdObjectiveCell.get();
584  else if( &rCtrl == m_xEdTargetValue.get() )
585  pEdit = mpEdActive = m_xEdTargetValue.get();
586  else if( &rCtrl == m_xEdVariableCells.get() )
587  pEdit = mpEdActive = m_xEdVariableCells.get();
588  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
589  {
590  if( &rCtrl == mpLeftEdit[nRow] )
591  pEdit = mpEdActive = mpLeftEdit[nRow];
592  else if( &rCtrl == mpRightEdit[nRow] )
593  pEdit = mpEdActive = mpRightEdit[nRow];
594  }
595 
596  if( pEdit )
597  pEdit->SelectAll();
598 }
599 
600 IMPL_LINK( ScOptSolverDlg, GetButtonFocusHdl, formula::RefButton&, rCtrl, void )
601 {
602  formula::RefEdit* pEdit = nullptr;
603  mpEdActive = nullptr;
604 
605  if( &rCtrl == m_xRBObjectiveCell.get() )
606  pEdit = mpEdActive = m_xEdObjectiveCell.get();
607  else if( &rCtrl == m_xRBTargetValue.get() )
608  pEdit = mpEdActive = m_xEdTargetValue.get();
609  else if( &rCtrl == m_xRBVariableCells.get() )
610  pEdit = mpEdActive = m_xEdVariableCells.get();
611  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
612  {
613  if( &rCtrl == mpLeftButton[nRow] )
614  pEdit = mpEdActive = mpLeftEdit[nRow];
615  else if( &rCtrl == mpRightButton[nRow] )
616  pEdit = mpEdActive = mpRightEdit[nRow];
617  }
618 
619  if( pEdit )
620  pEdit->SelectAll();
621 }
622 
623 
624 IMPL_LINK(ScOptSolverDlg, GetFocusHdl, weld::Widget&, rCtrl, void)
625 {
626  if( &rCtrl == m_xRbValue.get() ) // focus on "Value of" radio button
627  mpEdActive = m_xEdTargetValue.get(); // use value edit for ref input, but don't change selection
628  else
629  {
630  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
631  {
632  if( &rCtrl == mpOperator[nRow] ) // focus on "operator" list box
633  mpEdActive = mpRightEdit[nRow]; // use right edit for ref input, but don't change selection
634  }
635  }
636 }
637 
639 {
640  mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
641 }
642 
644 {
645  mbDlgLostFocus = !m_xDialog->has_toplevel_focus();
646 }
647 
648 IMPL_LINK(ScOptSolverDlg, DelBtnHdl, weld::Button&, rBtn, void)
649 {
650  for ( sal_uInt16 nRow = 0; nRow < EDIT_ROW_COUNT; ++nRow )
651  if (&rBtn == mpDelButton[nRow])
652  {
653  bool bHadFocus = rBtn.has_focus();
654 
655  ReadConditions();
656  tools::Long nVecPos = nScrollPos + nRow;
657  if ( nVecPos < static_cast<tools::Long>(maConditions.size()) )
658  {
659  maConditions.erase( maConditions.begin() + nVecPos );
660  ShowConditions();
661 
662  if ( bHadFocus && !rBtn.get_sensitive() )
663  {
664  // If the button is disabled, focus would normally move to the next control,
665  // (left edit of the next row). Move it to left edit of this row instead.
666 
667  mpEdActive = mpLeftEdit[nRow];
668  mpEdActive->GrabFocus();
669  }
670  }
671  }
672 }
673 
675 {
676  // modify handler for the target edit:
677  // select "Value of" if something is input into the edit
678  if ( !m_xEdTargetValue->GetText().isEmpty() )
679  m_xRbValue->set_active(true);
680 }
681 
683 {
684  // modify handler for the condition edits, just to enable/disable "delete" buttons
685  ReadConditions();
686  EnableButtons();
687 }
688 
690 {
691  // select handler for operator list boxes, just to enable/disable "delete" buttons
692  ReadConditions();
693  EnableButtons();
694 }
695 
697 {
698  ReadConditions();
699  nScrollPos = m_xScrollBar->vadjustment_get_value();
700  ShowConditions();
701  if( mpEdActive )
702  mpEdActive->SelectAll();
703 }
704 
705 IMPL_LINK( ScOptSolverDlg, CursorUpHdl, ScCursorRefEdit&, rEdit, void )
706 {
707  if ( &rEdit == mpLeftEdit[0] || &rEdit == mpRightEdit[0] )
708  {
709  if ( nScrollPos > 0 )
710  {
711  ReadConditions();
712  --nScrollPos;
713  ShowConditions();
714  if( mpEdActive )
715  mpEdActive->SelectAll();
716  }
717  }
718  else
719  {
720  formula::RefEdit* pFocus = nullptr;
721  for ( sal_uInt16 nRow = 1; nRow < EDIT_ROW_COUNT; ++nRow ) // second row or below: move focus
722  {
723  if ( &rEdit == mpLeftEdit[nRow] )
724  pFocus = mpLeftEdit[nRow-1];
725  else if ( &rEdit == mpRightEdit[nRow] )
726  pFocus = mpRightEdit[nRow-1];
727  }
728  if (pFocus)
729  {
730  mpEdActive = pFocus;
731  pFocus->GrabFocus();
732  }
733  }
734 }
735 
736 IMPL_LINK( ScOptSolverDlg, CursorDownHdl, ScCursorRefEdit&, rEdit, void )
737 {
738  if ( &rEdit == mpLeftEdit[EDIT_ROW_COUNT-1] || &rEdit == mpRightEdit[EDIT_ROW_COUNT-1] )
739  {
741  ReadConditions();
742  ++nScrollPos;
743  ShowConditions();
744  if( mpEdActive )
745  mpEdActive->SelectAll();
746  }
747  else
748  {
749  formula::RefEdit* pFocus = nullptr;
750  for ( sal_uInt16 nRow = 0; nRow+1 < EDIT_ROW_COUNT; ++nRow ) // before last row: move focus
751  {
752  if ( &rEdit == mpLeftEdit[nRow] )
753  pFocus = mpLeftEdit[nRow+1];
754  else if ( &rEdit == mpRightEdit[nRow] )
755  pFocus = mpRightEdit[nRow+1];
756  }
757  if (pFocus)
758  {
759  mpEdActive = pFocus;
760  pFocus->GrabFocus();
761  }
762  }
763 }
764 
765 void ScOptSolverDlg::ShowError( bool bCondition, formula::RefEdit* pFocus )
766 {
767  OUString aMessage = bCondition ? maConditionError : maInputError;
768  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
769  VclMessageType::Warning, VclButtonsType::Ok,
770  aMessage));
771  xBox->run();
772  if (pFocus)
773  {
774  mpEdActive = pFocus;
775  pFocus->GrabFocus();
776  }
777 }
778 
779 bool ScOptSolverDlg::ParseRef( ScRange& rRange, const OUString& rInput, bool bAllowRange )
780 {
782  ScRefFlags nFlags = rRange.ParseAny( rInput, mrDoc, aDetails );
783  if ( nFlags & ScRefFlags::VALID )
784  {
785  if ( (nFlags & ScRefFlags::TAB_3D) == ScRefFlags::ZERO)
786  rRange.aStart.SetTab( mnCurTab );
787  if ( (nFlags & ScRefFlags::TAB2_3D) == ScRefFlags::ZERO)
788  rRange.aEnd.SetTab( rRange.aStart.Tab() );
789  return ( bAllowRange || rRange.aStart == rRange.aEnd );
790  }
791  else if ( ScRangeUtil::MakeRangeFromName( rInput, mrDoc, mnCurTab, rRange, RUTL_NAMES, aDetails ) )
792  return ( bAllowRange || rRange.aStart == rRange.aEnd );
793 
794  return false; // not recognized
795 }
796 
797 bool ScOptSolverDlg::FindTimeout( sal_Int32& rTimeout )
798 {
799  bool bFound = false;
800 
801  if ( !maProperties.hasElements() )
802  maProperties = ScSolverUtil::GetDefaults( maEngine ); // get property defaults from component
803 
804  sal_Int32 nPropCount = maProperties.getLength();
805  for (sal_Int32 nProp=0; nProp<nPropCount && !bFound; ++nProp)
806  {
807  const beans::PropertyValue& rValue = maProperties[nProp];
808  if ( rValue.Name == SC_UNONAME_TIMEOUT )
809  bFound = ( rValue.Value >>= rTimeout );
810  }
811  return bFound;
812 }
813 
814 bool ScOptSolverDlg::CallSolver() // return true -> close dialog after calling
815 {
816  // show progress dialog
817 
818  auto xProgress = std::make_shared<ScSolverProgressDialog>(m_xDialog.get());
819  sal_Int32 nTimeout = 0;
820  if ( FindTimeout( nTimeout ) )
821  xProgress->SetTimeLimit( nTimeout );
822  else
823  xProgress->HideTimeLimit();
824 
825  weld::DialogController::runAsync(xProgress, [](sal_Int32 /*nResult*/){});
826 
827  // try to make sure the progress dialog is painted before continuing
829 
830  // collect solver parameters
831 
832  ReadConditions();
833 
834  uno::Reference<sheet::XSpreadsheetDocument> xDocument( mpDocShell->GetModel(), uno::UNO_QUERY );
835 
836  ScRange aObjRange;
837  if ( !ParseRef( aObjRange, m_xEdObjectiveCell->GetText(), false ) )
838  {
839  ShowError( false, m_xEdObjectiveCell.get() );
840  return false;
841  }
842  table::CellAddress aObjective( aObjRange.aStart.Tab(), aObjRange.aStart.Col(), aObjRange.aStart.Row() );
843 
844  // "changing cells" can be several ranges
845  ScRangeList aVarRanges;
846  if ( !ParseWithNames( aVarRanges, m_xEdVariableCells->GetText(), mrDoc ) )
847  {
848  ShowError( false, m_xEdVariableCells.get() );
849  return false;
850  }
851  uno::Sequence<table::CellAddress> aVariables;
852  sal_Int32 nVarPos = 0;
853 
854  for ( size_t nRangePos=0, nRange = aVarRanges.size(); nRangePos < nRange; ++nRangePos )
855  {
856  ScRange aRange( aVarRanges[ nRangePos ] );
857  aRange.PutInOrder();
858  SCTAB nTab = aRange.aStart.Tab();
859 
860  // resolve into single cells
861 
862  sal_Int32 nAdd = ( aRange.aEnd.Col() - aRange.aStart.Col() + 1 ) *
863  ( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
864  aVariables.realloc( nVarPos + nAdd );
865  auto pVariables = aVariables.getArray();
866 
867  for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
868  for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
869  pVariables[nVarPos++] = table::CellAddress( nTab, nCol, nRow );
870  }
871 
872  uno::Sequence<sheet::SolverConstraint> aConstraints;
873  sal_Int32 nConstrPos = 0;
874  for ( const auto& rConstr : maConditions )
875  {
876  if ( !rConstr.aLeftStr.isEmpty() )
877  {
878  sheet::SolverConstraint aConstraint;
879  // order of list box entries must match enum values
880  aConstraint.Operator = static_cast<sheet::SolverConstraintOperator>(rConstr.nOperator);
881 
882  ScRange aLeftRange;
883  if ( !ParseRef( aLeftRange, rConstr.aLeftStr, true ) )
884  {
885  ShowError( true, nullptr );
886  return false;
887  }
888 
889  bool bIsRange = false;
890  ScRange aRightRange;
891  if ( ParseRef( aRightRange, rConstr.aRightStr, true ) )
892  {
893  if ( aRightRange.aStart == aRightRange.aEnd )
894  aConstraint.Right <<= table::CellAddress( aRightRange.aStart.Tab(),
895  aRightRange.aStart.Col(), aRightRange.aStart.Row() );
896  else if ( aRightRange.aEnd.Col()-aRightRange.aStart.Col() == aLeftRange.aEnd.Col()-aLeftRange.aStart.Col() &&
897  aRightRange.aEnd.Row()-aRightRange.aStart.Row() == aLeftRange.aEnd.Row()-aLeftRange.aStart.Row() )
898  bIsRange = true; // same size as "left" range, resolve into single cells
899  else
900  {
901  ShowError( true, nullptr );
902  return false;
903  }
904  }
905  else
906  {
907  sal_uInt32 nFormat = 0;
908  double fValue = 0.0;
909  if ( mrDoc.GetFormatTable()->IsNumberFormat( rConstr.aRightStr, nFormat, fValue ) )
910  aConstraint.Right <<= fValue;
911  else if ( aConstraint.Operator != sheet::SolverConstraintOperator_INTEGER &&
912  aConstraint.Operator != sheet::SolverConstraintOperator_BINARY )
913  {
914  ShowError( true, nullptr );
915  return false;
916  }
917  }
918 
919  // resolve into single cells
920 
921  sal_Int32 nAdd = ( aLeftRange.aEnd.Col() - aLeftRange.aStart.Col() + 1 ) *
922  ( aLeftRange.aEnd.Row() - aLeftRange.aStart.Row() + 1 );
923  aConstraints.realloc( nConstrPos + nAdd );
924 
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  aConstraints[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[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:1775
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:2116
OUString aLeftStr
Definition: optsolver.hxx:50
void SetTimeLimit(sal_Int32 nSeconds)
Definition: optsolver.cxx:64
ScAddress aStart
Definition: address.hxx:499
ScDocShell * mpDocShell
Definition: optsolver.hxx:108
std::unique_ptr< weld::Label > m_xResultFT
Definition: optsolver.hxx:183
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:89
std::unique_ptr< weld::Label > m_xFtErrorText
Definition: optsolver.hxx:226
virtual void SetActive() override
Definition: optsolver.cxx:436
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:451
SCROW Row() const
Definition: address.hxx:261
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:106
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:638
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:94
virtual ~ScOptSolverDlg() override
Definition: optsolver.cxx:264
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:135
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:500
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:98
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:502
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:270
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:765
std::unique_ptr< ScCursorRefEdit > m_xEdLeft1
Definition: optsolver.hxx:146
void Init(const ScAddress &rCursorPos)
Definition: optsolver.cxx:268
std::unique_ptr< weld::ComboBox > m_xLbOp4
Definition: optsolver.hxx:171
void ShowConditions()
Definition: optsolver.cxx:395
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:860
void SetRefString(const OUString &rStr)
void SetTab(SCTAB nTabP)
Definition: address.hxx:282
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:441
void Justify()
std::unique_ptr< formula::RefEdit > m_xEdTargetValue
Definition: optsolver.hxx:138
static bool Reschedule(bool bHandleAllCurrentEvents=false)
void ReadConditions()
Definition: optsolver.cxx:371
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:689
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:2212
void SetCursorLinks(const Link< ScCursorRefEdit &, void > &rUp, const Link< ScCursorRefEdit &, void > &rDown)
Definition: optsolver.cxx:113
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:756
ScSolverNoSolutionDialog(weld::Window *pParent, const OUString &rErrorText)
Definition: optsolver.cxx:71
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:82
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:266
void EnableButtons()
Definition: optsolver.cxx:419
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:152
std::unique_ptr< weld::Entry > xEntry
sal_Int32 SCROW
Definition: types.hxx:17
void PutInOrder()
Definition: address.cxx:1582
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:797
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:55
OUString aName
bool CallSolver()
Definition: optsolver.cxx:814
ScSolverProgressDialog(weld::Window *pParent)
Definition: optsolver.cxx:48
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:428
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:144
std::unique_ptr< formula::RefButton > m_xRBLeft3
Definition: optsolver.hxx:163
std::unique_ptr< ScCursorRefEdit > m_xEdLeft4
Definition: optsolver.hxx:169
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:695
bool ParseRef(ScRange &rRange, const OUString &rInput, bool bAllowRange)
Definition: optsolver.cxx:779
bool ParseWithNames(ScRangeList &rRanges, const OUString &rStr, const ScDocument &pDoc)
Definition: anyrefdg.cxx:736
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:78
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:726
std::unique_ptr< weld::Label > m_xFtResult
Definition: optsolver.hxx:235
formula::RefButton * mpLeftButton[EDIT_ROW_COUNT]
Definition: optsolver.hxx:123
virtual bool KeyInput(const KeyEvent &rKEvt)
bool IsMod2() const
std::unique_ptr< weld::Button > m_xBtnDel3
Definition: optsolver.hxx:167