search across all wallet accounts, reveal child items if selected

This commit is contained in:
Craig Raw 2022-01-31 19:14:50 +02:00
parent 6d2167428f
commit 1eb595823b
9 changed files with 85 additions and 53 deletions

2
drongo

@ -1 +1 @@
Subproject commit 61317f15ac795ef1a40c120d1e8aae2b2735c6ec Subproject commit 9618c73c50e59035cd373d932970f446032cd9e5

View file

@ -1359,14 +1359,21 @@ public class AppController implements Initializable {
} }
public void searchWallet(ActionEvent event) { public void searchWallet(ActionEvent event) {
WalletForm selectedWalletForm = getSelectedWalletForm(); Tab selectedTab = tabs.getSelectionModel().getSelectedItem();
if(selectedWalletForm != null) { if(selectedTab != null) {
SearchWalletDialog searchWalletDialog = new SearchWalletDialog(selectedWalletForm); TabData tabData = (TabData) selectedTab.getUserData();
Optional<Entry> optEntry = searchWalletDialog.showAndWait(); if(tabData instanceof WalletTabData) {
if(optEntry.isPresent()) { TabPane subTabs = (TabPane) selectedTab.getContent();
Entry entry = optEntry.get(); List<WalletForm> walletForms = subTabs.getTabs().stream().map(subTab -> ((WalletTabData)subTab.getUserData()).getWalletForm()).collect(Collectors.toList());
EventManager.get().post(new FunctionActionEvent(entry.getWalletFunction(), entry.getWallet())); if(!walletForms.isEmpty()) {
Platform.runLater(() -> EventManager.get().post(new SelectEntryEvent(entry))); SearchWalletDialog searchWalletDialog = new SearchWalletDialog(walletForms);
Optional<Entry> optEntry = searchWalletDialog.showAndWait();
if(optEntry.isPresent()) {
Entry entry = optEntry.get();
EventManager.get().post(new FunctionActionEvent(entry.getWalletFunction(), entry.getWallet()));
Platform.runLater(() -> EventManager.get().post(new SelectEntryEvent(entry)));
}
}
} }
} }
} }

View file

