Exemplo n.º 1
0
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();
}