26#include "kspread_dlg_goalseek.h"
28#include "kspread_canvas.h"
29#include "kspread_cell.h"
30#include "kspread_doc.h"
31#include "kspread_map.h"
33#include "kspread_sheet.h"
34#include "kspread_undo.h"
35#include "kspread_util.h"
36#include "kspread_view.h"
38#include <tdeapplication.h>
41#include <tdemessagebox.h>
42#include <kstdguiitem.h>
43#include <kpushbutton.h>
48#include <tqlineedit.h>
51#include <tqwhatsthis.h>
57GoalSeekDialog::GoalSeekDialog(
View * parent, TQPoint
const & marker,
58 const char * name,
bool, WFlags fl )
59 : KDialog( parent, name, false, fl ),
64 m_anchor( m_pView->selectionInfo()->anchor() ),
65 m_marker( m_pView->selectionInfo()->marker() ),
66 m_selection( m_pView->selectionInfo()->selection() )
68 setWFlags( TQt::WDestructiveClose );
71 setName(
"GoalSeekDialog" );
74 setCaption( i18n(
"Goal Seek" ) );
75 setSizeGripEnabled(
true );
77 GoalSeekDialogLayout =
new TQGridLayout(
this, 1, 1, 11, 6,
"GoalSeekDialogLayout");
79 m_startFrame =
new TQFrame(
this,
"m_startFrame" );
80 m_startFrame->setFrameShape( TQFrame::StyledPanel );
81 m_startFrame->setFrameShadow( TQFrame::Raised );
82 m_startFrameLayout =
new TQGridLayout( m_startFrame, 1, 1, 11, 6,
"m_startFrameLayout");
84 TQLabel * TextLabel4 =
new TQLabel( m_startFrame,
"TextLabel4" );
85 TextLabel4->setText( i18n(
"To value:" ) );
86 m_startFrameLayout->addWidget( TextLabel4, 1, 0 );
88 m_targetValueEdit =
new TQLineEdit( m_startFrame,
"m_targetValueEdit" );
89 m_startFrameLayout->addWidget( m_targetValueEdit, 1, 1 );
91 m_targetEdit =
new TQLineEdit( m_startFrame,
"m_targetEdit" );
92 m_startFrameLayout->addWidget( m_targetEdit, 0, 1 );
93 m_targetEdit->setText(
Cell::name( marker.x(), marker.y() ) );
95 m_sourceEdit =
new TQLineEdit( m_startFrame,
"m_sourceEdit" );
96 m_startFrameLayout->addWidget( m_sourceEdit, 2, 1 );
98 TQLabel * TextLabel5 =
new TQLabel( m_startFrame,
"TextLabel5" );
99 TextLabel5->setText( i18n(
"By changing cell:" ) );
101 m_startFrameLayout->addWidget( TextLabel5, 2, 0 );
103 TQLabel * TextLabel3 =
new TQLabel( m_startFrame,
"TextLabel3" );
104 TextLabel3->setText( i18n(
"Set cell:" ) );
106 m_startFrameLayout->addWidget( TextLabel3, 0, 0 );
107 GoalSeekDialogLayout->addWidget( m_startFrame, 0, 0 );
109 TQVBoxLayout * Layout5 =
new TQVBoxLayout( 0, 0, 6,
"Layout5");
111 m_buttonOk =
new TQPushButton(
this,
"m_buttonOk" );
112 m_buttonOk->setText( i18n(
"&Start" ) );
113 m_buttonOk->setAccel( 276824143 );
114 m_buttonOk->setAutoDefault(
true );
115 m_buttonOk->setDefault(
true );
116 Layout5->addWidget( m_buttonOk );
118 m_buttonCancel =
new KPushButton( KStdGuiItem::cancel(),
this,
"m_buttonCancel" );
119 m_buttonCancel->setAccel( 276824131 );
120 m_buttonCancel->setAutoDefault(
true );
121 Layout5->addWidget( m_buttonCancel );
122 TQSpacerItem* spacer =
new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
123 Layout5->addItem( spacer );
125 GoalSeekDialogLayout->addMultiCellLayout( Layout5, 0, 1, 1, 1 );
127 m_resultFrame =
new TQFrame(
this,
"m_resultFrame" );
128 m_resultFrame->setFrameShape( TQFrame::StyledPanel );
129 m_resultFrame->setFrameShadow( TQFrame::Raised );
130 m_resultFrame->setMinimumWidth( 350 );
131 m_resultFrameLayout =
new TQGridLayout( m_resultFrame, 1, 1, 11, 6,
"m_resultFrameLayout");
133 m_currentValueLabel =
new TQLabel( m_resultFrame,
"m_currentValueLabel" );
134 m_currentValueLabel->setText( i18n(
"Current value:" ) );
136 m_resultFrameLayout->addWidget( m_currentValueLabel, 2, 0 );
138 m_newValueDesc =
new TQLabel( m_resultFrame,
"m_newValueDesc" );
139 m_newValueDesc->setText( i18n(
"New value:" ) );
141 m_resultFrameLayout->addWidget( m_newValueDesc, 1, 0 );
143 m_newValue =
new TQLabel( m_resultFrame,
"m_newValue" );
144 m_newValue->setText(
"m_targetValueEdit" );
146 m_resultFrameLayout->addWidget( m_newValue, 1, 1 );
148 m_currentValue =
new TQLabel( m_resultFrame,
"m_currentValue" );
149 m_currentValue->setText(
"m_currentValue" );
151 m_resultFrameLayout->addWidget( m_currentValue, 2, 1 );
153 m_resultText =
new TQLabel( m_resultFrame,
"m_resultText" );
154 m_resultText->setText(
"Goal seeking with cell <cell> found <a | no> solution:" );
155 m_resultText->setAlignment(
int( TQLabel::WordBreak | TQLabel::AlignVCenter ) );
157 m_resultFrameLayout->addMultiCellWidget( m_resultText, 0, 0, 0, 1 );
161 m_resultFrame->hide();
163 m_sheetName = m_pView->activeSheet()->sheetName();
166 m_pView->canvasWidget()->startChoose();
168 tqApp->installEventFilter(
this );
171 connect( m_buttonOk, TQ_SIGNAL( clicked() ),
this, TQ_SLOT( buttonOkClicked() ) );
172 connect( m_buttonCancel, TQ_SIGNAL( clicked() ),
this, TQ_SLOT( buttonCancelClicked() ) );
174 connect( m_pView->choice(), TQ_SIGNAL(changed(
const Region&)),
175 this, TQ_SLOT(slotSelectionChanged()));
178 setTabOrder( m_targetEdit, m_targetValueEdit );
179 setTabOrder( m_targetValueEdit, m_sourceEdit );
180 setTabOrder( m_sourceEdit, m_buttonOk );
181 setTabOrder( m_buttonOk, m_buttonCancel );
184GoalSeekDialog::~GoalSeekDialog()
186 kdDebug() <<
"~GoalSeekDialog" << endl;
190 m_pView->doc()->emitBeginOperation(
false );
191 m_sourceCell->setValue(m_oldSource);
192 m_targetCell->setCalcDirtyFlag();
193 m_targetCell->calc();
194 m_pView->slotUpdateView( m_pView->activeSheet() );
198bool GoalSeekDialog::eventFilter( TQObject* obj, TQEvent* ev )
200 if ( obj == m_targetValueEdit && ev->type() == TQEvent::FocusIn )
201 m_focus = m_targetValueEdit;
202 else if ( obj == m_targetEdit && ev->type() == TQEvent::FocusIn )
203 m_focus = m_targetEdit;
204 else if ( obj == m_sourceEdit && ev->type() == TQEvent::FocusIn )
205 m_focus = m_sourceEdit;
210 m_pView->canvasWidget()->startChoose();
215void GoalSeekDialog::closeEvent ( TQCloseEvent * e )
220void GoalSeekDialog::slotSelectionChanged()
225 if (m_pView->choice()->isValid())
227 TQString area = m_pView->choice()->name();
228 m_focus->setText( area );
232void GoalSeekDialog::buttonOkClicked()
234 Doc * pDoc = m_pView->doc();
238 Sheet * sheet = m_pView->activeSheet();
240 Point source( m_sourceEdit->text(), sheet->workbook(), sheet );
241 if (!source.isValid())
243 KMessageBox::error(
this, i18n(
"Cell reference is invalid.") );
244 m_sourceEdit->selectAll();
245 m_sourceEdit->setFocus();
247 m_pView->slotUpdateView( m_pView->activeSheet() );
251 Point target( m_targetEdit->text(), sheet->workbook(), sheet );
252 if (!target.isValid())
254 KMessageBox::error(
this, i18n(
"Cell reference is invalid.") );
255 m_targetEdit->selectAll();
256 m_targetEdit->setFocus();
258 m_pView->slotUpdateView( m_pView->activeSheet() );
263 double goal = m_pView->doc()->locale()->readNumber(m_targetValueEdit->text(), &ok );
266 KMessageBox::error(
this, i18n(
"Target value is invalid.") );
267 m_targetValueEdit->selectAll();
268 m_targetValueEdit->setFocus();
270 m_pView->slotUpdateView( m_pView->activeSheet() );
274 m_sourceCell = source.cell();
275 m_targetCell = target.cell();
277 if ( !m_sourceCell->value().isNumber() )
279 KMessageBox::error(
this, i18n(
"Source cell must contain a numeric value.") );
280 m_sourceEdit->selectAll();
281 m_sourceEdit->setFocus();
283 m_pView->slotUpdateView( m_pView->activeSheet() );
287 if ( !m_targetCell->isFormula() )
289 KMessageBox::error(
this, i18n(
"Target cell must contain a formula.") );
290 m_targetEdit->selectAll();
291 m_targetEdit->setFocus();
293 m_pView->slotUpdateView( m_pView->activeSheet() );
297 m_buttonOk->setText( i18n(
"&OK") );
298 m_buttonOk->setEnabled(
false);
299 m_buttonCancel->setEnabled(
false);
300 GoalSeekDialogLayout->addWidget( m_resultFrame, 0, 0 );
301 m_startFrame->hide();
302 m_resultFrame->show();
303 if ( m_startFrame->width() > 350 )
304 m_resultFrame->setMinimumWidth( m_startFrame->width() );
308 startCalc( m_sourceCell->value().asFloat(), goal );
309 m_pView->slotUpdateView( m_pView->activeSheet() );
318 =
new UndoSetText( pDoc, m_pView->activeSheet(), TQString::number(m_oldSource),
319 m_sourceCell->column(), m_sourceCell->row(),
320 m_sourceCell->formatType() );
329 m_pView->slotUpdateView( m_pView->activeSheet() );
333void GoalSeekDialog::buttonCancelClicked()
337 m_pView->doc()->emitBeginOperation(
false );
338 m_sourceCell->setValue(m_oldSource);
339 m_targetCell->setCalcDirtyFlag();
340 m_targetCell->calc();
342 m_pView->slotUpdateView( m_pView->activeSheet() );
349void GoalSeekDialog::chooseCleanup()
351 m_pView->canvasWidget()->endChoose();
356 if ( m_pView->activeSheet()->sheetName() != m_sheetName )
358 sheet = m_pView->doc()->map()->
findSheet( m_sheetName );
360 m_pView->setActiveSheet( sheet );
363 sheet = m_pView->activeSheet();
366 m_pView->selectionInfo()->initialize(TQRect(m_marker, m_anchor));
370void GoalSeekDialog::startCalc(
double _start,
double _goal)
372 m_resultText->setText( i18n(
"Starting..." ) );
373 m_newValueDesc->setText( i18n(
"Iteration:" ) );
379 double eps = 0.0000001;
381 double startA = 0.0, startB;
382 double resultA, resultB;
385 m_oldSource = m_sourceCell->value().asFloat();
390 double x = startB + 0.5;
394 while ( fabs( resultA ) > eps && ( m_maxIter >= 0 ) )
399 m_sourceCell->setValue(startA);
401 m_sourceCell->setCalcDirtyFlag();
402 m_targetCell->calc(
false );
403 resultA = m_targetCell->value().asFloat() - _goal;
406 m_sourceCell->setValue(startB);
408 m_sourceCell->setCalcDirtyFlag();
409 m_targetCell->calc(
false );
410 resultB = m_targetCell->value().asFloat() - _goal;
423 if ( resultB == resultA )
426 if ( fabs( resultA ) < eps )
437 x = ( startA * resultB - startB * resultA ) / ( resultB - resultA );
439 if ( fabs(x) > 100000000 )
449 if ( m_maxIter % 20 == 0 )
450 m_newValue->setText( TQString::number(m_maxIter) );
453 m_newValueDesc->setText( i18n(
"New value:" ) );
456 m_sourceCell->setValue( startA );
457 m_sourceCell->setCalcDirtyFlag();
458 m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect());
460 m_targetCell->calc(
false );
462 m_resultText->setText( i18n(
"Goal seeking with cell %1 found a solution:" ).arg( m_sourceEdit->text() ) );
463 m_newValue->setText( m_pView->doc()->locale()->formatNumber( startA ) );
464 m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) );
470 m_sourceCell->setValue( m_oldSource );
471 m_targetCell->setCalcDirtyFlag();
472 m_sourceCell->sheet()->setRegionPaintDirty(m_sourceCell->cellRect());
473 m_targetCell->calc(
false );
474 m_resultText->setText( i18n(
"Goal seeking with cell %1 has found NO solution." ).arg( m_sourceEdit->text() ) );
475 m_newValue->setText(
"" );
476 m_currentValue->setText( m_pView->doc()->locale()->formatNumber( m_oldSource ) );
480 m_buttonOk->setEnabled(
true );
481 m_buttonCancel->setEnabled(
true );
485#include "kspread_dlg_goalseek.moc"
TQString name() const
Returns the name of the cell.
bool undoLocked() const
Returns true if undo buffer is locked.
void emitBeginOperation(bool waitCursor)
Functions to begin a kspread 'operation'.
void addCommand(KCommand *command)
Adds a command to the command history.
Sheet * findSheet(const TQString &_name)
searches for a sheet named _name
The one for all class for points and ranges.
The View class displays a KSpread document.