@ -23,12 +23,16 @@ import java.util.List;
public class SearchWalletDialog extends Dialog<Entry> { public class SearchWalletDialog extends Dialog<Entry> {
private static final Logger log = LoggerFactory.getLogger(SearchWalletDialog.class); private static final Logger log = LoggerFactory.getLogger(SearchWalletDialog.class);
private final WalletForm walletForm; private final List<WalletForm> walletForms;
private final TextField search; private final TextField search;
private final CoinTreeTable results; private final CoinTreeTable results;
public SearchWalletDialog(WalletForm walletForm) { public SearchWalletDialog(List<WalletForm> walletForms) {
this.walletForm = walletForm; this.walletForms = walletForms;
if(walletForms.isEmpty()) {
throw new IllegalArgumentException("No wallets selected to search");
}
final DialogPane dialogPane = getDialogPane(); final DialogPane dialogPane = getDialogPane();
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
@ -65,11 +69,19 @@ public class SearchWalletDialog extends Dialog<Entry> {
results = new CoinTreeTable(); results = new CoinTreeTable();
results.setShowRoot(false); results.setShowRoot(false);
results.setPrefWidth(850); results.setPrefWidth(walletForms.size() > 1 ? 950 : 850);
results.setBitcoinUnit(walletForm.getWallet()); results.setBitcoinUnit(walletForms.iterator().next().getWallet());
results.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY); results.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);
results.setPlaceholder(new Label("No results")); results.setPlaceholder(new Label("No results"));
if(walletForms.size() > 1) {
TreeTableColumn<Entry, String> walletColumn = new TreeTableColumn<>("Wallet");
walletColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getWallet().getDisplayName());
});
results.getColumns().add(walletColumn);
}
TreeTableColumn<Entry, String> typeColumn = new TreeTableColumn<>("Type"); TreeTableColumn<Entry, String> typeColumn = new TreeTableColumn<>("Type");
typeColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> { typeColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<Entry, String> param) -> {
return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getEntryType()); return new ReadOnlyObjectWrapper<>(param.getValue().getValue().getEntryType());
@ -81,10 +93,8 @@ public class SearchWalletDialog extends Dialog<Entry> {
return new ReadOnlyObjectWrapper<>(param.getValue().getValue()); return new ReadOnlyObjectWrapper<>(param.getValue().getValue());
}); });
entryCol.setCellFactory(p -> new SearchEntryCell()); entryCol.setCellFactory(p -> new SearchEntryCell());
String address = walletForm.getNodeEntry(KeyPurpose.RECEIVE).getAddress().toString(); String address = walletForms.iterator().next().getNodeEntry(KeyPurpose.RECEIVE).getAddress().toString();
if(address != null) { entryCol.setMinWidth(TextUtils.computeTextWidth(AppServices.getMonospaceFont(), address, 0.0));
entryCol.setMinWidth(TextUtils.computeTextWidth(AppServices.getMonospaceFont(), address, 0.0));
}
results.getColumns().add(entryCol); results.getColumns().add(entryCol);
TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>("Label"); TreeTableColumn<Entry, String> labelCol = new TreeTableColumn<>("Label");
@ -138,43 +148,45 @@ public class SearchWalletDialog extends Dialog<Entry> {
//ignore //ignore
} }
WalletTransactionsEntry walletTransactionsEntry = walletForm.getWalletTransactionsEntry(); for(WalletForm walletForm : walletForms) {
for(Entry entry : walletTransactionsEntry.getChildren()) { WalletTransactionsEntry walletTransactionsEntry = walletForm.getWalletTransactionsEntry();
if(entry instanceof TransactionEntry transactionEntry) { for(Entry entry : walletTransactionsEntry.getChildren()) {
if(transactionEntry.getBlockTransaction().getHash().toString().equals(searchText) || if(entry instanceof TransactionEntry transactionEntry) {
(transactionEntry.getLabel() != null && transactionEntry.getLabel().toLowerCase().contains(searchText)) || if(transactionEntry.getBlockTransaction().getHash().toString().equals(searchText) ||
(transactionEntry.getValue() != null && searchValue != null && Math.abs(transactionEntry.getValue()) == searchValue)) { (transactionEntry.getLabel() != null && transactionEntry.getLabel().toLowerCase().contains(searchText)) ||
matchingEntries.add(entry); (transactionEntry.getValue() != null && searchValue != null && Math.abs(transactionEntry.getValue()) == searchValue)) {
matchingEntries.add(entry);
}
} }
} }
}
for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) { for(KeyPurpose keyPurpose : KeyPurpose.DEFAULT_PURPOSES) {
NodeEntry purposeEntry = walletForm.getNodeEntry(keyPurpose); NodeEntry purposeEntry = walletForm.getNodeEntry(keyPurpose);
for(Entry entry : purposeEntry.getChildren()) { for(Entry entry : purposeEntry.getChildren()) {
if(entry instanceof NodeEntry nodeEntry) { if(entry instanceof NodeEntry nodeEntry) {
if(nodeEntry.getAddress().toString().contains(searchText) || if(nodeEntry.getAddress().toString().contains(searchText) ||
(nodeEntry.getLabel() != null && nodeEntry.getLabel().toLowerCase().contains(searchText)) || (nodeEntry.getLabel() != null && nodeEntry.getLabel().toLowerCase().contains(searchText)) ||
(nodeEntry.getValue() != null && searchValue != null && Math.abs(nodeEntry.getValue()) == searchValue)) { (nodeEntry.getValue() != null && searchValue != null && Math.abs(nodeEntry.getValue()) == searchValue)) {
matchingEntries.add(entry);
}
}
}
}
WalletUtxosEntry walletUtxosEntry = walletForm.getWalletUtxosEntry();
for(Entry entry : walletUtxosEntry.getChildren()) {
if(entry instanceof HashIndexEntry hashIndexEntry) {
if(hashIndexEntry.getBlockTransaction().getHash().toString().equals(searchText) ||
(hashIndexEntry.getLabel() != null && hashIndexEntry.getLabel().toLowerCase().contains(searchText)) ||
(hashIndexEntry.getValue() != null && searchValue != null && Math.abs(hashIndexEntry.getValue()) == searchValue)) {
matchingEntries.add(entry); matchingEntries.add(entry);
} }
} }
} }
} }
WalletUtxosEntry walletUtxosEntry = walletForm.getWalletUtxosEntry();
for(Entry entry : walletUtxosEntry.getChildren()) {
if(entry instanceof HashIndexEntry hashIndexEntry) {
if(hashIndexEntry.getBlockTransaction().getHash().toString().equals(searchText) ||
(hashIndexEntry.getLabel() != null && hashIndexEntry.getLabel().toLowerCase().contains(searchText)) ||
(hashIndexEntry.getValue() != null && searchValue != null && Math.abs(hashIndexEntry.getValue()) == searchValue)) {
matchingEntries.add(entry);
}
}
}
} }
SearchWalletEntry rootEntry = new SearchWalletEntry(walletForm.getWallet(), matchingEntries); SearchWalletEntry rootEntry = new SearchWalletEntry(walletForms.iterator().next().getWallet(), matchingEntries);
RecursiveTreeItem<Entry> rootItem = new RecursiveTreeItem<>(rootEntry, Entry::getChildren); RecursiveTreeItem<Entry> rootItem = new RecursiveTreeItem<>(rootEntry, Entry::getChildren);
results.setRoot(rootItem); results.setRoot(rootItem);
} }

