diff --git a/LeftPanel.qml b/LeftPanel.qml
index 51ccd01d..c48f62d1 100644
--- a/LeftPanel.qml
+++ b/LeftPanel.qml
@@ -684,7 +684,7 @@ Rectangle {
anchors.right: parent.right
anchors.bottom: daemonProgressBar.top
height: 48 * scaleRatio
- syncType: qsTr("Wallet")
+ syncType: qsTr("Wallet") + translationManager.emptyString
visible: networkStatus.connected
}
@@ -693,7 +693,7 @@ Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
- syncType: qsTr("Daemon")
+ syncType: qsTr("Daemon") + translationManager.emptyString
visible: networkStatus.connected
height: 62 * scaleRatio
}
diff --git a/components/DaemonManagerDialog.qml b/components/DaemonManagerDialog.qml
index 07dec4a0..92298e3e 100644
--- a/components/DaemonManagerDialog.qml
+++ b/components/DaemonManagerDialog.qml
@@ -90,7 +90,7 @@ Window {
}
Text {
- text: qsTr("Starting local node in %1 seconds").arg(countDown);
+ text: qsTr("Starting local node in %1 seconds").arg(countDown) + translationManager.emptyString;
font.pixelSize: 18
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
@@ -108,7 +108,7 @@ Window {
id: okButton
visible:false
fontSize: 14
- text: qsTr("Start daemon (%1)").arg(countDown)
+ text: qsTr("Start daemon (%1)").arg(countDown) + translationManager.emptyString
KeyNavigation.tab: cancelButton
onClicked: {
timer.stop();
@@ -121,7 +121,7 @@ Window {
MoneroComponents.StandardButton {
id: cancelButton
fontSize: 14
- text: qsTr("Use custom settings")
+ text: qsTr("Use custom settings") + translationManager.emptyString
onClicked: {
timer.stop();
diff --git a/components/InputDialog.qml b/components/InputDialog.qml
index 65d249e3..26e1f18a 100644
--- a/components/InputDialog.qml
+++ b/components/InputDialog.qml
@@ -145,7 +145,7 @@ Item {
small: true
width: 120
fontSize: 14
- text: qsTr("Ok")
+ text: qsTr("Ok") + translationManager.emptyString
KeyNavigation.tab: cancelButton
onClicked: {
root.close()
diff --git a/components/LineEdit.qml b/components/LineEdit.qml
index c76f46f9..95ba1369 100644
--- a/components/LineEdit.qml
+++ b/components/LineEdit.qml
@@ -126,7 +126,7 @@ Item {
MoneroComponents.LabelButton {
id: copyButtonId
- text: qsTr("Copy")
+ text: qsTr("Copy") + translationManager.emptyString
anchors.right: parent.right
onClicked: {
if (input.text.length > 0) {
diff --git a/components/LineEditMulti.qml b/components/LineEditMulti.qml
index d251fe26..e28d9e75 100644
--- a/components/LineEditMulti.qml
+++ b/components/LineEditMulti.qml
@@ -134,7 +134,7 @@ ColumnLayout {
MoneroComponents.LabelButton {
id: copyButtonId
visible: copyButton && input.text !== ""
- text: qsTr("Copy")
+ text: qsTr("Copy") + translationManager.emptyString
onClicked: {
if (input.text.length > 0) {
console.log("Copied to clipboard");
@@ -147,7 +147,7 @@ ColumnLayout {
MoneroComponents.LabelButton {
id: pasteButtonId
onClicked: item.onPaste(clipboard.text())
- text: qsTr("Paste")
+ text: qsTr("Paste") + translationManager.emptyString
visible: pasteButton
}
}
diff --git a/components/NewPasswordDialog.qml b/components/NewPasswordDialog.qml
index 8de1fd9f..11e31008 100644
--- a/components/NewPasswordDialog.qml
+++ b/components/NewPasswordDialog.qml
@@ -101,7 +101,7 @@ Item {
Layout.maximumWidth: 400 * scaleRatio
Label {
- text: qsTr("Please enter new password")
+ text: qsTr("Please enter new password") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16 * scaleRatio
@@ -179,7 +179,7 @@ Item {
}
Label {
- text: qsTr("Please confirm new password")
+ text: qsTr("Please confirm new password") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16 * scaleRatio
@@ -280,7 +280,7 @@ Item {
}
MoneroComponents.StandardButton {
id: okButton
- text: qsTr("Continue")
+ text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: passwordInput1.text === passwordInput2.text
onClicked: {
diff --git a/components/PassphraseDialog.qml b/components/PassphraseDialog.qml
index 034c4610..a8b47f12 100644
--- a/components/PassphraseDialog.qml
+++ b/components/PassphraseDialog.qml
@@ -111,7 +111,7 @@ Item {
Layout.maximumWidth: 400 * scaleRatio
Label {
- text: root.walletName.length > 0 ? qsTr("Please enter wallet device passphrase for: ") + root.walletName : qsTr("Please enter wallet device passphrase")
+ text: (root.walletName.length > 0 ? qsTr("Please enter wallet device passphrase for: ") + root.walletName : qsTr("Please enter wallet device passphrase")) + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16 * scaleRatio
@@ -121,7 +121,7 @@ Item {
}
Label {
- text: qsTr("Warning: passphrase entry on host is a security risk as it can be captured by malware. It is advised to prefer device-based passphrase entry.");
+ text: qsTr("Warning: passphrase entry on host is a security risk as it can be captured by malware. It is advised to prefer device-based passphrase entry.") + translationManager.emptyString
Layout.fillWidth: true
wrapMode: Text.Wrap
@@ -211,7 +211,7 @@ Item {
}
Label {
- text: qsTr("Please re-enter")
+ text: qsTr("Please re-enter") + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16 * scaleRatio
@@ -312,7 +312,7 @@ Item {
}
MoneroComponents.StandardButton {
id: okButton
- text: qsTr("Continue")
+ text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
enabled: passphaseInput1.text === passphaseInput2.text
onClicked: {
diff --git a/components/PasswordDialog.qml b/components/PasswordDialog.qml
index 842c0549..e292603b 100644
--- a/components/PasswordDialog.qml
+++ b/components/PasswordDialog.qml
@@ -99,7 +99,7 @@ Item {
Layout.maximumWidth: 400 * scaleRatio
Label {
- text: root.walletName.length > 0 ? qsTr("Please enter wallet password for: ") + root.walletName : qsTr("Please enter wallet password")
+ text: (root.walletName.length > 0 ? qsTr("Please enter wallet password for: ") + root.walletName : qsTr("Please enter wallet password")) + translationManager.emptyString
Layout.fillWidth: true
font.pixelSize: 16 * scaleRatio
@@ -232,7 +232,7 @@ Item {
MoneroComponents.StandardButton {
id: okButton
small: true
- text: qsTr("Continue")
+ text: qsTr("Continue") + translationManager.emptyString
KeyNavigation.tab: cancelButton
onClicked: {
root.close()
diff --git a/main.qml b/main.qml
index 36180ae3..6d9a3d70 100644
--- a/main.qml
+++ b/main.qml
@@ -1201,7 +1201,7 @@ ApplicationWindow {
handleTransactionConfirmed()
}
} else {
- passwordDialog.showError(qsTr("Wrong password"));
+ passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
}
}
passwordDialog.onRejectedCallback = null;
@@ -1229,7 +1229,7 @@ ApplicationWindow {
//Open Wallet from file
FileDialog {
id: fileDialog
- title: qsTr("Please choose a file")
+ title: qsTr("Please choose a file") + translationManager.emptyString
folder: "file://" + moneroAccountsDir
nameFilters: [ "Wallet files (*.keys)"]
sidebarVisible: false
@@ -1397,7 +1397,7 @@ ApplicationWindow {
height: appWindow.height / 2
x: (appWindow.width - width) / 2
y: (appWindow.height - height) / 2
- messageText: qsTr("Please wait...")
+ messageText: qsTr("Please wait...") + translationManager.emptyString
}
Item {
diff --git a/pages/Account.qml b/pages/Account.qml
index ba06a81c..00ac4919 100644
--- a/pages/Account.qml
+++ b/pages/Account.qml
@@ -79,13 +79,13 @@ Rectangle {
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
textFormat: Text.RichText
- text: qsTr("Balance All")
+ text: qsTr("Balance All") + translationManager.emptyString
}
RowLayout {
Layout.topMargin: 22 * scaleRatio
Text {
- text: qsTr("Total balance: ")
+ text: qsTr("Total balance: ") + translationManager.emptyString
Layout.fillWidth: true
color: "#757575"
font.pixelSize: 14
@@ -118,7 +118,7 @@ Rectangle {
RowLayout {
Layout.topMargin: 10 * scaleRatio
Text {
- text: qsTr("Total unlocked balance: ")
+ text: qsTr("Total unlocked balance: ") + translationManager.emptyString
Layout.fillWidth: true
color: "#757575"
font.pixelSize: 14
@@ -156,7 +156,7 @@ Rectangle {
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
textFormat: Text.RichText
- text: qsTr("Accounts")
+ text: qsTr("Accounts") + translationManager.emptyString
}
ColumnLayout {
@@ -320,7 +320,7 @@ Rectangle {
text: qsTr("Create new account") + translationManager.emptyString;
onClicked: {
inputDialog.labelText = qsTr("Set the label of the new account:") + translationManager.emptyString
- inputDialog.inputText = qsTr("(Untitled)")
+ inputDialog.inputText = qsTr("(Untitled)") + translationManager.emptyString
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddressAccount.addRow(inputDialog.inputText)
appWindow.currentWallet.switchSubaddressAccount(appWindow.currentWallet.numSubaddressAccounts() - 1)
diff --git a/pages/AddressBook.qml b/pages/AddressBook.qml
index 2103b235..201e644c 100644
--- a/pages/AddressBook.qml
+++ b/pages/AddressBook.qml
@@ -396,7 +396,7 @@ Rectangle {
font.pixelSize: 16 * scaleRatio
font.bold: false
color: MoneroComponents.Style.defaultFontColor
- text: qsTr("Cancel")
+ text: qsTr("Cancel") + translationManager.emptyString
MouseArea {
anchors.fill: parent
@@ -413,7 +413,7 @@ Rectangle {
font.pixelSize: 16 * scaleRatio
font.bold: false
color: MoneroComponents.Style.defaultFontColor
- text: qsTr("Delete")
+ text: qsTr("Delete") + translationManager.emptyString
MouseArea {
anchors.fill: parent
diff --git a/pages/History.qml b/pages/History.qml
index 249db78c..8acd423d 100644
--- a/pages/History.qml
+++ b/pages/History.qml
@@ -100,7 +100,7 @@ Rectangle {
Layout.alignment: Qt.AlignVCenter
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Sort & filter")
+ text: qsTr("Sort & filter") + translationManager.emptyString
color: MoneroComponents.Style.defaultFontColor
MouseArea {
@@ -239,7 +239,7 @@ Rectangle {
id: sortBlockheightText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Blockheight")
+ text: qsTr("Blockheight") + translationManager.emptyString
color: root.sortBy === "blockheight" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -295,7 +295,7 @@ Rectangle {
id: sortDateText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Date")
+ text: qsTr("Date") + translationManager.emptyString
color: root.sortBy === "timestamp" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -351,7 +351,7 @@ Rectangle {
id: sortAmountText
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Amount")
+ text: qsTr("Amount") + translationManager.emptyString
color: root.sortBy === "amount" ? MoneroComponents.Style.defaultFontColor : MoneroComponents.Style.dimmedFontColor
anchors.verticalCenter: parent.verticalCenter
}
@@ -604,7 +604,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: isout ? qsTr("Sent") : qsTr("Received")
+ text: (isout ? qsTr("Sent") : qsTr("Received")) + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -652,7 +652,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: isout ? qsTr("Fee") : confirmationsRequired === 60 ? qsTr("Mined") : qsTr("Fee")
+ text: (isout ? qsTr("Fee") : confirmationsRequired === 60 ? qsTr("Mined") : qsTr("Fee")) + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -667,7 +667,7 @@ Rectangle {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
text: {
- if(!isout && confirmationsRequired === 60) return qsTr("Yes");
+ if(!isout && confirmationsRequired === 60) return qsTr("Yes") + translationManager.emptyString;
if(fee !== "") return fee + " XMR";
return "-";
}
@@ -711,7 +711,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Blockheight")
+ text: qsTr("Blockheight") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -725,7 +725,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 14 * scaleRatio
- text: blockheight > 0 ? blockheight : qsTr('Pending');
+ text: blockheight > 0 ? blockheight : qsTr('Pending') + translationManager.emptyString;
color: MoneroComponents.Style.defaultFontColor
anchors.verticalCenter: parent.verticalCenter
@@ -760,7 +760,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Confirmations")
+ text: qsTr("Confirmations") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -815,7 +815,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Date")
+ text: qsTr("Date") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -913,7 +913,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Description")
+ text: qsTr("Description") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -980,7 +980,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Transaction ID")
+ text: qsTr("Transaction ID") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -1022,7 +1022,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Transaction key")
+ text: qsTr("Transaction key") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -1070,7 +1070,7 @@ Rectangle {
Text {
font.family: MoneroComponents.Style.fontRegular.name
font.pixelSize: 15 * scaleRatio
- text: qsTr("Address sent to")
+ text: qsTr("Address sent to") + translationManager.emptyString
color: "#C0C0C0"
anchors.verticalCenter: parent.verticalCenter
}
@@ -1091,9 +1091,9 @@ Rectangle {
}
if(isout && blockheight === 0)
- return qsTr("Waiting for transaction to leave txpool.")
+ return qsTr("Waiting for transaction to leave txpool.") + translationManager.emptyString
else
- return qsTr("Unknown recipient");
+ return qsTr("Unknown recipient") + translationManager.emptyString;
}
color: MoneroComponents.Style.defaultFontColor
@@ -1489,9 +1489,9 @@ Rectangle {
function updateHistoryStatusMessage(){
if(root.txModelData.length <= 0){
- root.historyStatusMessage = qsTr("No transaction history yet.");
+ root.historyStatusMessage = qsTr("No transaction history yet.") + translationManager.emptyString;
} else if (root.txData.length <= 0){
- root.historyStatusMessage = qsTr("No results.");
+ root.historyStatusMessage = qsTr("No results.") + translationManager.emptyString;
} else {
root.historyStatusMessage = qsTr("%1 transactions total, showing %2.").arg(root.txData.length).arg(txListViewModel.count) + translationManager.emptyString;
}
@@ -1501,12 +1501,12 @@ Rectangle {
var tx_key = currentWallet.getTxKey(hash)
var tx_note = currentWallet.getUserNote(hash)
var rings = currentWallet.getRings(hash)
- var address_label = subaddrIndex == 0 ? qsTr("Primary address") : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex)
+ var address_label = subaddrIndex == 0 ? (qsTr("Primary address") + translationManager.emptyString) : currentWallet.getSubaddressLabel(subaddrAccount, subaddrIndex)
var address = currentWallet.address(subaddrAccount, subaddrIndex)
if (rings)
rings = rings.replace(/\|/g, '\n')
- informationPopup.title = qsTr("Transaction details");
+ informationPopup.title = qsTr("Transaction details") + translationManager.emptyString;
informationPopup.content = buildTxDetailsString(hash, paymentId, tx_key, tx_note, destinations, rings, address, address_label);
informationPopup.onCloseCallback = null
informationPopup.open();
@@ -1564,7 +1564,7 @@ Rectangle {
FileDialog {
id: writeCSVFileDialog
- title: qsTr("Please choose a folder")
+ title: qsTr("Please choose a folder") + translationManager.emptyString
selectFolder: true
onRejected: {
console.log("csv write canceled")
diff --git a/pages/Mining.qml b/pages/Mining.qml
index ca74ab1a..89710d9f 100644
--- a/pages/Mining.qml
+++ b/pages/Mining.qml
@@ -140,7 +140,7 @@ Rectangle {
enabled: startSoloMinerButton.enabled
onClicked: {
soloMinerThreadsLine.text = idealThreadCount
- appWindow.showStatusMessage(qsTr("Set to use all threads"),3)
+ appWindow.showStatusMessage(qsTr("Set to use all threads") + translationManager.emptyString,3)
}
}
}
@@ -197,9 +197,9 @@ Rectangle {
update()
} else {
errorPopup.title = qsTr("Error starting mining") + translationManager.emptyString;
- errorPopup.text = qsTr("Couldn't start mining.
")
+ errorPopup.text = qsTr("Couldn't start mining.
") + translationManager.emptyString
if (!walletManager.isDaemonLocal(appWindow.currentDaemonAddress))
- errorPopup.text += qsTr("Mining is only available on local daemons. Run a local daemon to be able to mine.
")
+ errorPopup.text += qsTr("Mining is only available on local daemons. Run a local daemon to be able to mine.
") + translationManager.emptyString
errorPopup.icon = StandardIcon.Critical
errorPopup.open()
}
diff --git a/pages/Receive.qml b/pages/Receive.qml
index 04f2cb1a..f0392a55 100644
--- a/pages/Receive.qml
+++ b/pages/Receive.qml
@@ -83,7 +83,7 @@ Rectangle {
MoneroComponents.LabelSubheader {
Layout.fillWidth: true
textFormat: Text.RichText
- text: qsTr("Addresses")
+ text: qsTr("Addresses") + translationManager.emptyString
}
ColumnLayout {
@@ -231,7 +231,7 @@ Rectangle {
text: qsTr("Create new address") + translationManager.emptyString;
onClicked: {
inputDialog.labelText = qsTr("Set the label of the new address:") + translationManager.emptyString
- inputDialog.inputText = qsTr("(Untitled)")
+ inputDialog.inputText = qsTr("(Untitled)") + translationManager.emptyString
inputDialog.onAcceptedCallback = function() {
appWindow.currentWallet.subaddress.addRow(appWindow.currentWallet.currentSubaddressAccount, inputDialog.inputText)
current_subaddress_table_index = appWindow.currentWallet.numSubaddresses(appWindow.currentWallet.currentSubaddressAccount) - 1
@@ -284,7 +284,7 @@ Rectangle {
rightIcon: "../images/external-link-white.png"
onClicked: {
clipboard.setText(TxUtils.makeQRCodeString(appWindow.current_address));
- appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3);
+ appWindow.showStatusMessage(qsTr("Copied to clipboard") + translationManager.emptyString, 3);
}
}
}
@@ -297,7 +297,7 @@ Rectangle {
FileDialog {
id: qrFileDialog
- title: qsTr("Please choose a name")
+ title: qsTr("Please choose a name") + translationManager.emptyString
folder: shortcuts.pictures
selectExisting: false
nameFilters: ["Image (*.png)"]
diff --git a/pages/SharedRingDB.qml b/pages/SharedRingDB.qml
index 6dc17e0e..d4d5f687 100644
--- a/pages/SharedRingDB.qml
+++ b/pages/SharedRingDB.qml
@@ -128,7 +128,7 @@ Rectangle {
"and you can import this list here.
" +
"Alternatively, you can scan the blockchain (and the blockchain of key-reusing Monero clones) yourself " +
"using the monero-blockchain-mark-spent-outputs tool to create a list of known spent outputs.
"
- )
+ ) + translationManager.emptyString
sharedRingDBDialog.icon = StandardIcon.Information
sharedRingDBDialog.open()
}
@@ -266,7 +266,7 @@ Rectangle {
"which allows you to then spend your Monero safely.
" +
"If you do not use a key-reusing Monero clone without these safety features, then you do not need to do anything " +
"as it is all automated.
"
- )
+ ) + translationManager.emptyString
sharedRingDBDialog.icon = StandardIcon.Information
sharedRingDBDialog.open()
}
@@ -324,7 +324,7 @@ Rectangle {
onClicked: {
var ring = appWindow.currentWallet.getRing(keyImageLine.text)
if (ring === "") {
- getRingLine.text = qsTr("No ring found");
+ getRingLine.text = qsTr("No ring found") + translationManager.emptyString;
}
else {
getRingLine.text = ring;
diff --git a/pages/merchant/Merchant.qml.autosave b/pages/merchant/Merchant.qml.autosave
new file mode 100644
index 00000000..d364fdb5
--- /dev/null
+++ b/pages/merchant/Merchant.qml.autosave
@@ -0,0 +1,700 @@
+import QtQuick 2.7
+import QtQuick.Layouts 1.1
+import QtQuick.Controls 2.0
+import QtGraphicalEffects 1.0
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Dialogs 1.2
+
+import moneroComponents.Clipboard 1.0
+import moneroComponents.Wallet 1.0
+import moneroComponents.WalletManager 1.0
+import moneroComponents.TransactionHistory 1.0
+import moneroComponents.TransactionHistoryModel 1.0
+import moneroComponents.Subaddress 1.0
+import moneroComponents.SubaddressModel 1.0
+
+import "../../js/Windows.js" as Windows
+import "../../js/TxUtils.js" as TxUtils
+import "../../js/Utils.js" as Utils
+import "../../components" as MoneroComponents
+import "../../pages"
+import "."
+
+Item {
+ id: root
+ anchors.margins: 0
+
+ property int minWidth: 900 * scaleRatio
+ property int qrCodeSize: 220 * scaleRatio
+ property bool enableTracking: false
+ property string trackingError: "" // setting this will show a message @ tracking table
+ property alias merchantHeight: mainLayout.height
+ property string addressLabel: ""
+ property var hiddenAmounts: []
+
+ function onPageCompleted() {
+ appWindow.titlebarToggleOrange();
+ appWindow.hideMenu();
+
+ // prepare tracking
+ trackingCheckbox.checked = root.enableTracking
+ root.update();
+ timer.running = true;
+
+ // set currently selected account indication
+ var _addressLabel = appWindow.currentWallet.getSubaddressLabel(
+ appWindow.currentWallet.currentSubaddressAccount,
+ appWindow.current_subaddress_table_index);
+ if(_addressLabel === ""){
+ root.addressLabel = "#" + appWindow.current_subaddress_table_index;
+ } else {
+ root.addressLabel = _addressLabel;
+ }
+ }
+
+ function onPageClosed() {
+ appWindow.titlebarToggleOrange();
+
+ // reset component objects
+ timer.running = false
+ root.enableTracking = false
+ trackingModel.clear()
+
+ appWindow.showMenu();
+ }
+
+ Image {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 300 * scaleRatio
+ source: "../../images/merchant/bg.png"
+ smooth: false
+ }
+
+ ColumnLayout {
+ id: mainLayout
+ visible: parent.width >= root.minWidth
+ spacing: 0
+
+ // emulates max-width + center for container
+ property int maxWidth: 1200 * scaleRatio
+ property int defaultMargin: 50 * scaleRatio
+ property int horizontalMargin: {
+ if(appWindow.width >= maxWidth){
+ return ((appWindow.width - maxWidth) / 2) + defaultMargin;
+ } else {
+ return defaultMargin;
+ }
+ }
+
+ anchors.leftMargin: horizontalMargin
+ anchors.rightMargin: horizontalMargin
+ anchors.margins: defaultMargin
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.right: parent.right
+
+ Item {
+ height: 220 * scaleRatio
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ Rectangle {
+ id: tracker
+ anchors.left: parent.left
+ anchors.top: parent.top
+ height: 220 * scaleRatio
+ width: (parent.width - qrImg.width) - 50 * scaleRatio
+ radius: 5
+
+ ColumnLayout {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ spacing: 0
+
+ RowLayout {
+ spacing: 0
+ height: 56 * scaleRatio
+
+ RowLayout {
+ Layout.alignment: Qt.AlignLeft
+ Layout.preferredWidth: 260 * scaleRatio
+ Layout.preferredHeight: parent.height
+ Layout.fillHeight: true
+ spacing: 8 * scaleRatio
+
+ Item {
+ Layout.preferredWidth: 10 * scaleRatio
+ }
+
+ Text {
+ font.pixelSize: 16 * scaleRatio
+ font.bold: true
+ color: "#767676"
+ text: qsTr("Sales") + translationManager.emptyString
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1 * scaleRatio
+ color: "#d9d9d9"
+ }
+
+ MerchantTrackingList {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 400 * scaleRatio
+ model: trackingModel
+ message: {
+ if(!root.enableTracking){
+ return qsTr(
+ "" +
+ "
This page will automatically scan the blockchain and the tx pool " + + "for incoming transactions using the QR code.
" + + "It's up to you whether to accept unconfirmed transactions or not. It is likely they'll be " + + "confirmed in short order, but there is still a possibility they might not, so for larger " + + "values you may want to wait for one or more confirmation(s).
" + ); + } else if(root.trackingError !== ""){ + return root.trackingError; + } else if(trackingModel.count < 1){ + return qsTr("Currently monitoring incoming transactions, none found yet."); + } else { + return "" + } + } + onHideAmountToggled: { + if(root.hiddenAmounts.indexOf(txid) < 0){ + root.hiddenAmounts.push(txid); + } else { + root.hiddenAmounts = root.hiddenAmounts.filter(function(_txid) { return _txid !== txid }); + } + } + } + } + } + + DropShadow { + anchors.fill: source + cached: true + horizontalOffset: 3 + verticalOffset: 3 + radius: 8.0 + samples: 16 + color: "#20000000" + smooth: true + source: tracker + } + + Rectangle { + id: qrImg + color: "white" + + anchors.right: parent.right + anchors.top: parent.top + + height: root.qrCodeSize + width: root.qrCodeSize + + Layout.maximumWidth: root.qrCodeSize + Layout.preferredHeight: width + radius: 5 + + Image { + id: qrCode + anchors.fill: parent + anchors.margins: 1 * scaleRatio + + smooth: false + fillMode: Image.PreserveAspectFit + source: "image://qrcode/" + TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text) + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: { + if (mouse.button == Qt.RightButton){ + qrMenu.x = this.mouseX; + qrMenu.y = this.mouseY; + qrMenu.open() + } + } + onPressAndHold: qrFileDialog.open() + } + } + + Menu { + id: qrMenu + title: "QrCode" + + MenuItem { + text: qsTr("Save As") + translationManager.emptyString; + onTriggered: qrFileDialog.open() + } + } + } + + DropShadow { + anchors.fill: source + cached: true + horizontalOffset: 3 + verticalOffset: 3 + radius: 8.0 + samples: 16 + color: "#30000000" + smooth: true + source: qrImg + } + } + + Item { + Layout.preferredHeight: 40 * scaleRatio + anchors.left: parent.left + anchors.right: parent.right + + Item { + width: (parent.width - qrImg.width) - (50 * scaleRatio) + height: 32 * scaleRatio + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 12 * scaleRatio + font.bold: false + color: "white" + text: "Currently selected address: " + addressLabel + " (Change)" + textFormat: Text.RichText + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: appWindow.showPageRequest("Receive") + } + } + } + + Item { + anchors.right: parent.right + anchors.top: parent.top + width: 220 * scaleRatio + height: 32 * scaleRatio + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 12 * scaleRatio + font.bold: false + color: "white" + text: qsTr("(right-click, save as)") + translationManager.emptyString + } + } + } + + Item { + Layout.preferredHeight: 120 * scaleRatio + Layout.topMargin: 20 * scaleRatio + Layout.fillWidth: true + + Rectangle { + id: payment_url_container + anchors.left: parent.left + anchors.top: parent.top + implicitHeight: 120 * scaleRatio + width: (parent.width - qrImg.width) - (50 * scaleRatio) + radius: 5 + + ColumnLayout { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + spacing: 0 + + RowLayout { + spacing: 0 + height: 56 * scaleRatio + + RowLayout { + Layout.alignment: Qt.AlignLeft + Layout.preferredWidth: 260 * scaleRatio + Layout.preferredHeight: parent.height + Layout.fillHeight: true + spacing: 8 + + Item { + Layout.preferredWidth: 10 * scaleRatio + } + + Text { + font.pixelSize: 14 * scaleRatio + font.bold: true + color: "#767676" + text: qsTr("Payment URL") + translationManager.emptyString + } + + Item { + Layout.fillWidth: true + } + } + + // @TODO: PaymentURL explanation +// Rectangle { +// // help box +// Layout.alignment: Qt.AlignLeft +// Layout.preferredWidth: 40 * scaleRatio +// Layout.fillHeight: true +// color: "transparent" + +// Text { +// anchors.verticalCenter: parent.verticalCenter +// anchors.right: parent.right +// anchors.rightMargin: 20 * scaleRatio +// font.pixelSize: 16 * scaleRatio +// font.bold: true +// color: "#767676" +// text:"?" +// } + +// MouseArea { +// anchors.fill: parent +// cursorShape: Qt.PointingHandCursor +// onClicked: { +// merchantPageDialog.title = qsTr("Payment URL") + translationManager.emptyString; +// merchantPageDialog.text = qsTr("payment url explanation") +// merchantPageDialog.icon = StandardIcon.Information +// merchantPageDialog.open() +// } +// } +// } + + Item { + Layout.fillWidth: true + } + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 1 + + color: "#d9d9d9" + } + + Text { + property string _color: "#767676" + Layout.fillWidth: true + Layout.margins: 20 * scaleRatio + Layout.topMargin: 10 * scaleRatio + + wrapMode: Text.WrapAnywhere + elide: Text.ElideRight + + font.pixelSize: 12 * scaleRatio + font.bold: true + color: _color + text: TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text) + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onEntered: { + parent.color = MoneroComponents.Style.orange + } + onExited: { + parent.color = parent._color + } + onClicked: { + console.log("Copied to clipboard"); + clipboard.setText(parent.text); + appWindow.showStatusMessage(qsTr("Copied to clipboard"), 3); + } + } + } + } + } + + DropShadow { + anchors.fill: source + cached: true + horizontalOffset: 3 + verticalOffset: 3 + radius: 8.0 + samples: 16 + color: "#20000000" + smooth: true + source: payment_url_container + } + + Item { + anchors.right: parent.right + anchors.top: parent.top + width: 220 * scaleRatio + height: 32 * scaleRatio + + ColumnLayout { + anchors.left: parent.left + anchors.right: parent.right + + Text { + font.pixelSize: 14 * scaleRatio + font.bold: false + color: "white" + text: qsTr("Amount to receive") + " (XMR)" + } + + Image { + height: 28 * scaleRatio + width: 220 * scaleRatio + source: "../../images/merchant/input_box.png" + + TextField { + id: amountToReceive + topPadding: 0 + leftPadding: 10 * scaleRatio + + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + anchors.topMargin: 3 * scaleRatio + font.pixelSize: 16 * scaleRatio + font.bold: true + horizontalAlignment: TextInput.AlignLeft + verticalAlignment: TextInput.AlignVCenter + selectByMouse: true + color: "#424242" + selectionColor: "#3f3fe3" + selectedTextColor: "white" + placeholderText: "0.00" + + background: Rectangle { + color: "transparent" + } + onTextChanged: { + if (amountToReceive.text.indexOf('.') === 0) { + amountToReceive.text = '0' + amountToReceive.text; + } + } + validator: RegExpValidator { + regExp: /^(\d{1,8})?([\.]\d{1,12})?$/ + } + } + } + + Item { + height: 2 * scaleRatio + width: 220 * scaleRatio + } + + Text { + // @TODO: When we have XMR/USD rate avi. in the future. + visible: false + font.pixelSize: 14 * scaleRatio + font.bold: false + color: "white" + text: qsTr("Amount to receive") + " (USD)" + opacity: 0.2 + } + + Image { + visible: false + height: 28 * scaleRatio + width: 220 * scaleRatio + source: "../../images/merchant/input_box.png" + opacity: 0.2 + } + } + } + } + + Item { + Layout.topMargin: 32 * scaleRatio + Layout.preferredHeight: 40 * scaleRatio + anchors.left: parent.left + anchors.right: parent.right + + ColumnLayout { + spacing: 16 * scaleRatio + + MerchantCheckbox { + id: trackingCheckbox + checked: root.enableTracking + text: qsTr("Enable sales tracker") + translationManager.emptyString + + onChanged: { + root.enableTracking = this.checked; + } + } + + Text { + id: content + font.pixelSize: 14 * scaleRatio + font.bold: false + color: "white" + text: qsTr("Leave this page") + translationManager.emptyString + + MouseArea { + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: appWindow.showPageRequest("Receive") + } + } + } + } + } + + Rectangle { + // Shows when the window is too small + visible: parent.width < root.minWidth + anchors.top: parent.top + anchors.topMargin: 100 * scaleRatio; + anchors.horizontalCenter: parent.horizontalCenter + height: 120 * scaleRatio + width: 400 * scaleRatio + radius: 5 + + Text { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: 14 * scaleRatio + font.bold: true + color: MoneroComponents.Style.moneroGrey + text: qsTr("The merchant page requires a larger window") + translationManager.emptyString + } + } + + function update() { + const max_tracking = 3; + + if (!appWindow.currentWallet || !root.enableTracking) { + root.trackingError = ""; + trackingModel.clear(); + return + } + + if (appWindow.currentWallet.connected() == Wallet.ConnectionStatus_Disconnected) { + root.trackingError = qsTr("WARNING: no connection to daemon"); + trackingModel.clear(); + return + } + + var model = appWindow.currentWallet.historyModel + var count = model.rowCount() + var totalAmount = 0 + var nTransactions = 0 + var blockchainHeight = null + var txs = [] + + // Currently selected subaddress as per Receive page + var current_subaddress_table_index = appWindow.current_subaddress_table_index; + + for (var i = 0; i < count && txs.length < max_tracking; ++i) { + var idx = model.index(i, 0) + var isout = model.data(idx, TransactionHistoryModel.TransactionIsOutRole); + var timeDate = model.data(idx, TransactionHistoryModel.TransactionDateRole); + var timeHour = model.data(idx, TransactionHistoryModel.TransactionTimeRole); + var timeEpoch = new Date(timeDate + "T" + timeHour) .getTime() / 1000; + var subaddrAccount = model.data(idx, TransactionHistoryModel.TransactionSubaddrAccountRole); + var subaddrIndex = model.data(idx, TransactionHistoryModel.TransactionSubaddrIndexRole); + + if (!isout && subaddrAccount == appWindow.currentWallet.currentSubaddressAccount && subaddrIndex == current_subaddress_table_index) { + var amount = model.data(idx, TransactionHistoryModel.TransactionAtomicAmountRole); + totalAmount = walletManager.addi(totalAmount, amount) + nTransactions += 1 + + var txid = model.data(idx, TransactionHistoryModel.TransactionHashRole); + var blockHeight = model.data(idx, TransactionHistoryModel.TransactionBlockHeightRole); + + var in_txpool = false; + var confirmations = 0; + var displayAmount = 0; + + if (blockHeight == 0) { + in_txpool = true; + } else { + if (blockchainHeight == null) + blockchainHeight = appWindow.currentWallet.blockChainHeight() + confirmations = blockchainHeight - blockHeight - 1 + displayAmount = model.data(idx, TransactionHistoryModel.TransactionDisplayAmountRole); + } + + txs.push({ + "amount": displayAmount, + "confirmations": confirmations, + "blockheight": blockHeight, + "in_txpool": in_txpool, + "txid": txid, + "time_epoch": timeEpoch, + "time_date": timeDate + " " + timeHour, + "hide_amount": root.hiddenAmounts.indexOf(txid) >= 0 + }) + } + } + + // Update tracking status label + if (nTransactions == 0) { + root.trackingError = qsTr("Currently monitoring incoming transactions, none found yet.") + translationManager.emptyString + return + } + + trackingModel.clear(); + txs.forEach(function(tx){ + trackingModel.append({ + "amount": tx.amount, + "blockheight": tx.blockheight, + "confirmations": tx.confirmations, + "blockheight": tx.blockHeight, + "in_txpool": tx.in_txpool, + "txid": tx.txid, + "time_epoch": tx.time_epoch, + "time_date": tx.time_date, + "hide_amount": tx.hide_amount + }); + }); + } + + ListModel { + id: trackingModel + } + + Timer { + id: timer + interval: 3000; running: false; repeat: true + onTriggered: update() + } + + MessageDialog { + id: merchantPageDialog + standardButtons: StandardButton.Ok + } + + FileDialog { + id: qrFileDialog + title: "Please choose a name" + folder: shortcuts.pictures + selectExisting: false + nameFilters: ["Image (*.png)"] + onAccepted: { + if(!walletManager.saveQrCode(TxUtils.makeQRCodeString(appWindow.current_address, amountToReceive.text), walletManager.urlToLocalPath(fileUrl))) { + console.log("Failed to save QrCode to file " + walletManager.urlToLocalPath(fileUrl) ) + receivePageDialog.title = qsTr("Save QrCode") + translationManager.emptyString; + receivePageDialog.text = qsTr("Failed to save QrCode to ") + walletManager.urlToLocalPath(fileUrl) + translationManager.emptyString; + receivePageDialog.icon = StandardIcon.Error + receivePageDialog.open() + } + } + } + + Clipboard { id: clipboard } +} diff --git a/pages/merchant/MerchantTrackingList.qml b/pages/merchant/MerchantTrackingList.qml index 33a756fc..a96b8be8 100644 --- a/pages/merchant/MerchantTrackingList.qml +++ b/pages/merchant/MerchantTrackingList.qml @@ -100,7 +100,7 @@ ListView { font.pixelSize: 12 * scaleRatio font.bold: false color: "#707070" - text: hide_amount ? "(" + qsTr("show") + ")" : "(" + qsTr("hide") + ")" + text: (hide_amount ? "(" + qsTr("show") + ")" : "(" + qsTr("hide") + ")") + translationManager.emptyString } MouseArea { diff --git a/pages/settings/SettingsWallet.qml b/pages/settings/SettingsWallet.qml index b362088f..cd1b17cc 100644 --- a/pages/settings/SettingsWallet.qml +++ b/pages/settings/SettingsWallet.qml @@ -403,7 +403,7 @@ Rectangle { newPasswordDialog.open() } else { informationPopup.title = qsTr("Error") + translationManager.emptyString; - informationPopup.text = qsTr("Wrong password"); + informationPopup.text = qsTr("Wrong password") + translationManager.emptyString; informationPopup.open() informationPopup.onCloseCallback = function() { passwordDialog.open() diff --git a/wizard/WizardAskPassword.qml b/wizard/WizardAskPassword.qml index fb75bcf2..7455baf4 100644 --- a/wizard/WizardAskPassword.qml +++ b/wizard/WizardAskPassword.qml @@ -152,7 +152,7 @@ ColumnLayout { Layout.fillWidth: true Label { - text: qsTr("Password") + text: qsTr("Password") + translationManager.emptyString Layout.fillWidth: true font.pixelSize: 14 * scaleRatio diff --git a/wizard/WizardCreateWallet4.qml b/wizard/WizardCreateWallet4.qml index 7c057936..15269703 100644 --- a/wizard/WizardCreateWallet4.qml +++ b/wizard/WizardCreateWallet4.qml @@ -63,7 +63,7 @@ Rectangle { WizardNav { Layout.topMargin: 24 * scaleRatio - btnNextText: qsTr("Open wallet") + btnNextText: qsTr("Open wallet") + translationManager.emptyString progressSteps: 4 progress: 4 diff --git a/wizard/WizardOpenWallet1.qml b/wizard/WizardOpenWallet1.qml index 8e3f7f52..d0b8d092 100644 --- a/wizard/WizardOpenWallet1.qml +++ b/wizard/WizardOpenWallet1.qml @@ -78,7 +78,7 @@ Rectangle { Layout.topMargin: 20 * scaleRatio id: btnNext small: true - text: qsTr("Browse filesystem") + text: qsTr("Browse filesystem") + translationManager.emptyString onClicked: { wizardController.openWallet();