The implementation is just
bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
{
if (row < 0 || column < 0)
return false;
return row < rowCount(parent) && column < columnCount(parent);
}
and yet it features as the most prominent part of the profile,
encompassing up to 25% of refresh()
Open-coding it makes refresh() 40% faster. Measurements from between
after wallet.get_full_history() and return from refresh()
Before:
1.8637257907539606
1.8563996930606663
1.7696567592211068
1.8933695629239082
After:
1.3133591176010668
1.3686819169670343
1.2470976510085166
1.2455544411204755
endInsertRows() triggers a sort, the history sort/filter proxy model
then launders the comparison requests through get_data_for_role()
with a custom key, which is then especially looked up in there,
but custom-flattened in the proxy model. This is OO hell
Measuring refresh() from after if transactions == self.transactions: return
to the final return, sorting the wallet from #9958/#6625 takes ~3.5s
and 132348 get_data_for_role() calls
Beside that get_data_for_role() is called maybe 10 times per on-hover?
It's immaterial
Thus: compute the sorting keys when constructing the HistoryNode
and use them directly in the comparison.
This decouples get_data_for_role() from the sorter
and speeds the sort up by ~2x,
now being mostly made up of the python interpreter overhead(?)
for upcalls to lessThan()
A dict wins with a list for the lookup a tiny bit
(and is 100x better code-wise):
1.896097298245877s list
1.840533264912665s list
1.757185084745288s list
1.8990754359401762s list
1.914668960031122s list
1.9349112827330828s list
2.432649422902614s list
1.929884395096451s list
1.9610795709304512s list
1.8694845158606768s list
1.9600030612200499s list
1.9199693519622087s dict
2.0466488380916417s dict
1.8510140180587769s dict
1.8978681536391377s dict
2.0079748439602554s dict
1.9111531740054488s dict
1.9525738609954715s dict
1.850804285146296s dict
1.860573346260935s dict
1.95173170696944s dict
1.8481200002133846s dict
Benchmark 1: dict
Time (mean ± σ): 1918.039234 ms ± 63.688609 ms
Range (min … max): 1848.120000 ms … 2046.648838 ms 11 runs
Benchmark 2: list
Time (mean ± σ): 1945.052027 ms ± 164.019588 ms
Range (min … max): 1757.185085 ms … 2432.649423 ms 11 runs
Summary
'dict' ran
1.014084 ± 0.090082 times faster than 'list'
if there is no amount in the payment request the notification would look
weird as it would just show `Payment received:` indicating something
might be missing. Now it just says `Payment received` instead.
and differenciate between a single 'provider' and multiple or 0
'providers'. Also update SwapDialog and SwapServerDialog
when new offers are incoming. Stops translating f-string.
The endInsertRows() call triggers the main calls to get_data_for_role():
in the current order, the try/except goes to the exception every time
In the updated order, it doesn't do it ever
We have full control over what's in the cache,
and we always fully populate it, so we can get rid of the fallback
Replaces the unmaintained and unreliable
`me.dm7.barcodescanner:zxing:1.9.8` qr code scanning library used only
on android with the `com.github.markusfisch:BarcodeScannerView:1.6.0`
(https://github.com/markusfisch/BarcodeScannerView) library which seems
more actively maintained.
The `BarcodeScannerView` library is incredibly fast and scanning qr
codes is now fun again :)
wip: still looking into ways to pin the library.
This change orders the list of swapproviders in the qml gui by the
`pow_bits` value in the announcement by inserting the orders at the
correct index in the list instead of just appending new incoming offers.
There was too much code duplication - there still is a bit...
- in some places buttons had text "Read QR code with camera", in others it was "Read QR code from camera"
- 63c224cb53 added a "on_qr_from_file_input_btn"
input method, which was not added everywhere.
- was missing in add_qr_input_combined_button and in editor_contextMenuEvent
Since users have to trust plugin publishers, we should expect
the plugin to be signed by its author, and the user to verify
the signature before installing.
i noticed that the `show_bitcoin_paper()` call can be a bit slow on some
machines blocking the gui for multiple seconds without giving feedback.
Wrapping it in a waiting dialog gives the user some feedback that
something is happening.
- we were already
- statically declaring "NSCameraUsageDescription" in the Info.plist
- this used to be enough in the past
- codesigning with an entitlements.plist that declares "com.apple.security.device.camera"
- I believe this is required for notarization to pass for an app that declares "NSCameraUsageDescription".
- previously this was enough to access the camera IIRC
- in any case, if the user goes into "System Preferences">"Security & Privacy", they can manually modify permissions there
- now with this commit, we on-demand trigger at runtime the OS permission prompt
- making it much easier for users to actually use the camera
- note: if you run via the Terminal, e.g. `$ $HOME/Desktop/Electrum.app/Contents/MacOS/run_electrum`,
then it will be the Terminal app that requires the camera permission. If you run by double-clicking Electrum.app,
then Electrum.app will be the "app" that requires the camera permission.
- `$ tccutil reset Camera` can be used to clear permissions for all apps (back to the Qt::PermissionStatus::Undetermined state)
ref https://doc.qt.io/qt-6.5/qcoreapplication.html#requestPermission-1
The user should still be able to open the Preferences dialog, despite the camera functionality being broken.
see https://github.com/spesmilo/electrum/issues/9949
```
6.36 | E | gui.qt.exception_window.Exception_Hook | exception caught by crash reporter
Traceback (most recent call last):
File "electrum\gui\qt\main_window.py", line 2672, in settings_dialog
File "electrum\gui\qt\settings_dialog.py", line 229, in __init__
File "electrum\gui\qt\qrreader\__init__.py", line 96, in find_system_cameras
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "PyInstaller\loader\pyimod02_importers.py", line 450, in exec_module
File "electrum\gui\qt\qrreader\qtmultimedia\__init__.py", line 28, in <module>
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "PyInstaller\loader\pyimod02_importers.py", line 450, in exec_module
File "electrum\gui\qt\qrreader\qtmultimedia\camera_dialog.py", line 32, in <module>
RuntimeError: PyQt6.QtMultimedia cannot import type '���d�⌂' from PyQt6.QtCore
```
The 'I Accept' button might not get enabled for some users where startup
is very slow.
The first check if the 'I Agree' button should be enabled gets fired
100ms after constructing the Dialog, which might not be enough.
So we can either remove the logic completely (done here) to prevent these
issues, or alternatively increase the initial timer to some large timout
after which the window should be assembled fully (e.g. 2 seconds). As
the user is not able to read the whole terms in few seconds this would
be a viable option too.
Explicitly sets the AA_DontShowIconsInMenus attribute to false as it
defaults to true on some Qt versions / environments which causes icons
to not show up in the menus (e.g. MacOS).
see https://forum.qt.io/post/813228
The attribute has to be set on self.app after the QApplication has been
instanciated (https://doc.qt.io/qt-6/qt.html#ApplicationAttribute-enum)
fixes exceptions ocurring when entering a '!' amount with a payment
identifier that is not allowed to send max (e.g. bolt11).
fixes exception when "Max" is still set from previous PI and the PI gets
replaced by one that doesn't allow max sending.
`do_export_history()` which is used by the qt history export function was
broken as it used a method that did not exist anymore.
this updates `do_export_history()` to use `get_full_history()` and also
adds support for payment grouping and lightning transactions to the
generated CSV file.
this changes PluginsDialog to disable the "Enable" button of plugins
that are missing dependencies (e.g. amodem) instead of not showing them
at all. A tooltip is shown explaining the user why the plugin is
disabled.