View file

@ -105,7 +105,7 @@ public class AddressesController extends WalletFormController implements Initial
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.ADDRESSES) { if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.ADDRESSES) {
List<AddressTreeTable> addressTreeTables = List.of(receiveTable, changeTable); List<AddressTreeTable> addressTreeTables = List.of(receiveTable, changeTable);
for(AddressTreeTable addressTreeTable : addressTreeTables) { for(AddressTreeTable addressTreeTable : addressTreeTables) {
selectEntry(addressTreeTable, event.getEntry()); selectEntry(addressTreeTable, addressTreeTable.getRoot(), event.getEntry());
} }
} }
} }

View file

@ -71,7 +71,7 @@ public class HashIndexEntry extends Entry implements Comparable<HashIndexEntry>
@Override @Override
public String getEntryType() { public String getEntryType() {
return "Hash Index"; return type == Type.INPUT ? "Input" : "Output";
} }
@Override @Override

View file

@ -33,4 +33,9 @@ public class TransactionHashIndexEntry extends HashIndexEntry {
public boolean isSpent() { public boolean isSpent() {
return false; return false;
} }
@Override
public Function getWalletFunction() {
return Function.TRANSACTIONS;
}
} }

View file

@ -281,7 +281,7 @@ public class TransactionsController extends WalletFormController implements Init
@Subscribe @Subscribe
public void selectEntry(SelectEntryEvent event) { public void selectEntry(SelectEntryEvent event) {
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.TRANSACTIONS) { if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.TRANSACTIONS) {
selectEntry(transactionsTable, event.getEntry()); selectEntry(transactionsTable, transactionsTable.getRoot(), event.getEntry());
} }
} }
} }

View file

@ -609,7 +609,7 @@ public class UtxosController extends WalletFormController implements Initializab
public void selectEntry(SelectEntryEvent event) { public void selectEntry(SelectEntryEvent event) {
if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.UTXOS) { if(event.getWallet().equals(getWalletForm().getWallet()) && event.getEntry().getWalletFunction() == Function.UTXOS) {
utxosTable.getSelectionModel().clearSelection(); utxosTable.getSelectionModel().clearSelection();
selectEntry(utxosTable, event.getEntry()); selectEntry(utxosTable, utxosTable.getRoot(), event.getEntry());
} }
} }
} }

View file

@ -68,16 +68,24 @@ public abstract class WalletFormController extends BaseController {
} }
} }
protected void selectEntry(TreeTableView<Entry> treeTableView, Entry entry) { protected boolean selectEntry(TreeTableView<Entry> treeTableView, TreeItem<Entry> parentEntry, Entry entry) {
for(TreeItem<Entry> treeEntry : treeTableView.getRoot().getChildren()) { for(TreeItem<Entry> treeEntry : parentEntry.getChildren()) {
if(treeEntry.getValue().equals(entry)) { if(treeEntry.getValue().equals(entry)) {
treeTableView.getSelectionModel().select(treeEntry);
Platform.runLater(() -> { Platform.runLater(() -> {
treeTableView.requestFocus(); treeTableView.requestFocus();
treeTableView.getSelectionModel().select(treeEntry);
treeTableView.scrollTo(treeTableView.getSelectionModel().getSelectedIndex()); treeTableView.scrollTo(treeTableView.getSelectionModel().getSelectedIndex());
}); });
break; return true;
}
boolean selectedChild = selectEntry(treeTableView, treeEntry, entry);
if(selectedChild) {
treeEntry.setExpanded(true);
return true;
} }
} }
return false;
} }
} }