diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties
index 9eb3417d60..4b8e5e2e95 100644
--- a/core/src/main/resources/i18n/displayStrings.properties
+++ b/core/src/main/resources/i18n/displayStrings.properties
@@ -219,7 +219,8 @@ shared.refundAgentForSupportStaff=Refund agent
shared.delayedPayoutTxId=Delayed payout transaction ID
shared.delayedPayoutTxReceiverAddress=Delayed payout transaction sent to
shared.unconfirmedTransactionsLimitReached=You have too many unconfirmed transactions at the moment. Please try again later.
-
+shared.numItemsLabel=Number of entries: {0}
+shared.filter=Filter
####################################################################
# UI views
@@ -1053,7 +1054,6 @@ funds.tx.dustAttackTx.popup=This transaction is sending a very small BTC amount
To protect your privacy the Bisq wallet ignores such dust outputs for spending purposes and in the balance display. \
You can set the threshold amount when an output is considered dust in the settings.
-
####################################################################
# Support
####################################################################
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java
index fcafade802..a2d80382dc 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java
+++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedListItem.java
@@ -18,12 +18,13 @@
package bisq.desktop.main.funds.locked;
import bisq.desktop.components.AutoTooltipLabel;
+import bisq.desktop.util.DisplayUtils;
import bisq.core.btc.listeners.BalanceListener;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.WalletService;
-import bisq.core.trade.Tradable;
+import bisq.core.locale.Res;
import bisq.core.trade.Trade;
import bisq.core.util.coin.CoinFormatter;
@@ -33,21 +34,34 @@ import org.bitcoinj.core.Transaction;
import javafx.scene.control.Label;
+import lombok.Getter;
+
import javax.annotation.Nullable;
class LockedListItem {
private final BalanceListener balanceListener;
- private final Label balanceLabel;
- private final Trade trade;
- private final AddressEntry addressEntry;
private final BtcWalletService btcWalletService;
private final CoinFormatter formatter;
+
+ @Getter
+ private final Label balanceLabel;
+ @Getter
+ private final Trade trade;
+ @Getter
+ private final AddressEntry addressEntry;
+ @Getter
private final String addressString;
@Nullable
private final Address address;
+ @Getter
private Coin balance;
+ @Getter
+ private String balanceString;
- public LockedListItem(Trade trade, AddressEntry addressEntry, BtcWalletService btcWalletService, CoinFormatter formatter) {
+ public LockedListItem(Trade trade,
+ AddressEntry addressEntry,
+ BtcWalletService btcWalletService,
+ CoinFormatter formatter) {
this.trade = trade;
this.addressEntry = addressEntry;
this.btcWalletService = btcWalletService;
@@ -55,15 +69,13 @@ class LockedListItem {
if (trade.getDepositTx() != null && !trade.getDepositTx().getOutputs().isEmpty()) {
address = WalletService.getAddressFromOutput(trade.getDepositTx().getOutput(0));
- addressString = address.toString();
+ addressString = address != null ? address.toString() : "";
} else {
address = null;
addressString = "";
}
-
- // balance
balanceLabel = new AutoTooltipLabel();
- balanceListener = new BalanceListener(getAddress()) {
+ balanceListener = new BalanceListener(address) {
@Override
public void onBalanceChanged(Coin balance, Transaction tx) {
updateBalance();
@@ -73,38 +85,36 @@ class LockedListItem {
updateBalance();
}
+ LockedListItem() {
+ this.trade = null;
+ this.addressEntry = null;
+ this.btcWalletService = null;
+ this.formatter = null;
+ addressString = null;
+ address = null;
+ balanceLabel = null;
+ balanceListener = null;
+ }
+
public void cleanup() {
btcWalletService.removeBalanceListener(balanceListener);
}
private void updateBalance() {
balance = addressEntry.getCoinLockedInMultiSigAsCoin();
- balanceLabel.setText(formatter.formatCoin(this.balance));
+ balanceString = formatter.formatCoin(this.balance);
+ balanceLabel.setText(balanceString);
}
- @Nullable
- private Address getAddress() {
- return address;
+ public String getDetails() {
+ return trade != null ?
+ Res.get("funds.locked.locked", trade.getShortId()) :
+ Res.get("shared.noDetailsAvailable");
}
- public AddressEntry getAddressEntry() {
- return addressEntry;
+ public String getDateString() {
+ return trade != null ?
+ DisplayUtils.formatDateTime(trade.getDate()) :
+ Res.get("shared.noDateAvailable");
}
-
- public Label getBalanceLabel() {
- return balanceLabel;
- }
-
- public Coin getBalance() {
- return balance;
- }
-
- public String getAddressString() {
- return addressString;
- }
-
- public Tradable getTrade() {
- return trade;
- }
-
}
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.fxml b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.fxml
index a47194ae33..623c3e99f6 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.fxml
@@ -17,8 +17,12 @@
~ along with Bisq. If not, see .
-->
+
+
+
+
-
+
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java
index 1e8875b8bc..df3db4eadc 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java
+++ b/desktop/src/main/java/bisq/desktop/main/funds/locked/LockedView.java
@@ -19,12 +19,12 @@ package bisq.desktop.main.funds.locked;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
+import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
-import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.GUIUtil;
import bisq.core.btc.listeners.BalanceListener;
@@ -43,6 +43,8 @@ import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
+import com.googlecode.jcsv.writer.CSVEntryConverter;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -50,12 +52,20 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
import javafx.fxml.FXML;
+import javafx.stage.Stage;
+
+import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+import javafx.geometry.Insets;
+
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
@@ -77,6 +87,12 @@ public class LockedView extends ActivatableView {
TableView tableView;
@FXML
TableColumn dateColumn, detailsColumn, addressColumn, balanceColumn;
+ @FXML
+ Label numItems;
+ @FXML
+ Region spacer;
+ @FXML
+ AutoTooltipButton exportButton;
private final BtcWalletService btcWalletService;
private final TradeManager tradeManager;
@@ -97,8 +113,13 @@ public class LockedView extends ActivatableView {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
- private LockedView(BtcWalletService btcWalletService, TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences,
- @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) {
+ private LockedView(BtcWalletService btcWalletService,
+ TradeManager tradeManager,
+ OpenOfferManager openOfferManager,
+ Preferences preferences,
+ @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
+ OfferDetailsWindow offerDetailsWindow,
+ TradeDetailsWindow tradeDetailsWindow) {
this.btcWalletService = btcWalletService;
this.tradeManager = tradeManager;
this.openOfferManager = openOfferManager;
@@ -138,6 +159,10 @@ public class LockedView extends ActivatableView {
};
openOfferListChangeListener = c -> updateList();
tradeListChangeListener = c -> updateList();
+
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+ numItems.setPadding(new Insets(-5, 0, 0, 10));
+ exportButton.updateText(Res.get("shared.exportCSV"));
}
@Override
@@ -149,6 +174,33 @@ public class LockedView extends ActivatableView {
updateList();
btcWalletService.addBalanceListener(balanceListener);
+
+ numItems.setText(Res.get("shared.numItemsLabel", sortedList.size()));
+ exportButton.setOnAction(event -> {
+ ObservableList> tableColumns = tableView.getColumns();
+ int reportColumns = tableColumns.size();
+ CSVEntryConverter headerConverter = transactionsListItem -> {
+ String[] columns = new String[reportColumns];
+ for (int i = 0; i < columns.length; i++)
+ columns[i] = ((AutoTooltipLabel) tableColumns.get(i).getGraphic()).getText();
+ return columns;
+ };
+ CSVEntryConverter contentConverter = item -> {
+ String[] columns = new String[reportColumns];
+ columns[0] = item.getDateString();
+ columns[1] = item.getDetails();
+ columns[2] = item.getAddressString();
+ columns[3] = item.getBalanceString();
+ return columns;
+ };
+
+ GUIUtil.exportCSV("lockedInTradesFunds.csv",
+ headerConverter,
+ contentConverter,
+ new LockedListItem(),
+ sortedList,
+ (Stage) root.getScene().getWindow());
+ });
}
@Override
@@ -158,6 +210,7 @@ public class LockedView extends ActivatableView {
sortedList.comparatorProperty().unbind();
observableList.forEach(LockedListItem::cleanup);
btcWalletService.removeBalanceListener(balanceListener);
+ exportButton.setOnAction(null);
}
@@ -169,7 +222,8 @@ public class LockedView extends ActivatableView {
observableList.forEach(LockedListItem::cleanup);
observableList.setAll(tradeManager.getTradesStreamWithFundsLockedIn()
.map(trade -> {
- final Optional addressEntryOptional = btcWalletService.getAddressEntry(trade.getId(), AddressEntry.Context.MULTI_SIG);
+ Optional addressEntryOptional = btcWalletService.getAddressEntry(trade.getId(),
+ AddressEntry.Context.MULTI_SIG);
return addressEntryOptional.map(addressEntry -> new LockedListItem(trade,
addressEntry,
btcWalletService,
@@ -227,9 +281,9 @@ public class LockedView extends ActivatableView {
super.updateItem(item, empty);
if (item != null && !empty) {
if (getTradable(item).isPresent())
- setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate())));
+ setGraphic(new AutoTooltipLabel(item.getDateString()));
else
- setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable")));
+ setGraphic(new AutoTooltipLabel(item.getDateString()));
} else {
setGraphic(null);
}
@@ -257,13 +311,13 @@ public class LockedView extends ActivatableView {
if (item != null && !empty) {
Optional tradableOptional = getTradable(item);
if (tradableOptional.isPresent()) {
- field = new HyperlinkWithIcon(Res.get("funds.locked.locked", item.getTrade().getShortId()),
+ field = new HyperlinkWithIcon(item.getDetails(),
AwesomeIcon.INFO_SIGN);
field.setOnAction(event -> openDetailPopup(item));
field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails")));
setGraphic(field);
} else {
- setGraphic(new AutoTooltipLabel(Res.get("shared.noDetailsAvailable")));
+ setGraphic(new AutoTooltipLabel(item.getDetails()));
}
} else {
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java
index 4b36ce9f12..04d7ad75a2 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java
+++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedListItem.java
@@ -18,12 +18,13 @@
package bisq.desktop.main.funds.reserved;
import bisq.desktop.components.AutoTooltipLabel;
+import bisq.desktop.util.DisplayUtils;
import bisq.core.btc.listeners.BalanceListener;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BtcWalletService;
+import bisq.core.locale.Res;
import bisq.core.offer.OpenOffer;
-import bisq.core.trade.Tradable;
import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Address;
@@ -34,26 +35,40 @@ import javafx.scene.control.Label;
import java.util.Optional;
+import lombok.Getter;
+
class ReservedListItem {
private final BalanceListener balanceListener;
- private final Label balanceLabel;
- private final OpenOffer openOffer;
- private final AddressEntry addressEntry;
private final BtcWalletService btcWalletService;
private final CoinFormatter formatter;
- private final String addressString;
- private Coin balance;
- public ReservedListItem(OpenOffer openOffer, AddressEntry addressEntry, BtcWalletService btcWalletService, CoinFormatter formatter) {
+ @Getter
+ private final Label balanceLabel;
+ @Getter
+ private final OpenOffer openOffer;
+ @Getter
+ private final AddressEntry addressEntry;
+ @Getter
+ private final String addressString;
+ @Getter
+ private final Address address;
+ @Getter
+ private Coin balance;
+ @Getter
+ private String balanceString;
+
+ public ReservedListItem(OpenOffer openOffer,
+ AddressEntry addressEntry,
+ BtcWalletService btcWalletService,
+ CoinFormatter formatter) {
this.openOffer = openOffer;
this.addressEntry = addressEntry;
this.btcWalletService = btcWalletService;
this.formatter = formatter;
addressString = addressEntry.getAddressString();
-
- // balance
+ address = addressEntry.getAddress();
balanceLabel = new AutoTooltipLabel();
- balanceListener = new BalanceListener(getAddress()) {
+ balanceListener = new BalanceListener(address) {
@Override
public void onBalanceChanged(Coin balance, Transaction tx) {
updateBalance();
@@ -63,41 +78,40 @@ class ReservedListItem {
updateBalance();
}
+ ReservedListItem() {
+ this.openOffer = null;
+ this.addressEntry = null;
+ this.btcWalletService = null;
+ this.formatter = null;
+ addressString = null;
+ address = null;
+ balanceLabel = null;
+ balanceListener = null;
+ }
+
public void cleanup() {
btcWalletService.removeBalanceListener(balanceListener);
}
private void updateBalance() {
- final Optional addressEntryOptional = btcWalletService.getAddressEntry(openOffer.getId(), AddressEntry.Context.RESERVED_FOR_TRADE);
+ Optional addressEntryOptional = btcWalletService.getAddressEntry(openOffer.getId(),
+ AddressEntry.Context.RESERVED_FOR_TRADE);
addressEntryOptional.ifPresent(addressEntry -> {
balance = btcWalletService.getBalanceForAddress(addressEntry.getAddress());
- if (balance != null)
- balanceLabel.setText(formatter.formatCoin(balance));
+ if (balance != null) {
+ balanceString = formatter.formatCoin(balance);
+ balanceLabel.setText(balanceString);
+ }
});
}
- private Address getAddress() {
- return addressEntry.getAddress();
+ public String getDateAsString() {
+ return DisplayUtils.formatDateTime(openOffer.getDate());
}
- public AddressEntry getAddressEntry() {
- return addressEntry;
+ public String getDetails() {
+ return openOffer != null ?
+ Res.get("funds.reserved.reserved", openOffer.getShortId()) :
+ Res.get("shared.noDetailsAvailable");
}
-
- public Label getBalanceLabel() {
- return balanceLabel;
- }
-
- public Coin getBalance() {
- return balance;
- }
-
- public String getAddressString() {
- return addressString;
- }
-
- public Tradable getOpenOffer() {
- return openOffer;
- }
-
}
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.fxml b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.fxml
index 59cec585db..8a43556b99 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.fxml
@@ -17,8 +17,12 @@
~ along with Bisq. If not, see .
-->
+
+
+
+
-
+
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java
index 061ed666e3..cac62e6c44 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java
+++ b/desktop/src/main/java/bisq/desktop/main/funds/reserved/ReservedView.java
@@ -19,12 +19,12 @@ package bisq.desktop.main.funds.reserved;
import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
+import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
-import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.GUIUtil;
import bisq.core.btc.listeners.BalanceListener;
@@ -43,6 +43,8 @@ import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction;
+import com.googlecode.jcsv.writer.CSVEntryConverter;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -50,12 +52,20 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
import javafx.fxml.FXML;
+import javafx.stage.Stage;
+
+import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+import javafx.geometry.Insets;
+
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
@@ -77,6 +87,12 @@ public class ReservedView extends ActivatableView {
TableView tableView;
@FXML
TableColumn dateColumn, detailsColumn, addressColumn, balanceColumn;
+ @FXML
+ Label numItems;
+ @FXML
+ Region spacer;
+ @FXML
+ AutoTooltipButton exportButton;
private final BtcWalletService btcWalletService;
private final TradeManager tradeManager;
@@ -97,8 +113,13 @@ public class ReservedView extends ActivatableView {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
- private ReservedView(BtcWalletService btcWalletService, TradeManager tradeManager, OpenOfferManager openOfferManager, Preferences preferences,
- @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) {
+ private ReservedView(BtcWalletService btcWalletService,
+ TradeManager tradeManager,
+ OpenOfferManager openOfferManager,
+ Preferences preferences,
+ @Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
+ OfferDetailsWindow offerDetailsWindow,
+ TradeDetailsWindow tradeDetailsWindow) {
this.btcWalletService = btcWalletService;
this.tradeManager = tradeManager;
this.openOfferManager = openOfferManager;
@@ -138,6 +159,10 @@ public class ReservedView extends ActivatableView {
};
openOfferListChangeListener = c -> updateList();
tradeListChangeListener = c -> updateList();
+
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+ numItems.setPadding(new Insets(-5, 0, 0, 10));
+ exportButton.updateText(Res.get("shared.exportCSV"));
}
@Override
@@ -149,6 +174,33 @@ public class ReservedView extends ActivatableView {
updateList();
btcWalletService.addBalanceListener(balanceListener);
+
+ numItems.setText(Res.get("shared.numItemsLabel", sortedList.size()));
+ exportButton.setOnAction(event -> {
+ ObservableList> tableColumns = tableView.getColumns();
+ int reportColumns = tableColumns.size();
+ CSVEntryConverter headerConverter = transactionsListItem -> {
+ String[] columns = new String[reportColumns];
+ for (int i = 0; i < columns.length; i++)
+ columns[i] = ((AutoTooltipLabel) tableColumns.get(i).getGraphic()).getText();
+ return columns;
+ };
+ CSVEntryConverter contentConverter = item -> {
+ String[] columns = new String[reportColumns];
+ columns[0] = item.getDateAsString();
+ columns[1] = item.getDetails();
+ columns[2] = item.getAddressString();
+ columns[3] = item.getBalanceString();
+ return columns;
+ };
+
+ GUIUtil.exportCSV("reservedInOffersFunds.csv",
+ headerConverter,
+ contentConverter,
+ new ReservedListItem(),
+ sortedList,
+ (Stage) root.getScene().getWindow());
+ });
}
@Override
@@ -158,6 +210,7 @@ public class ReservedView extends ActivatableView {
sortedList.comparatorProperty().unbind();
observableList.forEach(ReservedListItem::cleanup);
btcWalletService.removeBalanceListener(balanceListener);
+ exportButton.setOnAction(null);
}
@@ -226,9 +279,9 @@ public class ReservedView extends ActivatableView {
public void updateItem(final ReservedListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
- if (getTradable(item).isPresent())
- setGraphic(new AutoTooltipLabel(DisplayUtils.formatDateTime(getTradable(item).get().getDate())));
- else
+ if (getTradable(item).isPresent()) {
+ setGraphic(new AutoTooltipLabel(item.getDateAsString()));
+ } else
setGraphic(new AutoTooltipLabel(Res.get("shared.noDateAvailable")));
} else {
setGraphic(null);
@@ -257,13 +310,12 @@ public class ReservedView extends ActivatableView {
if (item != null && !empty) {
Optional tradableOptional = getTradable(item);
if (tradableOptional.isPresent()) {
- field = new HyperlinkWithIcon(Res.get("funds.reserved.reserved", item.getOpenOffer().getShortId()),
- AwesomeIcon.INFO_SIGN);
+ field = new HyperlinkWithIcon(item.getDetails(), AwesomeIcon.INFO_SIGN);
field.setOnAction(event -> openDetailPopup(item));
field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails")));
setGraphic(field);
} else {
- setGraphic(new AutoTooltipLabel(Res.get("shared.noDetailsAvailable")));
+ setGraphic(new AutoTooltipLabel(item.getDetails()));
}
} else {
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.fxml b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.fxml
index dde9599231..b2554dfca6 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.fxml
@@ -18,8 +18,11 @@
-->
+
+
+
-
-
+
+
-
+
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java
index 6fd38c1214..3020828aa1 100644
--- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java
+++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java
@@ -56,14 +56,20 @@ import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
+import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+import javafx.geometry.Insets;
+
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.event.EventHandler;
@@ -80,11 +86,16 @@ import javax.annotation.Nullable;
@FxmlView
public class TransactionsView extends ActivatableView {
+
@FXML
TableView tableView;
@FXML
TableColumn dateColumn, detailsColumn, addressColumn, transactionColumn, amountColumn, memoColumn, confidenceColumn, revertTxColumn;
@FXML
+ Label numItems;
+ @FXML
+ Region spacer;
+ @FXML
AutoTooltipButton exportButton;
private final DisplayedTransactions displayedTransactions;
@@ -180,6 +191,8 @@ public class TransactionsView extends ActivatableView {
}
};
+ HBox.setHgrow(spacer, Priority.ALWAYS);
+ numItems.setPadding(new Insets(-5, 0, 0, 10));
exportButton.updateText(Res.get("shared.exportCSV"));
}
@@ -195,6 +208,7 @@ public class TransactionsView extends ActivatableView {
if (scene != null)
scene.addEventHandler(KeyEvent.KEY_RELEASED, keyEventEventHandler);
+ numItems.setText(Res.get("shared.numItemsLabel", sortedDisplayedTransactions.size()));
exportButton.setOnAction(event -> {
final ObservableList> tableColumns = tableView.getColumns();
final int reportColumns = tableColumns.size() - 1; // CSV report excludes the last column (an icon)
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.fxml
index 1285d7e588..79f11c770e 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.fxml
@@ -20,10 +20,12 @@
+
+
+
+
+
+
+
+
@@ -50,10 +58,10 @@
-
-
-
-
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java
index 1c79620d9f..8d5284da62 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesView.java
@@ -53,6 +53,7 @@ import javafx.fxml.FXML;
import javafx.stage.Stage;
import javafx.scene.Node;
+import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
@@ -60,6 +61,7 @@ import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.geometry.Insets;
@@ -114,15 +116,19 @@ public class ClosedTradesView extends ActivatableViewAndModel applyFilteredListPredicate(filterTextField.getText());
- footerBox.setSpacing(5);
- HBox.setHgrow(spacer, Priority.ALWAYS);
+ searchBox.setSpacing(5);
+ HBox.setHgrow(searchBoxSpacer, Priority.ALWAYS);
exportButton.updateText(Res.get("shared.exportCSV"));
HBox.setMargin(exportButton, new Insets(0, 10, 0, 0));
+
+ HBox.setHgrow(footerSpacer, Priority.ALWAYS);
+ numItems.setPadding(new Insets(-5, 0, 0, 10));
+ exportButton.updateText(Res.get("shared.exportCSV"));
}
@Override
@@ -244,6 +253,7 @@ public class ClosedTradesView extends ActivatableViewAndModel {
final ObservableList> tableColumns = tableView.getColumns();
CSVEntryConverter headerConverter = transactionsListItem -> {
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesListItem.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesListItem.java
index 3d10b043f4..f16365e1d2 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesListItem.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesListItem.java
@@ -19,18 +19,17 @@ package bisq.desktop.main.portfolio.failedtrades;
import bisq.core.trade.Trade;
-/**
- * We could remove that wrapper if it is not needed for additional UI only fields.
- */
-class FailedTradesListItem {
+import lombok.Getter;
+class FailedTradesListItem {
+ @Getter
private final Trade trade;
FailedTradesListItem(Trade trade) {
this.trade = trade;
}
- Trade getTrade() {
- return trade;
+ FailedTradesListItem() {
+ this.trade = null;
}
}
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml
index 840a022f27..2ea03ddeee 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.fxml
@@ -17,8 +17,12 @@
~ along with Bisq. If not, see .
-->
+
+
+
+
+
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java
index 9d427d3da7..89e1986913 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java
@@ -19,11 +19,13 @@ package bisq.desktop.main.portfolio.failedtrades;
import bisq.desktop.common.view.ActivatableViewAndModel;
import bisq.desktop.common.view.FxmlView;
+import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
import bisq.desktop.util.FormBuilder;
+import bisq.desktop.util.GUIUtil;
import bisq.core.locale.Res;
import bisq.core.trade.Trade;
@@ -31,6 +33,8 @@ import bisq.core.trade.Trade;
import bisq.common.config.Config;
import bisq.common.util.Utilities;
+import com.googlecode.jcsv.writer.CSVEntryConverter;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -40,6 +44,8 @@ import com.jfoenix.controls.JFXButton;
import javafx.fxml.FXML;
+import javafx.stage.Stage;
+
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
@@ -48,12 +54,18 @@ import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+import javafx.geometry.Insets;
+
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.event.EventHandler;
+import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
@@ -68,6 +80,13 @@ public class FailedTradesView extends ActivatableViewAndModel priceColumn, amountColumn, volumeColumn,
marketColumn, directionColumn, dateColumn, tradeIdColumn, stateColumn, removeTradeColumn;
+ @FXML
+ Label numItems;
+ @FXML
+ Region spacer;
+ @FXML
+ AutoTooltipButton exportButton;
+
private final TradeDetailsWindow tradeDetailsWindow;
private SortedList sortedList;
private EventHandler keyEventEventHandler;
@@ -137,6 +156,10 @@ public class FailedTradesView extends ActivatableViewAndModel(model.getList());
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
+
+ numItems.setText(Res.get("shared.numItemsLabel", sortedList.size()));
+ exportButton.setOnAction(event -> {
+ ObservableList> tableColumns = tableView.getColumns();
+ int reportColumns = tableColumns.size() - 1; // CSV report excludes the last column (an icon)
+ CSVEntryConverter headerConverter = transactionsListItem -> {
+ String[] columns = new String[reportColumns];
+ for (int i = 0; i < columns.length; i++)
+ columns[i] = ((AutoTooltipLabel) tableColumns.get(i).getGraphic()).getText();
+ return columns;
+ };
+ CSVEntryConverter contentConverter = item -> {
+ String[] columns = new String[reportColumns];
+ columns[0] = model.getTradeId(item);
+ columns[1] = model.getDate(item);
+ columns[2] = model.getMarketLabel(item);
+ columns[3] = model.getPrice(item);
+ columns[4] = model.getAmount(item);
+ columns[5] = model.getVolume(item);
+ columns[6] = model.getDirectionLabel(item);
+ columns[7] = model.getState(item);
+ return columns;
+ };
+
+ GUIUtil.exportCSV("failedTrades.csv",
+ headerConverter,
+ contentConverter,
+ new FailedTradesListItem(),
+ sortedList,
+ (Stage) root.getScene().getWindow());
+ });
}
@Override
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOfferListItem.java b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOfferListItem.java
index b6dec35040..6640f2b0d1 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOfferListItem.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOfferListItem.java
@@ -20,19 +20,21 @@ package bisq.desktop.main.portfolio.openoffer;
import bisq.core.offer.Offer;
import bisq.core.offer.OpenOffer;
+import lombok.Getter;
+
/**
* We could remove that wrapper if it is not needed for additional UI only fields.
*/
class OpenOfferListItem {
-
+ @Getter
private final OpenOffer openOffer;
- public OpenOfferListItem(OpenOffer openOffer) {
+ OpenOfferListItem(OpenOffer openOffer) {
this.openOffer = openOffer;
}
- public OpenOffer getOpenOffer() {
- return openOffer;
+ OpenOfferListItem() {
+ openOffer = null;
}
public Offer getOffer() {
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.fxml b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.fxml
index 71deb94aaa..d47a52824a 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.fxml
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.fxml
@@ -17,8 +17,12 @@
~ along with Bisq. If not, see .
-->
+
+
+
+
-
+
+
+
+
+
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.java
index a1328c8435..3208c7078b 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersView.java
@@ -20,6 +20,7 @@ package bisq.desktop.main.portfolio.openoffer;
import bisq.desktop.Navigation;
import bisq.desktop.common.view.ActivatableViewAndModel;
import bisq.desktop.common.view.FxmlView;
+import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipCheckBox;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.AutoTooltipTableColumn;
@@ -30,28 +31,42 @@ import bisq.desktop.main.funds.withdrawal.WithdrawalView;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
import bisq.desktop.main.portfolio.PortfolioView;
+import bisq.desktop.util.GUIUtil;
import bisq.core.locale.Res;
import bisq.core.offer.OpenOffer;
import bisq.core.user.DontShowAgainLookup;
+import com.googlecode.jcsv.writer.CSVEntryConverter;
+
import javax.inject.Inject;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;
import javafx.fxml.FXML;
+import javafx.stage.Stage;
+
+import javafx.scene.Node;
+import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
+import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.Tooltip;
import javafx.scene.image.ImageView;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Priority;
+import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
+import javafx.geometry.Insets;
+
import javafx.beans.property.ReadOnlyObjectWrapper;
+import javafx.collections.ObservableList;
import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
@@ -71,6 +86,13 @@ public class OpenOffersView extends ActivatableViewAndModel priceColumn, deviationColumn, amountColumn, volumeColumn,
marketColumn, directionColumn, dateColumn, offerIdColumn, deactivateItemColumn,
removeItemColumn, editItemColumn, paymentMethodColumn;
+ @FXML
+ Label numItems;
+ @FXML
+ Region spacer;
+ @FXML
+ AutoTooltipButton exportButton;
+
private final Navigation navigation;
private final OfferDetailsWindow offerDetailsWindow;
private SortedList sortedList;
@@ -121,7 +143,7 @@ public class OpenOffersView extends ActivatableViewAndModel o.getOffer().getAmount()));
priceColumn.setComparator(Comparator.comparing(o -> o.getOffer().getPrice(), Comparator.nullsFirst(Comparator.naturalOrder())));
deviationColumn.setComparator(Comparator.comparing(o ->
- o.getOffer().isUseMarketBasedPrice() ? o.getOffer().getMarketPriceMargin() : 1,
+ o.getOffer().isUseMarketBasedPrice() ? o.getOffer().getMarketPriceMargin() : 1,
Comparator.nullsFirst(Comparator.naturalOrder())));
volumeColumn.setComparator(Comparator.comparing(o -> o.getOffer().getVolume(), Comparator.nullsFirst(Comparator.naturalOrder())));
dateColumn.setComparator(Comparator.comparing(o -> o.getOffer().getDate()));
@@ -129,6 +151,10 @@ public class OpenOffersView extends ActivatableViewAndModel(model.getList());
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
tableView.setItems(sortedList);
+
+ numItems.setText(Res.get("shared.numItemsLabel", sortedList.size()));
+ exportButton.setOnAction(event -> {
+ ObservableList> tableColumns = tableView.getColumns();
+ int reportColumns = tableColumns.size() - 2; // CSV report excludes the last columns (icons)
+ CSVEntryConverter headerConverter = transactionsListItem -> {
+ String[] columns = new String[reportColumns];
+ for (int i = 0; i < columns.length; i++) {
+ Node graphic = tableColumns.get(i).getGraphic();
+ if (graphic instanceof AutoTooltipLabel) {
+ columns[i] = ((AutoTooltipLabel) graphic).getText();
+ } else if (graphic instanceof HBox) {
+ // Deviation has a Hbox with AutoTooltipLabel as first child in header
+ columns[i] = ((AutoTooltipLabel) ((Parent) graphic).getChildrenUnmodifiable().get(0)).getText();
+ } else {
+ // Not expected
+ columns[i] = "N/A";
+ }
+ }
+ return columns;
+ };
+ CSVEntryConverter contentConverter = item -> {
+ String[] columns = new String[reportColumns];
+ columns[0] = model.getOfferId(item);
+ columns[1] = model.getDate(item);
+ columns[2] = model.getMarketLabel(item);
+ columns[3] = model.getPrice(item);
+ columns[4] = model.getPriceDeviation(item);
+ columns[5] = model.getAmount(item);
+ columns[6] = model.getVolume(item);
+ columns[7] = model.getPaymentMethod(item);
+ columns[8] = model.getDirectionLabel(item);
+ columns[9] = String.valueOf(!item.getOpenOffer().isDeactivated());
+ return columns;
+ };
+
+ GUIUtil.exportCSV("openOffers.csv",
+ headerConverter,
+ contentConverter,
+ new OpenOfferListItem(),
+ sortedList,
+ (Stage) root.getScene().getWindow());
+ });
}
@Override
@@ -226,7 +295,7 @@ public class OpenOffersView extends ActivatableViewAndModel offerDetailsWindow.show(item.getOffer()));
field.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails")));
setGraphic(field);
diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java
index 94b4533935..709ba4ee84 100644
--- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java
+++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java
@@ -27,8 +27,8 @@ import bisq.core.locale.Res;
import bisq.core.monetary.Price;
import bisq.core.offer.Offer;
import bisq.core.offer.OpenOffer;
-import bisq.core.util.coin.BsqFormatter;
import bisq.core.util.FormattingUtils;
+import bisq.core.util.coin.BsqFormatter;
import bisq.core.util.coin.CoinFormatter;
import bisq.network.p2p.P2PService;
@@ -78,7 +78,7 @@ class OpenOffersViewModel extends ActivatableWithDataModel
return dataModel.getList();
}
- String getTradeId(OpenOfferListItem item) {
+ String getOfferId(OpenOfferListItem item) {
return item.getOffer().getShortId();
}