add rename wallet menu command

This commit is contained in:
Craig Raw 2023-07-18 10:09:37 +02:00
parent c443bc78d3
commit 7bb22419df
7 changed files with 88 additions and 16 deletions

View file

@ -220,6 +220,8 @@ public class AppController implements Initializable {
private final Set<Wallet> emptyLoadingWallets = new LinkedHashSet<>();
private final Map<File, File> renamedWallets = new HashMap<>();
private final ChangeListener<Boolean> serverToggleOnlineListener = (observable, oldValue, newValue) -> {
Platform.runLater(() -> setServerToggleTooltip(getCurrentBlockHeight()));
};
@ -851,6 +853,10 @@ public class AppController implements Initializable {
}
}
public void renameWallet(ActionEvent event) {
renameWallet(getSelectedWalletForm());
}
public void deleteWallet(ActionEvent event) {
deleteWallet(getSelectedWalletForm());
}
@ -1548,6 +1554,11 @@ public class AppController implements Initializable {
tabs.getTabs().add(tab);
tabs.getSelectionModel().select(tab);
File oldWalletFile = renamedWallets.remove(storage.getWalletFile());
if(oldWalletFile != null) {
deleteStorage(new Storage(oldWalletFile), false);
}
} else {
for(Tab walletTab : tabs.getTabs()) {
TabData tabData = (TabData)walletTab.getUserData();
@ -1970,6 +1981,30 @@ public class AppController implements Initializable {
}
}
private void renameWallet(WalletForm selectedWalletForm) {
WalletNameDialog walletNameDialog = new WalletNameDialog(selectedWalletForm.getMasterWallet().getName(), false, null, true);
Optional<WalletNameDialog.NameAndBirthDate> optName = walletNameDialog.showAndWait();
if(optName.isPresent()) {
File walletFile = Storage.getWalletFile(optName.get().getName() + "." + PersistenceType.DB.getExtension());
if(walletFile.exists()) {
showErrorDialog("Error renaming wallet", "Wallet file " + walletFile.getAbsolutePath() + " already exists.");
return;
}
Storage.CopyWalletService copyWalletService = new Storage.CopyWalletService(selectedWalletForm.getWallet(), walletFile);
copyWalletService.setOnSucceeded(event -> {
renamedWallets.put(walletFile, selectedWalletForm.getStorage().getWalletFile());
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
openWalletFile(walletFile, true);
});
copyWalletService.setOnFailed(event -> {
log.error("Error renaming wallet", event.getSource().getException());
showErrorDialog("Error renaming wallet", event.getSource().getException().getMessage());
});
copyWalletService.start();
}
}
private void deleteWallet(WalletForm selectedWalletForm) {
Optional<ButtonType> optButtonType = AppServices.showWarningDialog("Delete " + selectedWalletForm.getWallet().getMasterName() + "?", "The wallet file and any backups will be deleted. Are you sure?", ButtonType.NO, ButtonType.YES);
if(optButtonType.isPresent() && optButtonType.get() == ButtonType.YES) {
@ -1985,7 +2020,7 @@ public class AppController implements Initializable {
try {
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
deleteStorage(storage);
deleteStorage(storage, true);
} finally {
encryptionFullKey.clear();
password.get().clear();
@ -2007,15 +2042,15 @@ public class AppController implements Initializable {
}
} else {
tabs.getTabs().remove(tabs.getSelectionModel().getSelectedItem());
deleteStorage(storage);
deleteStorage(storage, true);
}
}
}
private void deleteStorage(Storage storage) {
private void deleteStorage(Storage storage, boolean deleteBackups) {
if(storage.isClosed()) {
Platform.runLater(() -> {
Storage.DeleteWalletService deleteWalletService = new Storage.DeleteWalletService(storage);
Storage.DeleteWalletService deleteWalletService = new Storage.DeleteWalletService(storage, deleteBackups);
deleteWalletService.setDelay(Duration.seconds(3));
deleteWalletService.setPeriod(Duration.hours(1));
deleteWalletService.setOnSucceeded(event -> {
@ -2031,7 +2066,7 @@ public class AppController implements Initializable {
deleteWalletService.start();
});
} else {
Platform.runLater(() -> deleteStorage(storage));
Platform.runLater(() -> deleteStorage(storage, deleteBackups));
}
}

View file

@ -42,9 +42,13 @@ public class WalletNameDialog extends Dialog<WalletNameDialog.NameAndBirthDate>
}
public WalletNameDialog(String initialName, boolean hasExistingTransactions, Date startDate) {
this(initialName, hasExistingTransactions, startDate, false);
}
public WalletNameDialog(String initialName, boolean hasExistingTransactions, Date startDate, boolean rename) {
final DialogPane dialogPane = getDialogPane();
AppServices.setStageIcon(dialogPane.getScene().getWindow());
boolean requestBirthDate = (Config.get().getServerType() == null || Config.get().getServerType() == ServerType.BITCOIN_CORE);
boolean requestBirthDate = !rename && (Config.get().getServerType() == null || Config.get().getServerType() == ServerType.BITCOIN_CORE);
setTitle("Wallet Name");
dialogPane.setHeaderText("Enter a name for this wallet:");
@ -121,16 +125,16 @@ public class WalletNameDialog extends Dialog<WalletNameDialog.NameAndBirthDate>
));
});
final ButtonType okButtonType = new javafx.scene.control.ButtonType("Create Wallet", ButtonBar.ButtonData.OK_DONE);
final ButtonType okButtonType = new javafx.scene.control.ButtonType((rename ? "Rename" : "Create") + " Wallet", ButtonBar.ButtonData.OK_DONE);
dialogPane.getButtonTypes().addAll(okButtonType);
Button okButton = (Button) dialogPane.lookupButton(okButtonType);
BooleanBinding isInvalid = Bindings.createBooleanBinding(() ->
name.getText().length() == 0 || Storage.walletExists(name.getText()) || (existingCheck.isSelected() && existingPicker.getValue() == null), name.textProperty(), existingCheck.selectedProperty(), existingPicker.valueProperty());
name.getText().trim().length() == 0 || Storage.walletExists(name.getText()) || (existingCheck.isSelected() && existingPicker.getValue() == null), name.textProperty(), existingCheck.selectedProperty(), existingPicker.valueProperty());
okButton.disableProperty().bind(isInvalid);
name.setPromptText("Wallet Name");
Platform.runLater(name::requestFocus);
setResultConverter(dialogButton -> dialogButton == okButtonType ? new NameAndBirthDate(name.getText(), existingPicker.getValue()) : null);
setResultConverter(dialogButton -> dialogButton == okButtonType ? new NameAndBirthDate(name.getText().trim(), existingPicker.getValue()) : null);
}
public static class NameAndBirthDate {

View file

@ -39,8 +39,10 @@ public class Sparrow implements WalletImport, WalletExport {
Storage tempStorage = new Storage(persistence, tempFile);
tempStorage.setKeyDeriver(storage.getKeyDeriver());
tempStorage.setEncryptionPubKey(storage.getEncryptionPubKey());
tempStorage.saveWallet(exportedWallet);
for(Wallet childWallet : exportedWallet.getChildWallets()) {
Wallet copy = exportedWallet.copy();
tempStorage.saveWallet(copy);
for(Wallet childWallet : copy.getChildWallets()) {
tempStorage.saveWallet(childWallet);
}
persistence.close();

View file

@ -265,8 +265,11 @@ public class Storage {
persistence.copyWallet(walletFile, outputStream);
}
public boolean delete() {
deleteBackups();
public boolean delete(boolean deleteBackups) {
if(deleteBackups) {
deleteBackups();
}
return IOUtils.secureDelete(walletFile);
}
@ -735,18 +738,44 @@ public class Storage {
}
}
public static class CopyWalletService extends Service<Void> {
private final Wallet wallet;
private final File newWalletFile;
public CopyWalletService(Wallet wallet, File newWalletFile) {
this.wallet = wallet;
this.newWalletFile = newWalletFile;
}
@Override
protected Task<Void> createTask() {
return new Task<>() {
protected Void call() throws IOException, ExportException {
Sparrow export = new Sparrow();
try(BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(newWalletFile))) {
export.exportWallet(wallet, outputStream);
}
return null;
}
};
}
}
public static class DeleteWalletService extends ScheduledService<Boolean> {
private final Storage storage;
private final boolean deleteBackups;
public DeleteWalletService(Storage storage) {
public DeleteWalletService(Storage storage, boolean deleteBackups) {
this.storage = storage;
this.deleteBackups = deleteBackups;
}
@Override
protected Task<Boolean> createTask() {
return new Task<>() {
protected Boolean call() {
return storage.delete();
return storage.delete(deleteBackups);
}
};
}

View file

@ -583,7 +583,7 @@ public class DbPersistence implements Persistence {
@Override
public boolean isClosed() {
return dataSource.isClosed();
return dataSource == null || dataSource.isClosed();
}
@Override

View file

@ -21,6 +21,7 @@ public interface MixConfigDao {
default void addMixConfig(Wallet wallet) {
if(wallet.getMixConfig() != null) {
wallet.getMixConfig().setId(null);
addOrUpdate(wallet, wallet.getMixConfig());
}
}

View file

@ -49,6 +49,7 @@
<SeparatorMenuItem styleClass="osxHide" />
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Preferences..." accelerator="Shortcut+P" onAction="#openPreferences"/>
<SeparatorMenuItem />
<MenuItem fx:id="renameWallet" mnemonicParsing="false" text="Rename Wallet..." onAction="#renameWallet"/>
<MenuItem fx:id="deleteWallet" mnemonicParsing="false" text="Delete Wallet..." onAction="#deleteWallet"/>
<MenuItem fx:id="closeTab" mnemonicParsing="false" text="Close Tab" accelerator="Shortcut+W" onAction="#closeTab"/>
<MenuItem styleClass="osxHide" mnemonicParsing="false" text="Quit" accelerator="Shortcut+Q" onAction="#quit"/>