double EqonomizeValueEdit::fixup_sub(QString &input, QStringList &errors, bool &calculated) const { input = input.trimmed(); if(input.isEmpty()) { return 0.0; } if(o_currency) { input.remove(budget->monetary_group_separator); if(!budget->monetary_negative_sign.isEmpty()) input.replace(budget->monetary_negative_sign, "-"); if(!budget->monetary_positive_sign.isEmpty()) input.replace(budget->monetary_positive_sign, "+"); } else { input.remove(budget->group_separator); if(!budget->negative_sign.isEmpty()) input.replace(budget->negative_sign, "-"); if(!budget->positive_sign.isEmpty()) input.replace(budget->positive_sign, "+"); } input.replace(QLocale().negativeSign(), '-'); input.replace(QLocale().positiveSign(), '+'); int i = input.indexOf(')', 1); if(i < 1) { i = input.indexOf('(', 0); if(i == 0) { input.remove(0, 1); return fixup_sub(input, errors, calculated); } else if(i >= 0) { input += ')'; i = input.length() - 1; } else { i = -1; } } if(i >= 1) { int i2 = input.lastIndexOf('(', i - 1); if(i2 < 0 || i2 > i) { if(i == input.length() - 1) { input.chop(1); return fixup_sub(input, errors, calculated); } input.prepend('('); i++; i2 = 0; } if(i2 == 0 && i == input.length() - 1) { input.remove(0, 1); input.chop(1); return fixup_sub(input, errors, calculated); } if(i < input.length() - 1 && (input[i + 1].isNumber() || input[i + 1] == '(')) input.insert(i + 1, '*'); QString str = input.mid(i2 + 1, i - i2 - 1); double v = fixup_sub(str, errors, calculated); input.replace(i2, i - i2 + 1, o_currency ? o_currency->formatValue(0.5, decimals() + 2, false, false, true) : budget->formatValue(v, decimals() + 2)); if(i2 > 0 && (input[i2 - 1].isNumber() || input[i2 - 1] == ')')) input.insert(i2, '*'); calculated = true; return fixup_sub(input, errors, calculated); } i = input.indexOf(QRegExp("[-+]"), 1); if(i >= 1) { QStringList terms = input.split(QRegExp("[-+]")); i = 0; double v = 0.0; QList<bool> signs; signs << true; for(int terms_i = 0; terms_i < terms.size() - 1; terms_i++) { i += terms[terms_i].length(); if(input[i] == '-') signs << false; else signs << true; i++; } for(int terms_i = 0; terms_i < terms.size() - 1; terms_i++) { if(terms[terms_i].endsWith('*') || terms[terms_i].endsWith('/') || terms[terms_i].endsWith('^')) { if(!signs[terms_i + 1]) terms[terms_i] += '-'; else terms[terms_i] += '+'; terms[terms_i] += terms[terms_i + 1]; signs.removeAt(terms_i + 1); terms.removeAt(terms_i + 1); terms_i--; } } if(terms.size() > 1) { for(int terms_i = 0; terms_i < terms.size(); terms_i++) { if(terms[terms_i].isEmpty()) { if(!signs[terms_i] && terms_i + 1 < terms.size()) { signs[terms_i + 1] = !signs[terms_i + 1]; } } else { if(!signs[terms_i]) v -= fixup_sub(terms[terms_i], errors, calculated); else v += fixup_sub(terms[terms_i], errors, calculated); } } calculated = true; return v; } } if(input.indexOf("**") >= 0) input.replace("**", "^"); i = input.indexOf(QRegExp("[*/]"), 0); if(i >= 0) { QStringList terms = input.split(QRegExp("[*/]")); QChar c = '*'; i = 0; double v = 1.0; for(int terms_i = 0; terms_i < terms.size(); terms_i++) { if(terms[terms_i].isEmpty()) { if(c == '/') { errors << tr("Empty denominator."); } else { errors << tr("Empty factor."); } } else { i += terms[terms_i].length(); if(c == '/') { double den = fixup_sub(terms[terms_i], errors, calculated); if(den == 0.0) { errors << tr("Division by zero."); } else { v /= den; } } else { v *= fixup_sub(terms[terms_i], errors, calculated); } if(i < input.length()) c = input[i]; } i++; } calculated = true; return v; } i = input.indexOf(QLocale().percent()); if(i >= 0) { double v = 0.01; if(input.length() > 1) { if(i > 0 && i < input.length() - 1) { QString str = input.right(input.length() - 1 - i); input = input.left(i); i = 0; v = fixup_sub(str, errors, calculated) * v; } else if(i == input.length() - 1) { input = input.left(i); } else if(i == 0) { input = input.right(input.length() - 1); } v = fixup_sub(input, errors, calculated) * v; } calculated = true; return v; } if(o_currency) { QString reg_exp_str = "[\\d\\+\\-\\^"; reg_exp_str += '\\'; reg_exp_str += budget->monetary_decimal_separator; reg_exp_str += '\\'; reg_exp_str += budget->monetary_group_separator; if(budget->monetary_decimal_separator != "." && budget->monetary_group_separator != ".") { reg_exp_str += '\\'; reg_exp_str += '.'; } reg_exp_str += "]"; int i = input.indexOf(QRegExp(reg_exp_str)); if(i >= 1) { QString scur = input.left(i).trimmed(); Currency *cur = budget->findCurrency(scur); if(!cur && budget->defaultCurrency()->symbol(false) == scur) cur = budget->defaultCurrency(); if(!cur) cur = budget->findCurrencySymbol(scur, true); if(cur) { QString value = input.right(input.length() - i); double v = fixup_sub(value, errors, calculated); if(cur != o_currency) { v = cur->convertTo(v, o_currency); } calculated = true; return v; } errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(scur); } if(i >= 0) { i = input.lastIndexOf(QRegExp(reg_exp_str)); if(i >= 0 && i < input.length() - 1) { QString scur = input.right(input.length() - (i + 1)).trimmed(); Currency *cur = budget->findCurrency(scur); if(!cur && budget->defaultCurrency()->symbol(false) == scur) cur = budget->defaultCurrency(); if(!cur) cur = budget->findCurrencySymbol(scur, true); if(cur) { QString value = input.left(i + 1); double v = fixup_sub(value, errors, calculated); if(cur != o_currency) { v = cur->convertTo(v, o_currency); } calculated = true; return v; } errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(scur); } } else { Currency *cur = budget->findCurrency(input); if(!cur && budget->defaultCurrency()->symbol(false) == input) cur = budget->defaultCurrency(); if(!cur) cur = budget->findCurrencySymbol(input, true); if(cur) { double v = 1.0; if(cur != o_currency) { v = cur->convertTo(v, o_currency); } calculated = true; return v; } errors << tr("Unknown or ambiguous currency, or unrecognized characters, in expression: %1.").arg(input); } } i = input.indexOf('^', 0); if(i >= 0 && i != input.length() - 1) { QString base = input.left(i); if(base.isEmpty()) { errors << tr("Empty base."); } else { QString exp = input.right(input.length() - (i + 1)); double v; if(exp.isEmpty()) { errors << tr("Error"), tr("Empty exponent."); v = 1.0; } else { v = pow(fixup_sub(base, errors, calculated), fixup_sub(exp, errors, calculated)); } calculated = true; return v; } } if(!o_currency) { QString reg_exp_str = "[^\\d\\+\\-"; reg_exp_str += '\\'; reg_exp_str += budget->decimal_separator; reg_exp_str += '\\'; reg_exp_str += budget->group_separator; if(budget->decimal_separator != "." && budget->group_separator != ".") { reg_exp_str += '\\'; reg_exp_str += '.'; } reg_exp_str += "]"; i = input.indexOf(QRegExp(reg_exp_str)); if(i >= 0) { errors << tr("Unrecognized characters in expression."); } input.remove(budget->group_separator); input.replace(budget->decimal_separator, "."); return input.toDouble(); } input.remove(budget->monetary_group_separator); input.replace(budget->monetary_decimal_separator, "."); return input.toDouble(); }