Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Damir Islamov 2021-09-04 13:38:39 +07:00
commit cdfe7f03f1
13 changed files with 388 additions and 108 deletions

View File

@ -227,13 +227,13 @@ bool last_is_operator(std::string str, bool allow_exp) {
} else {
if(str.length() >= 3 && str[str.length() - 2] < 0) {
str = str.substr(str.length() - 3);
if(str == "" || str == "" || str == "" || str == "" || str == "" || str == "" || str == "" || str == SIGN_MULTIPLICATION || str == SIGN_DIVISION_SLASH || str == SIGN_MINUS) {
if(str == "" || str == "" || str == "" || str == "" || str == "" || str == "" || str == "" || str == settings->multiplicationSign() || str == settings->divisionSign() || str == SIGN_MINUS) {
return true;
}
}
if(str.length() >= 2) {
str = str.substr(str.length() - 2);
if(str == "¬" || str == SIGN_MULTIPLICATION || str == SIGN_DIVISION_SLASH || str == SIGN_MINUS) return true;
if(str == "¬" || str == settings->multiplicationSign() || str == settings->divisionSign() || str == SIGN_MINUS) return true;
}
}
return false;
@ -1157,7 +1157,6 @@ void ExpressionEdit::updateCompletion() {
if(i_end == std::string::npos) break;
i_pow = str.find("^", i_pow + 1);
}
//if(settings->printops.multiplication_sign == MULTIPLICATION_SIGN_DOT) gsub(saltdot, sdot, str);
gsub("_unit", "", str);
gsub("_eunit", "<sub>e</sub>", str);
}
@ -1354,8 +1353,8 @@ void ExpressionEdit::keyPressEvent(QKeyEvent *event) {
emit calculateRPNRequest(OPERATION_MULTIPLY);
return;
}
if(doChainMode(SIGN_MULTIPLICATION)) return;
wrapSelection(SIGN_MULTIPLICATION);
if(doChainMode(settings->multiplicationSign())) return;
wrapSelection(settings->multiplicationSign());
return;
}
case Qt::Key_Minus: {
@ -1399,8 +1398,8 @@ void ExpressionEdit::keyPressEvent(QKeyEvent *event) {
emit calculateRPNRequest(OPERATION_DIVIDE);
return;
}
if(doChainMode("/")) return;
wrapSelection("/");
if(doChainMode(settings->divisionSign(false))) return;
wrapSelection(settings->divisionSign(false));
return;
}
case Qt::Key_ParenRight: {
@ -2264,16 +2263,18 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
if(po.base == BASE_CUSTOM) CALCULATOR->setCustomOutputBase(nr_base);
size_t message_n = 0;
while(CALCULATOR->message()) {
MessageType mtype = CALCULATOR->message()->type();
if(mtype == MESSAGE_ERROR) {
if(message_n > 0) {
if(message_n == 1) parsed_expression_tooltip = "" + parsed_expression_tooltip;
parsed_expression_tooltip += "<br>• ";
if(CALCULATOR->message()->category() != MESSAGE_CATEGORY_IMPLICIT_MULTIPLICATION || !settings->implicit_question_asked) {
MessageType mtype = CALCULATOR->message()->type();
if(mtype == MESSAGE_ERROR) {
if(message_n > 0) {
if(message_n == 1) parsed_expression_tooltip = "" + parsed_expression_tooltip;
parsed_expression_tooltip += "<br>• ";
}
parsed_expression_tooltip += CALCULATOR->message()->message();
message_n++;
} else if(mtype == MESSAGE_WARNING) {
had_warnings = true;
}
parsed_expression_tooltip += CALCULATOR->message()->message();
message_n++;
} else if(mtype == MESSAGE_WARNING) {
had_warnings = true;
}
CALCULATOR->nextMessage();
}
@ -3297,19 +3298,21 @@ bool ExpressionEdit::doChainMode(const QString &op) {
std::string warnings;
int message_n = 0;
while(CALCULATOR->message()) {
MessageType mtype = CALCULATOR->message()->type();
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
if(mtype == MESSAGE_ERROR) return false;
if(message_n > 0) {
if(message_n == 1) warnings.insert(0, "");
warnings += "\n";
if(CALCULATOR->message()->category() != MESSAGE_CATEGORY_IMPLICIT_MULTIPLICATION || !settings->implicit_question_asked) {
MessageType mtype = CALCULATOR->message()->type();
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
if(mtype == MESSAGE_ERROR) return false;
if(message_n > 0) {
if(message_n == 1) warnings.insert(0, "");
warnings += "\n";
}
warnings += CALCULATOR->message()->message();
}
warnings += CALCULATOR->message()->message();
message_n++;
}
message_n++;
CALCULATOR->nextMessage();
}
if(m.size() > 0 && !m.isFunction() && !m.isVector() && (((!m.isMultiplication() || op != SIGN_MULTIPLICATION) && (!m.isAddition() || (op != "+" && op != SIGN_MINUS)) && (!m.isBitwiseOr() || op != BITWISE_OR) && (!m.isBitwiseAnd() || op != BITWISE_AND)))) {
if(m.size() > 0 && !m.isFunction() && !m.isVector() && (((!m.isMultiplication() || op != settings->multiplicationSign()) && (!m.isAddition() || (op != "+" && op != SIGN_MINUS)) && (!m.isBitwiseOr() || op != BITWISE_OR) && (!m.isBitwiseAnd() || op != BITWISE_AND)))) {
str.insert(0, "(");
str += ")";
}

View File

@ -238,7 +238,7 @@ void FPConversionDialog::updateFields(int base) {
sfloat = significand.print(po);
if(!subnormal || !significand.isZero()) {
sfloat += " ";
sfloat += SIGN_MULTIPLICATION;
sfloat += settings->multiplicationSign();
sfloat += " ";
sfloat += "2^";
sfloat += exponent.print(po);

View File

@ -41,7 +41,11 @@ class MathTextEdit : public QPlainTextEdit {
if(event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::GroupSwitchModifier || event->modifiers() == Qt::ShiftModifier || event->modifiers() == Qt::KeypadModifier) {
switch(event->key()) {
case Qt::Key_Asterisk: {
insertPlainText(SIGN_MULTIPLICATION);
insertPlainText(settings->multiplicationSign());
return;
}
case Qt::Key_Slash: {
insertPlainText(settings->divisionSign(false));
return;
}
case Qt::Key_Minus: {
@ -129,7 +133,8 @@ UserFunction *FunctionEditDialog::createFunction(MathFunction **replaced_item) {
gsub("y", "\\y", str);
gsub("z", "\\z", str);
}
gsub(SIGN_MULTIPLICATION, "*", str);
gsub(settings->multiplicationSign(), "*", str);
gsub(settings->divisionSign(), "/", str);
gsub(SIGN_MINUS, "-", str);
f = new UserFunction("", nameEdit->text().trimmed().toStdString(), str);
CALCULATOR->addFunction(f);
@ -157,7 +162,8 @@ bool FunctionEditDialog::modifyFunction(MathFunction *f, MathFunction **replaced
gsub("y", "\\y", str);
gsub("z", "\\z", str);
}
gsub(SIGN_MULTIPLICATION, "*", str);
gsub(settings->multiplicationSign(), "*", str);
gsub(settings->divisionSign(), "/", str);
gsub(SIGN_MINUS, "-", str);
((UserFunction*) f)->setFormula(str);
}
@ -169,7 +175,8 @@ void FunctionEditDialog::setFunction(MathFunction *f) {
if(f->subtype() == SUBTYPE_USER_FUNCTION) {
expressionEdit->setEnabled(true);
std::string str = CALCULATOR->localizeExpression(((UserFunction*) f)->formula(), settings->evalops.parse_options);
gsub("*", SIGN_MULTIPLICATION, str);
gsub("*", settings->multiplicationSign(), str);
gsub("/", settings->divisionSign(false), str);
gsub("-", SIGN_MINUS, str);
expressionEdit->setPlainText(QString::fromStdString(str));
} else {

View File

@ -18,6 +18,7 @@
#include <QKeySequence>
#include <QClipboard>
#include <QTextDocumentFragment>
#include <QScrollBar>
#include <QDebug>
#include <libqalculate/qalculate.h>
@ -168,7 +169,7 @@ void replace_colors(std::string &str) {
void HistoryView::loadInitial() {
if(!settings->v_expression.empty()) {
for(size_t i = 0; i < settings->v_expression.size(); i++) {
addResult(settings->v_result[i], settings->v_expression[i], true, false, QString(), true, i);
addResult(settings->v_result[i], settings->v_expression[i], true, false, QString(), NULL, true, i);
}
if(!s_text.isEmpty()) {
if((settings->color == 2 && s_text.contains("color:#00")) || (settings->color != 2 && s_text.contains("color:#FF"))) {
@ -184,7 +185,7 @@ void HistoryView::loadInitial() {
}
}
}
void HistoryView::addResult(std::vector<std::string> values, std::string expression, int exact, bool dual_approx, const QString &image, bool initial_load, size_t index) {
void HistoryView::addResult(std::vector<std::string> values, std::string expression, int exact, bool dual_approx, const QString &image, bool *implicit_warning, bool initial_load, size_t index) {
QFontMetrics fm(font());
int paste_h = fm.ascent();
if(paste_h < 16) paste_h = 12;
@ -200,9 +201,14 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
str += "</div>";
if(!initial_load) {
settings->v_expression.push_back(expression);
settings->v_delexpression.push_back(false);
settings->v_result.push_back(values);
settings->v_exact.push_back(std::vector<int>());
for(size_t i = 0; i < values.size(); i++) settings->v_exact[settings->v_exact.size() - 1].push_back(exact || i < values.size() - 1);
settings->v_delresult.push_back(std::vector<bool>());
for(size_t i = 0; i < values.size(); i++) {
settings->v_exact[settings->v_exact.size() - 1].push_back(exact || i < values.size() - 1);
settings->v_delresult[settings->v_delresult.size() - 1].push_back(false);
}
}
} else if(!initial_load && !settings->v_result.empty()) {
for(size_t i = values.size(); i > 0; i--) {
@ -212,29 +218,33 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
}
if(!initial_load && CALCULATOR->message()) {
do {
MessageType mtype = CALCULATOR->message()->type();
str += "<div style=\"text-align:left; font-size:normal";
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
str += "; color:";
if(mtype == MESSAGE_ERROR) {
if(settings->color == 2) str += "#FFAAAA";
else str += "#800000";
} else {
if(settings->color == 2) str += "#AAAAFF";
else str += "#000080";
if(CALCULATOR->message()->category() == MESSAGE_CATEGORY_IMPLICIT_MULTIPLICATION && (settings->implicit_question_asked || implicit_warning)) {
if(!settings->implicit_question_asked) *implicit_warning = true;
} else {
MessageType mtype = CALCULATOR->message()->type();
str += "<div style=\"text-align:left; font-size:normal";
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
str += "; color:";
if(mtype == MESSAGE_ERROR) {
if(settings->color == 2) str += "#FFAAAA";
else str += "#800000";
} else {
if(settings->color == 2) str += "#AAAAFF";
else str += "#000080";
}
str += "";
}
str += "";
str += "\">";
QString mstr = QString::fromStdString(CALCULATOR->message()->message());
if(!mstr.startsWith("-")) str += "- ";
if(settings->printops.use_unicode_signs) {
mstr.replace(">=", SIGN_GREATER_OR_EQUAL);
mstr.replace("<=", SIGN_LESS_OR_EQUAL);
mstr.replace("!=", SIGN_NOT_EQUAL);
}
str += mstr.toHtmlEscaped();
str += "</div>";
}
str += "\">";
QString mstr = QString::fromStdString(CALCULATOR->message()->message());
if(!mstr.startsWith("-")) str += "- ";
if(settings->printops.use_unicode_signs) {
mstr.replace(">=", SIGN_GREATER_OR_EQUAL);
mstr.replace("<=", SIGN_LESS_OR_EQUAL);
mstr.replace("!=", SIGN_NOT_EQUAL);
}
str += mstr.toHtmlEscaped();
str += "</div>";
} while(CALCULATOR->nextMessage());
if(str.isEmpty() && values.empty() && expression.empty()) return;
}
@ -271,7 +281,7 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
if(settings->color == 2) str += QString("<a href=\"%1:%3\"><img src=\":/icons/dark/actions/%2/edit-paste.svg\" height=\"%2\"/></a>").arg((int) index).arg(paste_h).arg((int) i);
else str += QString("<a href=\"%1:%3\"><img src=\":/icons/actions/%2/edit-paste.svg\" height=\"%2\"/></a>").arg((int) index).arg(paste_h).arg((int) i);
} else {
if(settings->color == 2) str += QString("<a href=\"#%1\"><img src=\":/icons/dark/actions/%2/edit-paste.svg\" height=\"%2\"/></a>").arg(dual_approx && i == 0 ? settings->history_answer.size() - 1 : settings->history_answer.size()).arg(paste_h);
if(settings->color == 2) str += QString("<a href=\"#%1:%2:%3\"><img src=\":/icons/dark/actions/%4/edit-paste.svg\" height=\"%4\"/></a>").arg(dual_approx && i == 0 ? settings->history_answer.size() - 1 : settings->history_answer.size()).arg(settings->v_expression.size() - 1).arg(settings->v_result[settings->v_result.size() - 1].size() - i - 1).arg(paste_h);
else str += QString("<a href=\"#%1\"><img src=\":/icons/actions/%2/edit-paste.svg\" height=\"%2\"/></a>").arg(dual_approx && i == 0 ? settings->history_answer.size() - 1 : settings->history_answer.size()).arg(paste_h);
}
str += "</div>";
@ -350,7 +360,9 @@ void HistoryView::mouseReleaseEvent(QMouseEvent *e) {
QString str = anchorAt(e->pos());
if(!str.isEmpty()) {
if(str[0] == '#') {
emit insertValueRequested(str.mid(1).toInt());
int index = str.indexOf(":");
if(index < 0) emit insertValueRequested(str.mid(1).toInt());
else emit insertValueRequested(str.mid(1, index - 1).toInt());
} else {
int index = str.indexOf(":");
if(index < 0) {
@ -391,30 +403,132 @@ void HistoryView::editClear() {
settings->v_expression.clear();
settings->v_result.clear();
}
void HistoryView::editRemove() {
int i1 = -1, i2 = -1;
QString sref;
indexAtPos(context_pos, &i1, &i2, &sref);
if(i1 < 0 || i1 >= (int) settings->v_delexpression.size()) return;
if(i2 >= 0 && settings->v_result[i1].size() <= 1) i2 = -1;
if(i2 < 0) {
sref = QString::number(i1);
settings->v_delexpression[i1] = true;
} else if(i2 < (int) settings->v_delresult[i1].size()) {
settings->v_delresult[i1][i2] = true;
}
int index = s_text.indexOf("<a href=\"" + sref + "\"");
if(index >= 0) {
int index2 = s_text.indexOf(i2 < 0 ? "<hr/>" : "</a></div>", index);
if(index2 >= 0) index2 += (i2 < 0 ? 5 : 10);
int index1 = s_text.lastIndexOf("<div", index);
QString new_text;
if(index1 > 0) new_text = s_text.left(index1);
if(index2 >= 0) new_text += s_text.mid(index2);
s_text = new_text;
}
int vpos = verticalScrollBar()->value();
setHtml("<body color=\"" + textColor().name() + "\">" + s_text + "</body>");
verticalScrollBar()->setValue(vpos);
}
void HistoryView::indexAtPos(const QPoint &pos, int *expression_index, int *result_index, QString *anchorstr) {
*expression_index = -1;
*result_index = -1;
QString sref = anchorAt(pos);
if(sref.isEmpty()) {
QTextCursor cur = cursorForPosition(pos);
while(true) {
cur.movePosition(QTextCursor::EndOfBlock, QTextCursor::MoveAnchor);
cur.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
QString str = cur.selection().toHtml();
int i = str.lastIndexOf("<a href=\"");
if(i >= 0) {
i += 9;
int i2 = str.indexOf("\"", i);
if(i2 < 0) return;
sref = str.mid(i, i2 - i);
if(sref.isEmpty()) return;
break;
} else if(str.lastIndexOf("text-align:left") > 0) {
if(!cur.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor)) return;
} else {
if(!cur.movePosition(QTextCursor::PreviousBlock, QTextCursor::MoveAnchor)) return;
}
}
}
if(anchorstr) *anchorstr = sref;
int i = sref.indexOf(":");
if(sref[0] == '#') {
if(i < 0) return;
int i2 = sref.indexOf(":", i + 1);
if(i >= 0) {
*expression_index = sref.mid(i + 1, i2 - (i + 1)).toInt();
*result_index = sref.mid(i2 + 1).toInt();
if(*expression_index >= 0 && *expression_index < (int) settings->v_result.size() && *result_index < (int) settings->v_result[*expression_index].size()) {
*result_index = settings->v_result[*expression_index].size() - *result_index - 1;
}
} else {
*expression_index = sref.mid(i + 1).toInt();
}
} else if(i >= 0) {
*expression_index = sref.left(i).toInt();
*result_index = sref.mid(i + 1).toInt();
} else {
*expression_index = sref.toInt();
}
}
void HistoryView::contextMenuEvent(QContextMenuEvent *e) {
if(!cmenu) {
cmenu = new QMenu(this);
copyAction = cmenu->addAction(tr("Copy"), this, SLOT(editCopy()));
copyAction->setShortcut(QKeySequence::Copy);
copyAction->setShortcutContext(Qt::WidgetShortcut);
copyFormattedAction = cmenu->addAction(tr("Copy Formatted Text"), this, SLOT(copy()));
copyFormattedAction = cmenu->addAction(tr("Copy Formatted Text"), this, SLOT(editCopyFormatted()));
selectAllAction = cmenu->addAction(tr("Select All"), this, SLOT(selectAll()));
selectAllAction->setShortcut(QKeySequence::SelectAll);
selectAllAction->setShortcutContext(Qt::WidgetShortcut);
delAction = cmenu->addAction(tr("Remove"), this, SLOT(editRemove()));
clearAction = cmenu->addAction(tr("Clear"), this, SLOT(editClear()));
}
copyAction->setEnabled(textCursor().hasSelection());
copyFormattedAction->setEnabled(textCursor().hasSelection());
int i1 = -1, i2 = -1;
context_pos = e->pos();
indexAtPos(context_pos, &i1, &i2);
copyAction->setEnabled(textCursor().hasSelection() || (i1 >= 0 && e->reason() == QContextMenuEvent::Mouse));
copyFormattedAction->setEnabled(textCursor().hasSelection() || (i1 >= 0 && e->reason() == QContextMenuEvent::Mouse));
selectAllAction->setEnabled(!s_text.isEmpty());
delAction->setEnabled(i1 >= 0 && e->reason() == QContextMenuEvent::Mouse && !textCursor().hasSelection());
clearAction->setEnabled(!s_text.isEmpty());
cmenu->popup(e->globalPos());
}
void HistoryView::editCopyFormatted() {
if(textCursor().hasSelection()) {
copy();
} else {
int i1 = -1, i2 = -1;
indexAtPos(context_pos, &i1, &i2);
if(i1 < 0) return;
if(i2 < 0) {
if(i1 >= 0 && (size_t) i1 < settings->v_expression.size()) QApplication::clipboard()->setText(QString::fromStdString(settings->v_expression[i1]));
} else {
if((size_t) i1 < settings->v_result.size() && (size_t) i2 < settings->v_result[i1].size()) QApplication::clipboard()->setText(QString::fromStdString(settings->v_result[i1][i2]));
}
}
}
void HistoryView::editCopy() {
QString str = textCursor().selection().toHtml();
int i = str.indexOf("<!--StartFragment-->");
int i2 = str.indexOf("<!--EndFragment-->", i + 20);
if(i >= 0 && i2 >= 0) str = str.mid(i + 20, i2 - i - 20).trimmed();
else str = textCursor().selectedText();
QApplication::clipboard()->setText(unhtmlize(str));
if(textCursor().hasSelection()) {
QString str = textCursor().selection().toHtml();
int i = str.indexOf("<!--StartFragment-->");
int i2 = str.indexOf("<!--EndFragment-->", i + 20);
if(i >= 0 && i2 >= 0) str = str.mid(i + 20, i2 - i - 20).trimmed();
else str = textCursor().selectedText();
QApplication::clipboard()->setText(unhtmlize(str));
} else {
int i1 = -1, i2 = -1;
indexAtPos(context_pos, &i1, &i2);
if(i1 < 0) return;
if(i2 < 0) {
if(i1 >= 0 && (size_t) i1 < settings->v_expression.size()) QApplication::clipboard()->setText(QString::fromStdString(unhtmlize(settings->v_expression[i1])));
} else {
if((size_t) i1 < settings->v_result.size() && (size_t) i2 < settings->v_result[i1].size()) QApplication::clipboard()->setText(QString::fromStdString(unhtmlize(settings->v_result[i1][i2])));
}
}
}

View File

@ -31,9 +31,10 @@ class HistoryView : public QTextBrowser {
ExpressionEdit *expressionEdit;
void addResult(std::vector<std::string> values, std::string expression = "", int exact = 1, bool dual_approx = false, const QString &image = QString(), bool initial_load = false, size_t index = 0);
void addResult(std::vector<std::string> values, std::string expression = "", int exact = 1, bool dual_approx = false, const QString &image = QString(), bool *implicit_warning = NULL, bool initial_load = false, size_t index = 0);
void addMessages();
void loadInitial();
void indexAtPos(const QPoint &pos, int *expression_index, int *result_index, QString *anchorstr = NULL);
protected:
@ -41,8 +42,9 @@ class HistoryView : public QTextBrowser {
int i_pos;
QImage *paste_image;
QMenu *cmenu;
QAction *copyAction, *copyFormattedAction, *selectAllAction, *clearAction;
QAction *copyAction, *copyFormattedAction, *selectAllAction, *delAction, *clearAction;
QColor prev_color;
QPoint context_pos;
void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
@ -53,7 +55,9 @@ class HistoryView : public QTextBrowser {
public slots:
void editCopy();
void editCopyFormatted();
void editClear();
void editRemove();
signals:

View File

@ -299,8 +299,9 @@ KeypadWidget::KeypadWidget(QWidget *parent) : QWidget(parent) {
connect(button, SIGNAL(clicked2()), this, SIGNAL(answerClicked()));
connect(button, SIGNAL(clicked3()), this, SIGNAL(answerClicked()));
grid->addWidget(button, 3, c, 1, 1);
OPERATOR_BUTTON3(SIGN_MULTIPLICATION, "&", "<<", 1, c);
OPERATOR_BUTTON3(settings->multiplicationSign(), "&", "<<", 1, c);
button->setToolTip(tr("Multiplication"), tr("Bitwise AND"), tr("Bitwise Shift"));
multiplicationButton = button;
delButton = new KeypadButton(LOAD_ICON("edit-delete"), this, true);
connect(delButton, SIGNAL(clicked()), this, SIGNAL(delClicked()));
connect(delButton, SIGNAL(clicked2()), this, SIGNAL(backspaceClicked()));
@ -318,8 +319,8 @@ KeypadWidget::KeypadWidget(QWidget *parent) : QWidget(parent) {
OPERATOR_SYMBOL_BUTTON(SIGN_MINUS, SIGN_MINUS, 2, c);
button->setToolTip(tr("Subtraction"), tr("Minus"));
}
OPERATOR_BUTTON3(SIGN_DIVISION_SLASH, "|", "~", 1, c);
button->setProperty(BUTTON_DATA, "/");
OPERATOR_BUTTON3(settings->divisionSign(), "|", "~", 1, c);
button->setProperty(BUTTON_DATA, settings->divisionSign());
button->setToolTip(tr("Division"), tr("Bitwise OR"), tr("Bitwise NOT"));
acButton = new KeypadButton(LOAD_ICON("edit-clear"), this);
acButton->setToolTip(tr("Clear expression"));
@ -357,6 +358,10 @@ KeypadWidget::KeypadWidget(QWidget *parent) : QWidget(parent) {
KeypadWidget::~KeypadWidget() {}
void KeypadWidget::updateSymbols() {
multiplicationButton->setText(settings->multiplicationSign());
multiplicationButton->setProperty(BUTTON_DATA, settings->multiplicationSign());
multiplicationButton->setText(settings->divisionSign());
multiplicationButton->setProperty(BUTTON_DATA, settings->divisionSign());
commaButton->setText(QString::fromStdString(CALCULATOR->getComma()));
commaButton->setProperty(BUTTON_DATA, QString::fromStdString(CALCULATOR->getComma()));
dotButton->setText(QString::fromStdString(CALCULATOR->getDecimalPoint()));

View File

@ -65,7 +65,7 @@ class KeypadWidget : public QWidget {
protected:
KeypadButton *sinButton, *cosButton, *tanButton, *delButton, *acButton, *backButton, *forwardButton, *dotButton, *commaButton;
KeypadButton *sinButton, *cosButton, *tanButton, *delButton, *acButton, *backButton, *forwardButton, *dotButton, *commaButton, *multiplicationButton;
void changeEvent(QEvent *e);
protected slots:

View File

@ -126,6 +126,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
combo->addItem(tr("Chain"), PARSING_MODE_CHAIN);
combo->addItem(tr("RPN"), PARSING_MODE_RPN);
combo->setCurrentIndex(combo->findData(settings->evalops.parse_options.parsing_mode));
parseCombo = combo;
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(parsingModeChanged(int)));
l2->addWidget(combo, r, 1); r++;
BOX_G(tr("Read precision"), settings->evalops.parse_options.read_precision != DONT_READ_PRECISION, readPrecisionToggled(bool));
@ -143,10 +144,13 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
BOX(tr("Binary two's complement representation"), settings->printops.twos_complement, binTwosToggled(bool));
BOX(tr("Hexadecimal two's complement representation"), settings->printops.hexadecimal_twos_complement, hexTwosToggled(bool));
BOX(tr("Use lower case letters in non-decimal numbers"), settings->printops.lower_case_numbers, lowerCaseToggled(bool));
BOX(tr("Use dot as multiplication sign"), settings->printops.multiplication_sign != MULTIPLICATION_SIGN_X, multiplicationDotToggled(bool));
BOX(tr("Use Unicode division slash in output"), settings->printops.division_sign == DIVISION_SIGN_DIVISION_SLASH, divisionSlashToggled(bool));
BOX(tr("Spell out logical operators"), settings->printops.spell_out_logical_operators, spellOutToggled(bool));
BOX(tr("Use E-notation instead of 10^n"), settings->printops.lower_case_e, eToggled(bool));
BOX(tr("Use 'j' as imaginary unit"), CALCULATOR->getVariableById(VARIABLE_ID_I)->hasName("j") > 0, imaginaryJToggled(bool));
BOX(tr("Use comma as decimal separator"), CALCULATOR->getDecimalPoint() == COMMA, decimalCommaToggled(bool));
decimalCommaBox = box;
BOX(tr("Ignore comma in numbers"), settings->evalops.parse_options.comma_as_separator, ignoreCommaToggled(bool)); ignoreCommaBox = box;
BOX(tr("Ignore dots in numbers"), settings->evalops.parse_options.dot_as_separator, ignoreDotToggled(bool)); ignoreDotBox = box;
BOX(tr("Round halfway numbers to even"), settings->printops.round_halfway_to_even, roundEvenToggled(bool));
@ -224,6 +228,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
combo->addItem(tr("Relative"), TEMPERATURE_CALCULATION_RELATIVE);
combo->addItem(tr("Hybrid"), TEMPERATURE_CALCULATION_HYBRID);
combo->setCurrentIndex(combo->findData(CALCULATOR->getTemperatureCalculationMode()));
tcCombo = combo;
l2->addWidget(combo, r, 1); r++;
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(temperatureCalculationChanged(int)));
box = new QCheckBox(tr("Exchange rates updates:"), this); box->setChecked(settings->auto_update_exchange_rates > 0); connect(box, SIGNAL(toggled(bool)), this, SLOT(exratesToggled(bool))); l2->addWidget(box, r, 0);
@ -282,6 +287,18 @@ void PreferencesDialog::lowerCaseToggled(bool b) {
settings->printops.lower_case_numbers = b;
emit resultDisplayUpdated();
}
void PreferencesDialog::multiplicationDotToggled(bool b) {
if(b) settings->printops.multiplication_sign = MULTIPLICATION_SIGN_ALTDOT;
else settings->printops.multiplication_sign = MULTIPLICATION_SIGN_X;
emit resultDisplayUpdated();
emit symbolsUpdated();
}
void PreferencesDialog::divisionSlashToggled(bool b) {
if(b) settings->printops.division_sign = DIVISION_SIGN_DIVISION_SLASH;
else settings->printops.division_sign = DIVISION_SIGN_SLASH;
emit resultDisplayUpdated();
emit symbolsUpdated();
}
void PreferencesDialog::spellOutToggled(bool b) {
settings->printops.spell_out_logical_operators = b;
emit resultDisplayUpdated();
@ -339,6 +356,7 @@ void PreferencesDialog::colorizeToggled(bool b) {
}
void PreferencesDialog::parsingModeChanged(int i) {
settings->evalops.parse_options.parsing_mode = (ParsingMode) qobject_cast<QComboBox*>(sender())->itemData(i).toInt();
settings->implicit_question_asked = (settings->evalops.parse_options.parsing_mode == PARSING_MODE_CONVENTIONAL || settings->evalops.parse_options.parsing_mode == PARSING_MODE_IMPLICIT_MULTIPLICATION_FIRST);
emit expressionFormatUpdated(false);
}
void PreferencesDialog::temperatureCalculationChanged(int i) {
@ -543,3 +561,26 @@ void PreferencesDialog::replaceExpressionChanged(int i) {
settings->replace_expression = qobject_cast<QComboBox*>(sender())->itemData(i).toInt();
}
void PreferencesDialog::updateDot() {
decimalCommaBox->blockSignals(true);
ignoreCommaBox->blockSignals(true);
ignoreDotBox->blockSignals(true);
decimalCommaBox->setChecked(CALCULATOR->getDecimalPoint() == COMMA);
ignoreCommaBox->setChecked(settings->evalops.parse_options.comma_as_separator);
ignoreDotBox->setChecked(settings->evalops.parse_options.dot_as_separator);
decimalCommaBox->blockSignals(false);
ignoreCommaBox->blockSignals(false);
ignoreDotBox->blockSignals(false);
if(CALCULATOR->getDecimalPoint() == COMMA) ignoreCommaBox->hide();
if(CALCULATOR->getDecimalPoint() == DOT) ignoreDotBox->hide();
}
void PreferencesDialog::updateParsingMode() {
parseCombo->blockSignals(true);
parseCombo->setCurrentIndex(parseCombo->findData(settings->evalops.parse_options.parsing_mode));
parseCombo->blockSignals(false);
}
void PreferencesDialog::updateTemperatureCalculation() {
tcCombo->blockSignals(true);
tcCombo->setCurrentIndex(tcCombo->findData(CALCULATOR->getTemperatureCalculationMode()));
tcCombo->blockSignals(false);
}

View File

@ -26,9 +26,9 @@ class PreferencesDialog : public QDialog {
protected:
QCheckBox *ignoreCommaBox, *ignoreDotBox;
QCheckBox *decimalCommaBox, *ignoreCommaBox, *ignoreDotBox;
QSpinBox *exratesSpin, *statusDelayWidget;
QComboBox *styleCombo;
QComboBox *styleCombo, *parseCombo, *tcCombo;
void closeEvent(QCloseEvent*) override;
@ -41,6 +41,8 @@ class PreferencesDialog : public QDialog {
void binTwosToggled(bool);
void hexTwosToggled(bool);
void lowerCaseToggled(bool);
void multiplicationDotToggled(bool);
void divisionSlashToggled(bool);
void spellOutToggled(bool);
void eToggled(bool);
void imaginaryJToggled(bool);
@ -90,6 +92,10 @@ class PreferencesDialog : public QDialog {
PreferencesDialog(QWidget *parent = NULL);
virtual ~PreferencesDialog();
void updateDot();
void updateParsingMode();
void updateTemperatureCalculation();
signals:
void resultFormatUpdated();

View File

@ -203,6 +203,7 @@ void QalculateQtSettings::loadPreferences() {
title_type = TITLE_APP;
dot_question_asked = false;
implicit_question_asked = false;
complex_angle_form = false;
decimal_comma = -1;
adaptive_interval_display = true;
@ -294,10 +295,18 @@ void QalculateQtSettings::loadPreferences() {
v = s2i(svalue);
if(svar == "history_expression") {
v_expression.push_back(svalue);
v_delexpression.push_back(false);
v_result.push_back(std::vector<std::string>());
v_exact.push_back(std::vector<int>());
v_delresult.push_back(std::vector<bool>());
} else if(svar == "history_result") {
if(!v_result.empty()) v_result[settings->v_result.size() - 1].push_back(svalue);
if(!v_result.empty()) {
v_result[settings->v_result.size() - 1].push_back(svalue);
v_delresult[settings->v_result.size() - 1].push_back(false);
if(v_exact[settings->v_exact.size() - 1].size() < v_result[settings->v_result.size() - 1].size()) {
v_exact[settings->v_exact.size() - 1].push_back(false);
}
}
} else if(svar == "history_exact") {
if(!v_exact.empty()) v_exact[settings->v_exact.size() - 1].push_back(v);
} else if(svar == "expression_history") {
@ -380,6 +389,12 @@ void QalculateQtSettings::loadPreferences() {
} else if(svar == "custom_application_font") {
custom_app_font = svalue;
save_custom_app_font = true;
} else if(svar == "multiplication_sign") {
if(v >= MULTIPLICATION_SIGN_ASTERISK && v <= MULTIPLICATION_SIGN_ALTDOT) {
printops.multiplication_sign = (MultiplicationSign) v;
}
} else if(svar == "division_sign") {
if(v >= DIVISION_SIGN_SLASH && v <= DIVISION_SIGN_DIVISION) printops.division_sign = (DivisionSign) v;
} else if(svar == "plot_legend_placement") {
if(v >= PLOT_LEGEND_NONE && v <= PLOT_LEGEND_OUTSIDE) default_plot_legend_placement = (PlotLegendPlacement) v;
} else if(svar == "plot_style") {
@ -598,6 +613,9 @@ void QalculateQtSettings::loadPreferences() {
printops.limit_implicit_multiplication = v;
} else if(svar == "parsing_mode") {
evalops.parse_options.parsing_mode = (ParsingMode) v;
if(evalops.parse_options.parsing_mode == PARSING_MODE_CONVENTIONAL || evalops.parse_options.parsing_mode == PARSING_MODE_IMPLICIT_MULTIPLICATION_FIRST) implicit_question_asked = true;
} else if(svar == "implicit_question_asked") {
implicit_question_asked = true;
} else if(svar == "default_assumption_type") {
if(v >= ASSUMPTION_TYPE_NONE && v <= ASSUMPTION_TYPE_BOOLEAN) {
CALCULATOR->defaultAssumptions()->setType((AssumptionType) v);
@ -804,6 +822,9 @@ void QalculateQtSettings::savePreferences(bool) {
if(use_custom_expression_font || save_custom_expression_font) fprintf(file, "custom_expression_font=%s\n", custom_expression_font.c_str());
if(use_custom_keypad_font || save_custom_keypad_font) fprintf(file, "custom_keypad_font=%s\n", custom_keypad_font.c_str());
if(use_custom_app_font || save_custom_app_font) fprintf(file, "custom_application_font=%s\n", custom_app_font.c_str());
if(printops.multiplication_sign != MULTIPLICATION_SIGN_X) fprintf(file, "multiplication_sign=%i\n", printops.multiplication_sign);
if(printops.division_sign != DIVISION_SIGN_DIVISION_SLASH) fprintf(file, "division_sign=%i\n", printops.division_sign);
if(implicit_question_asked) fprintf(file, "implicit_question_asked=%i\n", implicit_question_asked);
fprintf(file, "replace_expression=%i\n", replace_expression);
fprintf(file, "rpn_keys=%i\n", rpn_keys);
/*if(default_bits >= 0) fprintf(file, "bit_width=%i\n", default_bits);
@ -921,22 +942,26 @@ void QalculateQtSettings::savePreferences(bool) {
i--;
}
for(; i < v_expression.size(); i++) {
fprintf(file, "history_expression=%s\n", v_expression[i].c_str());
n++;
for(size_t i2 = 0; i2 < settings->v_result[i].size(); i2++) {
fprintf(file, "history_exact=%i\n", v_exact[i][i2]);
if(v_result[i][i2].length() > 6000) {
std::string str = unhtmlize(v_result[i][i2]);
if(str.length() > 5000) {
int index = 50;
while(index >= 0 && str[index] < 0 && (unsigned char) str[index + 1] < 0xC0) index--;
gsub("\n", "<br>", str);
fprintf(file, "history_result=%s …\n", str.substr(0, index + 1).c_str());
} else {
fprintf(file, "history_result=%s\n", v_result[i][i2].c_str());
if(!v_delexpression[i]) {
fprintf(file, "history_expression=%s\n", v_expression[i].c_str());
n++;
for(size_t i2 = 0; i2 < settings->v_result[i].size(); i2++) {
if(!v_delresult[i][i2]) {
fprintf(file, "history_exact=%i\n", v_exact[i][i2]);
if(v_result[i][i2].length() > 6000) {
std::string str = unhtmlize(v_result[i][i2]);
if(str.length() > 5000) {
int index = 50;
while(index >= 0 && str[index] < 0 && (unsigned char) str[index + 1] < 0xC0) index--;
gsub("\n", "<br>", str);
fprintf(file, "history_result=%s …\n", str.substr(0, index + 1).c_str());
} else {
fprintf(file, "history_result=%s\n", v_result[i][i2].c_str());
}
} else {
fprintf(file, "history_result=%s\n", v_result[i][i2].c_str());
}
}
} else {
fprintf(file, "history_result=%s\n", v_result[i][i2].c_str());
}
}
}
@ -950,6 +975,21 @@ void QalculateQtSettings::savePreferences(bool) {
}
const char *QalculateQtSettings::multiplicationSign() {
if(!printops.use_unicode_signs) return "*";
switch(printops.multiplication_sign) {
case MULTIPLICATION_SIGN_X: {return SIGN_MULTIPLICATION;}
case MULTIPLICATION_SIGN_DOT: {return SIGN_MULTIDOT;}
case MULTIPLICATION_SIGN_ALTDOT: {return SIGN_MIDDLEDOT;}
default: {return "*";}
}
}
const char *QalculateQtSettings::divisionSign(bool output) {
if(printops.division_sign == DIVISION_SIGN_DIVISION && printops.use_unicode_signs) return SIGN_DIVISION;
else if(output && printops.division_sign == DIVISION_SIGN_DIVISION_SLASH && printops.use_unicode_signs) return SIGN_DIVISION_SLASH;
return "/";
}
void QalculateQtSettings::updateMessagePrintOptions() {
PrintOptions message_printoptions = printops;
message_printoptions.interval_display = INTERVAL_DISPLAY_PLUSMINUS;
@ -1062,15 +1102,17 @@ bool QalculateQtSettings::displayMessages(QWidget *parent) {
MessageType mtype, mtype_highest = MESSAGE_INFORMATION;
while(true) {
mtype = CALCULATOR->message()->type();
if(index > 0) {
if(index == 1) str = "" + str;
str += "\n";
if(CALCULATOR->message()->category() != MESSAGE_CATEGORY_IMPLICIT_MULTIPLICATION || !implicit_question_asked) {
if(index > 0) {
if(index == 1) str = "" + str;
str += "\n";
}
str += CALCULATOR->message()->message();
if(mtype == MESSAGE_ERROR || (mtype_highest != MESSAGE_ERROR && mtype == MESSAGE_WARNING)) {
mtype_highest = mtype;
}
index++;
}
str += CALCULATOR->message()->message();
if(mtype == MESSAGE_ERROR || (mtype_highest != MESSAGE_ERROR && mtype == MESSAGE_WARNING)) {
mtype_highest = mtype;
}
index++;
if(!CALCULATOR->nextMessage()) break;
}
if(!str.empty()) {
@ -1177,11 +1219,11 @@ void QalculateQtSettings::checkVersion(bool force, QWidget *parent) {
if(ret > 0 && (force || new_version != last_found_version)) {
last_found_version = new_version;
#ifdef AUTO_UPDATE
if(QMessageBox::question(parent, QString(), tr("A new version of %1 is available at %2.\n\nDo you wish to update to version %3?").arg("Qalculate!").arg("<a href=\"http://qalculate.github.io/downloads.html\">qalculate.github.io</a>").arg(QString::fromStdString(new_version)) == QMessageBox::Yes)) {
if(QMessageBox::question(parent, QString(), tr("<div>A new version of %1 is available at %2.\n\nDo you wish to update to version %3?</div>").arg("Qalculate!").arg("<a href=\"https://qalculate.github.io/downloads.html\">qalculate.github.io</a>").arg(QString::fromStdString(new_version)) == QMessageBox::Yes)) {
autoUpdate(new_version);
}
#else
QMessageBox::information(parent, QString(), tr("A new version of %1 is available.\n\nYou can get version %3 at %2.").arg("Qalculate!").arg("<a href=\"http://qalculate.github.io/downloads.html\">qalculate.github.io</a>").arg(QString::fromStdString(new_version)));
QMessageBox::information(parent, QString(), tr("<div>A new version of %1 is available.\n\nYou can get version %3 at %2.</div>").arg("Qalculate!").arg("<a href=\"https://qalculate.github.io/downloads.html\">qalculate.github.io</a>").arg(QString::fromStdString(new_version)));
#endif
}
last_version_check_date.setToCurrentDate();

View File

@ -73,10 +73,12 @@ class QalculateQtSettings : QObject {
bool isAnswerVariable(Variable *v);
void checkVersion(bool force, QWidget *parent);
void autoUpdate(std::string new_version, QWidget *parent);
const char *multiplicationSign();
const char *divisionSign(bool output = true);
EvaluationOptions evalops;
PrintOptions printops;
bool complex_angle_form, dot_question_asked, adaptive_interval_display, tc_set, rpn_mode, chain_mode, caret_as_xor, ignore_locale, do_imaginary_j, fetch_exchange_rates_at_startup, always_on_top, display_expression_status, prefixes_default, rpn_keys;
bool complex_angle_form, dot_question_asked, implicit_question_asked, adaptive_interval_display, tc_set, rpn_mode, chain_mode, caret_as_xor, ignore_locale, do_imaginary_j, fetch_exchange_rates_at_startup, always_on_top, display_expression_status, prefixes_default, rpn_keys;
int allow_multiple_instances;
int decimal_comma, dual_fraction, dual_approximation, auto_update_exchange_rates, title_type;
int completion_delay, expression_status_delay;
@ -116,7 +118,9 @@ class QalculateQtSettings : QObject {
std::string last_found_version;
std::vector<std::string> v_expression;
std::vector<bool> v_delexpression;
std::vector<std::vector<std::string> > v_result;
std::vector<std::vector<bool> > v_delresult;
std::vector<std::vector<int> > v_exact;
};

View File

@ -925,7 +925,7 @@ void QalculateWindow::onOperatorClicked(const QString &str) {
do_exec = (str == "!") && cur.hasSelection() && cur.selectionStart() == 0 && cur.selectionEnd() == expressionEdit->toPlainText().length();
expressionEdit->wrapSelection(str);
} else if(str == "E") {
if(expressionEdit->textCursor().hasSelection()) expressionEdit->wrapSelection(SIGN_MULTIPLICATION "10^");
if(expressionEdit->textCursor().hasSelection()) expressionEdit->wrapSelection(QString::fromUtf8(settings->multiplicationSign()) + "10^");
else expressionEdit->insertPlainText(settings->printops.lower_case_e ? "e" : str);
} else {
if(!expressionEdit->doChainMode(str)) expressionEdit->wrapSelection(str);
@ -1675,6 +1675,7 @@ void QalculateWindow::setOption(std::string str) {
CALCULATOR->error(true, "Illegal value: %s.", svalue.c_str(), NULL);
} else {
settings->evalops.parse_options.parsing_mode = (ParsingMode) v;
settings->implicit_question_asked = (settings->evalops.parse_options.parsing_mode == PARSING_MODE_CONVENTIONAL || settings->evalops.parse_options.parsing_mode == PARSING_MODE_IMPLICIT_MULTIPLICATION_FIRST);
expressionFormatUpdated(true);
}
} else if(equalsIgnoreCase(svar, "update exchange rates") || svar == "upxrates") {
@ -4114,6 +4115,8 @@ void QalculateWindow::setResult(Prefix *prefix, bool update_history, bool update
parsed_text = result_text;
}
bool implicit_warning = false;
if(do_stack) {
RPNRegisterChanged(result_text, stack_index);
} else {
@ -4139,7 +4142,7 @@ void QalculateWindow::setResult(Prefix *prefix, bool update_history, bool update
}
int b_exact = (update_parse || !prev_approximate) && (exact_comparison || (!(*settings->printops.is_approximate) && !mstruct->isApproximate()));
if(alt_results.size() == 1 && (mstruct->isComparison() || ((mstruct->isLogicalAnd() || mstruct->isLogicalOr()) && mstruct->containsType(STRUCT_COMPARISON, true, false, false))) && (exact_comparison || b_exact || result_text.find(SIGN_ALMOST_EQUAL) != std::string::npos)) b_exact = -1;
historyView->addResult(alt_results, update_parse ? parsed_text : "", b_exact, update_parse && !mstruct_exact.isUndefined(), flag);
historyView->addResult(alt_results, update_parse ? parsed_text : "", b_exact, update_parse && !mstruct_exact.isUndefined(), flag, !supress_dialog && update_parse && settings->evalops.parse_options.parsing_mode <= PARSING_MODE_CONVENTIONAL && update_history ? &implicit_warning : NULL);
}
if(do_to) {
@ -4160,6 +4163,11 @@ void QalculateWindow::setResult(Prefix *prefix, bool update_history, bool update
b_busy--;
if(implicit_warning && askImplicit()) {
calculateExpression(true);
return;
}
if(!supress_dialog && !register_moved && !do_stack && mstruct->isMatrix() && matrix_mstruct.isMatrix()) {
QDialog *dialog = new QDialog(this);
if(settings->always_on_top) dialog->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
@ -4275,16 +4283,16 @@ bool QalculateWindow::askTC(MathStructure &m) {
group->setExclusive(true);
QRadioButton *w_abs = new QRadioButton(tr("Absolute"));
group->addButton(w_abs);
grid->addWidget(w_abs, 1, 0);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 274 K + 274 K ≈ 548 K\n1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K\n2 °C 1 °C = 1 K\n1 °C 5 °F = 16 K\n1 °C + 1 K = 2 °C</i>"), 1, 1);
grid->addWidget(w_abs, 1, 0, Qt::AlignTop);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 274 K + 274 K ≈ 548 K<br>1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K<br>2 °C 1 °C = 1 K<br>1 °C 5 °F = 16 K<br>1 °C + 1 K = 2 °C</i>"), 1, 1);
QRadioButton *w_relative = new QRadioButton(tr("Relative"));
group->addButton(w_relative);
grid->addWidget(w_relative, 2, 0);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 274 K + 274 K ≈ 548 K\n1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K\n2 °C 1 °C = 1 K\n1 °C 5 °F = 16 K\n1 °C + 1 K = 2 °C</i>"), 2, 1);
grid->addWidget(w_relative, 2, 0, Qt::AlignTop);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 274 K + 274 K ≈ 548 K<br>1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K<br>2 °C 1 °C = 1 K<br>1 °C 5 °F = 16 K<br>1 °C + 1 K = 2 °C</i>"), 2, 1);
QRadioButton *w_hybrid = new QRadioButton(tr("Hybrid"));
group->addButton(w_hybrid);
grid->addWidget(w_hybrid, 3, 0);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 2 °C\n1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K\n2 °C 1 °C = 1 °C\n1 °C 5 °F = 16 K\n1 °C + 1 K = 2 °C</i>"), 3, 1);
grid->addWidget(w_hybrid, 3, 0, Qt::AlignTop);
grid->addWidget(new QLabel("<i>1 °C + 1 °C ≈ 2 °C<br>1 °C + 5 °F ≈ 274 K + 258 K ≈ 532 K<br>2 °C 1 °C = 1 °C<br>1 °C 5 °F = 16 K<br>1 °C + 1 K = 2 °C</i>"), 3, 1);
switch(CALCULATOR->getTemperatureCalculationMode()) {
case TEMPERATURE_CALCULATION_ABSOLUTE: {w_abs->setChecked(true); break;}
case TEMPERATURE_CALCULATION_RELATIVE: {w_relative->setChecked(true); break;}
@ -4298,6 +4306,7 @@ bool QalculateWindow::askTC(MathStructure &m) {
settings->tc_set = true;
if(tc_mode != CALCULATOR->getTemperatureCalculationMode()) {
CALCULATOR->setTemperatureCalculationMode(tc_mode);
if(preferencesDialog) preferencesDialog->updateTemperatureCalculation();
return true;
}
return false;
@ -4358,9 +4367,53 @@ bool QalculateWindow::askDot(const std::string &str) {
} else {
settings->evalops.parse_options.dot_as_separator = false;
}
if(preferencesDialog) preferencesDialog->updateDot();
dialog->deleteLater();
return das != settings->evalops.parse_options.dot_as_separator;
}
bool QalculateWindow::askImplicit() {
QDialog *dialog = new QDialog(this);
QVBoxLayout *box = new QVBoxLayout(dialog);
if(settings->always_on_top) dialog->setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
dialog->setWindowTitle(tr("Parsing Mode"));
QGridLayout *grid = new QGridLayout();
box->addLayout(grid);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok, Qt::Horizontal, dialog);
connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), dialog, SLOT(accept()));
box->addWidget(buttonBox);
grid->addWidget(new QLabel(tr("The expression is ambiguous.\nPlease select interpretation of expressions with implicit multiplication\n(this can later be changed in preferences).")), 0, 0, 1, 2);
QButtonGroup *group = new QButtonGroup(dialog);
group->setExclusive(true);
QRadioButton *w_implicitfirst = new QRadioButton(tr("Implicit multiplication first"));
group->addButton(w_implicitfirst);
if(settings->evalops.parse_options.parsing_mode == PARSING_MODE_IMPLICIT_MULTIPLICATION_FIRST) w_implicitfirst->setChecked(true);
grid->addWidget(w_implicitfirst, 1, 0);
grid->addWidget(new QLabel("<i>1/2x = 1/(2x)</i>"), 1, 1);
QRadioButton *w_conventional = new QRadioButton(tr("Conventional"));
group->addButton(w_conventional);
if(settings->evalops.parse_options.parsing_mode == PARSING_MODE_CONVENTIONAL) w_conventional->setChecked(true);
grid->addWidget(w_conventional, 2, 0);
grid->addWidget(new QLabel("<i>1/2x = (1/2)x</i>"), 2, 1);
QRadioButton *w_adaptive = new QRadioButton(tr("Adaptive"));
group->addButton(w_adaptive);
grid->addWidget(w_adaptive, 3, 0);
grid->addWidget(new QLabel("<i>1/2x = 1/(2x); 1/2 x = (1/2)x</i>"), 3, 1);
if(settings->evalops.parse_options.parsing_mode == PARSING_MODE_ADAPTIVE) w_adaptive->setChecked(true);
dialog->exec();
settings->implicit_question_asked = true;
ParsingMode pm_bak = settings->evalops.parse_options.parsing_mode;
if(w_implicitfirst->isChecked()) {
settings->evalops.parse_options.parsing_mode = PARSING_MODE_IMPLICIT_MULTIPLICATION_FIRST;
} else if(w_conventional->isChecked()) {
settings->evalops.parse_options.parsing_mode = PARSING_MODE_CONVENTIONAL;
} else {
settings->evalops.parse_options.parsing_mode = PARSING_MODE_ADAPTIVE;
}
if(preferencesDialog) preferencesDialog->updateParsingMode();
dialog->deleteLater();
return pm_bak != settings->evalops.parse_options.parsing_mode;
}
void QalculateWindow::keyPressEvent(QKeyEvent *e) {
if(e->matches(QKeySequence::Undo)) {
expressionEdit->editUndo();

View File

@ -100,6 +100,7 @@ class QalculateWindow : public QMainWindow {
void changeEvent(QEvent *e) override;
bool askTC(MathStructure&);
bool askDot(const std::string&);
bool askImplicit();
void keyPressEvent(QKeyEvent*) override;
void closeEvent(QCloseEvent*) override;
void setPreviousExpression();