Created attachment 172708 [details] Screenshots of Bitcoin currency editors of v 5.1.3 and master SUMMARY Using KMyMoney 5.1 Version 5.1.3-eef0ff1, the Currency editor shows the Smallest account unit and Smallest cash unit of Bitcoin to be 0.00000001. Using the master branch of KMyMoney (build 3407), the Currency editor shows £0.00 for these properties. Possibly as a result of this behaviour, the Transaction Report of transactions in an account whose currency is Bitcoin displays the amounts as BTC £0.02. KMyMoney 5.1 shows BTC 0.01760000. The transaction editor also shows £0.02. SOFTWARE/OS VERSIONS Windows: 10 ADDITIONAL INFORMATION Attached are screenshots of the Currency Editor from v 5.1.3 and master 3407.
Very strange behavior which differs on Linux and Windows: The code section precision = MyMoneyMoney::denomToPrec(currency.smallestAccountFraction()); smallestFraction = MyMoneyMoney::ONE / MyMoneyMoney(currency.smallestAccountFraction()); qDebug() << "account precision" << precision << smallestFraction.formatMoney(QString(), precision); provides the following output on Linux: account precision 8 "0,00000001" but on Windows we get account precision 8 "0,00 €" I have not clue what is going on here. This explains why 0,00 € is shown in the dialog when editing the currency. BTW, the display in the edit currency is identical no matter if compiled with MSVC (KDE CI/CD) or cross-compiled (snapshots).
(In reply to Thomas Baumgart from comment #1) > Very strange behavior which differs on Linux and Windows: To exclude influences from the entire application, I suggest inserting an additional unit test in kmymoney/mymoney/tests/mymoneysecurity-test.cpp, e.g. void MyMoneySecurityTest::testSmallestAccountUnit() { MyMoneySecurity currency("BTC", "Bitcoin", "BTC", 100000000, 100000000); int precision = MyMoneyMoney::denomToPrec(currency.smallestAccountFraction()); MyMoneyMoney smallestFraction = MyMoneyMoney::ONE / MyMoneyMoney(currency.smallestAccountFraction()); QCOMPARE(smallestFraction.formatMoney(QString(), precision), QLatin1String("0.00000001")); } which can then be used more easily for debugging.
(In reply to Ralf Habacker from comment #2) As the problem here is the call to formatMoney() it may be named better: void MyMoneySecurityTest::testFormatMoney() { MyMoneySecurity currency("BTC", "Bitcoin", "BTC", 100000000, 100000000); int precision = MyMoneyMoney::denomToPrec(currency.smallestAccountFraction()); MyMoneyMoney smallestFraction = MyMoneyMoney::ONE / MyMoneyMoney(currency.smallestAccountFraction()); QCOMPARE(smallestFraction.formatMoney(QString(), precision), QLatin1String("0.00000001")); }
With a mingw build I edited Türkische Lira (alt), which shows in the log editing currency "Türkische Lira (alt)" "TL" 100 100 cash precision 2 "0,01 Ç" account precision 2 "0,01 Ç" Then I added "Bitcoin" as currency adding currency "Bitcoin" "BTC" 100000000 100000000 and edited it: editing currency "Bitcoin" "BTC" 100000000 100000000 cash precision 8 "0,00 Ç" account precision 8 "0,00 Ç" which should still using currency "TL" -> The currency used has not been updated.
(In reply to Ralf Habacker from comment #4) > which should still using currency "TL" -> The currency used has not been updated. correction: which is still using currency "TL" -> The currency used has not been
(In reply to Thomas Baumgart from comment #1) > precision = I changed the relevant code section to precision = MyMoneyMoney::denomToPrec(currency.smallestAccountFraction()); smallestFraction = MyMoneyMoney::ONE / MyMoneyMoney(currency.smallestAccountFraction()); qDebug() << "account precision" << precision << smallestFraction.formatMoney(QString(), precision) << smallestFaction.toDouble() << smallestFaction.toString() and got cash precision 8 "0,00 Bitcoin" 1e-08 "1/100000000" account precision 8 "0,00 Bitcoin" 1e-08 "1/100000000" which indicates that there is a issue with the formatMoney() method.
(In reply to Ralf Habacker from comment #6) > which indicates that there is a issue with the formatMoney() method. I think this error was introduced with https://invent.kde.org/office/kmymoney/-/commit/0487f47b6da4b2cee47a13983f375eda7f205501 in the method mentioned below QString MyMoneyMoney::formatMoney(const QString& currency, const int prec, bool showThousandSeparator) const { if (eMyMoney::Money::_useQtInternalFormmater) { return eMyMoney::Money::_locale.toCurrencyString(this->toDouble(), currency, prec); } `eMyMoney::Money::_useQtInternalFormmater` is true and thus the formatting of the numbers is carried out by Qt, which does not work here. Commenting out the whole if part, returns the expected value in the smallest ... unit.
(In reply to Ralf Habacker from comment #4) ... > editing currency "Türkische Lira (alt)" "TL" 100 100 > cash precision 2 "0,01 Ç" > account precision 2 "0,01 Ç" ... > editing currency "Bitcoin" "BTC" 100000000 100000000 > cash precision 8 "0,00 Ç" > account precision 8 "0,00 Ç" > > which is still using currency "TL" -> The currency used has not been updated. This issue is caused by using smallestFraction.formatMoney(QString(), precision) by changing this call to use currency.name() instead smallestFraction.formatMoney(currency.name(), precision) and with the fix mentioned in comment 7 I get cash precision 8 "0,00000001 Bitcoin"
This issue does not occur with a basic Qt test case. Running the following tests build with MinGW as simple qt console app const QLocale btc("BTC"); QCOMPARE(btc.toCurrencyString(double(1e-1), "BTC", 1), QString("0.1BTC")); QCOMPARE(btc.toCurrencyString(double(1e-2), "BTC", 2), QString("0.01BTC")); QCOMPARE(btc.toCurrencyString(double(1e-3), "BTC", 3), QString("0.001BTC")); QCOMPARE(btc.toCurrencyString(double(1e-4), "BTC", 4), QString("0.0001BTC")); QCOMPARE(btc.toCurrencyString(double(1e-5), "BTC", 5), QString("0.00001BTC")); QCOMPARE(btc.toCurrencyString(double(1e-6), "BTC", 6), QString("0.000001BTC")); QCOMPARE(btc.toCurrencyString(double(1e-7), "BTC", 7), QString("0.0000001BTC")); QCOMPARE(btc.toCurrencyString(double(1e-8), "BTC", 8), QString("0.00000001BTC")); does not fail. There must be something different in kmymoney.
A possibly relevant merge request was started @ https://invent.kde.org/office/kmymoney/-/merge_requests/226
(In reply to Bug Janitor Service from comment #10) > A possibly relevant merge request was started @ > https://invent.kde.org/office/kmymoney/-/merge_requests/226 Sorry, I used wrong bug number, please ignore this comment.
Git commit 2b802594c5ecb94f75f472c11ebdd4a520eb8984 by Thomas Baumgart. Committed on 20/08/2024 at 15:47. Pushed by tbaumgart into branch 'master'. Improve detection of currency formatting QLocale::toCurrencyString() returns different strings on Windows and Linux when using a value without fraction (e.g. 100). On Linux the output in locale de_DE was "100 €" and the same code on Windows returned "100,00 €". That caused the existing implementation of the format detection to fail. Changing the test value to 123.45 and enhancing the regex to extract the parts solves the issue. FIXED-IN: 5.2 M +4 -3 kmymoney/mymoney/mymoneymoney.cpp https://invent.kde.org/office/kmymoney/-/commit/2b802594c5ecb94f75f472c11ebdd4a520eb8984
I confirm that the Currency Editor and the Transaction Reports are fixed. The Balance field of the Ledger shows only two digits instead of eight for the Bitcoin account. I think it showed the £ symbol in front of it in the Windows 3407 build. (I just deleted it so I can't confirm it.) I'm unsure whether I should re-open this or submit a new ticket. If you prefer a new ticket I can create it.
(In reply to Tony from comment #13) > I confirm that the Currency Editor and the Transaction Reports are fixed. > The Balance field of the Ledger shows only two digits instead of eight for > the Bitcoin account. I think it showed the £ symbol in front of it in the > Windows 3407 build. (I just deleted it so I can't confirm it.) In analyzing this problem, I found that I need to make the changes mentioned in comment 8 before using commit https://invent.kde.org/office/kmymoney/-/commit/2b802594c5ecb94f75f472c11ebdd4a520eb8984 to fix this problem as well.
There's another related problem when trying to enter into the Ledger a transfer from an EUR account to a BTC account. When entering the transaction into the EUR account, I can only enter a BTC amount of up to 2 decimal places, not 8 decimal places. And if I try to change the BTC amount in the BTC account, then the EUR amount changes.
Additional info: Starting kmymoney on a german Windows 10 system from command line shows in the console: Monetary values will be formatted based on locale "de_DE" Example: "123,45 Ç" The used locale seems to be wrong.
(In reply to Ralf Habacker from comment #16) > Monetary values will be formatted based on locale "de_DE" Example: > "123,45 Ç" > > The used locale seems to be wrong. To be more precise: The locale used seems to be correct, but the currency symbol does not match.
(In reply to Ralf Habacker from comment #17) > (In reply to Ralf Habacker from comment #16) > > Monetary values will be formatted based on locale "de_DE" Example: > > "123,45 Ç" > > > > The used locale seems to be wrong. > > To be more precise: The locale used seems to be correct, but the currency > symbol does not match. The only information that KMyMoney would want from the OS's locale in order to format a money amount would be the thousands separator and decimal separator; the rest should come from the currency of the account, asset etc, or the base currency defined in KMyMoney.
Created attachment 172871 [details] QLocale testcase source Since kmymoney uses QLocale for formatting currency amounts, I created a Qt-only test case to see if the problem exists in the Qt library. The result is that the tests performed on native Linux, Linux with Wine and native Windows 10 produce identical results. $ test-qlocale-tocurrencystring/build-linux/testqlocaletocurrencystring ********* Start testing of QLocaleTest ********* Config: Using QtTest library 5.15.8, Qt 5.15.8 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 7.5.0), opensuse-leap 15.5 PASS : QLocaleTest::initTestCase() PASS : QLocaleTest::TestToCurrencyString() PASS : QLocaleTest::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 1ms ********* Finished testing of QLocaleTest ********* $ wine build/testqlocaletocurrencystring.exe ********* Start testing of QLocaleTest ********* Config: Using QtTest library 5.15.14, Qt 5.15.14 (i386-little_endian-ilp32 shared (dynamic) release build; by GCC 13. 2.0), windows 10 PASS : QLocaleTest::initTestCase() PASS : QLocaleTest::testToCurrencyString() PASS : QLocaleTest::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 52ms ********* Finished testing of QLocaleTest ********* W:\src\test-qt5\test-qlocale-toCurrencyString\build> testqlocaletocurrencystring.exe ********* Start testing of QLocaleTest ********* Config: Using QtTest library 5.15.14, Qt 5.15.14 (i386-little_endian-ilp32 shared (dynamic) release build; by GCC 13.2.0), windows 10 PASS : QLocaleTest::initTestCase() PASS : QLocaleTest::TestToCurrencyString() PASS : QLocaleTest::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 4ms ********* Finished testing of QLocaleTest ********* For the output of the smallest part of virtual currencies, such as cryptocurrencies, there is a flaw in the method used. QString QLocale::toCurrencyString(double value, const QString &symbol, int precision) If the value for the parameter symbol is NULL, QString() or QString(""), a currency symbol is always output in the default currency of the relevant locale (and this is also different, e.g. in the last two cases '€' or 'EUR' is used for 'de_DE'), which is inappropriate for outputting the smallest part of virtual currencies such as cryptocurrencies. If no output of a currency symbol is desired, a workaround is to use QString(" ") as the parameter (see the last 3 tests in the test case).
> Since kmymoney uses QLocale for formatting currency amounts, ... That is not completely correct. KMyMoney uses QLocale::toCurrencyString() only, if it was not able to match its test pattern in the output of QLocale::toCurrencyString(). This is the case for some e.g. arabic locales to my knowledge. KMyMoney indicates that with a debug output of "Using Qt internal formatter". If that output is not visible after the start of the application and outputting the result of the test pattern, then it uses it's own logic.
I have just tried the latest build (3490) and the Balance column of the ledger continues to show the amount as, e.g. 0.16 instead of 0.16688250 (the 8 decimal places configured for the BTC currency)