File indexing completed on 2024-05-12 16:35:19

0001 /* This file is part of the KDE project
0002    Copyright (C) 2008-2010 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003              (C) 2002-2003 Ariya Hidayat <ariya@kde.org>
0004              (C) 2002-2003 Norbert Andres <nandres@web.de>
0005              (C) 1999-2003 Laurent Montel <montel@kde.org>
0006              (C) 2002 Philipp Mueller <philipp.mueller@gmx.de>
0007              (C) 2002 John Dailey <dailey@vt.edu>
0008              (C) 2002 Daniel Herring <herring@eecs.ku.edu>
0009              (C) 2000-2001 Werner Trobin <trobin@kde.org>
0010              (C) 1998-2000 Torben Weis <weis@kde.org>
0011 
0012    This library is free software; you can redistribute it and/or
0013    modify it under the terms of the GNU Library General Public
0014    License as published by the Free Software Foundation; either
0015    version 2 of the License, or (at your option) any later version.
0016 
0017    This library is distributed in the hope that it will be useful,
0018    but WITHOUT ANY WARRANTY; without even the implied warranty of
0019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0020    Library General Public License for more details.
0021 
0022    You should have received a copy of the GNU Library General Public License
0023    along with this library; see the file COPYING.LIB.  If not, write to
0024    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0025    Boston, MA 02110-1301, USA.
0026 */
0027 
0028 // Local
0029 #include "FormulaDialog.h"
0030 
0031 #include <QTabWidget>
0032 #include <QApplication>
0033 #include <QCloseEvent>
0034 #include <QGridLayout>
0035 #include <QVBoxLayout>
0036 
0037 #include "CalculationSettings.h"
0038 #include "Cell.h"
0039 #include "Function.h"
0040 #include "FunctionDescription.h"
0041 #include "FunctionRepository.h"
0042 #include "Util.h"
0043 #include "ui/CellEditor.h"
0044 #include "Localization.h"
0045 #include "Map.h"
0046 #include "ui/Selection.h"
0047 #include "Sheet.h"
0048 #include "SheetsDebug.h"
0049 
0050 #include <KoIcon.h>
0051 
0052 #include <kcombobox.h>
0053 #include <klineedit.h>
0054 
0055 #include <QDoubleValidator>
0056 #include <QEvent>
0057 #include <QTextBrowser>
0058 #include <QLabel>
0059 #include <QPushButton>
0060 #include <QLayout>
0061 #include <QStringListModel>
0062 #include <QSortFilterProxyModel>
0063 #include <QItemSelectionModel>
0064 
0065 using namespace Calligra::Sheets;
0066 
0067 FormulaDialog::FormulaDialog(QWidget* parent, Selection* selection, CellEditorBase* editor, const QString& formulaName)
0068         : KoDialog(parent)
0069 {
0070     setCaption(i18n("Function"));
0071     setButtons(Ok | Cancel);
0072     //setWFlags( Qt::WDestructiveClose );
0073 
0074     m_selection = selection;
0075     m_editor = editor;
0076     m_focus = 0;
0077     m_desc = 0;
0078 
0079     Cell cell(m_selection->activeSheet(), m_selection->marker());
0080     m_oldText = cell.userInput();
0081     // Make sure that there is a cell editor running.
0082     if (cell.userInput().isEmpty())
0083         m_editor->setText("=");
0084     else if (cell.userInput().at(0) != '=')
0085         m_editor->setText('=' + cell.userInput());
0086     else
0087         m_editor->setText(cell.userInput());
0088 
0089     QWidget *page = new QWidget(this);
0090     setMainWidget(page);
0091 
0092     QGridLayout *grid1 = new QGridLayout(page);
0093 
0094     searchFunct = new KLineEdit(page);
0095     searchFunct->setClearButtonShown(true);
0096     searchFunct->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
0097 
0098     grid1->addWidget(searchFunct, 0, 0);
0099 
0100     typeFunction = new KComboBox(page);
0101     QStringList cats = FunctionRepository::self()->groups();
0102     cats.prepend(i18n("All"));
0103     typeFunction->setMaxVisibleItems(15);
0104     typeFunction->insertItems(0, cats);
0105     grid1->addWidget(typeFunction, 1, 0);
0106 
0107     functions = new QListView(page);
0108     functions->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
0109     functions->setSelectionMode(QAbstractItemView::SingleSelection);
0110     functions->setEditTriggers(QAbstractItemView::NoEditTriggers);
0111     grid1->addWidget(functions, 2, 0);
0112 
0113     functionsModel = new QStringListModel(this);
0114     proxyModel = new QSortFilterProxyModel(functions);
0115     proxyModel->setSourceModel(functionsModel);
0116     proxyModel->setFilterKeyColumn(0);
0117     proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
0118     functions->setModel(proxyModel);
0119 
0120     QItemSelectionModel* selectionmodel = new QItemSelectionModel(proxyModel, this);
0121     functions->setSelectionModel(selectionmodel);
0122     connect(selectionmodel, SIGNAL(currentRowChanged(QModelIndex,QModelIndex)),
0123             this, SLOT(slotSelected()));
0124     // When items are activated on single click, also change the help page on mouse-over, otherwise there is no (easy) way to get
0125     // the help without inserting the function
0126     if (functions->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, 0, functions)) {
0127         connect(functions, SIGNAL(entered(QModelIndex)), this, SLOT(slotIndexSelected(QModelIndex)));
0128         functions->setMouseTracking(true);
0129     }
0130     //connect(proxyModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(slotDataChanged(QModelIndex,QModelIndex)));
0131 
0132     selectFunction = new QPushButton(page);
0133     selectFunction->setToolTip(i18n("Insert function"));
0134     selectFunction->setIcon(koIcon("go-down"));
0135     grid1->addWidget(selectFunction, 3, 0);
0136 
0137     result = new KLineEdit(page);
0138     grid1->addWidget(result, 4, 0, 1, -1);
0139 
0140     m_tabwidget = new QTabWidget(page);
0141     m_tabwidget->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
0142     grid1->addWidget(m_tabwidget, 0, 1, 4, 1);
0143 
0144     m_browser = new QTextBrowser(m_tabwidget);
0145     m_browser->document()->setDefaultStyleSheet("h1 { font-size:x-large; } h2 { font-size:large; } h3 { font-size:medium; }");
0146     m_browser->setMinimumWidth(300);
0147 
0148     m_tabwidget->addTab(m_browser, i18n("Help"));
0149     int index = m_tabwidget->currentIndex();
0150 
0151     m_input = new QWidget(m_tabwidget);
0152     QVBoxLayout *grid2 = new QVBoxLayout(m_input);
0153 
0154     // grid2->setResizeMode (QLayout::Minimum);
0155 
0156     label1 = new QLabel(m_input);
0157     grid2->addWidget(label1);
0158 
0159     firstElement = new KLineEdit(m_input);
0160     grid2->addWidget(firstElement);
0161 
0162     label2 = new QLabel(m_input);
0163     grid2->addWidget(label2);
0164 
0165     secondElement = new KLineEdit(m_input);
0166     grid2->addWidget(secondElement);
0167 
0168     label3 = new QLabel(m_input);
0169     grid2->addWidget(label3);
0170 
0171     thirdElement = new KLineEdit(m_input);
0172     grid2->addWidget(thirdElement);
0173 
0174     label4 = new QLabel(m_input);
0175     grid2->addWidget(label4);
0176 
0177     fourElement = new KLineEdit(m_input);
0178     grid2->addWidget(fourElement);
0179 
0180     label5 = new QLabel(m_input);
0181     grid2->addWidget(label5);
0182 
0183     fiveElement = new KLineEdit(m_input);
0184     grid2->addWidget(fiveElement);
0185 
0186     grid2->addStretch(10);
0187 
0188     m_tabwidget->addTab(m_input, i18n("Parameters"));
0189     m_tabwidget->setTabEnabled(m_tabwidget->indexOf(m_input), false);
0190 
0191     m_tabwidget->setCurrentIndex(index);
0192 
0193     refresh_result = true;
0194 
0195     connect(this, SIGNAL(cancelClicked()), this, SLOT(slotClose()));
0196     connect(this, SIGNAL(okClicked()), this, SLOT(slotOk()));
0197     connect(typeFunction, SIGNAL(activated(QString)),
0198             this, SLOT(slotActivated(QString)));
0199     /*
0200         connect( functions, SIGNAL(highlighted(QString)),
0201                  this, SLOT(slotSelected(QString)) );
0202         connect( functions, SIGNAL(selected(QString)),
0203                  this, SLOT(slotSelected(QString)) );
0204     */
0205     connect(functions, SIGNAL(activated(QModelIndex)),
0206             this , SLOT(slotDoubleClicked(QModelIndex)));
0207 
0208     slotActivated(i18n("All"));
0209 
0210     connect(selectFunction, SIGNAL(clicked()),
0211             this, SLOT(slotSelectButton()));
0212 
0213     connect(firstElement, SIGNAL(textChanged(QString)),
0214             this, SLOT(slotChangeText(QString)));
0215     connect(secondElement, SIGNAL(textChanged(QString)),
0216             this, SLOT(slotChangeText(QString)));
0217     connect(thirdElement, SIGNAL(textChanged(QString)),
0218             this, SLOT(slotChangeText(QString)));
0219     connect(fourElement, SIGNAL(textChanged(QString)),
0220             this, SLOT(slotChangeText(QString)));
0221     connect(fiveElement, SIGNAL(textChanged(QString)),
0222             this, SLOT(slotChangeText(QString)));
0223 
0224     connect(m_selection, SIGNAL(changed(Region)),
0225             this, SLOT(slotSelectionChanged()));
0226 
0227     connect(m_browser, SIGNAL(anchorClicked(QUrl)),
0228             this, SLOT(slotShowFunction(QUrl)));
0229 
0230     // Save the name of the active sheet.
0231     m_sheetName = m_selection->activeSheet()->sheetName();
0232     // Save the cells current text.
0233     QString tmp_oldText = m_editor->toPlainText();
0234     // Position of the cell.
0235     m_column = m_selection->marker().x();
0236     m_row = m_selection->marker().y();
0237 
0238     if (tmp_oldText.isEmpty())
0239         result->setText("=");
0240     else {
0241         if (tmp_oldText.at(0) != '=')
0242             result->setText('=' + tmp_oldText);
0243         else
0244             result->setText(tmp_oldText);
0245     }
0246 
0247     // Allow the user to select cells on the spreadsheet.
0248     m_selection->startReferenceSelection();
0249 
0250     qApp->installEventFilter(this);
0251 
0252     // Was a function name passed along with the constructor ? Then activate it.
0253     if (!formulaName.isEmpty()) {
0254         debugSheets << "formulaName=" << formulaName;
0255 #if 0
0256         QList<QListWidgetItem *> items = functions->findItems(formulaName, Qt::MatchFixedString);
0257         if (items.count() > 0) {
0258             functions->setCurrentItem(items[0]);
0259             slotDoubleClicked(items[0]);
0260         }
0261 #else
0262         int row = functionsModel->stringList().indexOf(formulaName);
0263         const QModelIndex sourcemodelindex = functionsModel->index(row, 0);
0264         const QModelIndex proxymodelindex = proxyModel->mapFromSource(sourcemodelindex);
0265         if (proxymodelindex.isValid()) {
0266             functions->setCurrentIndex(proxymodelindex);
0267             slotDoubleClicked(proxymodelindex);
0268         }
0269 #endif
0270     } else {
0271         // Set keyboard focus to allow selection of a formula.
0272         searchFunct->setFocus();
0273     }
0274 
0275     // Add auto completion.
0276     searchFunct->setCompletionMode(KCompletion::CompletionAuto);
0277     searchFunct->setCompletionObject(&listFunct, true);
0278 
0279     if (functions->currentIndex().isValid())
0280         selectFunction->setEnabled(false);
0281 
0282     connect(searchFunct, SIGNAL(textChanged(QString)),
0283             this, SLOT(slotSearchText(QString)));
0284     connect(searchFunct, SIGNAL(returnPressed()),
0285             this, SLOT(slotPressReturn()));
0286 
0287     resize(QSize(660, 520).expandedTo(minimumSizeHint()));
0288 }
0289 
0290 FormulaDialog::~FormulaDialog()
0291 {
0292     debugSheets << "FormulaDialog::~FormulaDialog()";
0293 }
0294 
0295 void FormulaDialog::slotPressReturn()
0296 {
0297     //laurent 2001-07-07 desactivate this code
0298     //because Calligra Sheets crash.
0299     //TODO fix it
0300     /*
0301     if( !functions->currentText().isEmpty() )
0302         slotDoubleClicked( functions->findItem( functions->currentText() ) );
0303     */
0304 }
0305 
0306 void FormulaDialog::slotSearchText(const QString &_text)
0307 {
0308     proxyModel->setFilterFixedString(_text);
0309     if (functions->currentIndex().isValid())
0310         functions->scrollTo(functions->currentIndex());
0311 }
0312 
0313 bool FormulaDialog::eventFilter(QObject* obj, QEvent* ev)
0314 {
0315     if (obj == firstElement && ev->type() == QEvent::FocusIn)
0316         m_focus = firstElement;
0317     else if (obj == secondElement && ev->type() == QEvent::FocusIn)
0318         m_focus = secondElement;
0319     else if (obj == thirdElement && ev->type() == QEvent::FocusIn)
0320         m_focus = thirdElement;
0321     else if (obj == fourElement && ev->type() == QEvent::FocusIn)
0322         m_focus = fourElement;
0323     else if (obj == fiveElement && ev->type() == QEvent::FocusIn)
0324         m_focus = fiveElement;
0325     else
0326         return false;
0327 
0328     if (m_focus)
0329         m_selection->startReferenceSelection();
0330 
0331     return false;
0332 }
0333 
0334 void FormulaDialog::slotOk()
0335 {
0336     // Pretend none of the text edits have focus; otherwise the next line will change the
0337     // value of whatever parameter has focus to the name of the cell we're editing
0338     m_focus = 0;
0339 
0340     m_selection->endReferenceSelection();
0341 
0342     // Revert the marker to its original position
0343     m_selection->initialize(QPoint(m_column, m_row));
0344 
0345     // If there is still an editor then set the text.
0346     // Usually the editor is always in place.
0347     if (m_editor != 0) {
0348         Q_ASSERT(m_editor);
0349         QString tmp = result->text();
0350         if (tmp.at(0) != '=')
0351             tmp = '=' + tmp;
0352         int pos = m_editor->cursorPosition() + tmp.length();
0353         m_editor->setText(tmp);
0354         m_editor->widget()->setFocus();
0355         m_editor->setCursorPosition(pos);
0356     }
0357 
0358     m_selection->emitModified();
0359     accept();
0360     deleteLater();
0361 }
0362 
0363 void FormulaDialog::slotClose()
0364 {
0365     deleteLater();
0366 
0367     m_selection->endReferenceSelection();
0368 
0369     // Revert the marker to its original position
0370     m_selection->initialize(QPoint(m_column, m_row));
0371 
0372     // If there is still an editor then reset the text.
0373     // Usually the editor is always in place.
0374     if (m_editor != 0) {
0375         Q_ASSERT(m_editor);
0376         m_editor->setText(m_oldText);
0377         m_editor->widget()->setFocus();
0378     }
0379 
0380     m_selection->emitModified();
0381     reject();
0382 }
0383 
0384 void FormulaDialog::slotSelectButton()
0385 {
0386     if (functions->currentIndex().isValid()) {
0387 //slotDoubleClicked(functions->findItem(functions->text(functions->currentItem())));
0388         slotDoubleClicked(functions->currentIndex());
0389     }
0390 }
0391 
0392 void FormulaDialog::slotChangeText(const QString&)
0393 {
0394     // Test the lock
0395     if (!refresh_result)
0396         return;
0397 
0398     if (m_focus == 0)
0399         return;
0400 
0401     QString tmp = m_leftText + m_funcName + '(' + createFormula() + ')' + m_rightText;
0402 
0403     result->setText(tmp);
0404 }
0405 
0406 QString FormulaDialog::createFormula()
0407 {
0408     QString tmp("");
0409 
0410     if (!m_desc)
0411         return QString();
0412 
0413     bool first = true;
0414 
0415     int count = m_desc->params();
0416 
0417     if (!firstElement->text().isEmpty() && count >= 1) {
0418         tmp = tmp + createParameter(firstElement->text(), 0);
0419         first = false;
0420     }
0421 
0422     if (!secondElement->text().isEmpty() && count >= 2) {
0423         first = false;
0424         if (!first)
0425             tmp = tmp + ';' + createParameter(secondElement->text(), 1);
0426         else
0427             tmp = tmp + createParameter(secondElement->text(), 1);
0428     }
0429     if (!thirdElement->text().isEmpty() && count >= 3) {
0430         first = false;
0431         if (!first)
0432             tmp = tmp + ';' + createParameter(thirdElement->text(), 2);
0433         else
0434             tmp = tmp + createParameter(thirdElement->text(), 2);
0435     }
0436     if (!fourElement->text().isEmpty() && count >= 4) {
0437         first = false;
0438         if (!first)
0439             tmp = tmp + ';' + createParameter(fourElement->text(), 3);
0440         else
0441             tmp = tmp + createParameter(fourElement->text(), 3);
0442     }
0443     if (!fiveElement->text().isEmpty() && count >= 5) {
0444         first = false;
0445         if (!first)
0446             tmp = tmp + ';' + createParameter(fiveElement->text(), 4);
0447         else
0448             tmp = tmp + createParameter(fiveElement->text(), 4);
0449     }
0450 
0451     return(tmp);
0452 }
0453 
0454 QString FormulaDialog::createParameter(const QString& _text, int param)
0455 {
0456     if (_text.isEmpty())
0457         return QString("");
0458 
0459     if (!m_desc)
0460         return QString("");
0461 
0462     QString text;
0463 
0464     ParameterType elementType = m_desc->param(param).type();
0465 
0466     switch (elementType) {
0467     case KSpread_Any: {
0468         bool isNumber;
0469         double tmp = m_selection->activeSheet()->map()->calculationSettings()->locale()->readNumber(_text, &isNumber);
0470         Q_UNUSED(tmp);
0471 
0472         //In case of number or boolean return _text, else return value as KSpread_String
0473         if (isNumber || _text.toUpper() == "FALSE" || _text.toUpper() == "TRUE")
0474             return _text;
0475     }
0476     // fall through
0477     case KSpread_String: {
0478         // Does the text start with quotes?
0479         if (_text[0] == '"') {
0480             text = '\\'; // changed: was '"'
0481 
0482             // Escape quotes
0483             QString tmp = _text;
0484             int pos;
0485             int start = 1;
0486             while ((pos = tmp.indexOf('"', start)) != -1) {
0487                 if (tmp[pos - 1] != '\\')
0488                     tmp.replace(pos, 1, "\\\"");
0489                 else
0490                     start = pos + 1;
0491             }
0492 
0493             text += tmp;
0494             text += '"';
0495         } else {
0496             const Region region(_text, m_selection->activeSheet()->map());
0497             if (!region.isValid()) {
0498                 text = '"';
0499 
0500                 // Escape quotes
0501                 QString tmp = _text;
0502                 int pos;
0503                 int start = 1;
0504                 while ((pos = tmp.indexOf('"', start)) != -1) {
0505                     if (tmp[pos - 1] != '\\')
0506                         tmp.replace(pos, 1, "\\\"");
0507                     else
0508                         start = pos + 1;
0509                 }
0510 
0511                 text += tmp;
0512                 text += '"';
0513             } else
0514                 text = _text;
0515         }
0516     }
0517     return text;
0518     case KSpread_Float:
0519         return _text;
0520     case KSpread_Boolean:
0521         return _text;
0522     case KSpread_Int:
0523         return _text;
0524     case KSpread_Date:
0525         return _text;
0526     }
0527 
0528     // Never reached
0529     return text;
0530 }
0531 
0532 static void showEntry(KLineEdit* edit, QLabel* label,
0533                       FunctionDescription* desc, int param)
0534 {
0535     edit->show();
0536     label->setText(desc->param(param).helpText() + ':');
0537     label->show();
0538     ParameterType elementType = desc->param(param).type();
0539     switch (elementType) {
0540     case KSpread_String:
0541     case KSpread_Boolean:
0542     case KSpread_Any:
0543     case KSpread_Date:
0544         edit->setValidator(0);
0545         break;
0546     case KSpread_Float:
0547         edit->setValidator(new QDoubleValidator(edit));
0548         edit->setText("0");
0549         break;
0550     case KSpread_Int:
0551         edit->setValidator(new QIntValidator(edit));
0552         edit->setText("0");
0553         break;
0554     }
0555 
0556 
0557 
0558 }
0559 
0560 void FormulaDialog::slotDoubleClicked(QModelIndex item)
0561 {
0562     if (!item.isValid()) {
0563         item = functions->currentIndex();
0564         if (!item.isValid())
0565             return;
0566     }
0567     refresh_result = false;
0568     if (!m_desc) {
0569         m_browser->setText("");
0570         return;
0571     }
0572 
0573     m_focus = 0;
0574     int old_length = result->text().length();
0575 
0576     // Do not change order of these function calls due to a bug in Qt 2.2
0577     m_browser->setText(m_desc->toQML());
0578     m_tabwidget->setTabEnabled(m_tabwidget->indexOf(m_input), true);
0579     m_tabwidget->setCurrentIndex(1);
0580 
0581     //
0582     // Show as many KLineEdits as needed.
0583     //
0584     if (m_desc->params() > 0) {
0585         m_focus = firstElement;
0586         firstElement->setFocus();
0587 
0588         showEntry(firstElement, label1, m_desc, 0);
0589     } else {
0590         label1->hide();
0591         firstElement->hide();
0592     }
0593 
0594     if (m_desc->params() > 1) {
0595         showEntry(secondElement, label2, m_desc, 1);
0596     } else {
0597         label2->hide();
0598         secondElement->hide();
0599     }
0600 
0601     if (m_desc->params() > 2) {
0602         showEntry(thirdElement, label3, m_desc, 2);
0603     } else {
0604         label3->hide();
0605         thirdElement->hide();
0606     }
0607 
0608     if (m_desc->params() > 3) {
0609         showEntry(fourElement, label4, m_desc, 3);
0610     } else {
0611         label4->hide();
0612         fourElement->hide();
0613     }
0614 
0615     if (m_desc->params() > 4) {
0616         showEntry(fiveElement, label5, m_desc, 4);
0617     } else {
0618         label5->hide();
0619         fiveElement->hide();
0620     }
0621 
0622     if (m_desc->params() > 5)
0623         debugSheets << "Error in param->nb_param";
0624     refresh_result = true;
0625 
0626     //
0627     // Put the new function call in the result.
0628     //
0629     if (result->cursorPosition() < old_length) {
0630         m_rightText = result->text().right(old_length - result->cursorPosition());
0631         m_leftText = result->text().left(result->cursorPosition());
0632     } else {
0633         m_rightText.clear();
0634         m_leftText = result->text();
0635     }
0636 
0637     int pos = result->cursorPosition();
0638 
0639     {
0640         const QString text = proxyModel->data(functions->currentIndex()).toString();
0641         result->setText(m_leftText + text + "()" + m_rightText);
0642         if (result->text()[0] != '=')
0643             result->setText('=' + result->text());
0644     }
0645 
0646     //
0647     // Put focus somewhere is there are no KLineEdits visible
0648     //
0649     if (m_desc->params() == 0) {
0650         label1->show();
0651         label1->setText(i18n("This function has no parameters."));
0652         result->setFocus();
0653         const QString text = proxyModel->data(functions->currentIndex()).toString();
0654         result->setCursorPosition(pos + text.length() + 2);
0655     }
0656     slotChangeText("");
0657 }
0658 
0659 void FormulaDialog::slotIndexSelected(const QModelIndex& index)
0660 {
0661     // This slot is only called when single-click to activate is uesd in the listbox, when the mouse moves over a item; to prevent
0662     // the active selection to change after the user activated one, slotSelected is only called when the current tab is the Help tab,
0663     // and not when the parameters tab is active
0664     if (m_tabwidget->currentIndex() != 0) return;
0665     QString function = proxyModel->data(index).toString();
0666     slotSelected(function);
0667 }
0668 
0669 void FormulaDialog::slotSelected(const QString& afunction)
0670 {
0671     QString function = afunction;
0672     if (function.isNull())
0673         function = proxyModel->data(functions->currentIndex()).toString();
0674 
0675     FunctionDescription* desc = FunctionRepository::self()->functionInfo(function);
0676     if (!desc) {
0677         m_browser->setText(i18n("Description is not available."));
0678         return;
0679     }
0680 
0681     if (functions->currentIndex().isValid())
0682         selectFunction->setEnabled(true);
0683 
0684     // Lock
0685     refresh_result = false;
0686 
0687     m_funcName = function;
0688     m_desc = desc;
0689 
0690     // Set the help text
0691     m_browser->setText(m_desc->toQML());
0692     //m_browser->setContentsPos( 0, 0 );
0693 
0694     m_focus = 0;
0695 
0696     m_tabwidget->setCurrentIndex(0);
0697     m_tabwidget->setTabEnabled(m_tabwidget->indexOf(m_input), false);
0698 
0699     // Unlock
0700     refresh_result = true;
0701 }
0702 
0703 // from hyperlink in the "Related Function"
0704 void FormulaDialog::slotShowFunction(const QUrl& functionUrl)
0705 {
0706     const QString function = functionUrl.toString();
0707 
0708     FunctionDescription* desc =
0709         FunctionRepository::self()->functionInfo(function);
0710     if (!desc) return;
0711 
0712     // select the category
0713     QString category = desc->group();
0714     typeFunction->setCurrentIndex(typeFunction->findText(category));
0715     slotActivated(category);
0716 
0717     // select the function
0718     int row = functionsModel->stringList().indexOf(function);
0719     const QModelIndex sourcemodelindex = functionsModel->index(row, 0);
0720     const QModelIndex proxymodelindex = proxyModel->mapFromSource(sourcemodelindex);
0721     if (proxymodelindex.isValid())
0722         functions->setCurrentIndex(proxymodelindex);
0723 
0724     slotSelected(function);
0725 }
0726 
0727 void FormulaDialog::slotSelectionChanged()
0728 {
0729     if (!m_focus)
0730         return;
0731 
0732     if (m_selection->isValid()) {
0733         QString area = m_selection->name();
0734         m_focus->setText(area);
0735     }
0736 }
0737 
0738 void FormulaDialog::slotActivated(const QString& category)
0739 {
0740     const QStringList lst = (category == i18n("All")) ?
0741         FunctionRepository::self()->functionNames() : FunctionRepository::self()->functionNames(category);
0742 
0743     debugSheets << "category:" << category << " (" << lst.count() << "functions)";
0744 
0745     functionsModel->setStringList(lst);
0746 
0747     QStringList upperList;
0748     for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it)
0749         upperList.append((*it).toUpper());
0750     listFunct.setItems(upperList);
0751 
0752     // Go to the first function in the list.
0753     const QString text = proxyModel->data(proxyModel->index(0, 0)).toString();
0754     slotSelected(text);
0755 }
0756 
0757 void FormulaDialog::closeEvent(QCloseEvent * e)
0758 {
0759     deleteLater();
0760     e->accept();
0761 }