Option (enabled by default) to show expression status (parsed expression and calculated value) as you type in history list, instead of in tooltip; Show parse error in tooltip; Modify behaviour of tooltip with function hint

This commit is contained in:
Hanna K. 2024-05-20 18:14:04 +02:00
parent f50f732fc8
commit 97f3970901
12 changed files with 468 additions and 183 deletions

47
data/scalable/warning.svg Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 128 128"
id="svg2"
sodipodi:docname="warning.svg"
width="128"
height="128"
inkscape:version="1.3.2 (091e20ef0f, 2023-11-25, custom)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs2" />
<sodipodi:namedview
id="namedview2"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="4.9137461"
inkscape:cx="-63.80061"
inkscape:cy="17.501922"
inkscape:current-layer="svg2" />
<style
type="text/css"
id="current-color-scheme">
.ColorScheme-NeutralText {
color:#f67400;
}
</style>
<path
class="ColorScheme-NeutralText"
d="m 64.048003,16.000214 a 6.0001505,5.9999866 0 0 0 -5.418135,3.317992 L 16.628815,103.31802 A 6.0001505,5.9999866 0 0 0 21.99895,112 h 84.00211 a 6.0001505,5.9999866 0 0 0 5.37013,-8.68198 L 69.37014,19.318206 a 6.0001505,5.9999866 0 0 0 -5.322137,-3.317992 z"
fill="currentColor"
id="path1"
style="stroke-width:8" />
<path
d="M 56,44 V 76 H 72 V 44 Z m 0,40 v 16 H 72 V 84 Z"
fill="#ffffff"
id="path2"
style="stroke-width:8" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -26,6 +26,7 @@
<file alias="actions/scalable/rpn-swap.svg">data/scalable/rpn-swap.svg</file>
<file alias="actions/scalable/table.svg">data/scalable/table.svg</file>
<file alias="actions/scalable/units.svg">data/scalable/units.svg</file>
<file alias="actions/scalable/warning.svg">data/scalable/warning.svg</file>
<file alias="dark/actions/scalable/calendars.svg">data/scalable/calendars-dark.svg</file>
<file alias="dark/actions/scalable/configure.svg">data/scalable/configure-dark.svg</file>
<file alias="dark/actions/scalable/convert.svg">data/scalable/convert-dark.svg</file>
@ -51,6 +52,7 @@
<file alias="dark/actions/scalable/rpn-swap.svg">data/scalable/rpn-swap-dark.svg</file>
<file alias="dark/actions/scalable/table.svg">data/scalable/table-dark.svg</file>
<file alias="dark/actions/scalable/units.svg">data/scalable/units-dark.svg</file>
<file alias="dark/actions/scalable/warning.svg">data/scalable/warning.svg</file>
<file alias="apps/16x16/qalculate-qt.png">data/16/qalculate-qt.png</file>
<file alias="apps/22x22/qalculate-qt.png">data/22/qalculate-qt.png</file>
<file alias="apps/32x32/qalculate-qt.png">data/32/qalculate-qt.png</file>

View File

