void FormulaEditorHighlighter::highlightBlock(const QString& text) { // reset syntax highlighting setFormat(0, text.length(), QApplication::palette().text().color()); // save the old ones to identify range changes Tokens oldTokens = d->tokens; // interpret the text as formula // we accept invalid/incomplete formulas Formula f; d->tokens = f.scan(text); QFont editorFont = document()->defaultFont(); QFont font; uint oldRangeCount = d->rangeCount; d->rangeCount = 0; QList<QColor> colors = d->selection->colors(); QList<QString> alreadyFoundRanges; Sheet *const originSheet = d->selection->originSheet(); Map *const map = originSheet->map(); for (int i = 0; i < d->tokens.count(); ++i) { Token token = d->tokens[i]; Token::Type type = token.type(); switch (type) { case Token::Cell: case Token::Range: { // don't compare, if we have already found a change if (!d->rangeChanged && i < oldTokens.count() && token.text() != oldTokens[i].text()) { d->rangeChanged = true; } const Region newRange(token.text(), map, originSheet); if (!newRange.isValid()) { continue; } int index = alreadyFoundRanges.indexOf(newRange.name()); if (index == -1) { /* not found */ alreadyFoundRanges.append(newRange.name()); index = alreadyFoundRanges.count() - 1; } const QColor color(colors[index % colors.size()]); setFormat(token.pos() + 1, token.text().length(), color); ++d->rangeCount; } break; case Token::Boolean: // True, False (also i18n-ized) /* font = QFont(editorFont); font.setBold(true); setFormat(token.pos() + 1, token.text().length(), font);*/ break; case Token::Identifier: // function name or named area*/ /* font = QFont(editorFont); font.setBold(true); setFormat(token.pos() + 1, token.text().length(), font);*/ break; case Token::Unknown: case Token::Integer: // 14, 3, 1977 case Token::Float: // 3.141592, 1e10, 5.9e-7 case Token::String: // "Calligra", "The quick brown fox..." case Token::Error: break; case Token::Operator: { // +, *, /, - switch (token.asOperator()) { case Token::LeftPar: case Token::RightPar: //Check where this brace is in relation to the cursor and highlight it if necessary. handleBrace(i); break; default: break; } } break; } } if (oldRangeCount != d->rangeCount) d->rangeChanged = true; }
QString Calligra::Sheets::Odf::encodeFormula(const QString& expr, const KLocale* locale) { // use locale settings const QString decimal = locale ? locale->decimalSymbol() : "."; QString result('='); Formula formula; Tokens tokens = formula.scan(expr, locale); if (!tokens.valid() || tokens.count() == 0) return expr; // no altering on error for (int i = 0; i < tokens.count(); ++i) { const QString tokenText = tokens[i].text(); const Token::Type type = tokens[i].type(); switch (type) { case Token::Cell: case Token::Range: { result.append('['); // FIXME Stefan: Hack to get the apostrophes right. Fix and remove! const int pos = tokenText.lastIndexOf('!'); if (pos != -1 && tokenText.left(pos).contains(' ')) result.append(Region::saveOdf('\'' + tokenText.left(pos) + '\'' + tokenText.mid(pos))); else result.append(Region::saveOdf(tokenText)); result.append(']'); break; } case Token::Float: { QString tmp(tokenText); result.append(tmp.replace(decimal, ".")); break; } case Token::Operator: { if (tokens[i].asOperator() == Token::Equal) result.append('='); else result.append(tokenText); break; } case Token::Identifier: { if (tokenText == "ERRORTYPE") { // need to replace this result.append("ERROR.TYPE"); } else if (tokenText == "LEGACYNORMSDIST") { result.append("LEGACY.NORMSDIST"); } else if (tokenText == "LEGACYNORMSINV") { result.append("LEGACY.NORMSINV"); } else { // dump it out unchanged result.append(tokenText); } break; } case Token::Boolean: case Token::Integer: case Token::String: default: result.append(tokenText); break; } } return result; }