From 1f0e0a531e1f32e3ad24544ec9fa9a6a38de61ce Mon Sep 17 00:00:00 2001 From: "Hanna K." Date: Sat, 16 Nov 2024 17:26:19 +0100 Subject: [PATCH] Option to automatically group digits in input (experimental, disabled by default) (issue #170) --- src/expressionedit.cpp | 55 ++++++++++++++++++++++++++++++++++++- src/preferencesdialog.cpp | 4 +++ src/preferencesdialog.h | 1 + src/qalculateqtsettings.cpp | 4 +++ src/qalculateqtsettings.h | 1 + 5 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/expressionedit.cpp b/src/expressionedit.cpp index d73accb..8d4af76 100644 --- a/src/expressionedit.cpp +++ b/src/expressionedit.cpp @@ -2829,8 +2829,61 @@ void ExpressionEdit::onTextChanged() { if(completionTimer) completionTimer->stop(); if(tipLabel && settings->expression_status_delay > 0 && current_status_type != 2) tipLabel->hideTip(); if(block_text_change) return; - previous_text = str; previous_pos = textCursor().position(); + if(settings->automatic_digit_grouping && settings->evalops.parse_options.base == BASE_DECIMAL && previous_pos > 3 && previous_text != str && !str.isEmpty() && str[previous_pos - 1].isDigit()) { + int n = 0, ns = 0, ns_p = 0; + int last_pos = 0; + if(previous_pos < str.length()) { + last_pos = previous_pos - 1; + for(; last_pos < str.length(); last_pos++) { + if(!str[last_pos].isDigit() && (!str[last_pos].isSpace() || last_pos == str.length() - 1 || !str[last_pos + 1].isDigit())) { + break; + } + } + last_pos--; + } else { + last_pos = str.length() - 1; + } + int first_pos = 0; + for(int i = last_pos; i >= 0; i--) { + if(str[i].isDigit()) { + n++; + } else if(str[i].isSpace() && i > 0 && str[i - 1].isDigit()) { + if(i < previous_pos) ns_p++; + ns++; + } else { + first_pos = i + 1; + break; + } + } + if((n > 4 && ns < (n + 1) / 3) || (ns > 0 && str.length() < previous_text.length())) { + for(int i = last_pos - 1; ns > 0 && i >= 0;) { + if(str[i].isSpace()) { + str.remove(i, 1); + ns--; + last_pos--; + } else { + i--; + } + } + previous_pos -= ns_p; + ns_p = 0; + for(int i = last_pos - 2; n > 4 && i > first_pos; i -= 3) { + str.insert(i, THIN_SPACE); + if(i < previous_pos) ns_p++; + } + previous_pos += ns_p; + block_text_change++; + setCursorWidth(0); + setPlainText(str); + QTextCursor cur = textCursor(); + cur.setPosition(previous_pos); + setTextCursor(cur); + setCursorWidth(1); + block_text_change--; + } + } + previous_text = str; if(expression_undo_buffer.isEmpty() || str != expression_undo_buffer.last()) { if(expression_undo_buffer.isEmpty()) { expression_undo_buffer.push_back(QString()); diff --git a/src/preferencesdialog.cpp b/src/preferencesdialog.cpp index 1f9b4cc..6210746 100644 --- a/src/preferencesdialog.cpp +++ b/src/preferencesdialog.cpp @@ -304,6 +304,7 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) : QDialog(parent) { combo->setCurrentIndex(combo->findData(settings->printops.digit_grouping)); connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(groupingChanged(int))); l->addWidget(combo, r, 1); r++; + BOX(tr("Automatically group digits in input (experimental)"), settings->automatic_digit_grouping, automaticDigitGroupingToggled(bool)); l->addWidget(new QLabel(tr("Interval display:"), this), r, 0); combo = new QComboBox(this); combo->addItem(tr("Adaptive"), -1); @@ -686,6 +687,9 @@ void PreferencesDialog::copyAsciiWithoutUnitsToggled(bool b) { void PreferencesDialog::caretAsXorToggled(bool b) { settings->caret_as_xor = b; } +void PreferencesDialog::automaticDigitGroupingToggled(bool b) { + settings->automatic_digit_grouping = b; +} void PreferencesDialog::closeWithEscToggled(bool b) { settings->close_with_esc = b; } diff --git a/src/preferencesdialog.h b/src/preferencesdialog.h index e8bde5f..4c4ffa4 100644 --- a/src/preferencesdialog.h +++ b/src/preferencesdialog.h @@ -107,6 +107,7 @@ class PreferencesDialog : public QDialog { void copyAsciiToggled(bool); void copyAsciiWithoutUnitsToggled(bool); void caretAsXorToggled(bool); + void automaticDigitGroupingToggled(bool); void closeWithEscToggled(bool); public: diff --git a/src/qalculateqtsettings.cpp b/src/qalculateqtsettings.cpp index 298fc5d..4c04082 100644 --- a/src/qalculateqtsettings.cpp +++ b/src/qalculateqtsettings.cpp @@ -842,6 +842,8 @@ void QalculateQtSettings::readPreferenceValue(const std::string &svar, const std printops.spell_out_logical_operators = v; } else if(svar == "caret_as_xor") { caret_as_xor = v; + } else if(svar == "automatic_digit_grouping") { + automatic_digit_grouping = v; } else if(svar == "close_with_esc") { close_with_esc = v; } else if(svar == "copy_ascii") { @@ -987,6 +989,7 @@ void QalculateQtSettings::loadPreferences() { rpn_keys = true; rpn_shown = false; caret_as_xor = false; + automatic_digit_grouping = false; copy_ascii = false; copy_ascii_without_units = false; do_imaginary_j = false; @@ -1565,6 +1568,7 @@ bool QalculateQtSettings::savePreferences(const char *filename, bool is_workspac if(default_signed >= 0) fprintf(file, "signed_integer=%i\n", default_signed); fprintf(file, "spell_out_logical_operators=%i\n", printops.spell_out_logical_operators); fprintf(file, "caret_as_xor=%i\n", caret_as_xor); + fprintf(file, "automatic_digit_grouping=%i\n", automatic_digit_grouping); fprintf(file, "close_with_esc=%i\n", close_with_esc); fprintf(file, "copy_ascii=%i\n", copy_ascii); fprintf(file, "copy_ascii_without_units=%i\n", copy_ascii_without_units); diff --git a/src/qalculateqtsettings.h b/src/qalculateqtsettings.h index cca4d45..c7271e3 100644 --- a/src/qalculateqtsettings.h +++ b/src/qalculateqtsettings.h @@ -230,6 +230,7 @@ class QalculateQtSettings : QObject { EvaluationOptions evalops; PrintOptions printops; 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, sinc_set; + bool automatic_digit_grouping; int simplified_percentage; bool programming_base_changed; int previous_precision;