@ -1881,8 +1881,12 @@ void ExpressionEdit::contextMenuEvent(QContextMenuEvent *e) {
menu = cmenu->addMenu(tr("Expression Status"));
group = new QActionGroup(this);
action = menu->addAction(tr("Off"), this, SLOT(onStatusModeChanged())); action->setData(0); action->setCheckable(true); group->addAction(action); statusOffAction = action;
action = menu->addAction(tr("With delay"), this, SLOT(onStatusModeChanged())); action->setData(1); action->setCheckable(true); group->addAction(action); statusDelayAction = action;
action = menu->addAction(tr("Without delay"), this, SLOT(onStatusModeChanged())); action->setData(2); action->setCheckable(true); group->addAction(action); statusNoDelayAction = action;
action = menu->addAction(tr("In history list"), this, SLOT(onStatusModeChanged())); action->setData(1); action->setCheckable(true); group->addAction(action); statusHistoryAction = action;
action = menu->addAction(tr("In expression field"), this, SLOT(onStatusModeChanged())); action->setData(2); action->setCheckable(true); group->addAction(action); statusExpressionAction = action;
menu->addSeparator();
group = new QActionGroup(this);
action = menu->addAction(tr("With delay"), this, SLOT(onStatusModeChanged())); action->setData(3); action->setCheckable(true); group->addAction(action); statusDelayAction = action;
action = menu->addAction(tr("Without delay"), this, SLOT(onStatusModeChanged())); action->setData(4); action->setCheckable(true); group->addAction(action); statusNoDelayAction = action;
#ifndef _WIN32
QAction *enableIMAction = cmenu->addAction(tr("Use input method"), this, SLOT(enableIM())); enableIMAction->setCheckable(true);
enableIMAction->setChecked(settings->enable_input_method);
@ -1900,7 +1904,9 @@ void ExpressionEdit::contextMenuEvent(QContextMenuEvent *e) {
clearAction->setEnabled(!b_empty);
clearHistoryAction->setEnabled(!settings->expression_history.empty());
if(!settings->display_expression_status) statusOffAction->setChecked(true);
else if(settings->expression_status_delay > 0) statusDelayAction->setChecked(true);
else if(settings->status_in_history) statusHistoryAction->setChecked(true);
else statusExpressionAction->setChecked(true);
if(settings->expression_status_delay > 0) statusDelayAction->setChecked(true);
else statusNoDelayAction->setChecked(true);
cmenu->popup(e->globalPos());
}
@ -1956,10 +1962,13 @@ void ExpressionEdit::onCompletionModeChanged() {
}
void ExpressionEdit::onStatusModeChanged() {
int i = qobject_cast<QAction*>(sender())->data().toInt();
settings->display_expression_status = (i > 0);
if(i == 1) settings->expression_status_delay = 1000;
else if(i == 2) settings->expression_status_delay = 0;
emit expressionStatusModeChanged();
if(i == 3) settings->expression_status_delay = 1000;
else if(i == 4) settings->expression_status_delay = 0;
if(i < 3) {
settings->display_expression_status = (i > 0);
settings->status_in_history = (i == 1);
}
emit expressionStatusModeChanged(i < 3);
}
void ExpressionEdit::editUndo() {
if(undo_index == 0) return;
@ -2025,40 +2034,14 @@ void ExpressionEdit::blockUndo(bool b) {
if(b) block_add_to_undo++;
else block_add_to_undo--;
}
void remove_spaces(std::string &str) {
size_t i = 0;
while(true) {
i = str.find(' ', i);
if(i != std::string::npos) str.erase(i, 1);
else break;
}
i = 0;
while(true) {
i = str.find(THIN_SPACE, i);
if(i != std::string::npos) str.erase(i, strlen(THIN_SPACE));
else break;
}
i = 0;
while(true) {
i = str.find(NNBSP, i);
if(i != std::string::npos) str.erase(i, strlen(NNBSP));
else break;
}
i = 0;
while(true) {
i = str.find(NBSP, i);
if(i != std::string::npos) str.erase(i, strlen(NBSP));
else break;
}
}
void ExpressionEdit::showCurrentStatus() {
if(!expression_has_changed || current_status_text.isEmpty() || (completionView->isVisible() && completionView->selectionModel()->hasSelection())) {
if(!expression_has_changed || current_status_text.isEmpty() || (completionView->isVisible() && (completionView->selectionModel()->hasSelection() || current_status_type == 3))) {
HIDE_TOOLTIP
} else {
QString str = current_status_text;
std::string str_nohtml = unhtmlize(current_status_text.toStdString());
std::string current_text = toPlainText().toStdString();
if(current_status_is_expression && settings->auto_calculate && str_nohtml.length() <= 2000 && !contains_plot_or_save(current_text)) {
if(current_status_type == 1 && settings->auto_calculate && str_nohtml.length() <= 2000 && !contains_plot_or_save(current_text)) {
bool b_comp = false, is_approximate = false;
PrintOptions po = settings->printops;
po.is_approximate = &is_approximate;
@ -2085,14 +2068,14 @@ void ExpressionEdit::showCurrentStatus() {
if(str_nohtml == current_text || str_nohtml.length() > 2000) {
HIDE_TOOLTIP
} else if(tipLabel && tipLabel->isVisible()) {
tipLabel->reuseTip(str, mapToGlobal(cursorRect().bottomRight()));
if(!tipLabel->placeTip(mapToGlobal(cursorRect().bottomRight()), completionView->isVisible() ? completionView->geometry(): QRect())) {
tipLabel->reuseTip(str, mapToGlobal((current_status_type == 2 ? function_pos : cursorRect().bottomRight())));
if(!tipLabel->placeTip(mapToGlobal((current_status_type == 2 ? function_pos : cursorRect().bottomRight())), completionView->isVisible() ? completionView->geometry(): QRect())) {
HIDE_TOOLTIP
}
} else {
if(tipLabel) tipLabel->deleteLater();
tipLabel = new ExpressionTipLabel(str, mapToGlobal(cursorRect().bottomRight()), this);
if(tipLabel->placeTip(mapToGlobal(cursorRect().bottomRight()), completionView->isVisible() ? completionView->geometry(): QRect())) {
tipLabel = new ExpressionTipLabel(str, mapToGlobal((current_status_type == 2 ? function_pos : cursorRect().bottomRight())), this);
if(tipLabel->placeTip(mapToGlobal((current_status_type == 2 ? function_pos : cursorRect().bottomRight())), completionView->isVisible() ? completionView->geometry(): QRect())) {
tipLabel->showNormal();
} else {
HIDE_TOOLTIP
@ -2100,14 +2083,15 @@ void ExpressionEdit::showCurrentStatus() {
}
}
}
void ExpressionEdit::setStatusText(const QString &text, bool is_expression) {
void ExpressionEdit::setStatusText(const QString &text, int stype) {
if(toolTipTimer) toolTipTimer->stop();
if(text.isEmpty()) {
if(text.isEmpty() || !settings->display_expression_status) {
HIDE_TOOLTIP
} else if(settings->display_expression_status) {
} else {
current_status_text = text;
current_status_is_expression = is_expression;
if(settings->expression_status_delay > 0) {
bool prev_func = (current_status_type == 2);
current_status_type = stype;
if(settings->expression_status_delay > 0 && (current_status_type != 2 || !prev_func || !tipLabel || !tipLabel->isVisible())) {
if(tipLabel) tipLabel->hideTip();
if(!toolTipTimer) {
toolTipTimer = new QTimer(this);
@ -2128,12 +2112,15 @@ bool ExpressionEdit::displayFunctionHint(MathFunction *f, int arg_index) {
if((iargs == 0 && arg_index == 0) || (iargs == 1 && arg_index == 1)) return false;
const ExpressionName *ename = &f->preferredName(false, settings->printops.use_unicode_signs, false, false, &can_display_unicode_string_function, (void*) parent());
bool last_is_vctr = f->getArgumentDefinition(iargs) && f->getArgumentDefinition(iargs)->type() == ARGUMENT_TYPE_VECTOR;
if(arg_index == 0 || function_pos.isNull()) function_pos = cursorRect().bottomRight();
if(iargs == 0 || (arg_index > iargs && iargs >= 0 && (!last_is_vctr || iargs == 1))) {
if(last_is_vctr || (iargs == 1 && f->getArgumentDefinition(1) && f->getArgumentDefinition(1)->handlesVector())) {
function_pos = QPoint();
return false;
} else {
setStatusText(tr("Too many arguments for %1().").arg(QString::fromStdString(ename->formattedName(TYPE_FUNCTION, true, true))), 2);
return true;
}
setStatusText(tr("Too many arguments for %1().").arg(QString::fromStdString(ename->formattedName(TYPE_FUNCTION, true, true))));
return true;
}
if(arg_index <= 0) arg_index = 1;
Argument *arg;
@ -2200,7 +2187,7 @@ bool ExpressionEdit::displayFunctionHint(MathFunction *f, int arg_index) {
}
}
str += ")";
setStatusText(str);
setStatusText(str, 2);
return true;
}
@ -2256,7 +2243,9 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
cdata->current_function = NULL;
if(block_display_parse) return;
if(document()->isEmpty()) {
function_pos = QPoint();
setStatusText("");
if(settings->status_in_history) emit statusChanged(QString(), false, false);
prev_parsed_expression = "";
expression_has_changed2 = false;
return;
@ -2274,6 +2263,7 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
else text += to_str;
text += ")";
} else if(text.empty()) {
function_pos = QPoint();
setStatusText("");
prev_parsed_expression = "";
expression_has_changed2 = false;
@ -2283,20 +2273,50 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
if(text[0] == '/' && text.length() > 1) {
size_t i = text.find_first_not_of(SPACES, 1);
if(i != std::string::npos && (signed char) text[i] > 0 && is_not_in(NUMBER_ELEMENTS OPERATORS, text[i])) {
if(show_tooltip) setStatusText("qalc command");
if(settings->status_in_history) {
setStatusText("");
emit statusChanged("qalc command", false, false);
} else if(show_tooltip) {
setStatusText("qalc command");
function_pos = QPoint();
}
return;
}
} else if(text == "MC") {
if(show_tooltip) setStatusText(tr("MC (memory clear)"));
if(settings->status_in_history) {
setStatusText("");
emit statusChanged(tr("MC (memory clear)"), false, false);
} else if(show_tooltip) {
setStatusText(tr("MC (memory clear)"));
function_pos = QPoint();
}
return;
} else if(text == "MS") {
if(show_tooltip) setStatusText(tr("MS (memory store)"));
if(settings->status_in_history) {
setStatusText("");
emit statusChanged(tr("MS (memory store)"), false, false);
} else if(show_tooltip) {
setStatusText(tr("MS (memory store)"));
function_pos = QPoint();
}
return;
} else if(text == "M+") {
if(show_tooltip) setStatusText(tr("M+ (memory plus)"));
if(settings->status_in_history) {
setStatusText("");
emit statusChanged(tr("M+ (memory plus)"), false, false);
} else if(show_tooltip) {
setStatusText(tr("M+ (memory plus)"));
function_pos = QPoint();
}
return;
} else if(text == "M-" || text == "M") {
if(show_tooltip) setStatusText(tr("M (memory minus)"));
if(settings->status_in_history) {
setStatusText("");
emit statusChanged(tr("M (memory minus)"), false, false);
} else if(show_tooltip) {
setStatusText(tr("M (memory minus)"));
function_pos = QPoint();
}
return;
}
gsub(ID_WRAP_LEFT, LEFT_PARENTHESIS, text);
@ -2359,6 +2379,7 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
b_func = displayFunctionHint(mfunc.function(), mfunc.countChildren());
}
}
if(!b_func) function_pos = QPoint();
if(expression_has_changed2) {
bool last_is_space = false;
parsed_expression_tooltip = "";
@ -2429,17 +2450,17 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
MathStructure mwhere;
CALCULATOR->parseExpressionAndWhere(&mparse, &mwhere, str_e, str_w, settings->evalops.parse_options);
mparse.format(po);
parsed_expression = mparse.print(po, true, false, TAG_TYPE_HTML);
parsed_expression = mparse.print(po, true, settings->status_in_history ? settings->color : false, TAG_TYPE_HTML);
parsed_expression += CALCULATOR->localWhereString();
mwhere.format(po);
parsed_expression += mwhere.print(po, true, false, TAG_TYPE_HTML);
parsed_expression += mwhere.print(po, true, settings->status_in_history ? settings->color : false, TAG_TYPE_HTML);
CALCULATOR->endTemporaryStopMessages();
} else if(str_e.empty()) {
parsed_expression = "";
} else {
CALCULATOR->beginTemporaryStopMessages();
mparse.format(po);
parsed_expression = mparse.print(po, true, false, TAG_TYPE_HTML);
parsed_expression = mparse.print(po, true, settings->status_in_history ? settings->color : false, TAG_TYPE_HTML);
CALCULATOR->endTemporaryStopMessages();
}
if(!str_u.empty()) {
@ -2671,7 +2692,7 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
parsed_expression += p->preferredDisplayName(po.abbreviate_names, po.use_unicode_signs, false, false, po.can_display_unicode_string_function, po.can_display_unicode_string_arg).formattedName(-1, true, TAG_TYPE_HTML, 0, true, po.hide_underscore_spaces);
} else {
CALCULATOR->beginTemporaryStopMessages();
parsed_expression += mparse.print(po, true, false, TAG_TYPE_HTML);
parsed_expression += mparse.print(po, true, settings->status_in_history ? settings->color : false, TAG_TYPE_HTML);
CALCULATOR->endTemporaryStopMessages();
}
had_to_conv = true;
@ -2682,7 +2703,7 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
}
if(mparse2) {
mparse2->format(po);
parsed_expression.replace(0, parse_l, mparse2->print(po, true, false, TAG_TYPE_HTML));
parsed_expression.replace(0, parse_l, mparse2->print(po, true, settings->status_in_history ? settings->color : false, TAG_TYPE_HTML));
mparse2->unref();
}
}
@ -2697,6 +2718,7 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
parsed_expression_tooltip += "<br>• ";
}
parsed_expression_tooltip += CALCULATOR->message()->message();
had_errors = true;
message_n++;
} else if(mtype == MESSAGE_WARNING) {
had_warnings = true;
@ -2704,17 +2726,25 @@ void ExpressionEdit::displayParseStatus(bool update, bool show_tooltip) {
}
CALCULATOR->nextMessage();
}
bool status_error = had_errors;
parsed_had_errors = had_errors; parsed_had_warnings = had_warnings;
if(!str_f.empty()) {str_f += " "; parsed_expression.insert(0, str_f);}
if(had_errors) prev_parsed_expression = QString::fromStdString(parsed_expression_tooltip);
else prev_parsed_expression = QString::fromStdString(parsed_expression);
settings->evalops.parse_options.preserve_format = false;
if(!b_func && show_tooltip) setStatusText(settings->chain_mode ? "" : prev_parsed_expression, true);
if(settings->status_in_history) {
emit statusChanged(QString::fromStdString(parsed_expression), !str_e.empty(), status_error);
if(!b_func) setStatusText(settings->chain_mode || !had_errors ? "" : prev_parsed_expression, had_errors ? 3 : 0);
} else if(!b_func && show_tooltip) {
setStatusText(settings->chain_mode ? "" : prev_parsed_expression, had_errors ? 3 : 1);
}
expression_has_changed2 = false;
} else if(!b_func) {
CALCULATOR->clearMessages();
settings->evalops.parse_options.preserve_format = false;
if(prev_func && show_tooltip) setStatusText(settings->chain_mode ? "" : prev_parsed_expression, true);
if(prev_func && show_tooltip) {
setStatusText((settings->status_in_history && !parsed_had_errors) || settings->chain_mode ? "" : prev_parsed_expression, parsed_had_errors ? 3 : 1);
}
} else {
settings->evalops.parse_options.preserve_format = false;
}
@ -2728,7 +2758,7 @@ void ExpressionEdit::onTextChanged() {
previous_pos = textCursor().position();
tabbed_index = -1;
if(completionTimer) completionTimer->stop();
if(tipLabel && settings->expression_status_delay > 0) tipLabel->hideTip();
if(tipLabel && settings->expression_status_delay > 0 && current_status_type != 2) tipLabel->hideTip();
if(block_text_change) return;
if(expression_undo_buffer.isEmpty() || str != expression_undo_buffer.last()) {
if(expression_undo_buffer.isEmpty()) {
@ -3104,7 +3134,7 @@ void ExpressionEdit::onCursorPositionChanged() {
tabbed_index = -1;
if(completionTimer) completionTimer->stop();
if(toolTipTimer) toolTipTimer->stop();
if(tipLabel && settings->expression_status_delay > 0) tipLabel->hideTip();
if(tipLabel && settings->expression_status_delay > 0 && current_status_type != 2) tipLabel->hideTip();
if(block_text_change) return;
cursor_has_moved = true;
int epos = document()->characterCount() - 1 - textCursor().position();

View File

@ -61,7 +61,7 @@ class ExpressionEdit : public QPlainTextEdit {
QStandardItemModel *sourceModel;
QTableView *completionView;
QMenu *cmenu;
QAction *undoAction, *redoAction, *cutAction, *copyAction, *pasteAction, *deleteAction, *selectAllAction, *clearAction, *statusOffAction, *statusDelayAction, *statusNoDelayAction, *clearHistoryAction;
QAction *undoAction, *redoAction, *cutAction, *copyAction, *pasteAction, *deleteAction, *selectAllAction, *clearAction, *statusOffAction, *statusDelayAction, *statusNoDelayAction, *statusHistoryAction, *statusExpressionAction, *clearHistoryAction;
QTimer *completionTimer, *toolTipTimer;
ExpressionTipLabel *tipLabel;
QWidget *tb;
@ -86,16 +86,17 @@ class ExpressionEdit : public QPlainTextEdit {
bool disable_history_arrow_keys, dont_change_index, cursor_has_moved;
int block_display_parse;
QString prev_parsed_expression, parsed_expression_tooltip, current_status_text;
bool current_status_is_expression;
int current_status_type;
bool expression_has_changed, expression_has_changed2;
bool parsed_had_errors, parsed_had_warnings;
int previous_epos;
QPoint function_pos;
bool parentheses_highlighted;
int default_frame;
QRect prev_rect;
void setCurrentObject();
void setStatusText(const QString &text, bool is_expression = false);
void setStatusText(const QString &text, int = 0);
bool displayFunctionHint(MathFunction *f, int arg_index = 1);
void highlightParentheses();
@ -164,7 +165,8 @@ class ExpressionEdit : public QPlainTextEdit {
void returnPressed();
void toConversionRequested(std::string);
void calculateRPNRequest(int);
void expressionStatusModeChanged();
void expressionStatusModeChanged(bool);
void statusChanged(QString, bool, bool);
};

View File

@ -155,6 +155,7 @@ HistoryView::HistoryView(QWidget *parent) : QTextEdit(parent) {
i_pos = 0;
i_pos_p = 0;
previous_cursor = 0;
previous_temporary = 0;
last_ans = 0;
#ifdef _WIN32
has_lock_symbol = 1;
@ -176,43 +177,43 @@ HistoryView::HistoryView(QWidget *parent) : QTextEdit(parent) {
}
HistoryView::~HistoryView() {}
void HistoryView::replaceColors(QString &s_text, QColor prev_text_color) {
void HistoryView::replaceColors(QString &str, QColor prev_text_color) {
if(settings->color == 2) {
s_text.replace("color: #585858", "color: #AAAAAA");
s_text.replace("color: #800000", "color: #FFAAAA");
s_text.replace("color: #000080", "color: #AAAAFF");
s_text.replace("color:#005858", "color:#AAFFFF");
s_text.replace("color:#585800", "color:#FFFFAA");
s_text.replace("color:#580058", "color:#FFAAFF");
s_text.replace("color:#800000", "color:#FFAAAA");
s_text.replace("color:#000080", "color:#AAAAFF");
s_text.replace("color:#008000", "color:#BBFFBB");
s_text.replace("color:#668888", "color:#88AAAA");
s_text.replace("color:#888866", "color:#AAAA88");
s_text.replace("color:#886688", "color:#AA88AA");
s_text.replace("color:#666699", "color:#AA8888");
s_text.replace("color:#669966", "color:#99BB99");
s_text.replace("color: #666666", "color: #AAAAAA");
s_text.replace(prev_text_color.name(QColor::HexRgb), text_color.name(QColor::HexRgb));
s_text.replace(":/icons/actions", ":/icons/dark/actions");
str.replace("color: #585858", "color: #AAAAAA");
str.replace("color: #800000", "color: #FFAAAA");
str.replace("color: #000080", "color: #AAAAFF");
str.replace("color:#005858", "color:#AAFFFF");
str.replace("color:#585800", "color:#FFFFAA");
str.replace("color:#580058", "color:#FFAAFF");
str.replace("color:#800000", "color:#FFAAAA");
str.replace("color:#000080", "color:#AAAAFF");
str.replace("color:#008000", "color:#BBFFBB");
str.replace("color:#668888", "color:#88AAAA");
str.replace("color:#888866", "color:#AAAA88");
str.replace("color:#886688", "color:#AA88AA");
str.replace("color:#666699", "color:#AA8888");
str.replace("color:#669966", "color:#99BB99");
str.replace("color: #666666", "color: #AAAAAA");
str.replace(prev_text_color.name(QColor::HexRgb), text_color.name(QColor::HexRgb));
str.replace(":/icons/actions", ":/icons/dark/actions");
} else {
s_text.replace("color: #AAAAAA", "color: #585858");
s_text.replace("color: #AAAAFF", "color: #000080");
s_text.replace("color: #FFAAAA", "color: #800000");
s_text.replace("color:#AAFFFF", "color:#005858");
s_text.replace("color:#FFFFAA", "color:#585800");
s_text.replace("color:#FFAAFF", "color:#580058");
s_text.replace("color:#FFAAAA", "color:#800000");
s_text.replace("color:#AAAAFF", "color:#000080");
s_text.replace("color:#BBFFBB", "color:#008000");
s_text.replace("color:#88AAAA", "color:#668888");
s_text.replace("color:#AAAA88", "color:#888866");
s_text.replace("color:#AA88AA", "color:#886688");
s_text.replace("color:#AA8888", "color:#666699");
s_text.replace("color:#99BB99", "color:#669966");
s_text.replace("color: #AAAAAA", "color: #666666");
s_text.replace(prev_text_color.name(QColor::HexRgb), text_color.name(QColor::HexRgb));
s_text.replace(":/icons/dark/actions", ":/icons/actions");
str.replace("color: #AAAAAA", "color: #585858");
str.replace("color: #AAAAFF", "color: #000080");
str.replace("color: #FFAAAA", "color: #800000");
str.replace("color:#AAFFFF", "color:#005858");
str.replace("color:#FFFFAA", "color:#585800");
str.replace("color:#FFAAFF", "color:#580058");
str.replace("color:#FFAAAA", "color:#800000");
str.replace("color:#AAAAFF", "color:#000080");
str.replace("color:#BBFFBB", "color:#008000");
str.replace("color:#88AAAA", "color:#668888");
str.replace("color:#AAAA88", "color:#888866");
str.replace("color:#AA88AA", "color:#886688");
str.replace("color:#AA8888", "color:#666699");
str.replace("color:#99BB99", "color:#669966");
str.replace("color: #AAAAAA", "color: #666666");
str.replace(prev_text_color.name(QColor::HexRgb), text_color.name(QColor::HexRgb));
str.replace(":/icons/dark/actions", ":/icons/actions");
}
}
void replace_colors(std::string &str) {
@ -303,10 +304,16 @@ void HistoryView::loadInitial(bool reload) {
if(reload && !initial_loaded) return;
s_text.clear();
i_pos = 0;
previous_html.clear();
i_pos_p = 0;
previous_html.clear();
last_ans = 0;
last_ref = "";
i_pos2 = 0;
i_pos_p2 = 0;
previous_html2.clear();
last_ans2 = 0;
last_ref2 = "";
previous_temporary = false;
for(size_t i = 0; i < settings->v_expression.size() && !reload;) {
if(i > 0 && !settings->v_protected[i] && settings->v_expression[i] == settings->v_expression[i - 1] && settings->v_parse[i] == settings->v_parse[i - 1] && settings->v_result[i] == settings->v_result[i - 1] && settings->v_pexact[i] == settings->v_pexact[i] && settings->v_exact[i] == settings->v_exact[i - 1] && settings->v_value[i] == settings->v_value[i - 1] && settings->v_parse[i].find("rand") == std::string::npos && settings->v_expression[i].find("rand") == std::string::npos) {
settings->v_expression.erase(settings->v_expression.begin() + i);
@ -365,7 +372,45 @@ void HistoryView::loadInitial(bool reload) {
int paste_h = fm.ascent() * 0.75; \
if(paste_h < 12) paste_h = 12;
void HistoryView::addResult(std::vector<std::string> values, std::string expression, bool pexact, std::string parse, int exact, bool dual_approx, const QString &image, bool *implicit_warning, int initial_load, size_t index) {
void HistoryView::clearTemporary() {
if(!previous_temporary || previous_html.isEmpty()) return;
QTextCursor cur = textCursor();
cur.setPosition(previous_cursor);
cur.setPosition(0, QTextCursor::KeepAnchor);
setTextCursor(cur);
cur.deleteChar();
if(!previous_html2.isEmpty()) {
cur.setPosition(previous_cursor2);
cur.setPosition(0, QTextCursor::KeepAnchor);
setTextCursor(cur);
cur.deleteChar();
insertHtml("<table width=\"100%\">" + previous_html2 + "</table>");
previous_html = previous_html2;
previous_cursor = textCursor().position();
} else {
previous_html.clear();
previous_cursor = 0;
}
previous_temporary = false;
i_pos = i_pos2;
i_pos_p = i_pos_p2;
last_ans = last_ans2;
last_ref = last_ref2;
previous_cursor2 = 0;
i_pos2 = 0;
i_pos_p2 = 0;
previous_html2.clear();
last_ans2 = 0;
last_ref2 = "";
}
void HistoryView::addResult(std::vector<std::string> values, std::string expression, bool pexact, std::string parse, int exact, bool dual_approx, const QString &image, bool *implicit_warning, int initial_load, size_t index, bool temporary) {
if(temporary && !previous_temporary) {
previous_cursor2 = previous_cursor;
}
if(!temporary && previous_temporary && expression.empty() && parse.empty()) {
clearTemporary();
}
QString serror;
bool b_parse_error = (initial_load && !expression.empty() && settings->v_parseerror[index] && !settings->v_messages[index].isEmpty());
if(!initial_load && CALCULATOR->message()) {
@ -373,30 +418,40 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
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();
serror += "<tr><td class=\"message\" colspan=\"2\" style=\"text-align:left; font-size:normal";
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
serror += "; color: ";
if(mtype == MESSAGE_ERROR) {
if(settings->color == 2) serror += "#FFAAAA";
else serror += "#800000";
} else {
if(settings->color == 2) serror += "#AAAAFF";
else serror += "#000080";
}
serror += "";
if(CALCULATOR->message()->stage() == MESSAGE_STAGE_PARSING) b_parse_error = true;
}
serror += "\">";
QString mstr = QString::fromStdString(CALCULATOR->message()->message());
if(!mstr.startsWith("-")) serror += "- ";
if(settings->printops.use_unicode_signs) {
mstr.replace(">=", SIGN_GREATER_OR_EQUAL);
mstr.replace("<=", SIGN_LESS_OR_EQUAL);
mstr.replace("!=", SIGN_NOT_EQUAL);
}
serror += mstr.toHtmlEscaped();
serror += "</td></tr>";
MessageType mtype = CALCULATOR->message()->type();
if(temporary) {
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
if(!serror.isEmpty()) {
if(!serror.startsWith("")) serror = "" + serror;
serror += "\n";
}
serror += mstr;
}
} else {
serror += "<tr><td class=\"message\" colspan=\"2\" style=\"text-align:left; font-size:normal";
if(mtype == MESSAGE_ERROR || mtype == MESSAGE_WARNING) {
serror += "; color: ";
if(mtype == MESSAGE_ERROR) {
if(settings->color == 2) serror += "#FFAAAA";
else serror += "#800000";
} else {
if(settings->color == 2) serror += "#AAAAFF";
else serror += "#000080";
}
serror += "";
if(CALCULATOR->message()->stage() == MESSAGE_STAGE_PARSING) b_parse_error = true;
}
serror += "\">";
if(!mstr.startsWith("-")) serror += "- ";
serror += mstr.toHtmlEscaped();
if(!temporary) serror += "</td></tr>";
}
}
} while(CALCULATOR->nextMessage());
if(serror.isEmpty() && values.empty() && expression.empty() && parse.empty()) return;
@ -406,7 +461,7 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
if(!expression.empty() || !parse.empty()) {
if(initial_load && index != settings->v_expression.size() - 1) str += QString("<tr><td colspan=\"2\" style=\"padding-bottom: %1 px; padding-top: %3px; border-top: 1px dashed %2; text-align:left\">").arg(paste_h / 4).arg(text_color.name()).arg(paste_h / 2);
else str += QString("<tr><td colspan=\"2\" style=\"padding-bottom: %1 px; padding-top: 0px; border-top: 0px none %2; text-align:left\">").arg(paste_h / 4).arg(text_color.name());
if(!initial_load) {
if(!initial_load && !temporary) {
settings->v_expression.push_back(expression);
settings->v_parse.push_back(parse);
settings->v_pexact.push_back(pexact);
@ -422,7 +477,7 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
}
}
gsub("</i>", "<img src=\"data://img1px.png\" width=\"1\"/></i>", parse);
if(!expression.empty() && (settings->history_expression_type > 0 || parse.empty())) {
if(!temporary && !expression.empty() && (settings->history_expression_type > 0 || parse.empty())) {
if(!parse.empty() && settings->history_expression_type > 1 && parse != expression) {
str += QString("<a name=\"e%1\" style=\"text-decoration: none\">").arg(initial_load ? (int) index : settings->v_expression.size() - 1);
str += QString::fromStdString(expression).toHtmlEscaped();
@ -442,12 +497,12 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
str += "</a>";
}
} else {
str += QString("<a name=\"%1\" style=\"text-decoration: none\">").arg(initial_load ? (int) index : settings->v_expression.size() - 1);
if(!temporary) str += QString("<a name=\"%1\" style=\"text-decoration: none\">").arg(initial_load ? (int) index : settings->v_expression.size() - 1);
if(!pexact) str += SIGN_ALMOST_EQUAL " ";
if(!settings->colorize_result) str += QString::fromStdString(uncolorize(parse, false));
else str += QString::fromStdString(parse);
str += "</a>";
if(b_parse_error && !expression.empty()) {
if(!temporary) str += "</a>";
if(!temporary && b_parse_error && !expression.empty()) {
str += "&nbsp;&nbsp;&nbsp; ";
if(settings->color == 2) str += "<i style=\"color: #AAAAAA\">";
else str += "<i style=\"color: #666666\">";
@ -466,6 +521,10 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
if(has_lock_symbol) str += " <small><sup>🔒</sup></small>";
else str += " <small><sup>[P]</sup></small>";
}
if(temporary) {
temporary_error = serror;
if(!serror.isEmpty()) str += QString("<img src=\"data://img1px.png\" width=\"2\"/><img valign=\"top\" src=\"%1\" height=\"%2\" alt=\"temporary_error\"/>").arg(":/icons/actions/scalable/warning.svg").arg(fm.ascent());
}
str += "</td></tr>";
} else if(!initial_load && !settings->v_result.empty()) {
for(size_t i = values.size(); i > 0; i--) {
@ -477,18 +536,21 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
settings->v_messages[settings->v_messages.size() - 1] += serror;
}
}
str += serror;
if(!temporary) str += serror;
if(initial_load) str += settings->v_messages[index];
str.replace("</i>", "<img src=\"data://img1px.png\" width=\"1\"/></i>");
if(!expression.empty() || !parse.empty()) {
if((!expression.empty() || !parse.empty()) && !temporary) {
i_pos = str.length();
if(initial_load != 1) i_pos_p = i_pos;
}
size_t i_answer_pre = 0;
if(temporary && values.empty()) {
values.push_back("");
}
for(size_t i = 0; i < values.size(); i++) {
size_t i_answer = 0;
if(initial_load) i_answer = settings->v_value[index][i];
else i_answer = dual_approx && i == 0 ? settings->history_answer.size() - 1 : settings->history_answer.size();
else if(!temporary) i_answer = dual_approx && i == 0 ? settings->history_answer.size() - 1 : settings->history_answer.size();
QFontMetrics fm(font());
int w = fm.boundingRect("#9999").width();
str += "<tr><td valign=\"center\" width=\""; str += QString::number(w); str += "\">";
@ -537,10 +599,14 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
if(exact < 0) b_exact = -1;
else if(exact == 0 && i == values.size() - 1) b_exact = 0;
}
if(i_answer == 0) str += QString("<a name=\"%1:%2\" style=\"text-decoration: none\">").arg(initial_load ? index : settings->v_expression.size() - 1).arg(initial_load ? (int) i : settings->v_result[settings->v_result.size() - 1].size() - i - 1);
else str += QString("<a name=\"p%1:%2:%3\" style=\"text-decoration: none\">").arg(i_answer).arg(initial_load ? index : settings->v_expression.size() - 1).arg(initial_load ? (int) i : settings->v_result[settings->v_result.size() - 1].size() - i - 1);
if(b_exact > 0) str += "= ";
else if(b_exact == 0) str += SIGN_ALMOST_EQUAL " ";
if(!temporary) {
if(i_answer == 0) str += QString("<a name=\"%1:%2\" style=\"text-decoration: none\">").arg(initial_load ? index : settings->v_expression.size() - 1).arg(initial_load ? (int) i : settings->v_result[settings->v_result.size() - 1].size() - i - 1);
else str += QString("<a name=\"p%1:%2:%3\" style=\"text-decoration: none\">").arg(i_answer).arg(initial_load ? index : settings->v_expression.size() - 1).arg(initial_load ? (int) i : settings->v_result[settings->v_result.size() - 1].size() - i - 1);
}
if(!temporary || !values[i].empty()) {
if(b_exact > 0) str += "= ";
else if(b_exact == 0) str += SIGN_ALMOST_EQUAL " ";
}
if(!settings->colorize_result) str += QString::fromStdString(uncolorize(values[i], false));
else str += QString::fromStdString(values[i]);
if(!image.isEmpty() && i == values.size() - 1 && w * 2 <= width()) {
@ -567,11 +633,19 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
}
str += "/>";
}
str += "</a></td></tr>";
if(!temporary) str += "</a>";
str += "</td></tr>";
i_answer_pre = i_answer;
}
str.replace("\n", "<br>");
int i = 0;
if(!previous_temporary && (!expression.empty() || !parse.empty())) {
previous_html2 = previous_html;
i_pos2 = i_pos;
i_pos_p2 = i_pos_p;
last_ans2 = last_ans;
last_ref2 = last_ref;
}
if(!initial_load) {
if(settings->format_result) {
previous_html.replace("font-size:normal", "font-size:small ");
@ -617,6 +691,11 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
previous_html.insert(i_pos_p, str);
insertHtml("<table width=\"100%\">" + previous_html + "</table>");
previous_cursor = textCursor().position();
previous_html2 = previous_html;
i_pos2 = i_pos;
i_pos_p2 = i_pos_p;
last_ans2 = last_ans;
last_ref2 = last_ref;
}
} else {
if(initial_load) {
@ -633,7 +712,7 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
} else {
if(previous_html.isEmpty()) {
setHtml("<body color=\"" + text_color.name() + "\"></body>");
} else {
} else if(!previous_temporary) {
if(settings->format_result) {
previous_html.remove("; font-size:x-large");
previous_html.remove("; font-size:large");
@ -650,6 +729,7 @@ void HistoryView::addResult(std::vector<std::string> values, std::string express
previous_cursor = textCursor().position();
}
}
previous_temporary = temporary;
}
void HistoryView::changeEvent(QEvent *e) {
if(e->type() == QEvent::PaletteChange || e->type() == QEvent::ApplicationPaletteChange) {
@ -678,27 +758,26 @@ void HistoryView::mouseMoveEvent(QMouseEvent *e) {
QString str = anchorAt(e->pos());
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
bool b_tooltip = false;
if(str.isEmpty() && e->pos().x() > width() - 150) {
if(document()->documentLayout()->imageAt(e->pos()).indexOf(":/data/flags") == 0) {
QPoint p(viewport()->mapFromParent(e->pos()));
for(int n = 0; n < 5; n++) {
QTextCursor cur = cursorForPosition(p);
cur.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
QString str = cur.selection().toHtml();
int i = str.lastIndexOf(" alt=\"");
if(i >= 0) {
i += 6;
int i2 = str.indexOf("\"", i + 1);
if(i2 > i) {
str = str.mid(i, i2 - i);
str.replace("\\n", "\n");
QToolTip::showText(mapToGlobal(e->pos()), str);
b_tooltip = true;
}
break;
if(str.isEmpty() && (document()->documentLayout()->imageAt(e->pos()).indexOf(":/icons") == 0 || (e->pos().x() > width() - 150 && document()->documentLayout()->imageAt(e->pos()).indexOf(":/data/flags") == 0))) {
QPoint p(viewport()->mapFromParent(e->pos()));
for(int n = 0; n < 5; n++) {
QTextCursor cur = cursorForPosition(p);
cur.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
QString str = cur.selection().toHtml();
int i = str.lastIndexOf(" alt=\"");
if(i >= 0) {
i += 6;
int i2 = str.indexOf("\"", i + 1);
if(i2 > i) {
str = str.mid(i, i2 - i);
if(str == "temporary_error") str = temporary_error;
else str.replace("\\n", "\n");
QToolTip::showText(mapToGlobal(e->pos()), str);
b_tooltip = true;
}
p.rx() += QFontMetrics(font()).ascent() / 2;
break;
}
p.rx() += QFontMetrics(font()).ascent() / 2;
}
}
if(!b_tooltip) QToolTip::hideText();
@ -857,6 +936,7 @@ void HistoryView::editMoveToTop() {
void HistoryView::reloadHistory() {
int vpos = verticalScrollBar()->value();
loadInitial(true);
emit historyReloaded();
verticalScrollBar()->setValue(vpos);
}
void HistoryView::editRemove() {

View File

@ -35,7 +35,8 @@ class HistoryView : public QTextEdit {
QAction *findAction;
QDialog *searchDialog;
void addResult(std::vector<std::string> values, std::string expression = "", bool pexact = true, std::string parse = "", int exact = 1, bool dual_approx = false, const QString &image = QString(), bool *implicit_warning = NULL, int initial_load = 0, size_t index = 0);
void addResult(std::vector<std::string> values, std::string expression = "", bool pexact = true, std::string parse = "", int exact = 1, bool dual_approx = false, const QString &image = QString(), bool *implicit_warning = NULL, int initial_load = 0, size_t index = 0, bool temporary = false);
void clearTemporary();
void addMessages();
void loadInitial(bool reload = false);
void indexAtPos(const QPoint &pos, int *expression_index, int *result_index, int *value_index = NULL, QString *anchorstr = NULL);
@ -43,8 +44,8 @@ class HistoryView : public QTextEdit {
protected:
QString s_text, previous_html;
int i_pos, i_pos_p, previous_cursor;
QString s_text, previous_html, previous_html2, temporary_error;
int i_pos, i_pos2, i_pos_p, i_pos_p2, previous_cursor, previous_cursor2, previous_temporary;
int has_lock_symbol;
QMenu *cmenu;
QAction *insertTextAction, *insertValueAction, *copyAction, *copyFormattedAction, *copyAsciiAction, *selectAllAction, *delAction, *clearAction, *protectAction, *movetotopAction;
@ -52,8 +53,8 @@ class HistoryView : public QTextEdit {
QRect prev_fonti;
QPoint context_pos;
QLineEdit *searchEdit;
size_t last_ans;
QString last_ref;
size_t last_ans, last_ans2;
QString last_ref, last_ref2;
bool initial_loaded;
void mouseDoubleClickEvent(QMouseEvent *e) override;
@ -86,6 +87,7 @@ class HistoryView : public QTextEdit {
void insertTextRequested(std::string);
void insertValueRequested(int);
void historyReloaded();
};

View File

@ -59,7 +59,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
tabs->addTab(w2, tr("Numbers && Operators"));
tabs->addTab(w3, tr("Units && Currencies"));
tabs->addTab(w4, tr("Parsing && Calculation"));
QCheckBox *box; QGridLayout *l; QComboBox *combo;
QAbstractButton *box; QGridLayout *l; QComboBox *combo;
int r = 0;
l = new QGridLayout(w1); l->setSizeConstraint(QLayout::SetFixedSize);
BOX(tr("Ignore system language (requires restart)"), settings->ignore_locale, ignoreLocaleToggled(bool));
@ -155,11 +155,18 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
l->setRowStretch(r, 1);
r = 0;
l = new QGridLayout(w4); l->setSizeConstraint(QLayout::SetFixedSize);
box = new QCheckBox(tr("Display expression status"), this); l->addWidget(box, r, 0); box->setChecked(settings->display_expression_status); connect(box, SIGNAL(toggled(bool)), this, SLOT(expressionStatusToggled(bool)));
statusBox = box;
QHBoxLayout *hbox = new QHBoxLayout();
l->addLayout(hbox, r, 1); r++;
hbox->addWidget(new QLabel(tr("Delay:")));
l->addWidget(new QLabel(tr("Expression status:"), this), r, 0);
combo = new QComboBox(this);
combo->addItem(tr("Off"), 0);
combo->addItem(tr("In history list"), 1);
combo->addItem(tr("In expression field"), 2);
if(!settings->display_expression_status) combo->setCurrentIndex(0);
else if(settings->status_in_history) combo->setCurrentIndex(1);
else combo->setCurrentIndex(2);
statusCombo = combo;
connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(statusModeChanged(int)));
l->addWidget(combo, r, 1); r++;
l->addWidget(new QLabel(tr("Status tooltip delay:")), r, 0);
statusDelayWidget = new QSpinBox(this);
statusDelayWidget->setRange(0, 10000);
statusDelayWidget->setSingleStep(250);
@ -167,8 +174,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) {
statusDelayWidget->setSuffix(" " + tr("ms"));
statusDelayWidget->setValue(settings->expression_status_delay);
connect(statusDelayWidget, SIGNAL(valueChanged(int)), this, SLOT(statusDelayChanged(int)));
hbox->addWidget(statusDelayWidget);
hbox->addStretch(1);
l->addWidget(statusDelayWidget, r, 1); r++;
l->addWidget(new QLabel(tr("Expression in history:"), this), r, 0);
combo = new QComboBox(this);
combo->addItem(tr("Parsed"), 0);
@ -413,10 +419,11 @@ void PreferencesDialog::tooltipsChanged(int i) {
settings->enable_tooltips = qobject_cast<QComboBox*>(sender())->itemData(i).toInt();
emit enableTooltipsChanged();
}
void PreferencesDialog::expressionStatusToggled(bool b) {
settings->display_expression_status = b;
statusDelayWidget->setEnabled(b);
if(!b) QToolTip::hideText();
void PreferencesDialog::statusModeChanged(int i) {
settings->display_expression_status = (i > 0);
settings->status_in_history = (i == 1);
statusDelayWidget->setEnabled(settings->display_expression_status);
emit statusModeChanged();
}
void PreferencesDialog::statusDelayChanged(int v) {
settings->expression_status_delay = v;
@ -826,12 +833,14 @@ void PreferencesDialog::updateParsingMode() {
}
void PreferencesDialog::updateExpressionStatus() {
statusDelayWidget->blockSignals(true);
statusBox->blockSignals(true);
statusCombo->blockSignals(true);
if(!settings->display_expression_status) statusCombo->setCurrentIndex(0);
else if(settings->status_in_history) statusCombo->setCurrentIndex(1);
else statusCombo->setCurrentIndex(2);
statusDelayWidget->setValue(settings->expression_status_delay);
statusBox->setChecked(settings->display_expression_status);
statusDelayWidget->setEnabled(settings->display_expression_status);
statusDelayWidget->blockSignals(false);
statusBox->blockSignals(false);
statusCombo->blockSignals(false);
}
void PreferencesDialog::updateTemperatureCalculation() {
tcCombo->blockSignals(true);

View File

@ -16,7 +16,7 @@
#include <libqalculate/qalculate.h>
class QCheckBox;
class QAbstractButton;
class QSpinBox;
class QComboBox;
@ -26,9 +26,9 @@ class PreferencesDialog : public QDialog {
protected:
QCheckBox *decimalCommaBox, *ignoreCommaBox, *ignoreDotBox, *statusBox, *ignoreLocaleBox, *variableUnitsBox, *conciseUncertaintyInputBox;
QAbstractButton *decimalCommaBox, *ignoreCommaBox, *ignoreDotBox, *ignoreLocaleBox, *variableUnitsBox, *conciseUncertaintyInputBox;
QSpinBox *exratesSpin, *statusDelayWidget;
QComboBox *styleCombo, *parseCombo, *tcCombo, *langCombo, *complexFormCombo, *intervalDisplayCombo, *intervalCalculationCombo;
QComboBox *styleCombo, *parseCombo, *tcCombo, *langCombo, *complexFormCombo, *intervalDisplayCombo, *intervalCalculationCombo, *statusCombo;
void closeEvent(QCloseEvent*) override;
@ -37,7 +37,7 @@ class PreferencesDialog : public QDialog {
void ignoreLocaleToggled(bool);
void keepAboveToggled(bool);
void tooltipsChanged(int);
void expressionStatusToggled(bool);
void statusModeChanged(int);
void statusDelayChanged(int);
void binTwosToggled(bool);
void hexTwosToggled(bool);
@ -135,6 +135,7 @@ class PreferencesDialog : public QDialog {
void symbolsUpdated();
void historyExpressionTypeChanged();
void binaryBitsChanged();
void statusModeChanged();
void dialogClosed();
};

View File

@ -71,7 +71,32 @@ bool item_in_calculator(ExpressionItem *item) {
if(item->type() == TYPE_FUNCTION) return CALCULATOR->hasFunction((MathFunction*) item);
return false;
}
void remove_spaces(std::string &str) {
size_t i = 0;
while(true) {
i = str.find(' ', i);
if(i != std::string::npos) str.erase(i, 1);
else break;
}
i = 0;
while(true) {
i = str.find(THIN_SPACE, i);
if(i != std::string::npos) str.erase(i, strlen(THIN_SPACE));
else break;
}
i = 0;
while(true) {
i = str.find(NNBSP, i);
if(i != std::string::npos) str.erase(i, strlen(NNBSP));
else break;
}
i = 0;
while(true) {
i = str.find(NBSP, i);
if(i != std::string::npos) str.erase(i, strlen(NBSP));
else break;
}
}
long int get_fixed_denominator_qt2(const std::string &str, int &to_fraction, char sgn, const QString &localized_fraction, bool qalc_command) {
long int fden = 0;
if(!qalc_command && (equalsIgnoreCase(str, "fraction") || equalsIgnoreCase(str, localized_fraction.toStdString()))) {
@ -791,6 +816,8 @@ void QalculateQtSettings::readPreferenceValue(const std::string &svar, const std
implicit_question_asked = true;
} else if(svar == "calculate_as_you_type") {
auto_calculate = v;
} else if(svar == "status_in_history") {
status_in_history = v;
}
}
}
@ -879,6 +906,7 @@ void QalculateQtSettings::loadPreferences() {
title_type = TITLE_APP;
programming_base_changed = false;
auto_calculate = true;
status_in_history = true;
dot_question_asked = false;
implicit_question_asked = false;
complex_angle_form = false;
@ -1482,6 +1510,7 @@ bool QalculateQtSettings::savePreferences(const char *filename, bool is_workspac
fprintf(file, "local_currency_conversion=%i\n", evalops.local_currency_conversion);
fprintf(file, "use_binary_prefixes=%i\n", CALCULATOR->usesBinaryPrefixes());
fprintf(file, "calculate_as_you_type=%i\n", auto_calculate);
fprintf(file, "status_in_history=%i\n", status_in_history);
if(previous_precision > 0) fprintf(file, "previous_precision=%i\n", previous_precision);
}
if(read_default) {

View File

@ -44,6 +44,7 @@ bool item_in_calculator(ExpressionItem *item);
bool name_matches(ExpressionItem *item, const std::string &str);
bool country_matches(Unit *u, const std::string &str, size_t minlength = 0);
bool title_matches(ExpressionItem *item, const std::string &str, size_t minlength = 0);
void remove_spaces(std::string &str);
bool contains_plot_or_save(const std::string &str);
void base_from_string(std::string str, int &base, Number &nbase, bool input_base = false);
long int get_fixed_denominator_qt(const std::string &str, int &to_fraction, const QString &localized_fraction, bool qalc_command = false);
@ -256,7 +257,7 @@ class QalculateQtSettings : QObject {
bool keep_function_dialog_open;
bool save_defs_on_exit, save_mode_on_exit, clear_history_on_exit;
bool rpn_shown;
bool auto_calculate;
bool auto_calculate, status_in_history;
int history_expression_type;
bool copy_ascii, copy_ascii_without_units;
bool close_with_esc;

View File

@ -128,6 +128,8 @@ int to_caf = -1;
unsigned int to_bits = 0;
Number to_nbase;
std::string result_bin, result_oct, result_dec, result_hex;
std::string auto_expression, auto_result;
bool auto_format_updated = false, auto_error = false;
bool bases_is_result = false;
Number max_bases, min_bases;
bool title_modified = false;
@ -920,11 +922,13 @@ QalculateWindow::QalculateWindow() : QMainWindow() {
connect(historyView, SIGNAL(insertTextRequested(std::string)), this, SLOT(onInsertTextRequested(std::string)));
connect(historyView, SIGNAL(insertValueRequested(int)), this, SLOT(onInsertValueRequested(int)));
connect(historyView, SIGNAL(historyReloaded()), this, SLOT(onHistoryReloaded()));
connect(expressionEdit, SIGNAL(returnPressed()), this, SLOT(calculate()));
connect(expressionEdit, SIGNAL(textChanged()), this, SLOT(onExpressionChanged()));
connect(expressionEdit, SIGNAL(statusChanged(QString, bool, bool)), this, SLOT(onStatusChanged(QString, bool, bool)));
connect(expressionEdit, SIGNAL(toConversionRequested(std::string)), this, SLOT(onToConversionRequested(std::string)));
connect(expressionEdit, SIGNAL(calculateRPNRequest(int)), this, SLOT(calculateRPN(int)));
connect(expressionEdit, SIGNAL(expressionStatusModeChanged()), this, SLOT(onExpressionStatusModeChanged()));
connect(expressionEdit, SIGNAL(expressionStatusModeChanged(bool)), this, SLOT(onExpressionStatusModeChanged(bool)));
connect(keypadDock, SIGNAL(visibilityChanged(bool)), this, SLOT(onKeypadVisibilityChanged(bool)));
connect(basesDock, SIGNAL(visibilityChanged(bool)), this, SLOT(onBasesVisibilityChanged(bool)));
connect(rpnDock, SIGNAL(visibilityChanged(bool)), this, SLOT(onRPNVisibilityChanged(bool)));
@ -3258,7 +3262,8 @@ void QalculateWindow::resultFormatUpdated(int delay) {
settings->updateMessagePrintOptions();
workspace_changed = true;
setResult(NULL, true, false, false);
if(!QToolTip::text().isEmpty()) expressionEdit->displayParseStatus(true);
auto_format_updated = true;
if(!QToolTip::text().isEmpty() || (settings->status_in_history && expressionEdit->expressionHasChanged())) expressionEdit->displayParseStatus(true);
}
void QalculateWindow::resultDisplayUpdated() {
resultFormatUpdated();
@ -3290,6 +3295,7 @@ void QalculateWindow::expressionCalculationUpdated(int delay) {
return;
}
workspace_changed = true;
auto_format_updated = true;
expressionEdit->displayParseStatus(true, !QToolTip::text().isEmpty());
settings->updateMessagePrintOptions();
if(!settings->rpn_mode) {
@ -6054,6 +6060,72 @@ void QalculateWindow::onExpressionChanged() {
updateResultBases();
}
void QalculateWindow::onHistoryReloaded() {
if(settings->status_in_history && settings->display_expression_status) {
historyView->clearTemporary();
auto_expression = "";
expressionEdit->displayParseStatus(true);
}
}
void QalculateWindow::onStatusChanged(QString status, bool is_expression, bool had_error) {
if(!settings->status_in_history) return;
std::string current_text = expressionEdit->toPlainText().toStdString();
remove_blank_ends(current_text);
if(status.isEmpty()) {
historyView->clearTemporary();
auto_expression = "";
auto_result = "";
} else if(!is_expression || !settings->auto_calculate || contains_plot_or_save(current_text)) {
if(auto_result.empty() && auto_expression == status.toStdString()) return;
std::vector<std::string> values;
auto_expression = status.toStdString();
auto_result = "";
historyView->addResult(values, current_text, true, auto_expression, false, false, QString(), NULL, 0, 0, true);
} else {
if(!had_error && !auto_error && !auto_format_updated && auto_expression == status.toStdString()) return;
bool b_comp = false, is_approximate = false;
PrintOptions po = settings->printops;
po.is_approximate = &is_approximate;
std::string result = CALCULATOR->unlocalizeExpression(current_text, settings->evalops.parse_options);
CALCULATOR->beginTemporaryStopMessages();
if(!settings->simplified_percentage) settings->evalops.parse_options.parsing_mode = (ParsingMode) (settings->evalops.parse_options.parsing_mode | PARSE_PERCENT_AS_ORDINARY_CONSTANT);
result = CALCULATOR->calculateAndPrint(result, 50, settings->evalops, po, settings->dual_fraction == 0 ? AUTOMATIC_FRACTION_OFF : AUTOMATIC_FRACTION_SINGLE, settings->dual_approximation == 0 ? AUTOMATIC_APPROXIMATION_OFF : AUTOMATIC_APPROXIMATION_SINGLE, NULL, -1, &b_comp, true, settings->color, TAG_TYPE_HTML);
if(!settings->simplified_percentage) settings->evalops.parse_options.parsing_mode = (ParsingMode) (settings->evalops.parse_options.parsing_mode & ~PARSE_PERCENT_AS_ORDINARY_CONSTANT);
auto_format_updated = false;
std::vector<CalculatorMessage> messages;
CALCULATOR->endTemporaryStopMessages(false, &messages);
bool b_error = false, b_warning = false;
for(size_t i = 0; i < messages.size(); i++) {
if(messages[i].type() == MESSAGE_ERROR) {
b_error = true;
break;
} else if(messages[i].type() == MESSAGE_WARNING) {
b_warning = true;
}
}
if(!b_error && !b_warning && !auto_error && auto_result == result && auto_expression == status.toStdString()) return;
auto_error = b_error || b_warning;
std::vector<std::string> values;
std::string status_nohtml = unhtmlize(status.toStdString());
std::string result_nohtml = unhtmlize(result);
remove_spaces(result_nohtml);
remove_spaces(current_text);
if(!b_error && !result.empty() && result != CALCULATOR->timedOutString() && result_nohtml.length() < 500 && (!auto_result.empty() || (result_nohtml != status_nohtml && result_nohtml != current_text))) {
auto_result = result;
if(b_comp) {
result.insert(0, "(");
result += ")";
}
values.push_back(result);
} else {
auto_result = "";
}
auto_expression = status.toStdString();
CALCULATOR->addMessages(&messages);
historyView->addResult(values, "", true, auto_expression, !is_approximate, false, QString(), NULL, 0, 0, true);
}
}
void QalculateWindow::onBinaryBitsChanged() {
if(basesDock->isVisible() && bases_is_result && settings->current_result) {
CALCULATOR->beginTemporaryStopMessages();
@ -6562,6 +6634,8 @@ void QalculateWindow::setResult(Prefix *prefix, bool update_history, bool update
}
}
if(b_add) {
auto_expression = "";
auto_result = "";
historyView->addResult(alt_results, update_parse ? prev_result_text : "", !parsed_approx, update_parse ? parsed_text : "", b_exact, alt_results.size() > 1 && !mstruct_exact.isUndefined(), flag, !supress_dialog && update_parse && settings->evalops.parse_options.parsing_mode <= PARSING_MODE_CONVENTIONAL && update_history ? &implicit_warning : NULL);
} else if(update_parse) {
settings->history_answer.pop_back();
@ -7447,8 +7521,13 @@ void QalculateWindow::onAppFontChanged() {
}
if(!settings->use_custom_keypad_font) keypad->setFont(QApplication::font());
}
void QalculateWindow::onExpressionStatusModeChanged() {
void QalculateWindow::onExpressionStatusModeChanged(bool b) {
if(preferencesDialog) preferencesDialog->updateExpressionStatus();
if(b) {
if(!settings->status_in_history) historyView->clearTemporary();
auto_expression = "";
expressionEdit->displayParseStatus(true);
}
}
void QalculateWindow::removeShortcutClicked() {
QTreeWidgetItem *item = shortcutList->currentItem();
@ -7867,6 +7946,7 @@ void QalculateWindow::editPreferences() {
connect(preferencesDialog, SIGNAL(symbolsUpdated()), keypad, SLOT(updateSymbols()));
connect(preferencesDialog, SIGNAL(historyExpressionTypeChanged()), historyView, SLOT(reloadHistory()));
connect(preferencesDialog, SIGNAL(binaryBitsChanged()), this, SLOT(onBinaryBitsChanged()));
connect(preferencesDialog, SIGNAL(statusModeChanged()), this, SLOT(onExpressionStatusModeChanged()));
connect(preferencesDialog, SIGNAL(dialogClosed()), this, SLOT(onPreferencesClosed()));
if(settings->always_on_top) preferencesDialog->setWindowFlags(preferencesDialog->windowFlags() | Qt::WindowStaysOnTopHint);
preferencesDialog->show();

View File

@ -189,6 +189,8 @@ class QalculateWindow : public QMainWindow {
void onRPNVisibilityChanged(bool);
void onRPNClosed();
void onExpressionChanged();
void onHistoryReloaded();
void onStatusChanged(QString, bool, bool);
void onToConversionRequested(std::string);
void onInsertTextRequested(std::string);
void onInsertValueRequested(int);
@ -247,7 +249,7 @@ class QalculateWindow : public QMainWindow {
void registerChanged(int);
void calculateRPN(int);
void approximateResult();
void onExpressionStatusModeChanged();
void onExpressionStatusModeChanged(bool = true);
void functionActivated();
void unitActivated();
void prefixActivated();