diff --git a/src/ui/AddressBook.qml b/src/ui/AddressBook.qml deleted file mode 100644 index 5354450b..00000000 --- a/src/ui/AddressBook.qml +++ /dev/null @@ -1,300 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -// import "qrc:/ui/src/ui/Dialogs" -import "Delegates/" // For quick UI development, switch back to resources when making a release -import "Dialogs/" // For quick UI development, switch back to resources when making a release - -Page { - id: addressBook - - enum SecurityType { LowSecurity, MediumSecurity, StrongSecurity } - - signal canceled() - -// property int currentContact: -1 - property int secType - property string password - - Component.onCompleted: { - if (abm.hasInit()) { - if (abm.getSecType() !== AddressBook.SecurityType.StrongSecurity) { - abm.loadContacts() - } else { - getpass.open() - } - } else { - dialogCreateAddrsBk.open() - } - } - - ScrollView { - anchors.fill: parent - clip: true - - ListView { - id: addrsBook - - model: abm - delegate: ContactDelegate { - id: contactDelegate - width: parent.width - - onClicked: { - dialogShowContact.name = name - dialogShowContact.addressModel = address - dialogShowContact.open() - } - - onEditRequested: { - contactDialog.isEdit = true - contactDialog.name = name - contactDialog.index = index - contactDialog.cId = id - contactDialog.addressModel = address - contactDialog.open() - } - - onDeleteRequested: { - dialogConfirmation.index = index - dialogConfirmation.cId = id - dialogConfirmation.name = name - dialogConfirmation.open() - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - - onClicked: { - menu.index = index - menu.cId = id - menu.name = name - menu.address = address - menu.popup() - } - } - } - - section.property: "name" - section.criteria: ViewSection.FirstCharacter - section.delegate: SectionDelegate { - width: addrsBook.width - } - } - } // ScrollView - - RoundButton { - anchors.margins: 10 - anchors.right: parent.right - anchors.bottom: parent.bottom - icon.source: "qrc:/images/resources/images/icons/add.svg" - highlighted: true - onClicked: { - contactDialog.isEdit = false - contactDialog.open() - } - } //RoundButton - - AddrsBookModel { - id: abm - } - - Menu { - id: menu - - property int index: -1 - property int cId: -1 - property string name - property AddrsBkAddressModel address - - MenuItem { - text: qsTr("&View") - icon.source: "qrc:/images/resources/images/icons/visibleOn.svg" - onTriggered: { - dialogShowContact.name = menu.name - dialogShowContact.addressModel = menu.address - dialogShowContact.open() - } - } - - MenuSeparator {} - - MenuItem { - text: qsTr("&Edit") - icon.source: "qrc:/images/resources/images/icons/edit.svg" - onTriggered: { - contactDialog.isEdit = true - contactDialog.open() - } - } - - MenuSeparator {} - - MenuItem { - text: qsTr("&Remove") - icon.source: "qrc:/images/resources/images/icons/delete.svg" - icon.color: Material.accent - Material.accent: Material.Red - - onTriggered: { - dialogConfirmation.index = menu.index - dialogConfirmation.cId = menu.cId - dialogConfirmation.name = menu.name - dialogConfirmation.open() - } - } - } // Menu - - DialogAddContact { - id: contactDialog - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 540 ? 540 : applicationWindow.width - height: applicationWindow.height > 640 ? 640 : applicationWindow.height - - focus: visible - modal: true - - onAccepted: { - for (var i = 0; i < listModelAddresses.count; i++) { - abm.addAddress(listModelAddresses.get(i).value, listModelAddresses.get(i).coinType) - } - if (isEdit) { - abm.editContact(index, cId, name) - } else { - abm.newContact(name) - } - } - } - - DialogSelectSecType { - id: dialogCreateAddrsBk - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 480 ? 480 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 400 ? 400 - 40 : applicationWindow.height - 40 - - title: qsTr("Initial setup") - focus: visible - modal: true - - onAccepted: { - secType = select - if (secType === AddressBook.SecurityType.StrongSecurity) { - setpass.open() - } else { - abm.initAddrsBook(secType, "") - } - } - - onRejected: { - canceled() - } - } - - DialogSetPassword { - id: setpass - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > implicitHeight + 40 ? implicitHeight : applicationWindow.height - 40 - - focus: visible - modal: true - - onAccepted: { - abm.initAddrsBook(AddressBook.SecurityType.StrongSecurity, setpass.password) - } - - onRejected: { - canceled() - } - } - - DialogGetPassword { - id: getpass - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > implicitHeight + 40 ? implicitHeight : applicationWindow.height - 40 - - modal: true - focus: visible - - onAccepted: { - if (!abm.authenticate(getpass.password)) { - getpass.open() - } else { - abm.loadContacts() - } - } - - onRejected:{ - canceled() - } - } - - DialogShowContact { - id: dialogShowContact - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 440 ? 440 - 40 : applicationWindow.height - 40 - - modal: true - focus: visible - } - - Dialog { - id: dialogConfirmation - - property int index: -1 - property int cId: -1 - property string name - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 300 ? 300 - 40 : applicationWindow.width - 40 - - standardButtons: Dialog.Ok | Dialog.Cancel - title: qsTr("Confirm action") - modal: true - focus: visible - - RowLayout { - width: parent.width - spacing: 30 - - Image { - id: icon - source: "qrc:/images/resources/images/icons/trash.svg" - sourceSize: "64x64" - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - } - - Label { - id: labelQuestion - - Layout.fillWidth: true - text: qsTr("Delete contact %1?").arg(dialogConfirmation.name) - wrapMode: Text.Wrap - font.italic: true - } - } - - Component.onCompleted: { - standardButton(Dialog.Ok).Material.accent = Material.Red - standardButton(Dialog.Ok).highlighted = true - standardButton(Dialog.Ok).text = qsTr("Delete") - } - - onAccepted: { - abm.removeContact(dialogConfirmation.index, dialogConfirmation.cId) - } - } // Dialog -} diff --git a/src/ui/Blockchain.qml b/src/ui/Blockchain.qml deleted file mode 100644 index 76cad7ae..00000000 --- a/src/ui/Blockchain.qml +++ /dev/null @@ -1,202 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import BlockchainModels 1.0 - -Page { - id: blockchain - - property BlockchainStatusModel model: null - - property string numberOfBlocks: model.numberOfBlocks - property date timestampLastBlock: model.timestampLastBlock - property string hashLastBlock: model.hashLastBlock - - property string currentSkySupply: model.currentSkySupply - property string totalSkySupply: model.totalSkySupply - property string currentCoinHoursSupply: model.currentCoinHoursSupply - property string totalCoinHoursSupply: model.totalCoinHoursSupply - - ColumnLayout { - id: columnLayoutRoot - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.margins: 20 - spacing: 20 - - GroupBox { - id: groupBoxBlockDetails - title: qsTr("Block details") - clip: true - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - - ColumnLayout { - id: columnLayoutBlockDetails - anchors.fill: parent - spacing: 20 - - ColumnLayout { - Label { - text: qsTr("Number of blocks") - font.bold: true - } - Label { - id: labelNumberOfBlocks - text: numberOfBlocks - } - } - - RowLayout { - spacing: 20 - - ColumnLayout { - Label { - text: qsTr("Timestamp of last block") - font.bold: true - } - Label { - id: labelTimestampLastBlock - text: Qt.formatDateTime(timestampLastBlock, Qt.DefaultLocaleShortDate) - } - } - - ColumnLayout { - Layout.fillWidth: true - Label { - text: qsTr("Hash of last block") - font.bold: true - - ToolButton { - id: toolButtonCopy - anchors.left: parent.right - anchors.verticalCenter: parent.verticalCenter - icon.source: "qrc:/images/resources/images/icons/copy.svg" - visible: textInputHashLastBlock.text - ToolTip.text: qsTr("Copy to clipboard") - ToolTip.visible: hovered // TODO: pressed when mobile? - ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - - Image { - id: imageCopied - anchors.centerIn: parent - source: "qrc:/images/resources/images/icons/check-simple.svg" - fillMode: Image.PreserveAspectFit - sourceSize: Qt.size(toolButtonCopy.icon.width*1.5, toolButtonCopy.icon.height*1.5) - z: 1 - - opacity: 0.0 - } - - onClicked: { - if (textInputHashLastBlock.text) { - textInputHashLastBlock.selectAll() - textInputHashLastBlock.copy() - textInputHashLastBlock.deselect() - if (copyAnimation.running) { - copyAnimation.restart() - } else { - copyAnimation.start() - } - } - } - - SequentialAnimation { - id: copyAnimation - NumberAnimation { target: imageCopied; property: "opacity"; to: 1.0; easing.type: Easing.OutCubic } - PauseAnimation { duration: 1000 } - NumberAnimation { target: imageCopied; property: "opacity"; to: 0.0; easing.type: Easing.OutCubic } - } - } // ToolButton - } // Label - TextInput { - id: textInputHashLastBlock - Layout.fillWidth: true - text: hashLastBlock - readOnly: true - font.family: "Code New Roman" - wrapMode: Label.WrapAnywhere - } - } // ColumnLayout - } // RowLayout - } // ColumnLayout (block details) - } // GroupBox (block details) - - GroupBox { - id: groupBoxSkyDetails - title: qsTr("Sky details") - clip: true - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - - GridLayout { - rows: 2 - columns: 2 - - ColumnLayout { - Label { - text: qsTr("Current SKY supply") - font.bold: true - } - Label { - id: labelCurrentSkySupply - text: currentSkySupply - } - } - - ColumnLayout { - Label { - text: qsTr("Total SKY supply") - font.bold: true - } - Label { - id: labelTotalSkySupply - text: totalSkySupply - } - } - - ColumnLayout { - Label { - text: qsTr("Current Coin Hours supply") - font.bold: true - } - Label { - id: labelCurrentCoinHoursSupply - text: currentCoinHoursSupply - } - } - - ColumnLayout { - Label { - text: qsTr("Total Coin Hours supply") - font.bold: true - } - Label { - id: labelTotalCoinHoursSupply - text: totalCoinHoursSupply - } - } - } // GridLayout - } // GroupBox (sky details) - } // ColumnLayout (root) - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - // Create a `busy` property in the backend and bind it to `running` here: - running: model.loading - property Timer timer: Timer{ - id: blockchainTimer - repeat: true - running: true - interval: 3000 - onTriggered: { - model.update() - } - - } - } -} diff --git a/src/ui/BusyPopup.qml b/src/ui/BusyPopup.qml deleted file mode 100644 index 52482c9b..00000000 --- a/src/ui/BusyPopup.qml +++ /dev/null @@ -1,74 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Popup { - id: root - - property alias actionText: actionMsg.text - property alias text: msg.text - - focus: true - modal: true - closePolicy: Popup.NoAutoClose - - RowLayout { - anchors.fill: parent - spacing: 13 - - BusyIndicator { - id: busyIndicator - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - property color color: "#2196F3" - Material.accent: color - SequentialAnimation on color { - loops: Animation.Infinite - running: root.visible - ColorAnimation { from: "#2196F3"; to: "#00BCD4"; duration: 500 } - ColorAnimation { from: "#00BCD4"; to: "#009688"; duration: 500 } - ColorAnimation { from: "#009688"; to: "#4CAF50"; duration: 500 } - ColorAnimation { from: "#4CAF50"; to: "#8BC34A"; duration: 500 } - ColorAnimation { from: "#8BC34A"; to: "#CDDC39"; duration: 500 } - ColorAnimation { from: "#CDDC39"; to: "#FFC107"; duration: 500 } - ColorAnimation { from: "#FFC107"; to: "#FF9800"; duration: 500 } - ColorAnimation { from: "#FF9800"; to: "#FF5722"; duration: 500 } - ColorAnimation { from: "#FF5722"; to: "#F44336"; duration: 500 } - ColorAnimation { from: "#F44336"; to: "#E91E63"; duration: 500 } - ColorAnimation { from: "#E91E63"; to: "#9C27B0"; duration: 500 } - ColorAnimation { from: "#9C27B0"; to: "#673AB7"; duration: 500 } - ColorAnimation { from: "#673AB7"; to: "#3F51B5"; duration: 500 } - ColorAnimation { from: "#3F51B5"; to: "#2196F3"; duration: 500 } - } - } - - ColumnLayout { - - Label { - id: actionMsg - font.pointSize: 13 - font.italic: true - Layout.fillWidth: true - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - - // To avoid a binding loop - Component.onCompleted: { - if (text === "") { - text = qsTr("Loading...") - } - } - } - - Label { - id: msg - visible: text !== "" - font.italic: true - Layout.fillWidth: true - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - wrapMode: Text.WordWrap - } - - } - } - -} diff --git a/src/ui/ControlCustomSwitch.qml b/src/ui/ControlCustomSwitch.qml deleted file mode 100644 index 14a5b66f..00000000 --- a/src/ui/ControlCustomSwitch.qml +++ /dev/null @@ -1,83 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.impl 2.12 -import QtQuick.Controls.Material 2.12 - -// Colors are only implemented for Material Style -// TODO: Implement the same colors for the other styles - -Rectangle { - id: root - - readonly property real spacing: 10 - property color backgroundColor: Material.primary - property bool isInLeftSide: true - property string leftText: "Left Text" - property string rightText: "Right Text" - property int animationsSpeed: 150 - property color textColor: Material.foreground - property color hoveredColor: "#0A000000" - property color pressedColor: "#1A000000" - property real controlRadius: 40 - - signal toggled() - - color: backgroundColor - radius: controlRadius - - Button { - id: switchButton - clip: true - - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.leftMargin: root.isInLeftSide ? spacing : root.width/2 + spacing*2 - anchors.right: parent.right - anchors.rightMargin: root.isInLeftSide ? root.width/2 + spacing*2 : spacing - - Material.foreground: textColor - - Behavior on anchors.leftMargin { NumberAnimation { duration: animationsSpeed; easing.type: Easing.OutQuint } } - Behavior on anchors.rightMargin { NumberAnimation { duration: animationsSpeed; easing.type: Easing.OutQuint } } - - text: "" + (root.isInLeftSide ? root.leftText : root.rightText) + "" - - onClicked: { - root.isInLeftSide = !root.isInLeftSide - parent.toggled() - } - - contentItem: IconLabel { - spacing: switchButton.spacing - mirrored: switchButton.mirrored - display: switchButton.display - - icon: switchButton.icon - text: switchButton.text - font: switchButton.font - color: !switchButton.enabled ? switchButton.Material.hintTextColor : switchButton.Material.foreground - } - - background: Rectangle { - implicitWidth: 64 - implicitHeight: switchButton.Material.buttonHeight - - radius: root.controlRadius - color: !switchButton.enabled ? switchButton.Material.buttonDisabledColor : "white" - Behavior on color { ColorAnimation { duration: animationsSpeed } } - - layer.enabled: switchButton.enabled && switchButton.Material.buttonColor.a > 0 - - Rectangle { - id: rectangleColorEffect - anchors.fill: parent - radius: root.controlRadius - - color: switchButton.down ? pressedColor : switchButton.hovered ? hoveredColor : "transparent" - - Behavior on color { ColorAnimation { duration: animationsSpeed } } - } - } // Rectangle (button's background) - } // Button -} diff --git a/src/ui/ControlGenerateSeed.qml b/src/ui/ControlGenerateSeed.qml deleted file mode 100644 index 7a85937f..00000000 --- a/src/ui/ControlGenerateSeed.qml +++ /dev/null @@ -1,122 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "Controls" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - implicitWidth: 100 - implicitHeight: 60 - signal dataModified() - property Item nextTabItem - property alias textArea: textArea - property alias text: textArea.text - property alias placeholderText: textArea.placeholderText - property alias readOnly: textArea.readOnly - property alias buttonLeftText: buttonLeft.text - property alias buttonRightText: buttonRight.text - - property bool buttonsVisible: buttonRight.visible - - readonly property alias inputControlWidth: textArea.width - readonly property alias inputControlHeight: textArea.height - - function generateSeed( words){ - if (words == 12 ){ - textArea.text = walletManager.getNewSeed(128) - } else if (words == 24){ - textArea.text = walletManager.getNewSeed(256) - } - } - function clear() { - textArea.clear() - if (mode === CreateLoadWallet.Create){ - generateSeed(12) - } - - } - - Row { - id: rowButtons - anchors.bottom: textArea.top - anchors.bottomMargin: -10 - anchors.right: textArea.right - z: textArea.z + 1 - - ItemDelegate { - id: buttonLeft - onClicked: generateSeed(12) - - height: buttonRight.height - - text: "ButtonLeft" - font.pointSize: 8 - visible: buttonRight.visible - opacity: buttonRight.opacity - - contentItem: Label { - text: buttonLeft.text - font: buttonLeft.font - color: buttonLeft.enabled ? buttonLeft.Material.foreground : buttonLeft.Material.hintTextColor - } - } - - ItemDelegate { - id: buttonRight - onClicked: generateSeed(24) - - - height: 30 - opacity: buttonsVisible ? 1.0 : 0.0 - visible: opacity > 0.0 - - Behavior on opacity { NumberAnimation { easing.type: Easing.OutQuint } } - - text: "ButtonRight" - font.pointSize: 8 - - contentItem: Label { - text: buttonRight.text - font: buttonRight.font - color: buttonRight.enabled ? buttonRight.Material.foreground : buttonRight.Material.hintTextColor - } - } // ItemDelegate - } // Row - - /* - // Put the text area inside this to make it scrollable - // but we have a bug. - // Set the anchors of the left button relative to this ScrollView - ScrollView { - id: scrollerTextArea - anchors.left: parent.left - anchors.right: parent.right - - width: root.width - height: root.height - buttonRight.height - - contentWidth: width - contentHeight: height - - clip: true - } - */ - - TextArea { - id: textArea - anchors.left: parent.left - anchors.right: parent.right - height: 80 - wrapMode: TextArea.Wrap - clip: true - - selectByMouse: true - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.tab: nextTabItem - onTextChanged: dataModified() - } -} diff --git a/src/ui/Controls/+material/TextArea.qml b/src/ui/Controls/+material/TextArea.qml deleted file mode 100755 index 5f644960..00000000 --- a/src/ui/Controls/+material/TextArea.qml +++ /dev/null @@ -1,128 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Templates 2.12 as T -import QtQuick.Controls 2.12 -import QtQuick.Controls.impl 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Controls.Material.impl 2.12 - -T.TextArea { - id: control - - implicitWidth: Math.max(contentWidth + leftPadding + rightPadding, - implicitBackgroundWidth + leftInset + rightInset, - placeholder.implicitWidth + leftPadding + rightPadding) - implicitHeight: Math.max(contentHeight + topPadding + bottomPadding, - implicitBackgroundHeight + topInset + bottomInset, - placeholder.implicitHeight + 1 + topPadding + bottomPadding) - - topPadding: 16 - bottomPadding: 9 - - color: enabled ? Material.foreground : Material.hintTextColor - selectionColor: Material.accentColor - selectedTextColor: Material.primaryHighlightedTextColor - placeholderTextColor: Material.hintTextColor - cursorDelegate: CursorDelegate { } - - PlaceholderText { - id: placeholder - - property bool floatPlaceholderText: !(!control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)) - readonly property real placeholderTextScaleFactor: 0.9 - - x: (floatPlaceholderText ? 0 : control.leftPadding) - width * (1-scale)/2 - y: floatPlaceholderText ? -control.topPadding*(1.05 - placeholderTextScaleFactor) : control.topPadding - Behavior on y { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - scale: floatPlaceholderText ? placeholderTextScaleFactor : 1 - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - height: control.height - (control.topPadding + control.bottomPadding) - text: control.placeholderText - color: floatPlaceholderText && control.activeFocus ? control.Material.accentColor : control.placeholderTextColor - Behavior on color { ColorAnimation { duration: 250 } } - verticalAlignment: control.verticalAlignment - elide: Text.ElideRight - renderType: control.renderType - } - - background: Rectangle { - y: control.height - height - control.bottomPadding + 8 - implicitWidth: 120 - height: 1 - color: control.hovered ? control.Material.primaryTextColor : control.Material.hintTextColor - Behavior on color { ColorAnimation {} } - - Rectangle { - id: accentRect - - readonly property bool controlHasActiveFocus: control.activeFocus - - onControlHasActiveFocusChanged: { - if (controlHasActiveFocus) { - animationOnActiveFocus.start() - } else { - animationOnUnactiveFocus.start() - } - } - - y: parent.y - implicitWidth: 120 - width: control.activeFocus ? parent.width : 0 - height: 2 - anchors.centerIn: parent - color: control.Material.accentColor - - NumberAnimation { - id: animationOnActiveFocus - - target: accentRect - property: "width" - from: 0 - to: accentRect.parent.width - duration: 350 - easing.type: Easing.OutQuint - } - - NumberAnimation { - id: animationOnUnactiveFocus - - target: accentRect - property: "opacity" - from: 1.0 - to: 0.0 - duration: 350 - easing.type: Easing.OutQuint - - onFinished: { - target.width = 0 - target.opacity = 1.0 - } - } - } - } - - Menu { - id: contextMenu - - focus: false - - ItemDelegate { text: qsTr("Cut"); icon.source: "qrc:/images/resources/images/icons/cut-content.svg"; onClicked: { control.cut(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Copy"); icon.source: "qrc:/images/resources/images/icons/copy-content.svg"; onClicked: { control.copy(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Paste"); icon.source: "qrc:/images/resources/images/icons/paste-content.svg"; onClicked: { control.paste(); contextMenu.close() } enabled: control.canPaste } - MenuSeparator {} - ItemDelegate { text: qsTr("Select all"); icon.source: "qrc:/images/resources/images/icons/selectAll-content.svg"; onClicked: { control.selectAll(); contextMenu.close() } enabled: control.selectedText !== control.text } - MenuSeparator {} - ItemDelegate { text: qsTr("Undo"); icon.source: "qrc:/images/resources/images/icons/undo.svg"; onClicked: { control.undo(); contextMenu.close() } enabled: control.canUndo } - ItemDelegate { text: qsTr("Redo"); icon.source: "qrc:/images/resources/images/icons/redo.svg"; onClicked: { control.redo(); contextMenu.close() } enabled: control.canRedo } - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - cursorShape: Qt.IBeamCursor - - onClicked: { - control.focus = true - contextMenu.popup() - } - } -} diff --git a/src/ui/Controls/+material/TextField.qml b/src/ui/Controls/+material/TextField.qml deleted file mode 100755 index 158f9c50..00000000 --- a/src/ui/Controls/+material/TextField.qml +++ /dev/null @@ -1,129 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Templates 2.12 as T -import QtQuick.Controls 2.12 -import QtQuick.Controls.impl 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Controls.Material.impl 2.12 - -T.TextField { - id: control - - implicitWidth: implicitBackgroundWidth + leftInset + rightInset - || Math.max(contentWidth, placeholder.implicitWidth) + leftPadding + rightPadding - implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, - contentHeight + topPadding + bottomPadding, - placeholder.implicitHeight + topPadding + bottomPadding) - - topPadding: 16 - bottomPadding: 9 - - color: enabled ? Material.foreground : Material.hintTextColor - selectionColor: Material.accentColor - selectedTextColor: Material.primaryHighlightedTextColor - placeholderTextColor: Material.hintTextColor - verticalAlignment: TextInput.AlignVCenter - - cursorDelegate: CursorDelegate { } - - PlaceholderText { - id: placeholder - - property bool floatPlaceholderText: !(!control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)) - readonly property real placeholderTextScaleFactor: 0.9 - - x: (floatPlaceholderText ? 0 : control.leftPadding) - width * (1-scale)/2 - y: floatPlaceholderText ? -control.topPadding*(1 - placeholderTextScaleFactor) : control.topPadding - Behavior on y { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - scale: floatPlaceholderText ? placeholderTextScaleFactor : 1 - Behavior on scale { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - height: control.height - (control.topPadding + control.bottomPadding) - text: control.placeholderText - color: floatPlaceholderText && control.activeFocus ? control.Material.accentColor : control.placeholderTextColor - Behavior on color { ColorAnimation { duration: 250 } } - verticalAlignment: control.verticalAlignment - elide: Text.ElideRight - renderType: control.renderType - } - - background: Rectangle { - y: control.height - height - control.bottomPadding + 8 - implicitWidth: 120 - height: 1 - color: control.hovered ? control.Material.primaryTextColor : control.Material.hintTextColor - Behavior on color { ColorAnimation { duration: 200 } } - - Rectangle { - id: accentRect - - readonly property bool controlHasActiveFocus: control.activeFocus - - onControlHasActiveFocusChanged: { - if (controlHasActiveFocus) { - animationOnActiveFocus.start() - } else { - animationOnUnactiveFocus.start() - } - } - - y: parent.y - implicitWidth: 120 - // width: - Component.onCompleted: width = control.activeFocus ? parent.width : 0 - height: 2 - anchors.centerIn: parent - color: control.Material.accentColor - - NumberAnimation { - id: animationOnActiveFocus - - target: accentRect - property: "width" - to: accentRect.parent.width - duration: 350 - easing.type: Easing.OutQuint - } - - - NumberAnimation { - id: animationOnUnactiveFocus - - target: accentRect - property: "opacity" - to: 0.0 - duration: 350 - easing.type: Easing.OutQuint - - onFinished: { - target.width = 0 - target.opacity = 1.0 - } - } - } // Rectangle (accent) - } // Ractangle (decoration) - - Menu { - id: contextMenu - - focus: false - - ItemDelegate { text: qsTr("Cut"); icon.source: "qrc:/images/resources/images/icons/cut-content.svg"; onClicked: { control.cut(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Copy"); icon.source: "qrc:/images/resources/images/icons/copy-content.svg"; onClicked: { control.copy(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Paste"); icon.source: "qrc:/images/resources/images/icons/paste-content.svg"; onClicked: { control.paste(); contextMenu.close() } enabled: control.canPaste } - MenuSeparator {} - ItemDelegate { text: qsTr("Select all"); icon.source: "qrc:/images/resources/images/icons/selectAll-content.svg"; onClicked: { control.selectAll(); contextMenu.close() } enabled: control.selectedText !== control.text } - MenuSeparator {} - ItemDelegate { text: qsTr("Undo"); icon.source: "qrc:/images/resources/images/icons/undo.svg"; onClicked: { control.undo(); contextMenu.close() } enabled: control.canUndo } - ItemDelegate { text: qsTr("Redo"); icon.source: "qrc:/images/resources/images/icons/redo.svg"; onClicked: { control.redo(); contextMenu.close() } enabled: control.canRedo } - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - cursorShape: Qt.IBeamCursor - - onClicked: { - control.focus = true - contextMenu.popup() - } - } -} diff --git a/src/ui/Controls/TextArea.qml b/src/ui/Controls/TextArea.qml deleted file mode 100644 index 3caabe4c..00000000 --- a/src/ui/Controls/TextArea.qml +++ /dev/null @@ -1,32 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -TextArea { - id: control - - Menu { - id: contextMenu - - focus: false - - ItemDelegate { text: qsTr("Cut"); icon.source: "qrc:/images/resources/images/icons/cut-content.svg"; onClicked: { control.cut(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Copy"); icon.source: "qrc:/images/resources/images/icons/copy-content.svg"; onClicked: { control.copy(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Paste"); icon.source: "qrc:/images/resources/images/icons/paste-content.svg"; onClicked: { control.paste(); contextMenu.close() } enabled: control.canPaste } - MenuSeparator {} - ItemDelegate { text: qsTr("Select all"); icon.source: "qrc:/images/resources/images/icons/selectAll-content.svg"; onClicked: { control.selectAll(); contextMenu.close() } enabled: control.selectedText !== control.text } - MenuSeparator {} - ItemDelegate { text: qsTr("Undo"); icon.source: "qrc:/images/resources/images/icons/undo.svg"; onClicked: { control.undo(); contextMenu.close() } enabled: control.canUndo } - ItemDelegate { text: qsTr("Redo"); icon.source: "qrc:/images/resources/images/icons/redo.svg"; onClicked: { control.redo(); contextMenu.close() } enabled: control.canRedo } - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - cursorShape: Qt.IBeamCursor - - onClicked: { - control.focus = true - contextMenu.popup() - } - } -} diff --git a/src/ui/Controls/TextField.qml b/src/ui/Controls/TextField.qml deleted file mode 100644 index 4294ebfa..00000000 --- a/src/ui/Controls/TextField.qml +++ /dev/null @@ -1,32 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -TextField { - id: control - - Menu { - id: contextMenu - - focus: false - - ItemDelegate { text: qsTr("Cut"); onClicked: { control.cut(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Copy"); onClicked: { control.copy(); contextMenu.close() } enabled: control.selectedText && control.echoMode === TextInput.Normal } - ItemDelegate { text: qsTr("Paste"); onClicked: { control.paste(); contextMenu.close() } enabled: control.canPaste } - MenuSeparator {} - ItemDelegate { text: qsTr("Select all"); onClicked: { control.selectAll(); contextMenu.close() } enabled: control.selectedText !== control.text } - MenuSeparator {} - ItemDelegate { text: qsTr("Undo"); onClicked: { control.undo(); contextMenu.close() } enabled: control.canUndo } - ItemDelegate { text: qsTr("Redo"); onClicked: { control.redo(); contextMenu.close() } enabled: control.canRedo } - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.RightButton - cursorShape: Qt.IBeamCursor - - onClicked: { - control.focus = true - contextMenu.popup() - } - } -} diff --git a/src/ui/CreateLoadWallet.qml b/src/ui/CreateLoadWallet.qml deleted file mode 100644 index b4e621cd..00000000 --- a/src/ui/CreateLoadWallet.qml +++ /dev/null @@ -1,91 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "Controls" // For quick UI development, switch back to resources when making a release - -Item { - id: createLoadWallet - - enum Mode { Create, Load } - - property Item nextTabItem - property int mode: CreateLoadWallet.Create - property alias name: walletName.text - property alias seed: walletSeed.text - property alias seedConfirm: walletSeedConfirm.text - - signal dataModified() - signal walletCreationRequested() - - function clear() { - walletName.clear() - walletSeed.clear() - walletSeedConfirm.clear() - } - - - Component.onCompleted:{ - dataModified() - } - implicitHeight: walletName.height + walletSeed.height + (mode === CreateLoadWallet.Create ? walletSeedConfirm.height : 0) + 2*column.spacing - Behavior on implicitHeight { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - clip: true - - Column { - id: column - anchors.fill: parent - spacing: 30 - - TextField { - id: walletName - width: parent.width - - selectByMouse: true - placeholderText: qsTr("Wallet's name") - focus: true - - onTextChanged: { - dataModified() - } - } - - ControlGenerateSeed { - id: walletSeed - width: parent.width - height: inputControlHeight - 10 - - placeholderText: qsTr("Wallet's seed") - buttonLeftText: qsTr("12 words") - onDataModified: createLoadWallet.dataModified() - buttonRightText: qsTr("24 words") - buttonsVisible: mode === CreateLoadWallet.Create - nextTabItem: walletSeedConfirm - } - - TextArea { - id: walletSeedConfirm - width: parent.width - height: walletSeed.inputControlHeight - 10 - - clip: true - selectByMouse: true - wrapMode: TextArea.Wrap - placeholderText: qsTr("Confirm the wallet's seed") - opacity: mode === CreateLoadWallet.Create ? 1 : 0 - visible: opacity > 0 - - Behavior on opacity { NumberAnimation { duration: 100 } } - - KeyNavigation.priority: KeyNavigation.BeforeItem - KeyNavigation.tab: nextTabItem - - onTextChanged: { - dataModified() - } - } // TextArea - } // Column -} diff --git a/src/ui/CustomHeader.qml b/src/ui/CustomHeader.qml deleted file mode 100755 index b76060a9..00000000 --- a/src/ui/CustomHeader.qml +++ /dev/null @@ -1,21 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Label { - id: labelHeaderText - anchors.top: parent.top - anchors.topMargin: (customMenuBar.toolButtonBack.hide) ? -(menuBar.height + height) : -menuBar.height - anchors.left: parent.left - anchors.right: parent.right - height: menuBar.height - font.pointSize: Qt.application.font.pointSize * 1.6 - font.bold: true - color: applicationWindow.Material.background - opacity: customMenuBar.toolButtonBack.opacity - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - z: 10 - Behavior on anchors.topMargin { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } -} diff --git a/src/ui/CustomMenuBar.qml b/src/ui/CustomMenuBar.qml deleted file mode 100755 index e012f56f..00000000 --- a/src/ui/CustomMenuBar.qml +++ /dev/null @@ -1,245 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -RowLayout { - spacing: 0 - - property alias backButtonHide: toolButtonBack.hide - property alias toolButtonBack: toolButtonBack - property alias menuBarReal: menuBarReal - property alias menuBarColor: menuBarReal.color - - property alias enableOutputs: menuItemOutputs.enabled - property alias enablePendingTransactions: menuItemPendingTransactions.enabled - property alias enableBlockchain: menuItemBlockchain.enabled - property alias enableNetworking: menuItemNetworking.enabled - property alias enableSettings: menuItemSettings.enabled - property alias enableSettingsAddressBook: toolButtonSettingsAddressBook.enabled - property alias enableAddrsBook: menuItemAddressBook.enabled - - // Signals - signal outputsRequested() - signal pendingTransactionsRequested() - signal networkingRequested() - signal settingsRequested() - signal settingsAddressBookRequested() - signal blockchainRequested() - signal aboutRequested() - signal aboutQtRequested() - signal licenseRequested() - signal addressBookRequested() - - - // Functions - function back() { - if (!toolButtonBack.hide) { - toolButtonBack.clicked() - } - } - - ToolButton { - id: toolButtonBack - - property bool hide: generalStackView.depth === 1 || (generalStackView.depth >= 1 && generalStackView.busy) - - focusPolicy: Qt.NoFocus - - // opacity - opacity: hide ? 0 : 1 - Behavior on opacity { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - - // position - implicitHeight: menuBarReal.height - implicitWidth: implicitHeight - Layout.leftMargin: hide ? -(width + padding) : 0 - Behavior on Layout.leftMargin { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - z: 1 - - // icon - icon.source: "qrc:/images/resources/images/icons/back.svg" - icon.color: Material.background - - // PointingHandCursor - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.NoButton - cursorShape: Qt.PointingHandCursor - } - - onClicked: { - generalStackView.pop() - - enableOutputs = true - enablePendingTransactions = true - enableBlockchain = true - enableNetworking = true - enableSettings = true - enableAddrsBook = generalStackView.depth <= 1 - enableSettingsAddressBook = generalStackView.depth > 1 - if (generalStackView.depth > 1) { - customHeader.text = qsTr("Address book") - } - } - } - - MenuBar { - id: menuBarReal - - readonly property color iconColor: "transparent" - property color color: backButtonHide ? Material.dialogColor : Material.accent - property color menuTextColor: toolButtonBack.hide ? Material.primaryTextColor : Material.background - - Layout.fillWidth: true - topInset: -1 - leftInset: (backButtonHide ? 0 : -(toolButtonBack.width + toolButtonBack.padding)) - rightInset: (toolButtonTheme.visible ? -(toolButtonTheme.width + toolButtonTheme.padding) : 0) + - (toolButtonSettingsAddressBook.visible ? -(toolButtonBack.width + toolButtonBack.padding) : 0) - Material.foreground: menuTextColor - Behavior on menuTextColor { ColorAnimation { } } - - background: Rectangle { - id: backgroundRectangle - implicitHeight: 40 - color: menuBarReal.color - - Behavior on color { ColorAnimation { duration: accentColorAnimationActive ? 0 : 250 } } - } - - Menu { - id: menuTools - title: qsTr("&Tools") - - CustomMenuItem { - id: menuItemOutputs - text: qsTr("&Outputs") - iconSource: "qrc:/images/resources/images/icons/outputs.svg" - - onClicked: outputsRequested() - } - CustomMenuItem { - id: menuItemPendingTransactions - text: qsTr("&Pending transactions") - iconSource: "qrc:/images/resources/images/icons/pending-transactions.svg" - - onClicked: pendingTransactionsRequested() - } - CustomMenuItem { - id: menuItemBlockchain - text: qsTr("&Blockchain") - iconSource: "qrc:/images/resources/images/icons/blockchain.svg" - - onClicked: blockchainRequested() - } - CustomMenuItem { - id: menuItemNetworking - text: qsTr("&Networking") - iconSource: "qrc:/images/resources/images/icons/networking.svg" - - onClicked: networkingRequested() - } - CustomMenuItem { - id: menuItemAddressBook - text: qsTr("&Address Book") - iconSource: "qrc:/images/resources/images/icons/contacts.svg" - - onClicked: addressBookRequested() - } - CustomMenuItem { - id: menuItemSettings - text: qsTr("&Settings") - iconSource: "qrc:/images/resources/images/icons/settings.svg" - - onClicked: settingsRequested() - } - } // menuTools - - Menu { - id: menuLanguage - - title: qsTr("&Language") - - CustomMenuItem { - text: qsTr("&System") - iconSource: "qrc:/images/resources/images/icons/system-language.svg" - enabled: false - - onClicked: { /* nothing to do (for now) */ } - } - - CustomMenuItem { - text: "English" - iconSource: "qrc:/images/resources/images/icons/country-flags/united_states.svg" - - onClicked: { /* nothing to do (for now) */ } - } - } - - Menu { - id: menuHelp - - title: qsTr("&Help") - - CustomMenuItem { - text: qsTr("&About FiberCrypto") - iconSource: "qrc:/images/resources/images/icons/appIcon/appIcon.png" - - onClicked: aboutRequested() - } - - CustomMenuItem { - text: qsTr("About &Qt") - iconSource: "qrc:/images/resources/images/icons/qt_logo_green_rgb_256x256.png" - - onClicked: aboutQtRequested() - } - - MenuSeparator {} - - CustomMenuItem { - text: qsTr("&License") - iconSource: "qrc:/images/resources/images/icons/license.svg" - - onClicked: licenseRequested() - } - } // menuHelp - } // menuBarReal - - ToolButton { - id: toolButtonSettingsAddressBook - - // positioning - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - - visible: opacity > 0 - opacity: enabled ? 1.0 : 0.0 - enabled: false - Behavior on opacity { NumberAnimation { duration: 500 } } - - // icon - icon.source: "qrc:/images/resources/images/icons/settings.svg" - icon.color: menuBarReal.Material.foreground - - onClicked: settingsAddressBookRequested() - } - - ToolButton { - id: toolButtonTheme - - // positioning - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - - // icon - icon.source: "qrc:/images/resources/images/icons/" + (Material.theme === Material.Light ? "moon" : "sun") + ".svg" - icon.color: menuBarReal.Material.foreground - - onClicked: { - menuThemeAccent.popup() - } - - MenuThemeAccent { - id: menuThemeAccent - } - } -} // RowLayout (menuBar) diff --git a/src/ui/CustomMenuItem.qml b/src/ui/CustomMenuItem.qml deleted file mode 100644 index 9b4b207b..00000000 --- a/src/ui/CustomMenuItem.qml +++ /dev/null @@ -1,29 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -MenuItem { - id: customMenuItem - - property alias iconSource: imageIcon.source - property alias iconSourceSize: imageIcon.sourceSize - - leftPadding: highlighted ? imageIcon.sourceSize.width + 12 : padding - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - - Image { - id: imageIcon - anchors.left: parent.left - anchors.leftMargin: parent.highlighted ? 6 : -width/2 - Behavior on anchors.leftMargin { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - anchors.verticalCenter: parent.verticalCenter - - sourceSize: "24x24" // same as Qt.size(24, 24) - fillMode: Image.PreserveAspectFit - - visible: opacity > 0 - opacity: parent.highlighted ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - } -} diff --git a/src/ui/Delegates/AddressListDelegate.qml b/src/ui/Delegates/AddressListDelegate.qml deleted file mode 100644 index 622d8ce0..00000000 --- a/src/ui/Delegates/AddressListDelegate.qml +++ /dev/null @@ -1,116 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -// import "qrc:/ui/src/ui" -import "../" // For quick UI development, switch back to resources when making a release -import "../Controls" // For quick UI development, switch back to resources when making a release - -Item { - id: addressListDelegate - - signal qrCodeRequested(var data) - signal addressTextChanged(string text) - signal numberOfAddressesChanged(int count) - - onQrCodeRequested: { - dialogQR.setVars(data) - dialogQR.open() - } - - implicitHeight: rootLayout.height - clip: true - - RowLayout { - id: rootLayout - width: addressListDelegate.width - clip: true - spacing: 20 - opacity: 0.0 - - Component.onCompleted: { opacity = 1.0 } // Not the best way to do this - Behavior on opacity { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - - RowLayout { - Layout.fillWidth: true - spacing: 8 - - ToolButtonQR { - id: toolButtonQR - - iconSize: "24x24" - - onClicked: { - qrCodeRequested(value) - } - } - - TextField { - id: tfAddr - font.family: "Code New Roman" - placeholderText: qsTr("Address No.") + " " + (index + 1) - text: value ? value : "" - selectByMouse: true - Layout.fillWidth: true - Material.accent: abm.addressIsValid(text) ? parent.Material.accent : Material.color(Material.Red) - onTextChanged: { - value = text - addressTextChanged(text) - } - } - } // RowLayout - - RowLayout { - ComboBox { - id: cbCoinTypes - model: coins - currentIndex: getIndexForCoinType(coinType) - onCurrentTextChanged: { - coinType = cbCoinTypes.currentText - } - } - } - - ToolButton { - id: toolButtonAddRemoveDestination - // The 'accent' attribute is used for button highlighting - Material.accent: index === 0 ? Material.Teal : Material.Red - icon.source: "qrc:/images/resources/images/icons/" + (index === 0 ? "add" : "remove") + "-circle.svg" - highlighted: true // enable the usage of the `Material.accent` attribute - - Layout.alignment: Qt.AlignRight - - onClicked: { - if (index === 0) { - listModelAddresses.append( { "address": "", "coinType": "" } ) - } else { - listModelAddresses.remove(index) - } - numberOfAddressesChanged(listModelAddresses.count) - } - } // ToolButton - } // RowLayout (rootLayout) - - ListModel { - id:coins - ListElement{ - type:"SKY" - } - // ListElement{ - // type:"BTC" - // } - } - - function getIndexForCoinType(coinType) { - var index = 0; - for(var i = 0; i < coins.count; i++) { - if (coins.get(i).type === coinType) { - index = i - } - } - return index; - } -} diff --git a/src/ui/Delegates/ContactDelegate.qml b/src/ui/Delegates/ContactDelegate.qml deleted file mode 100644 index d9aff029..00000000 --- a/src/ui/Delegates/ContactDelegate.qml +++ /dev/null @@ -1,42 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import "../Dialogs" -// import "qrc:/ui/src/ui/Dialogs" - -ItemDelegate { - id: contactDelegate - - signal editRequested() - signal deleteRequested() - - contentItem: RowLayout { - spacing: 20 - Image { - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - source: "qrc:/images/resources/images/icons/user.svg" - sourceSize: "24x24" - } - Label { - Layout.fillWidth: true - text: name - font.bold: true - elide: Text.ElideRight - } - ToolButton { - id: toolButtonEdit - icon.source: "qrc:/images/resources/images/icons/edit.svg" - - onClicked: editRequested() - } - ToolButton { - id: toolButtonDelete - icon.source: "qrc:/images/resources/images/icons/delete.svg" - icon.color: Material.accent - Material.accent: Material.Red - - onClicked: deleteRequested() - } - } -} diff --git a/src/ui/Delegates/DestinationListDelegate.qml b/src/ui/Delegates/DestinationListDelegate.qml deleted file mode 100644 index 62b6e49d..00000000 --- a/src/ui/Delegates/DestinationListDelegate.qml +++ /dev/null @@ -1,197 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui" -// import "qrc:/ui/src/ui/Controls" -// import "qrc:/ui/src/ui/Dialogs" -import "../" // For quick UI development, switch back to resources when making a release -import "../Controls" // For quick UI development, switch back to resources when making a release -import "../Dialogs" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - enum SecurityType { LowSecurity, MediumSecurity, StrongSecurity } - - signal qrCodeRequested(var data) - - onQrCodeRequested: { - dialogQR.setVars(data) - dialogQR.open() - } - - function getAddressList() { - contactAddrsModel.clear() - for(var i = 0; i < abm.count; i++){ - for(var j = 0; j < abm.contacts[i].address.address.length; j++){ - contactAddrsModel.append( { - name: abm.contacts[i].name, - address: abm.contacts[i].address.address[j].value, - coinType: abm.contacts[i].address.address[j].coinType - }) - } - } - } - - implicitHeight: rootLayout.height - clip: true - - RowLayout { - id: rootLayout - width: root.width - clip: true - spacing: 20 - opacity: 0.0 - - // TODO: Use `add`, `remove`, etc. transitions - Component.onCompleted: { opacity = 1.0 } // Not the best way to do this - Behavior on opacity { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - Button { - id: buttonSelectCustomChangeAddress - text: qsTr("Select") - flat: true - highlighted: true - - onClicked: { - if (abm.getSecType() !== DestinationListDelegate.SecurityType.StrongSecurity) { - abm.loadContacts() - dialogSelectAddressByAddressBook.open() - } else { - getpass.open() - } - } - } - - RowLayout { - Layout.fillWidth: true - spacing: 8 - - ToolButtonQR { - id: toolButtonQR - - iconSize: "24x24" - - onClicked: { - qrCodeRequested(address) - } - } - - TextField { - id: textFieldDestinationAddress - font.family: "Code New Roman" - placeholderText: qsTr("Destination address") - text: address - selectByMouse: true - Layout.fillWidth: true - Material.accent: abm.addressIsValid(text) ? parent.Material.accent : Material.color(Material.Red) - onTextChanged: address = text - } - - } // RowLayout - - RowLayout { - TextField { - id: textFieldDestinationAmount - onTextChanged: sky = text - text: sky - selectByMouse: true - implicitWidth: 60 - validator: DoubleValidator { - notation: DoubleValidator.StandardNotation - } - } - Label { text: qsTr("SKY") } - } - - RowLayout { - visible: !checkBoxAutomaticCoinHoursAllocation.checked - - TextField { - id: textFieldCoinHoursAmount - onTextChanged: coinHours = text - text: coinHours - selectByMouse: true - implicitWidth: 60 - validator: DoubleValidator { - notation: DoubleValidator.StandardNotation - } - } - Label { - text: qsTr("Coin hours") - } - } // RowLayout - - ToolButton { - id: toolButtonAddRemoveDestination - - Layout.topMargin: 12 - // The 'accent' attribute is used for button highlighting - Material.accent: index === 0 ? Material.Teal : Material.Red - icon.source: "qrc:/images/resources/images/icons/" + (index === 0 ? "add" : "remove") + "-circle.svg" - highlighted: true // enable the usage of the `Material.accent` attribute - - Layout.alignment: Qt.AlignRight - - onClicked: { - if (index === 0) { - listModelDestinations.append( { "address": "", "sky": "0.0", "coinHours": "0.0" } ) - } else { - listModelDestinations.remove(index) - } - } - - } // ToolButton (Add/Remove) - } // RowLayout (rootLayout) - - DialogGetPassword { - id: getpass - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 280 ? 280 - 40 : applicationWindow.height - 40 - - modal: true - focus: visible - - onAccepted: { - if (!abm.authenticate(getpass.password)) { - getpass.open() - } else { - abm.loadContacts() - dialogSelectAddressByAddressBook.open() - } - } - } - - DialogSelectAddressByAddressBook { - id: dialogSelectAddressByAddressBook - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height - 40 - - focus: visible - modal: true - - listAddrsModel: contactAddrsModel - onAboutToShow: { - getAddressList() - } - - onAccepted: { - textFieldDestinationAddress.text = selectedAddress - } - } - - ListModel { - id: contactAddrsModel - } - - AddrsBookModel { - id: abm - } -} diff --git a/src/ui/Delegates/HistoryFilterListAddressDelegate.qml b/src/ui/Delegates/HistoryFilterListAddressDelegate.qml deleted file mode 100644 index 103c8079..00000000 --- a/src/ui/Delegates/HistoryFilterListAddressDelegate.qml +++ /dev/null @@ -1,20 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 - -CheckDelegate { - id: root - - text: ""// a role of the model - font.family: "Code New Roman" - leftPadding: 20 - scale: 0.85 - - LayoutMirroring.enabled: true - contentItem: Label { - leftPadding: root.indicator.width + root.spacing - text: root.text - verticalAlignment: Qt.AlignVCenter - color: root.enabled ? root.Material.foreground : root.Material.hintTextColor - } -} diff --git a/src/ui/Delegates/HistoryFilterListDelegate.qml b/src/ui/Delegates/HistoryFilterListDelegate.qml deleted file mode 100644 index 7f8cf792..00000000 --- a/src/ui/Delegates/HistoryFilterListDelegate.qml +++ /dev/null @@ -1,126 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - property alias tristate: checkDelegate.tristate - property alias walletText: checkDelegate.text - - clip: true - implicitWidth: width - implicitHeight: height - width: 300 - height: checkDelegate.height + columnLayout.spacing + listViewFilterAddress.height - - ColumnLayout { - id: columnLayout - anchors.fill: parent - - CheckDelegate { - id: checkDelegate - - Layout.fillWidth: true - tristate: true - text: name - LayoutMirroring.enabled: true - - nextCheckState: function() { - if (checkState === Qt.Checked) { - if (!listViewFilterAddress.allChecked) { - listViewFilterAddress.allChecked = true - } - listViewFilterAddress.allChecked = false - return Qt.Unchecked - } else { - if (listViewFilterAddress.allChecked) { - listViewFilterAddress.allChecked = false - } - listViewFilterAddress.allChecked = true - return Qt.Checked - } - } - - contentItem: Label { - leftPadding: checkDelegate.indicator.width + checkDelegate.spacing - verticalAlignment: Qt.AlignVCenter - text: checkDelegate.text - color: checkDelegate.enabled ? checkDelegate.Material.foreground : checkDelegate.Material.hintTextColor - } - } // CheckDelegate - - ListView { - id: listViewFilterAddress - - property AddressModel listAddresses - property int checkedDelegates: 0 - property bool allChecked: false - - model: listAddresses - - Layout.fillWidth: true - implicitHeight: contentHeight - interactive: false - - - onCheckedDelegatesChanged: { - if (checkedDelegates === 0) { - checkDelegate.checkState = Qt.Unchecked - } else if (checkedDelegates === count) { - checkDelegate.checkState = Qt.Checked - } else { - checkDelegate.checkState = Qt.PartiallyChecked - - } - } - - - - Component.onCompleted: { - modelManager.setWalletManager(walletManager) - listAddresses = modelManager.getAddressModel(fileName) - } - - - - delegate: HistoryFilterListAddressDelegate { - // BUG: Checking the wallet does not change the check state of addresses - // Is `checked: marked` ok? Or it should be the opposite? - checked: marked - width: parent.width - text: address - Connections{ - target: listViewFilterAddress - onAllCheckedChanged: { - if (listViewFilterAddress.allChecked) { - historyManager.addFilter(address) - } else { - historyManager.removeFilter(address) - } - walletManager.editMarkAddress(address, listViewFilterAddress.allChecked) - listViewFilterAddress.listAddresses.editAddress(index, address, sky, coinHours, listViewFilterAddress.allChecked) - } - } - onCheckedChanged: { - ListView.view.checkedDelegates += checked ? 1: -1 - - if (checked == true) { - historyManager.addFilter(address) - } else { - historyManager.removeFilter(address) - } - walletManager.editMarkAddress(address, checked) - listViewFilterAddress.listAddresses.editAddress(index, address, sky, coinHours, checked) - - } - } // HistoryFilterListAddressDelegate (delegate) - } // ListView - } // ColumnLayout -} diff --git a/src/ui/Delegates/HistoryListDelegate.qml b/src/ui/Delegates/HistoryListDelegate.qml deleted file mode 100644 index 7213a26c..00000000 --- a/src/ui/Delegates/HistoryListDelegate.qml +++ /dev/null @@ -1,100 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -// Backend imports -import HistoryModels 1.0 - -ItemDelegate { - id: root - - property date modelDate: date - property int modelType: type - property int modelStatus: status - property var modelStatusString: [ qsTr("Confirmed"), qsTr("Pending"), qsTr("Preview") ] - property string modelAmount: amount - property string modelHoursReceived: hoursTraspassed - property string modelHoursBurned: hoursBurned - property string modelTransactionID: transactionID - property QAddressList modelAddresses: addresses - property QAddressList modelInputs: inputs - property QAddressList modelOutputs: outputs - - signal qrCodeRequested(var data) - - onQrCodeRequested: { - dialogQR.setVars(data) - dialogQR.open() - } - - implicitWidth: parent.width - implicitHeight: (columnLayoutMainContent.height < 78 ? 78 : columnLayoutMainContent.height) + rowLayoutRoot.anchors.topMargin + rowLayoutRoot.anchors.bottomMargin - - RowLayout { - id: rowLayoutRoot - - anchors.fill: parent - anchors.leftMargin: 20 - anchors.rightMargin: 20 - anchors.topMargin: 10 - anchors.bottomMargin: 12 - - spacing: 20 - - Image { - source: "qrc:/images/resources/images/icons/send-blue.svg" - sourceSize: "32x32" - fillMode: Image.PreserveAspectFit - mirror: modelType === TransactionDetails.Type.Receive - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - } - - ColumnLayout { - id: columnLayoutMainContent - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - - RowLayout { - Layout.alignment: Qt.AlignLeft - spacing: 20 - - RowLayout { - Layout.fillWidth:true - spacing: 20 - - Label { - font.bold: true - text: (modelType == TransactionDetails.Type.Receive ? qsTr("Received") : (modelType == TransactionDetails.Type.Send ? qsTr("Sent") : qsTr("Internal"))) + " SKY" - } - - Label { - Material.foreground: Material.Grey - text: modelDate.toLocaleString("2000-01-01 00:00") // model's role - font.pointSize: Qt.application.font.pointSize * 0.9 - } - } // RowLayout - } // RowLayout - - ListView { - Layout.alignment: Qt.AlignLeft - height: contentHeight - id: listViewAddresses - model: modelAddresses - delegate: TransactionAddressDelegate {} - } - } // ColumnLayout (main content) - - Label { - text: (modelType === TransactionDetails.Type.Receive ? "" : "-") + amount + " SKY" // model's role - font.pointSize: Qt.application.font.pointSize * 1.25 - font.bold: true - Layout.alignment: Qt.AlignTop | Qt.AlignRight - } - - } // RowLayout (root) -} diff --git a/src/ui/Delegates/InputOutputDelegate.qml b/src/ui/Delegates/InputOutputDelegate.qml deleted file mode 100644 index 0900f9d7..00000000 --- a/src/ui/Delegates/InputOutputDelegate.qml +++ /dev/null @@ -1,63 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Item { - id: root - implicitHeight: 80 - - ColumnLayout { - id: columnLayoutRoot - anchors.fill: parent - - RowLayout { - id: rowLayoutHeader - spacing: 10 - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - Label { - id: labelIndex - text: index + 1 - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - id: labelAddress - text: address - font.family: "Code New Roman" - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - Layout.fillWidth: true - } - } - - GridLayout { - columns: 2 - Layout.alignment: Qt.AlignTop - Layout.leftMargin: labelIndex.width + rowLayoutHeader.spacing - Layout.fillWidth: true - - Label { - text: qsTr("Coins:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: addressSky - font.pointSize: Qt.application.font.pointSize * 0.9 - } - - Label { - text: qsTr("Hours:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: addressCoinHours - font.pointSize: Qt.application.font.pointSize * 0.9 - } - } - } // ColumnLayout -} diff --git a/src/ui/Delegates/NetworkingListDelegate.qml b/src/ui/Delegates/NetworkingListDelegate.qml deleted file mode 100644 index 236c0988..00000000 --- a/src/ui/Delegates/NetworkingListDelegate.qml +++ /dev/null @@ -1,87 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -ItemDelegate { - id: root - - property string modelIp: "0.0.0.0" - property int modelPort: 0 - property string modelSource: qsTr("Default peer") - property int modelBlock: 0 - property string modelLastSeenIn - property string modelLastSeenOut - - - width: parent.width - height: columnLayoutLastSeen.height + rowLayoutRoot.anchors.topMargin + rowLayoutRoot.anchors.bottomMargin - - RowLayout { - id: rowLayoutRoot - anchors.fill: parent - anchors.leftMargin: 20 - anchors.rightMargin: 20 - anchors.topMargin: 10 - anchors.bottomMargin: 12 - - spacing: 20 - - Image { - source: "qrc:/images/resources/images/icons/send-blue.svg" - sourceSize: "32x32" - fillMode: Image.PreserveAspectFit - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - } - - Label { - Material.foreground: Material.Grey - text: modelIp + ':' + modelPort // model's roles - Layout.fillWidth: true - Layout.minimumWidth: 160 - } - - Label { - text: modelSource // model's role - Layout.preferredWidth: 100 - } - - Label { - text: modelBlock // model's role - Layout.preferredWidth: 80 - } - - ColumnLayout { - id: columnLayoutLastSeen - Layout.preferredWidth: 160 - spacing: 0 - - RowLayout { - Image { - source: "qrc:/images/resources/images/icons/up.svg" - sourceSize: Qt.size(labelLastSeenOut.font.pixelSize, labelLastSeenOut.font.pixelSize) - fillMode: Image.PreserveAspectFit - } - Label { - id: labelLastSeenOut - text: modelLastSeenOut +" seconds ago" // model's role - } - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - } - - RowLayout { - Image { - source: "qrc:/images/resources/images/icons/down.svg" - sourceSize: Qt.size(labelLastSeenIn.font.pixelSize, labelLastSeenIn.font.pixelSize) - fillMode: Image.PreserveAspectFit - } - Label { - id: labelLastSeenIn - text: modelLastSeenIn +" seconds ago"// model's role - } - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - } - } // ColumnLayout - - } // RowLayout (root) -} diff --git a/src/ui/Delegates/OutputsListAddressDelegate.qml b/src/ui/Delegates/OutputsListAddressDelegate.qml deleted file mode 100644 index 900d77b5..00000000 --- a/src/ui/Delegates/OutputsListAddressDelegate.qml +++ /dev/null @@ -1,86 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import OutputsModels 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Item { - id: outputsListAddressDelegate - - property bool expanded: false - - signal qrCodeRequested(var data) - - implicitHeight: itemDelegateAddress.height + (expanded ? listViewAddressOutputs.height : 0) - Behavior on implicitHeight { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - - clip: true - Component.onCompleted: { - outputsListAddressDelegate.qrCodeRequested.connect(genQR) - } - - function genQR(data) { - dialogQR.setQRVars(data) - dialogQR.open() - - } - - ItemDelegate { - id: itemDelegateAddress - - property color textColor: expanded ? parent.Material.accent : parent.Material.foreground - Behavior on textColor { ColorAnimation {} } - - anchors.top: parent.top - anchors.left: parent.left - anchors.leftMargin: 10 - anchors.right: parent.right - leftPadding: padding + toolButtonQR.width - - Material.foreground: textColor - text: address // a role of the model - font.family: "Code New Roman" - font.bold: expanded - - ToolButtonQR { - id: toolButtonQR - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 10 - - onClicked: { - qrCodeRequested(address) - } - } - - onClicked: { - expanded = !expanded - } - } // ItemDelegate - - ListView { - id: listViewAddressOutputs - anchors.top: itemDelegateAddress.bottom - anchors.left: parent.left - anchors.right: parent.right - height: contentItem.height - - opacity: expanded ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: expanded ? 250 : 1000; easing.type: Easing.OutQuint } } - - clip: true - interactive: false - model: qoutputs - - - delegate: OutputsListAddressOutputDelegate { - width: listViewAddressOutputs.width - } - } // ListView - - // Roles: outputID, addressSky, addressCoinHours -} diff --git a/src/ui/Delegates/OutputsListAddressOutputDelegate.qml b/src/ui/Delegates/OutputsListAddressOutputDelegate.qml deleted file mode 100644 index ac3aa816..00000000 --- a/src/ui/Delegates/OutputsListAddressOutputDelegate.qml +++ /dev/null @@ -1,84 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Item { - id: outputsListAddressOutputDelegate - - implicitHeight: Math.max(textOutputID.height, (toolButtonCopy.height - toolButtonCopy.topPadding*2), labelAddressSky.height, labelAddressCoins.height) - - RowLayout { - id: rowLayoutRoot - anchors.fill: parent - anchors.leftMargin: listOutputsLeftMargin * 2 - anchors.rightMargin: listOutputsRightMargin - spacing: listOutputsSpacing - - RowLayout { - id: rowLayoutOutputID - Layout.fillWidth: true - - TextInput { - id: textOutputID - Layout.fillWidth: true - text: outputID // a role of the model - readOnly: true - font.family: "Code New Roman" - wrapMode: TextInput.WrapAnywhere - } - ToolButton { - id: toolButtonCopy - icon.source: "qrc:/images/resources/images/icons/copy.svg" - Layout.alignment: Qt.AlignLeft - ToolTip.text: qsTr("Copy to clipboard") - ToolTip.visible: hovered // TODO: pressed when mobile? - ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - - Image { - id: imageCopied - anchors.centerIn: parent - source: "qrc:/images/resources/images/icons/check-simple.svg" - fillMode: Image.PreserveAspectFit - sourceSize: Qt.size(toolButtonCopy.icon.width*1.5, toolButtonCopy.icon.height*1.5) - z: 1 - - opacity: 0.0 - } - - onClicked: { - textOutputID.selectAll() - textOutputID.copy() - textOutputID.deselect() - if (copyAnimation.running) { - copyAnimation.restart() - } else { - copyAnimation.start() - } - } - - SequentialAnimation { - id: copyAnimation - NumberAnimation { target: imageCopied; property: "opacity"; to: 1.0; easing.type: Easing.OutCubic } - PauseAnimation { duration: 1000 } - NumberAnimation { target: imageCopied; property: "opacity"; to: 0.0; easing.type: Easing.OutCubic } - } - } // ToolButton - } // RowLayout (output ID) - - Label { - id: labelAddressSky - text: addressSky // a role of the model - color: Material.accent - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth/2 - } - - Label { - id: labelAddressCoins - text: addressCoinHours // a role of the model - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - } - } // RowLayout (addresses) -} diff --git a/src/ui/Delegates/OutputsListDelegate.qml b/src/ui/Delegates/OutputsListDelegate.qml deleted file mode 100644 index f08892c1..00000000 --- a/src/ui/Delegates/OutputsListDelegate.qml +++ /dev/null @@ -1,58 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import OutputsModels 1.0 - - -Item { - id: outputsListDelegate - - property bool expanded: false - property bool animateDisplacement: false - - implicitHeight: itemDelegateWalletName.height + (expanded ? listViewAddresses.height : 0) - Behavior on implicitHeight { NumberAnimation { duration: animateDisplacement ? 250 : 0; easing.type: Easing.OutQuint; onRunningChanged: animateDisplacement = false } } - - clip: true - ItemDelegate { - id: itemDelegateWalletName - - property color textColor: expanded ? parent.Material.accent : parent.Material.foreground - Behavior on textColor { ColorAnimation {} } - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - - Material.foreground: textColor - text: name // a role of the model - font.bold: true - - onClicked: { - animateDisplacement = true - expanded = !expanded - } - } // ItemDelegate - - ListView { - id: listViewAddresses - anchors.top: itemDelegateWalletName.bottom - anchors.left: parent.left - anchors.right: parent.right - height: contentItem.height - - opacity: expanded ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: expanded ? 250 : 1000; easing.type: Easing.OutQuint } } - - clip: true - interactive: false - model: qaddresses - - delegate: OutputsListAddressDelegate { - width: listViewAddresses.width - } - } // ListView - - // Roles: address -} diff --git a/src/ui/Delegates/PasswordRequesterDelegate.qml b/src/ui/Delegates/PasswordRequesterDelegate.qml deleted file mode 100644 index c2f2528a..00000000 --- a/src/ui/Delegates/PasswordRequesterDelegate.qml +++ /dev/null @@ -1,34 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import OutputsModels 1.0 - - -Item { - id: passwordRequesterDelegate - - TextField { - id: textFieldPassword - text: name - placeholderText: qsTr("Password") - selectByMouse: true - echoMode: TextField.Password - focus: true - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - } - - Button { - id: buttonForgot - text: qsTr("I forgot my password") - flat: true - highlighted: hovered - Layout.alignment: Qt.AlignHCenter | Qt.AlignTop - Layout.fillWidth: true - - onClicked: { - passwordForgotten() - } - } -} diff --git a/src/ui/Delegates/PendingTransactionsDelegate.qml b/src/ui/Delegates/PendingTransactionsDelegate.qml deleted file mode 100644 index cbcba86a..00000000 --- a/src/ui/Delegates/PendingTransactionsDelegate.qml +++ /dev/null @@ -1,49 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -ItemDelegate { - id: root - - property bool modelMine - property string modelTransactionID - property string modelSky - property string modelCoinHours - property date modelTimestamp - - RowLayout { - id: rowLayoutRoot - anchors.fill: parent - anchors.leftMargin: 10 - anchors.rightMargin: 10 - - spacing: 20 - - Label { - Material.foreground: Material.Grey - text: modelTransactionID // model's roles - font.family: "Code New Roman" - font.pointSize: Qt.application.font.pointSize * 0.9 - wrapMode: Label.WrapAnywhere - Layout.fillWidth: true - Layout.minimumWidth: implicitWidth/2 // As the font is monospaced, this should work fine - } - - Label { - text: modelSky // model's role - Layout.preferredWidth: 100 - } - - Label { - text: modelCoinHours // model's role - Layout.preferredWidth: 80 - } - - Label { - text: modelTimestamp // model's role - Layout.preferredWidth: 150 - } - - } // RowLayout (root) -} diff --git a/src/ui/Delegates/SectionDelegate.qml b/src/ui/Delegates/SectionDelegate.qml deleted file mode 100644 index 4db1eaff..00000000 --- a/src/ui/Delegates/SectionDelegate.qml +++ /dev/null @@ -1,22 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -ColumnLayout{ -RowLayout{ - Label { - Layout.leftMargin: 5 - id: label - text: section - Layout.fillWidth: true - } - } - RowLayout{ - Rectangle { - id: rect - Layout.fillWidth: true - height: 1 - color: "#DDDDDD" - } - } - } diff --git a/src/ui/Delegates/TransactionAddressDelegate.qml b/src/ui/Delegates/TransactionAddressDelegate.qml deleted file mode 100644 index 7b690c35..00000000 --- a/src/ui/Delegates/TransactionAddressDelegate.qml +++ /dev/null @@ -1,37 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release -Item { - id: root - - implicitHeight: 30 - - RowLayout { - id: rowLayoutSent - - ToolButtonQR { - - id: toolButtonQRSent - Layout.alignment: Qt.AlignLeft - iconSize: "24x24" - onClicked: { - qrCodeRequested(address) - } - } - Label { - - text: address // model's role - Layout.alignment: Qt.AlignLeft - font.family: "Code New Roman" - Layout.fillWidth: true - } - } -} - - - diff --git a/src/ui/Delegates/WalletListAddressDelegate.qml b/src/ui/Delegates/WalletListAddressDelegate.qml deleted file mode 100644 index 3d2055a5..00000000 --- a/src/ui/Delegates/WalletListAddressDelegate.qml +++ /dev/null @@ -1,214 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - readonly property bool itemVisible: index === 0 || addressSky > 0 || emptyAddressVisible - property bool showOnlyAddresses: false - - signal addAddressesRequested() - signal editWalletRequested() - signal toggleEncryptionRequested() - signal qrCodeRequested(var data) - - Component.onCompleted: { - root.qrCodeRequested.connect(genQR) - } - - function genQR(data) { - dialogQR.setQRVars(data) - dialogQR.open() - } - - - visible: itemVisible || opacity > 0.0 - opacity: itemVisible ? 1.0 : 0.0 - - Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.OutQuint } } - - RowLayout { - id: delegateAddressMenuRowLayout - anchors.fill: parent - anchors.leftMargin: listWalletLeftMargin - anchors.rightMargin: listWalletRightMargin - spacing: listWalletSpacing - visible: index === 0 && !showOnlyAddresses - - ToolButton { - id: buttonAddAddress - text: qsTr("Add address") - icon.source: "qrc:/images/resources/images/icons/add.svg" - Material.accent: Material.Teal - Material.foreground: Material.accent - Layout.fillWidth: true - - onClicked: { - - addAddressesRequested() - } - } - ToolButton { - id: buttonToggleVisibility - text: qsTr("Show empty") - checkable: true - checked: emptyAddressVisible - icon.source: "qrc:/images/resources/images/icons/visible" + (checked ? "On" : "Off") + ".svg" - Material.accent: Material.Indigo - Material.foreground: Material.Grey - Layout.fillWidth: true - - onCheckedChanged: { - emptyAddressVisible = checked - } - } - ToolButton { - id: buttonToggleEncryption - text: checked ? qsTr("Decrypt wallet") : qsTr("Encrypt wallet") - checkable: true - checked: encryptionEnabled - icon.source: "qrc:/images/resources/images/icons/lock" + (checked ? "On" : "Off") + ".svg" - Material.accent: Material.Amber - Material.foreground: Material.Grey - Layout.fillWidth: true - - onCheckedChanged: { - checked = encryptionEnabled - text = checked ? "Decrypt wallet" : "Encrypt wallet" - } - - Connections { - target: root.ListView.view.parentRoot.ListView.view.model - onDataChanged: { - buttonToggleEncryption.checked = encryptionEnabled - } - } - onClicked:{ - toggleEncryptionRequested() - } - } - ToolButton { - id: buttonEdit - text: qsTr("Edit wallet") - icon.source: "qrc:/images/resources/images/icons/edit.svg" - Material.accent: Material.Blue - Material.foreground: Material.accent - Layout.fillWidth: true - - onClicked: { - editWalletRequested() - } - } - } // RowLayout (menu) - - RowLayout { - id: delegateAddressRowLayout - anchors.fill: parent - anchors.leftMargin: listWalletLeftMargin - anchors.rightMargin: listWalletRightMargin - spacing: listWalletSpacing - visible: root.visible && index > 0 - - Label { - id: labelNumber - visible: !showOnlyAddresses - text: index - } - - ToolButtonQR { - id: toolButtonQR - - onClicked: { - qrCodeRequested(address) - } - } - - RowLayout { - TextInput { - id: textAddress - text: address // a role of the model - readOnly: true - font.family: "Code New Roman" - } - ToolButton { - id: toolButtonCopy - visible: !showOnlyAddresses - icon.source: "qrc:/images/resources/images/icons/copy.svg" - Layout.alignment: Qt.AlignLeft - ToolTip.text: qsTr("Copy to clipboard") - ToolTip.visible: hovered // TODO: pressed when mobile? - ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval - - Image { - id: imageCopied - anchors.centerIn: parent - visible: !showOnlyAddresses - source: "qrc:/images/resources/images/icons/check-simple.svg" - fillMode: Image.PreserveAspectFit - sourceSize: Qt.size(toolButtonCopy.icon.width*1.5, toolButtonCopy.icon.height*1.5) - z: 1 - - opacity: 0.0 - } - - onClicked: { - textAddress.selectAll() - textAddress.copy() - textAddress.deselect() - if (copyAnimation.running) { - copyAnimation.restart() - } else { - copyAnimation.start() - } - } - - SequentialAnimation { - id: copyAnimation - NumberAnimation { target: imageCopied; property: "opacity"; to: 1.0; easing.type: Easing.OutCubic } - PauseAnimation { duration: 1000 } - NumberAnimation { target: imageCopied; property: "opacity"; to: 0.0; easing.type: Easing.OutCubic } - } - } // ToolButton - Rectangle { - id: spacer - visible: !showOnlyAddresses - Layout.fillWidth: true - } - } - - Label { - id: labelAddressSky - visible: !showOnlyAddresses - color: Material.accent - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - - text: addressSky === qsTr("N/A") ? "" : addressSky // a role of the model - - BusyIndicator { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - running: addressSky === qsTr("N/A") ? true : false - - implicitWidth: implicitHeight - implicitHeight: parent.height + 10 - } - } - - Label { - id: labelAddressCoins - visible: !showOnlyAddresses - text: addressCoinHours // a role of the model - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - } - } // RowLayout (addresses) -} diff --git a/src/ui/Delegates/WalletListDelegate.qml b/src/ui/Delegates/WalletListDelegate.qml deleted file mode 100644 index 88f57917..00000000 --- a/src/ui/Delegates/WalletListDelegate.qml +++ /dev/null @@ -1,253 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import QtGraphicalEffects 1.12 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -import "../Dialogs/" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - readonly property real delegateHeight: 30 - property bool emptyAddressVisible: true - property bool expanded: expand - // The following property is used to avoid a binding conflict with the `height` property. - // Also avoids a bug with the animation when collapsing a wallet - readonly property real finalViewHeight: expanded ? delegateHeight*(addressList.count) + 50 : 0 - - - width: walletList.width - height: itemDelegateMainButton.height + (expanded ? finalViewHeight : 0) - - Behavior on height { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - - ColumnLayout { - id: delegateColumnLayout - anchors.fill: parent - - ItemDelegate { - id: itemDelegateMainButton - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - font.bold: expanded - - RowLayout { - id: delegateRowLayout - anchors.fill: parent - anchors.leftMargin: listWalletLeftMargin - anchors.rightMargin: listWalletRightMargin - spacing: listWalletSpacing - - Rectangle { - width: 10 - height: 6 - visible: hasHardwareWallet - color: "red" - } - Image { - id: status - source: statusIcon - sourceSize: "24x24" - } - - Label { - id: labelWalletName - text: name // a role of the model - Layout.fillWidth: true - } - - Item { - id: itemImageLockIcon - - width: lockIcon.width - height: lockIcon.height - - Image { - id: lockIcon - source: "qrc:/images/resources/images/icons/lock" + (encryptionEnabled ? "On" : "Off") + ".svg" - sourceSize: "24x24" - } - - ColorOverlay { - anchors.fill: lockIcon - source: lockIcon - color: Material.theme === Material.Dark ? Material.foreground : "undefined" - } - } - - Label { - id: labelSky - text: sky === qsTr("N/A") ? "" : sky // a role of the model - color: Material.accent - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - BusyIndicator { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - running: sky === qsTr("N/A") ? true : false - - implicitWidth: implicitHeight - implicitHeight: parent.height + 10 - } - } - - Label { - id: labelCoins - text: coinHours // a role of the model - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - } - } // RowLayout - - onClicked: { - - expanded = !expanded - walletModel.changeExpanded(fileName) - } - } // ItemDelegate - - ListView { - id: addressList - model: listAddresses - implicitHeight: expanded ? delegateHeight*(addressList.count) + 50 : 0 - property alias parentRoot: root - opacity: expanded ? 1.0 : 0.0 - clip: true - interactive: false - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - - Behavior on implicitHeight { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - Behavior on opacity { NumberAnimation { duration: expanded ? 250 : 1000; easing.type: Easing.OutQuint } } - - delegate: WalletListAddressDelegate { - width: walletList.width - height: index == 0 ? delegateHeight + 20 : visible ? delegateHeight : 0 - - onAddAddressesRequested: { - dialogAddAddresses.open() - } - onEditWalletRequested: { - dialogEditWallet.originalWalletName = name - dialogEditWallet.name = name - dialogEditWallet.open() - } - onToggleEncryptionRequested: { - if (encryptionEnabled) { - dialogGetPassword.addAddress = false - dialogGetPassword.open() - } else { - dialogSetPassword.open() - } - } - } - - } // ListView - } // ColumnLayout - - DialogAddAddresses { - id: dialogAddAddresses - anchors.centerIn: Overlay.overlay - - modal: true - focus: true - - onAccepted: { - if (encryptionEnabled) { - dialogGetPassword.addAddress = true - dialogGetPassword.title = qsTr("Enter Password") - dialogGetPassword.nAddress = spinValue - dialogGetPassword.open() - } else { - walletManager.newWalletAddress(fileName, spinValue, "") - listAddresses.loadModel(walletManager.getAddresses(fileName)) - } - } - } // DialogAddAddresses - - DialogGetPassword { - id: dialogGetPassword - - property bool addAddress: false - property int nAddress - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > implicitHeight + 40 ? implicitHeight : applicationWindow.height - 40 - - headerMessage: addAddress ? "" : qsTr("Warning: for security reasons, it is not recommended to keep the wallets unencrypted. Caution is advised.") - Material.primary: Material.Red - headerMessageColor: Material.primary - - focus: visible - modal: true - - onAccepted: { - if (addAddress) { - walletManager.newWalletAddress(fileName, nAddress, password) - listAddresses.loadModel(walletManager.getAddresses(fileName)) - } else { - var isEncrypted = walletManager.decryptWallet(fileName, password) - walletModel.editWallet(index, name, isEncrypted, sky, coinHours) - } - } - } - - DialogSetPassword { - id: dialogSetPassword - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > implicitHeight + 40 ? implicitHeight : applicationWindow.height - 40 - - headerMessage: qsTr("Warning: We suggest that you encrypt each one of your wallets with a password. If you forget your password, you can reset it with your seed. Make sure you have your seed saved somewhere safe before encrypting your wallet.") - headerMessageColor: Material.primary - Material.primary: Material.Red - focus: visible - modal: true - - onAccepted: { - var isEncypted = walletManager.encryptWallet(fileName, password) - walletModel.editWallet(index, name, isEncypted, sky, coinHours) - } - } // DialogSetPassword - - DialogEditWallet { - id: dialogEditWallet - anchors.centerIn: Overlay.overlay - - focus: true - modal: true - - onAccepted: { - var qwallet = walletManager.editWallet(fileName, name) - walletModel.editWallet(index, qwallet.name, encryptionEnabled, qwallet.sky, qwallet.coinHours ) - } - } // DialogEditWallet - - // Roles: address, addressSky, addressCoinHours - // Use listModel.append( { "address": value, "addressSky": value, "addressCoinHours": value } ) - // Or implement the model in the backend (a more recommendable approach) - AddressModel { - - id: listAddresses - // property Timer timer: Timer { - // id: addressModelTimer - // interval: 3000 - // repeat: true - // running: true - // onTriggered: { - // listAddresses.updateModel(fileName); - // } - // } - } - Component.onCompleted: { - //listAddresses.updateModel(fileName); - listAddresses.updateModel(fileName) - listAddresses.suscribe(fileName) - } -} diff --git a/src/ui/Dialogs/DialogAbout.qml b/src/ui/Dialogs/DialogAbout.qml deleted file mode 100644 index 4d1fe4c8..00000000 --- a/src/ui/Dialogs/DialogAbout.qml +++ /dev/null @@ -1,80 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -Dialog { - id: about - - modal: true - title: qsTr("About") + " " + Qt.application.name - standardButtons: Dialog.Close - - signal licenseRequested() - - Flickable { - id: flickable - clip: true - anchors.fill: parent - contentHeight: column.height - - Column { - id: column - spacing: 20 - width: parent.width - - Image { - id: logo - width: parent.width / 2 - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: "qrc:/images/resources/images/icons/appIcon/appIcon.png" - } - - Label { - width: parent.width - text: "

" + Qt.application.name + ' v' + Qt.application.version + "
" - + "" + qsTr("Multi-coin cryptocurrency wallet") + "
" - + "Copyright © 2019 " + Qt.application.organization + "


" - - + qsTr("

License terms and disclaimer
" - + "This program is free software; you can redistribute it and/or modify " - + "it under the terms of the GNU General Public License as published by " - + "the Free Software Foundation; either version 3 of the License, or " - + "(at your option) any later version.
" - + "This program is distributed in the hope that it will be useful, " - + "but WITHOUT ANY WARRANTY; without even the implied warranty of " - + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " - + "GNU General Public License for more details.
" - + "You should have received a copy of the GNU General Public License along " - + "with this program; if not, see %1.


").arg("http://www.gnu.org/licenses/") - - + qsTr("Contact information: %1").arg("simelo@gmail.com") - wrapMode: Label.Wrap - onHoveredLinkChanged: { - mouseAreaLinkHovered.cursorShape = hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor - } - onLinkActivated: { - if (link === "License") { - licenseRequested() - } else { - Qt.openUrlExternally(link) - } - } - - MouseArea { - id: mouseAreaLinkHovered - anchors.fill: parent - acceptedButtons: Qt.NoButton - } - } // Label - } // Column - - ScrollIndicator.vertical: ScrollIndicator { - parent: about.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -about.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/DialogAboutLicense.qml b/src/ui/Dialogs/DialogAboutLicense.qml deleted file mode 100755 index acd37bfa..00000000 --- a/src/ui/Dialogs/DialogAboutLicense.qml +++ /dev/null @@ -1,695 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -Dialog { - id: dialogAboutLicense - - modal: true - title: qsTr("License") - standardButtons: Dialog.Close - - Flickable { - id: flickable - clip: true - anchors.fill: parent - contentHeight: licenseContent.height - - Label { - id: licenseContent - width: parent.width - text: licenseText - wrapMode: Label.Wrap - onHoveredLinkChanged: { - mouseAreaLinkHovered.cursorShape = hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor - } - onLinkActivated: { Qt.openUrlExternally(link) } - - MouseArea { - id: mouseAreaLinkHovered - anchors.fill: parent - acceptedButtons: Qt.NoButton - } - } // Label - - ScrollIndicator.vertical: ScrollIndicator { - parent: dialogAboutLicense.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -dialogAboutLicense.rightPadding + 1 - } - } // Flickable - - property string licenseText: "

GNU GENERAL PUBLIC LICENSE
" - + "Version 3, June 2007

" - + "
" - + "

Copyright (C) 2007 Free Software Foundation, Inc. http://fsf.org
" - + "Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

" - + "
" - + "

Preamble

" - + "
" - + "

The GNU General Public License is a free, copyleft license for " - + "software and other kinds of works." - + "
" - + "

The licenses for most software and other practical works are designed " - + "to take away your freedom to share and change the works. By contrast, " - + "the GNU General Public License is intended to guarantee your freedom to " - + "share and change all versions of a program--to make sure it remains free " - + "software for all its users. We, the Free Software Foundation, use the " - + "GNU General Public License for most of our software; it applies also to " - + "any other work released this way by its authors. You can apply it to " - + "your programs, too.

" - + "
" - + "

When we speak of free software, we are referring to freedom, not " - + "price. Our General Public Licenses are designed to make sure that you " - + "have the freedom to distribute copies of free software (and charge for " - + "this service if you wish), that you receive source code or can get it " - + "if you want it, that you can change the software or use pieces of it " - + "in new free programs, and that you know you can do these things.

" - + "
" - + "

To protect your rights, we need to prevent others from denying you " - + "these rights or asking you to surrender the rights. Therefore, you have " - + "certain responsibilities if you distribute copies of the software, or if " - + "you modify it: responsibilities to respect the freedom of others.

" - + "
" - + "

For example, if you distribute copies of such a program, whether " - + "gratis or for a fee, you must pass on to the recipients the same " - + "freedoms that you received. You must make sure that they, too, receive " - + "or can get the source code. And you must show them these terms so they " - + "know their rights.

" - + "
" - + "

Developers that use the GNU GPL protect your rights with two steps: " - + "(1) assert copyright on the software, and (2) offer you this License " - + "giving you legal permission to copy, distribute and/or modify it.

" - + "
" - + "

For the developers' and authors' protection, the GPL clearly explains " - + "that there is no warranty for this free software. For both users' and " - + "authors' sake, the GPL requires that modified versions be marked as " - + "changed, so that their problems will not be attributed erroneously to " - + "authors of previous versions.

" - + "
" - + "

Some devices are designed to deny users access to install or run " - + "modified versions of the software inside them, although the manufacturer " - + "can do so. This is fundamentally incompatible with the aim of " - + "protecting users' freedom to change the software. The systematic " - + "pattern of such abuse occurs in the area of products for individuals to " - + "use, which is precisely where it is most unacceptable. Therefore, we " - + "have designed this version of the GPL to prohibit the practice for those " - + "products. If such problems arise substantially in other domains, we " - + "stand ready to extend this provision to those domains in future versions " - + "of the GPL, as needed to protect the freedom of users.

" - + "
" - + "

Finally, every program is threatened constantly by software patents. " - + "States should not allow patents to restrict development and use of " - + "software on general-purpose computers, but in those that do, we wish to " - + "avoid the special danger that patents applied to a free program could " - + "make it effectively proprietary. To prevent this, the GPL assures that " - + "patents cannot be used to render the program non-free.

" - + "
" - + "

The precise terms and conditions for copying, distribution and " - + "modification follow.

" - + "
" - + "

TERMS AND CONDITIONS

" - + "
" - + "

0. Definitions

" - + "
" - + "

\"This License\" refers to version 3 of the GNU General Public License.

" - + "
" - + "

\"Copyright\" also means copyright-like laws that apply to other kinds of " - + "works, such as semiconductor masks.

" - + "
" - + "

\"The Program\" refers to any copyrightable work licensed under this " - + "License. Each licensee is addressed as \"you\". \"Licensees\" and " - + "\"recipients\" may be individuals or organizations.

" - + "
" - + "

To \"modify\" a work means to copy from or adapt all or part of the work " - + "in a fashion requiring copyright permission, other than the making of an " - + "exact copy. The resulting work is called a \"modified version\" of the " - + "earlier work or a work \"based on\" the earlier work.

" - + "
" - + "

1. Source Code.

" - + "
" - + "

The \"source code\" for a work means the preferred form of the work " - + "for making modifications to it. \"Object code\" means any non-source " - + "form of a work.

" - + "
" - + "

A \"Standard Interface\" means an interface that either is an official " - + "standard defined by a recognized standards body, or, in the case of" - + "interfaces specified for a particular programming language, one that" - + "is widely used among developers working in that language.

" - + "
" - + "

The \"System Libraries\" of an executable work include anything, other " - + "than the work as a whole, that (a) is included in the normal form of " - + "packaging a Major Component, but which is not part of that Major " - + "Component, and (b) serves only to enable use of the work with that " - + "Major Component, or to implement a Standard Interface for which an " - + "implementation is available to the public in source code form. A " - + "\"Major Component\", in this context, means a major essential component " - + "(kernel, window system, and so on) of the specific operating system " - + "(if any) on which the executable work runs, or a compiler used to " - + "produce the work, or an object code interpreter used to run it.

" - + "
" - + "

The \"Corresponding Source\" for a work in object code form means all " - + "the source code needed to generate, install, and (for an executable " - + "work) run the object code and to modify the work, including scripts to " - + "control those activities. However, it does not include the work's " - + "System Libraries, or general-purpose tools or generally available free " - + "programs which are used unmodified in performing those activities but " - + "which are not part of the work. For example, Corresponding Source " - + "includes interface definition files associated with source files for " - + "the work, and the source code for shared libraries and dynamically " - + "linked subprograms that the work is specifically designed to require, " - + "such as by intimate data communication or control flow between those " - + "subprograms and other parts of the work.

" - + "
" - + "

The Corresponding Source need not include anything that users " - + "can regenerate automatically from other parts of the Corresponding " - + "Source.

" - + "
" - + "

The Corresponding Source for a work in source code form is that " - + "same work.

" - + "
" - + "

2. Basics permissions.

" - + "
" - + "

All rights granted under this License are granted for the term of " - + "copyright on the Program, and are irrevocable provided the stated " - + "conditions are met. This License explicitly affirms your unlimited " - + "permission to run the unmodified Program. The output from running a " - + "covered work is covered by this License only if the output, given its " - + "content, constitutes a covered work. This License acknowledges your " - + "rights of fair use or other equivalent, as provided by copyright law.

" - + "
" - + "

You may make, run and propagate covered works that you do not " - + "convey, without conditions so long as your license otherwise remains " - + "in force. You may convey covered works to others for the sole purpose " - + "of having them make modifications exclusively for you, or provide you " - + "with facilities for running those works, provided that you comply with " - + "the terms of this License in conveying all material for which you do " - + "not control copyright. Those thus making or running the covered works " - + "for you must do so exclusively on your behalf, under your direction " - + "and control, on terms that prohibit them from making any copies of " - + "your copyrighted material outside their relationship with you.

" - + "
" - + "

Conveying under any other circumstances is permitted solely under " - + "the conditions stated below. Sublicensing is not allowed; section 10 " - + "makes it unnecessary.

" - + "
" - + "

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

" - + "
" - + "

No covered work shall be deemed part of an effective technological " - + "measure under any applicable law fulfilling obligations under article " - + "11 of the WIPO copyright treaty adopted on 20 December 1996, or " - + "similar laws prohibiting or restricting circumvention of such " - + "measures.

" - + "
" - + "

When you convey a covered work, you waive any legal power to forbid " - + "circumvention of technological measures to the extent such circumvention " - + "is effected by exercising rights under this License with respect to " - + "the covered work, and you disclaim any intention to limit operation or " - + "modification of the work as a means of enforcing, against the work's " - + "users, your or third parties' legal rights to forbid circumvention of " - + "technological measures.

" - + "
" - + "

4. Conveying Verbatim Copies.

" - + "
" - + "

You may convey verbatim copies of the Program's source code as you " - + "receive it, in any medium, provided that you conspicuously and " - + "appropriately publish on each copy an appropriate copyright notice; " - + "keep intact all notices stating that this License and any " - + "non-permissive terms added in accord with section 7 apply to the code; " - + "keep intact all notices of the absence of any warranty; and give all " - + "recipients a copy of this License along with the Program.

" - + "
" - + "

You may charge any price or no price for each copy that you convey, " - + "and you may offer support or warranty protection for a fee.

" - + "
" - + "

5. Conveying Modified Source Versions.

" - + "
" - + "

You may convey a work based on the Program, or the modifications to " - + "produce it from the Program, in the form of source code under the " - + "terms of section 4, provided that you also meet all of these conditions:

" - + "
" - + "

a) The work must carry prominent notices stating that you modified " - + "it, and giving a relevant date.

" - + "
" - + "

b) The work must carry prominent notices stating that it is " - + "released under this License and any conditions added under section " - + "7. This requirement modifies the requirement in section 4 to " - + "\"keep intact all notices\".

" - + "
" - + "

c) You must license the entire work, as a whole, under this " - + "License to anyone who comes into possession of a copy. This " - + "License will therefore apply, along with any applicable section 7 " - + "additional terms, to the whole of the work, and all its parts, " - + "regardless of how they are packaged. This License gives no " - + "permission to license the work in any other way, but it does not " - + "invalidate such permission if you have separately received it.

" - + "
" - + "

d) If the work has interactive user interfaces, each must display " - + "Appropriate Legal Notices; however, if the Program has interactive " - + "interfaces that do not display Appropriate Legal Notices, your " - + "work need not make them do so.

" - + "
" - + "

A compilation of a covered work with other separate and independent " - + "works, which are not by their nature extensions of the covered work, " - + "and which are not combined with it such as to form a larger program, " - + "in or on a volume of a storage or distribution medium, is called an " - + "\"aggregate\" if the compilation and its resulting copyright are not " - + "used to limit the access or legal rights of the compilation's users " - + "beyond what the individual works permit. Inclusion of a covered work " - + "in an aggregate does not cause this License to apply to the other " - + "parts of the aggregate.

" - + "
" - + "

6. Conveying Non-Source Forms.

" - + "
" - + "

You may convey a covered work in object code form under the terms " - + "of sections 4 and 5, provided that you also convey the " - + "machine-readable Corresponding Source under the terms of this License, " - + "in one of these ways:

" - + "
" - + "

a) Convey the object code in, or embodied in, a physical product " - + "(including a physical distribution medium), accompanied by the " - + "Corresponding Source fixed on a durable physical medium " - + "customarily used for software interchange.

" - + "
" - + "

b) Convey the object code in, or embodied in, a physical product " - + "(including a physical distribution medium), accompanied by a " - + "written offer, valid for at least three years and valid for as " - + "long as you offer spare parts or customer support for that product " - + "model, to give anyone who possesses the object code either (1) a " - + "copy of the Corresponding Source for all the software in the " - + "product that is covered by this License, on a durable physical " - + "medium customarily used for software interchange, for a price no " - + "more than your reasonable cost of physically performing this " - + "conveying of source, or (2) access to copy the " - + "Corresponding Source from a network server at no charge.

" - + "
" - + "

c) Convey individual copies of the object code with a copy of the " - + "written offer to provide the Corresponding Source. This " - + "alternative is allowed only occasionally and noncommercially, and " - + "only if you received the object code with such an offer, in accord " - + "with subsection 6b.

" - + "
" - + "

d) Convey the object code by offering access from a designated " - + "place (gratis or for a charge), and offer equivalent access to the " - + "Corresponding Source in the same way through the same place at no " - + "further charge. You need not require recipients to copy the " - + "Corresponding Source along with the object code. If the place to " - + "copy the object code is a network server, the Corresponding Source " - + "may be on a different server (operated by you or a third party) " - + "that supports equivalent copying facilities, provided you maintain " - + "clear directions next to the object code saying where to find the " - + "Corresponding Source. Regardless of what server hosts the " - + "Corresponding Source, you remain obligated to ensure that it is " - + "available for as long as needed to satisfy these requirements.

" - + "
" - + "

e) Convey the object code using peer-to-peer transmission, provided " - + "you inform other peers where the object code and Corresponding " - + "Source of the work are being offered to the general public at no " - + "charge under subsection 6d.

" - + "
" - + "

A separable portion of the object code, whose source code is excluded " - + "from the Corresponding Source as a System Library, need not be " - + "included in conveying the object code work.

" - + "
" - + "

A \"User Product\" is either (1) a \"consumer product\", which means any " - + "tangible personal property which is normally used for personal, family, " - + "or household purposes, or (2) anything designed or sold for incorporation " - + "into a dwelling. In determining whether a product is a consumer product, " - + "doubtful cases shall be resolved in favor of coverage. For a particular " - + "product received by a particular user, \"normally used\" refers to a " - + "typical or common use of that class of product, regardless of the status " - + "of the particular user or of the way in which the particular user " - + "actually uses, or expects or is expected to use, the product. A product " - + "is a consumer product regardless of whether the product has substantial " - + "commercial, industrial or non-consumer uses, unless such uses represent " - + "the only significant mode of use of the product.

" - + "
" - + "

\"Installation Information\" for a User Product means any methods, " - + "procedures, authorization keys, or other information required to install " - + "and execute modified versions of a covered work in that User Product from " - + "a modified version of its Corresponding Source. The information must " - + "suffice to ensure that the continued functioning of the modified object " - + "code is in no case prevented or interfered with solely because " - + "modification has been made.

" - + "
" - + "

If you convey an object code work under this section in, or with, or " - + "specifically for use in, a User Product, and the conveying occurs as " - + "part of a transaction in which the right of possession and use of the " - + "User Product is transferred to the recipient in perpetuity or for a " - + "fixed term (regardless of how the transaction is characterized), the " - + "Corresponding Source conveyed under this section must be accompanied " - + "by the Installation Information. But this requirement does not apply " - + "if neither you nor any third party retains the ability to install " - + "modified object code on the User Product (for example, the work has " - + "been installed in ROM).

" - + "
" - + "

The requirement to provide Installation Information does not include a " - + "requirement to continue to provide support service, warranty, or updates " - + "for a work that has been modified or installed by the recipient, or for " - + "the User Product in which it has been modified or installed. Access to a " - + "network may be denied when the modification itself materially and " - + "adversely affects the operation of the network or violates the rules and " - + "protocols for communication across the network.

" - + "
" - + "

Corresponding Source conveyed, and Installation Information provided, " - + "in accord with this section must be in a format that is publicly " - + "documented (and with an implementation available to the public in " - + "source code form), and must require no special password or key for " - + "unpacking, reading or copying.

" - + "
" - + "

7. Additional Terms.

" - + "
" - + "

\"Additional permissions\" are terms that supplement the terms of this " - + "License by making exceptions from one or more of its conditions. " - + "Additional permissions that are applicable to the entire Program shall " - + "be treated as though they were included in this License, to the extent " - + "that they are valid under applicable law. If additional permissions " - + "apply only to part of the Program, that part may be used separately " - + "under those permissions, but the entire Program remains governed by " - + "this License without regard to the additional permissions.

" - + "
" - + "

When you convey a copy of a covered work, you may at your option " - + "remove any additional permissions from that copy, or from any part of " - + "it. (Additional permissions may be written to require their own " - + "removal in certain cases when you modify the work.) You may place " - + "additional permissions on material, added by you to a covered work, " - + "for which you have or can give appropriate copyright permission.

" - + "
" - + "

Notwithstanding any other provision of this License, for material you " - + "add to a covered work, you may (if authorized by the copyright holders of " - + "that material) supplement the terms of this License with terms:

" - + "
" - + "

a) Disclaiming warranty or limiting liability differently from the " - + "terms of sections 15 and 16 of this License; or

" - + "
" - + "

b) Requiring preservation of specified reasonable legal notices or " - + "author attributions in that material or in the Appropriate Legal " - + "Notices displayed by works containing it; or

" - + "
" - + "

c) Prohibiting misrepresentation of the origin of that material, or " - + "requiring that modified versions of such material be marked in " - + "reasonable ways as different from the original version; or

" - + "
" - + "

d) Limiting the use for publicity purposes of names of licensors or " - + "authors of the material; or

" - + "
" - + "

e) Declining to grant rights under trademark law for use of some " - + "trade names, trademarks, or service marks; or

" - + "
" - + "

f) Requiring indemnification of licensors and authors of that " - + "material by anyone who conveys the material (or modified versions of " - + "it) with contractual assumptions of liability to the recipient, for " - + "any liability that these contractual assumptions directly impose on " - + "those licensors and authors.

" - + "
" - + "

All other non-permissive additional terms are considered \"further " - + "restrictions\" within the meaning of section 10. If the Program as you " - + "received it, or any part of it, contains a notice stating that it is " - + "governed by this License along with a term that is a further " - + "restriction, you may remove that term. If a license document contains " - + "a further restriction but permits relicensing or conveying under this " - + "License, you may add to a covered work material governed by the terms " - + "of that license document, provided that the further restriction does " - + "not survive such relicensing or conveying.

" - + "
" - + "

If you add terms to a covered work in accord with this section, you " - + "must place, in the relevant source files, a statement of the " - + "additional terms that apply to those files, or a notice indicating " - + "where to find the applicable terms.

" - + "
" - + "

Additional terms, permissive or non-permissive, may be stated in the " - + "form of a separately written license, or stated as exceptions; " - + "the above requirements apply either way.

" - + "
" - + "

8. Termination.

" - + "
" - + "

You may not propagate or modify a covered work except as expressly " - + "provided under this License. Any attempt otherwise to propagate or " - + "modify it is void, and will automatically terminate your rights under " - + "this License (including any patent licenses granted under the third " - + "paragraph of section 11).

" - + "
" - + "

However, if you cease all violation of this License, then your " - + "license from a particular copyright holder is reinstated (a) " - + "provisionally, unless and until the copyright holder explicitly and " - + "finally terminates your license, and (b) permanently, if the copyright " - + "holder fails to notify you of the violation by some reasonable means " - + "prior to 60 days after the cessation.

" - + "
" - + "

Moreover, your license from a particular copyright holder is " - + "reinstated permanently if the copyright holder notifies you of the " - + "violation by some reasonable means, this is the first time you have " - + "received notice of violation of this License (for any work) from that " - + "copyright holder, and you cure the violation prior to 30 days after " - + "your receipt of the notice.

" - + "
" - + "

Termination of your rights under this section does not terminate the " - + "licenses of parties who have received copies or rights from you under " - + "this License. If your rights have been terminated and not permanently " - + "reinstated, you do not qualify to receive new licenses for the same " - + "material under section 10.

" - + "
" - + "

9. Acceptance Not Required for Having Copies.

" - + "
" - + "

You are not required to accept this License in order to receive or " - + "run a copy of the Program. Ancillary propagation of a covered work " - + "occurring solely as a consequence of using peer-to-peer transmission " - + "to receive a copy likewise does not require acceptance. However, " - + "nothing other than this License grants you permission to propagate or " - + "modify any covered work. These actions infringe copyright if you do " - + "not accept this License. Therefore, by modifying or propagating a " - + "covered work, you indicate your acceptance of this License to do so.

" - + "
" - + "

10. Automatic Licensing of Downstream Recipients.

" - + "
" - + "

Each time you convey a covered work, the recipient automatically " - + "receives a license from the original licensors, to run, modify and " - + "propagate that work, subject to this License. You are not responsible " - + "for enforcing compliance by third parties with this License.

" - + "
" - + "

An \"entity transaction\" is a transaction transferring control of an " - + "organization, or substantially all assets of one, or subdividing an " - + "organization, or merging organizations. If propagation of a covered " - + "work results from an entity transaction, each party to that " - + "transaction who receives a copy of the work also receives whatever " - + "licenses to the work the party's predecessor in interest had or could " - + "give under the previous paragraph, plus a right to possession of the " - + "Corresponding Source of the work from the predecessor in interest, if " - + "the predecessor has it or can get it with reasonable efforts.

" - + "
" - + "

You may not impose any further restrictions on the exercise of the " - + "rights granted or affirmed under this License. For example, you may " - + "not impose a license fee, royalty, or other charge for exercise of " - + "rights granted under this License, and you may not initiate litigation " - + "(including a cross-claim or counterclaim in a lawsuit) alleging that " - + "any patent claim is infringed by making, using, selling, offering for " - + "sale, or importing the Program or any portion of it.

" - + "
" - + "

11. Patents.

" - + "
" - + "

A \"contributor\" is a copyright holder who authorizes use under this " - + "License of the Program or a work on which the Program is based. The " - + "work thus licensed is called the contributor's \"contributor version\".

" - + "
" - + "

A contributor's \"essential patent claims\" are all patent claims " - + "owned or controlled by the contributor, whether already acquired or " - + "hereafter acquired, that would be infringed by some manner, permitted " - + "by this License, of making, using, or selling its contributor version, " - + "but do not include claims that would be infringed only as a " - + "consequence of further modification of the contributor version. For " - + "purposes of this definition, \"control\" includes the right to grant " - + "patent sublicenses in a manner consistent with the requirements of " - + "this License.

" - + "
" - + "

Each contributor grants you a non-exclusive, worldwide, royalty-free " - + "patent license under the contributor's essential patent claims, to " - + "make, use, sell, offer for sale, import and otherwise run, modify and " - + "propagate the contents of its contributor version.

" - + "
" - + "

In the following three paragraphs, a \"patent license\" is any express " - + "agreement or commitment, however denominated, not to enforce a patent " - + "(such as an express permission to practice a patent or covenant not to " - + "sue for patent infringement). To \"grant\" such a patent license to a " - + "party means to make such an agreement or commitment not to enforce a " - + "patent against the party.

" - + "
" - + "

If you convey a covered work, knowingly relying on a patent license, " - + "and the Corresponding Source of the work is not available for anyone " - + "to copy, free of charge and under the terms of this License, through a " - + "publicly available network server or other readily accessible means, " - + "then you must either (1) cause the Corresponding Source to be so " - + "available, or (2) arrange to deprive yourself of the benefit of the " - + "patent license for this particular work, or (3) arrange, in a manner " - + "consistent with the requirements of this License, to extend the patent " - + "license to downstream recipients. \"Knowingly relying\" means you have " - + "actual knowledge that, but for the patent license, your conveying the " - + "covered work in a country, or your recipient's use of the covered work " - + "in a country, would infringe one or more identifiable patents in that " - + "country that you have reason to believe are valid.

" - + "
" - + "

If, pursuant to or in connection with a single transaction or " - + "arrangement, you convey, or propagate by procuring conveyance of, a " - + "covered work, and grant a patent license to some of the parties " - + "receiving the covered work authorizing them to use, propagate, modify " - + "or convey a specific copy of the covered work, then the patent license " - + "you grant is automatically extended to all recipients of the covered " - + "work and works based on it.

" - + "
" - + "

A patent license is \"discriminatory\" if it does not include within " - + "the scope of its coverage, prohibits the exercise of, or is " - + "conditioned on the non-exercise of one or more of the rights that are " - + "specifically granted under this License. You may not convey a covered " - + "work if you are a party to an arrangement with a third party that is " - + "in the business of distributing software, under which you make payment " - + "to the third party based on the extent of your activity of conveying " - + "the work, and under which the third party grants, to any of the " - + "parties who would receive the covered work from you, a discriminatory " - + "patent license (a) in connection with copies of the covered work " - + "conveyed by you (or copies made from those copies), or (b) primarily " - + "for and in connection with specific products or compilations that " - + "contain the covered work, unless you entered into that arrangement, " - + "or that patent license was granted, prior to 28 March 2007.

" - + "
" - + "

Nothing in this License shall be construed as excluding or limiting " - + "any implied license or other defenses to infringement that may " - + "otherwise be available to you under applicable patent law.

" - + "
" - + "

12. No Surrender of Others' Freedom.

" - + "
" - + "

If conditions are imposed on you (whether by court order, agreement or " - + "otherwise) that contradict the conditions of this License, they do not " - + "excuse you from the conditions of this License. If you cannot convey a " - + "covered work so as to satisfy simultaneously your obligations under this " - + "License and any other pertinent obligations, then as a consequence you may " - + "not convey it at all. For example, if you agree to terms that obligate you " - + "to collect a royalty for further conveying from those to whom you convey " - + "the Program, the only way you could satisfy both those terms and this " - + "License would be to refrain entirely from conveying the Program.

" - + "
" - + "

13. Use with the GNU Affero General Public License.

" - + "
" - + "

Notwithstanding any other provision of this License, you have " - + "permission to link or combine any covered work with a work licensed " - + "under version 3 of the GNU Affero General Public License into a single " - + "combined work, and to convey the resulting work. The terms of this " - + "License will continue to apply to the part which is the covered work, " - + "but the special requirements of the GNU Affero General Public License, " - + "section 13, concerning interaction through a network will apply to the " - + "combination as such.

" - + "
" - + "

14. Revised Versions of this License.

" - + "
" - + "

The Free Software Foundation may publish revised and/or new versions of " - + "the GNU General Public License from time to time. Such new versions will " - + "be similar in spirit to the present version, but may differ in detail to " - + "address new problems or concerns.

" - + "
" - + "

Each version is given a distinguishing version number. If the " - + "Program specifies that a certain numbered version of the GNU General " - + "Public License \"or any later version\" applies to it, you have the " - + "option of following the terms and conditions either of that numbered " - + "version or of any later version published by the Free Software " - + "Foundation. If the Program does not specify a version number of the " - + "GNU General Public License, you may choose any version ever published " - + "by the Free Software Foundation.

" - + "
" - + "

If the Program specifies that a proxy can decide which future " - + "versions of the GNU General Public License can be used, that proxy's " - + "public statement of acceptance of a version permanently authorizes you " - + "to choose that version for the Program.

" - + "
" - + "

Later license versions may give you additional or different " - + "permissions. However, no additional obligations are imposed on any " - + "author or copyright holder as a result of your choosing to follow a " - + "later version.

" - + "
" - + "

15. Disclaimer of Warranty.

" - + "
" - + "

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY " - + "APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT " - + "HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY " - + "OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, " - + "THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR " - + "PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM " - + "IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF " - + "ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

" - + "
" - + "

16. Limitation of Liability.

" - + "
" - + "

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING " - + "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS " - + "THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY " - + "GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE " - + "USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF " - + "DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD " - + "PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), " - + "EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF " - + "SUCH DAMAGES.

" - + "
" - + "

17. Interpretation of Sections 15 and 16.

" - + "
" - + "

If the disclaimer of warranty and limitation of liability provided " - + "above cannot be given local legal effect according to their terms, " - + "reviewing courts shall apply local law that most closely approximates " - + "an absolute waiver of all civil liability in connection with the " - + "Program, unless a warranty or assumption of liability accompanies a " - + "copy of the Program in return for a fee.

" - + "
" - + "

END OF TERMS AND CONDITIONS

" - + "

" - + "

How to Apply These Terms to Your New Programs

" - + "
" - + "

If you develop a new program, and you want it to be of the greatest " - + "possible use to the public, the best way to achieve this is to make it " - + "free software which everyone can redistribute and change under these terms.

" - + "
" - + "

To do so, attach the following notices to the program. It is safest " - + "to attach them to the start of each source file to most effectively " - + "convey the exclusion of warranty; and each file should have at least " - + "the \"copyright\" line and a pointer to where the full notice is found.

" - + "
" - + "


" - + "Copyright (C) <year> <name of author>

" - + "
" - + "

This program is free software; you can redistribute it and/or modify " - + "it under the terms of the GNU General Public License as published by " - + "the Free Software Foundation; either version 3 of the License, or " - + "(at your option) any later version.

" - + "
" - + "

This program is distributed in the hope that it will be useful, " - + "but WITHOUT ANY WARRANTY; without even the implied warranty of " - + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " - + "GNU General Public License for more details.

" - + "
" - + "

You should have received a copy of the GNU General Public License along " - + "with this program; if not, see http://www.gnu.org/licenses/

" - + "
" - + "

Also add information on how to contact you by electronic and paper mail.

" - + "
" - + "

If the program is interactive, make it output a short notice like this " - + "when it starts in an interactive mode:

" - + "
" - + "

<program> Copyright (C) <year> <name of author>
" - + "This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
" - + "This is free software, and you are welcome to redistribute it " - + "under certain conditions; type `show c' for details.

" - + "
" - + "

The hypothetical commands `show w' and `show c' should show the appropriate " - + "parts of the General Public License. Of course, your program's commands " - + "be called something other than `show w' and `show c'; they could even be " - + "might be different; for a GUI interface, you would use an \"about box\".

" - + "
" - + "

You should also get your employer (if you work as a programmer) or school " - + "if any, to sign a \"copyright disclaimer\" for the program, if necessary.
" - + "For more information on this, and how to apply and follow the GNU GPL, see " - + "http://www.gnu.org/licenses/.

" - + "
" - + "

The GNU General Public License does not permit incorporating your program into " - + "proprietary programs. If your program is a subroutine library, you may " - + "consider it more useful to permit linking proprietary applications with the " - + "library. If this is what you want to do, use the GNU Lesser General " - + "Public License instead of this License. But first, please read " - + "http://www.gnu.org/philosophy/why-not-lgpl.html.

" -} diff --git a/src/ui/Dialogs/DialogAboutQt.qml b/src/ui/Dialogs/DialogAboutQt.qml deleted file mode 100644 index fc58b45f..00000000 --- a/src/ui/Dialogs/DialogAboutQt.qml +++ /dev/null @@ -1,67 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -Dialog { - id: aboutQt - - readonly property string qtVersionString: "5.13.1" - - modal: true - title: qsTr("About") + " Qt" - standardButtons: Dialog.Close - - Flickable { - id: flickable - clip: true - anchors.fill: parent - contentHeight: column.height - - Column { - id: column - spacing: 20 - width: parent.width - - Image { - id: logo - width: parent.width / 2 - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: "qrc:/images/resources/images/icons/qt_logo_green_rgb.svg" - } - - Label { - width: parent.width - text: "" + qsTr("This program uses Qt %1").arg(qtVersionString) + "
" - + qsTr("

Qt is a C++ toolkit for cross-platform application " + - "development.

" + - "

Qt provides single-source portability across all major desktop and mobile " + - "operating systems. It is also available for embedded Linux and other " + - "embedded operating systems.


" + - "

Qt offers both commercial and opensource licences. Please see %2 " + - "for an overview of Qt licensing.


" + - "

Copyright © %1 The Qt Company Ltd and other " + - "contributors. See %3 for more information.

").arg("2019").arg("qt.io/licensing").arg("qt.io") - wrapMode: Label.Wrap - onHoveredLinkChanged: { - mouseAreaLinkHovered.cursorShape = hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor - } - onLinkActivated: { Qt.openUrlExternally(link) } - - MouseArea { - id: mouseAreaLinkHovered - anchors.fill: parent - acceptedButtons: Qt.NoButton - } - } // Label - } // Column - - ScrollIndicator.vertical: ScrollIndicator { - parent: aboutQt.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -aboutQt.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/DialogAddAddresses.qml b/src/ui/Dialogs/DialogAddAddresses.qml deleted file mode 100644 index 749619cd..00000000 --- a/src/ui/Dialogs/DialogAddAddresses.qml +++ /dev/null @@ -1,36 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.12 - -Dialog { - id: dialogAddAddresses - - title: Qt.application.name - standardButtons: Dialog.Ok | Dialog.Cancel - closePolicy: Dialog.NoAutoClose - property alias spinValue: spinBoxAmount.value - - onAboutToShow: { - spinBoxAmount.forceActiveFocus() - } - - ColumnLayout { - id: columnLayoutRoot - anchors.fill: parent - - Label { - text: qsTr("Amount") - font.bold: true - Layout.fillWidth: true - } - SpinBox { - id: spinBoxAmount - Layout.fillWidth: true - from: 1 - to: 100 - value: 1 - editable: true - focus: true - } - } // ColumnLayout (root) -} diff --git a/src/ui/Dialogs/DialogAddContact.qml b/src/ui/Dialogs/DialogAddContact.qml deleted file mode 100644 index 9a70e7fa..00000000 --- a/src/ui/Dialogs/DialogAddContact.qml +++ /dev/null @@ -1,108 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - - -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -// import "qrc:/ui/src/ui" -// import "qrc:/ui/src/ui/Delegates" -import "../Controls" // For quick UI development, switch back to resources when making a release -import "../" // For quick UI development, switch back to resources when making a release -import "../Delegates" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogAddContact - - property alias name: textFieldName.text - property int index: -1 - property int cId: -1 - property AddrsBkAddressModel addressModel - property alias listModelAddresses: listModelAddresses - property bool isEdit: false - - title: isEdit ? qsTr("Edit contact") : qsTr("Add contact") - standardButtons: Dialog.Save | Dialog.Cancel - - Component.onCompleted: { - standardButton(Dialog.Save).enabled = false - standardButton(Dialog.Save).text = Qt.binding( function() { return isEdit ? qsTr("Save") : qsTr("Add") } ) - } - - onAboutToShow: { - listModelAddresses.clear() - if (isEdit) { - for (var i = 0; i < addressModel.rowCount(); i++) { - listModelAddresses.append( { - value: addressModel.address[i].value, - coinType: addressModel.address[i].coinType - }) - } - } else { - name = "" - listModelAddresses.append( { value: "", coinType: "" } ) - } - - updateAcceptButtonStatus() - } - - function updateAcceptButtonStatus() { - for (var i = 0; i < listModelAddresses.count; i++) { - if ( !(abm.addressIsValid(listModelAddresses.get(i).value)) || - name === "" || abm.nameExist(index, name) || - abm.addressExist(index, listModelAddresses.get(i).value, listModelAddresses.get(i).coinType)) { - standardButton(Dialog.Save).enabled = false - return - } - } - standardButton(Dialog.Save).enabled = true - } - - ColumnLayout { - anchors.fill: parent - - TextField { - id: textFieldName - Layout.fillWidth: true - - placeholderText: qsTr("Name") - selectByMouse: true - onTextChanged: { - updateAcceptButtonStatus() - } - } - - ScrollView { - id: scrollView - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - id: listViewDestinations - - interactive: false - clip: true - - model: listModelAddresses - - delegate: AddressListDelegate { - width: listViewDestinations.width - - onAddressTextChanged: { - updateAcceptButtonStatus() - } - onNumberOfAddressesChanged: { - updateAcceptButtonStatus() - } - } - } // ListView - } // ScrollView - } // ColumnLayout - - ListModel { - id: listModelAddresses - } -} \ No newline at end of file diff --git a/src/ui/Dialogs/DialogAddLoadWallet.qml b/src/ui/Dialogs/DialogAddLoadWallet.qml deleted file mode 100644 index 77b4cc67..00000000 --- a/src/ui/Dialogs/DialogAddLoadWallet.qml +++ /dev/null @@ -1,234 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui" -// import "qrc:/ui/src/ui/Controls" -import "../" // For quick UI development, switch back to resources when making a release -import "../Controls" // For quick UI development, switch back to resources when making a release - - -Dialog { - id: dialogAddWallet - - property alias mode: createLoadWallet.mode - property alias name: createLoadWallet.name - property alias seed: createLoadWallet.seed - property alias encryptionEnabled: checkBoxEncryptWallet.checked - - Component.onCompleted: { - standardButton(Dialog.Ok).text = mode === CreateLoadWallet.Create ? qsTr("Create") : qsTr("Load") - } - - onModeChanged: { - standardButton(Dialog.Ok).text = mode === CreateLoadWallet.Create ? qsTr("Create") : qsTr("Load") - } - onAccepted:{ - var scanA = 0 - if(encryptionEnabled){ - if (mode === CreateLoadWallet.Load){ - scanA = 10 - } - - walletModel.addWallet(walletManager.createEncryptedWallet(seed, name, comboBoxWalletType.model[comboBoxWalletType.currentIndex].name, textFieldPassword.text, scanA)) - - } else{ - - if (mode === CreateLoadWallet.Load){ - scanA = 10 - } - walletModel.addWallet(walletManager.createUnencryptedWallet(seed, name, comboBoxWalletType.model[comboBoxWalletType.currentIndex].name, scanA)) - } - textFieldPassword.text = "" - } - - function updateAcceptButtonStatus() { - - var walletName = createLoadWallet.name - var walletSeed = createLoadWallet.seed - var walletSeedConfirm = createLoadWallet.seedConfirm - - var words = walletSeed.split(' ') - - var invalidNumberOfWords = words.length != 12 && words.length != 24 - var invalidChars = walletSeed.search("[^a-z ]|[ ]{2}") != -1 - var unconventionalSeed = invalidNumberOfWords || invalidChars - var continueWithUnconventionalSeed = checkBoxContinueWithSeedWarning.checked - - var seedMatchConfirmation = walletSeed === walletSeedConfirm - if (createLoadWallet.mode === CreateLoadWallet.Load){ - seedMatchConfirmation = true - } - var passwordNeeded = checkBoxEncryptWallet.checked - var passwordSet = textFieldPassword.text - var passwordMatchConfirmation = textFieldPassword.text === textFieldConfirmPassword.text - - columnLayoutSeedWarning.warn = walletName && walletSeed && seedMatchConfirmation && !(!unconventionalSeed) - - var okButton = standardButton(Dialog.Ok) - - var isSeedValid = walletManager.verifySeed(createLoadWallet.seed) - - okButton.enabled = walletName && walletSeed && seedMatchConfirmation && ((passwordSet && passwordMatchConfirmation) || !passwordNeeded) && (!unconventionalSeed || continueWithUnconventionalSeed) && isSeedValid - } - - title: Qt.application.name - standardButtons: Dialog.Ok | Dialog.Cancel - - onAboutToShow: { - createLoadWallet.clear() - } - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - - CreateLoadWallet { - id: createLoadWallet - Layout.fillWidth: true - nextTabItem: columnLayoutSeedWarning.warn ? checkBoxContinueWithSeedWarning : checkBoxEncryptWallet - - onDataModified: { - updateAcceptButtonStatus() - } - } - - ColumnLayout { - id: columnLayoutSeedWarning - - property bool warn: false - - Layout.fillWidth: true - Layout.preferredHeight: warn ? implicitHeight : 0 - Behavior on Layout.preferredHeight { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - opacity: warn ? 1 : 0 - Behavior on opacity { NumberAnimation {} } - clip: true - - Material.foreground: Material.Pink - Material.accent: Material.Pink - - Label { - Layout.fillWidth: true - text: qsTr("Warning") - font.pointSize: 14 - font.bold: true - wrapMode: Text.WordWrap - } - Label { - Layout.fillWidth: true - text: qsTr("You introduced an unconventional seed. " - + "If you did it for any special reason, " - + "you can continue (only recommended for advanced users). " - + "However, if your intention is to use a normal system seed, " - + "you must delete all the additional text and special characters.") - wrapMode: Text.WordWrap - } - CheckBox { - id: checkBoxContinueWithSeedWarning - text: qsTr("Continue with the unconventional seed") - - onCheckedChanged: { - updateAcceptButtonStatus() - } - } - } // ColumnLayoutSeedWarning - - RowLayout{ - Label{ - text:qsTr("Wallet Type: ") - } - ComboBox{ - id: comboBoxWalletType - Layout.fillWidth: true - textRole: "name" - Component.onCompleted:{ - var availables = walletManager.getAvailableWalletTypes() - var mod = [] - var defaultWalletType = walletManager.getDefaultWalletType() - mod.push({name:defaultWalletType}) - for (var i = 0; i < availables.length; i++){ - var a = {name: availables[i]} - if (availables[i] == defaultWalletType){ - continue - } - mod.push(a) - } - model = mod - } - - } - } - - CheckBox { - id: checkBoxEncryptWallet - text: qsTr("Encrypt wallet") - checked: true - - onCheckedChanged: { - updateAcceptButtonStatus() - if (checked && visible) { - textFieldPassword.forceActiveFocus() - } - } - } - - Label { - Layout.fillWidth: true - Layout.leftMargin: checkBoxEncryptWallet.indicator.width + 2*checkBoxEncryptWallet.padding - text: qsTr("We suggest that you encrypt each one of your wallets with a password. " - + "If you forget your password, you can reset it with your seed. " - + "Make sure you have your seed saved somewhere safe before encrypting your wallet.") - wrapMode: Label.WordWrap - } - - RowLayout { - id: rowLayoutPassword - Layout.fillWidth: true - spacing: 10 - enabled: checkBoxEncryptWallet.checked - - TextField { - id: textFieldPassword - Layout.fillWidth: true - - placeholderText: qsTr("Password") - echoMode: TextField.Password - selectByMouse: true - - onTextChanged: { - updateAcceptButtonStatus() - } - } - TextField { - id: textFieldConfirmPassword - Layout.fillWidth: true - - placeholderText: qsTr("Confirm password") - echoMode: TextField.Password - selectByMouse: true - - onTextChanged: { - updateAcceptButtonStatus() - } - } - } // RowLayout - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: dialogAddWallet.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -dialogAddWallet.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/DialogEditWallet.qml b/src/ui/Dialogs/DialogEditWallet.qml deleted file mode 100644 index 1a3de027..00000000 --- a/src/ui/Dialogs/DialogEditWallet.qml +++ /dev/null @@ -1,43 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogEditWallet - - property string originalWalletName - property alias name: textFieldName.text - - title: qsTr("Edit wallet") - standardButtons: Dialog.Ok | Dialog.Cancel - - function clear() { - textFieldName.clear() - } - - Component.onCompleted: { - } - - onAboutToShow: { - textFieldName.forceActiveFocus() - standardButton(Dialog.Ok).enabled = name && name != originalWalletName - } - - - TextField { - id: textFieldName - - anchors.fill: parent - placeholderText: qsTr("Wallet's name") - selectByMouse: true - focus: true - - onTextChanged: { - standardButton(Dialog.Ok).enabled = text && text != originalWalletName - } - } -} diff --git a/src/ui/Dialogs/DialogGetPassword.qml b/src/ui/Dialogs/DialogGetPassword.qml deleted file mode 100644 index f7e9f58e..00000000 --- a/src/ui/Dialogs/DialogGetPassword.qml +++ /dev/null @@ -1,59 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogGetPassword - - property alias headerMessage: labelHeaderMessage.text - property alias headerMessageColor: labelHeaderMessage.color - property alias password: passwordRequester.text - - property url forgottenPasswordUrl: "http://skycoin.com/" - - function clear() { - passwordRequester.clear() - standardButton(Dialog.Ok).enabled = password - } - - onAboutToShow: { - clear() - passwordRequester.forceTextFocus() - } - - title: qsTr("Password requested") - standardButtons: Dialog.Ok | Dialog.Cancel - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 10 - clip: true - - Label { - id: labelHeaderMessage - - Layout.fillWidth: true - wrapMode: Text.Wrap - visible: text - } - - PasswordRequester { - id: passwordRequester - - Layout.fillWidth: true - - onPasswordForgotten: { - Qt.openUrlExternally(forgottenPasswordUrl) - } - onTextChanged: { - dialogGetPassword.standardButton(Dialog.Ok).enabled = text !== "" - password = text - } - } - } // ColumnLayout (root) -} diff --git a/src/ui/Dialogs/DialogQR.qml b/src/ui/Dialogs/DialogQR.qml deleted file mode 100644 index 6b32e8d9..00000000 --- a/src/ui/Dialogs/DialogQR.qml +++ /dev/null @@ -1,44 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -// Resource imports -// import "qrc:/ui/src/ui/Utils" -import "../Utils" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogQR - - title: Qt.application.name + " - QR" - standardButtons: Dialog.Close - - signal setQRVars(var data) - - Component.onCompleted: { - dialogQR.setQRVars.connect(setVars) - } - - function setVars(data) { - qrDisplay.value = data; - textDisplay.text = data; - } - - QRCode { - id: qrDisplay - anchors.top : parent.top - anchors.topMargin : 30 - anchors.horizontalCenter : parent.horizontalCenter - width : 320 - height : 320 - level : "H" - } - TextInput { - id : textDisplay - anchors.bottom : parent.bottom - anchors.bottomMargin : 30 - anchors.horizontalCenter : parent.horizontalCenter - onAccepted: { - textDisplay.text = dialogQR.text - } - } -} diff --git a/src/ui/Dialogs/DialogSelectAddressByAddressBook.qml b/src/ui/Dialogs/DialogSelectAddressByAddressBook.qml deleted file mode 100644 index 323f027d..00000000 --- a/src/ui/Dialogs/DialogSelectAddressByAddressBook.qml +++ /dev/null @@ -1,101 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -// import "qrc:/ui/src/ui/Delegates" -import "../Controls" // For quick UI development, switch back to resources when making a release -import "../Delegates" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogSelectAddressByAddressBook - - property ListModel listAddrsModel - property string selectedAddress - - padding: 0 - standardButtons: Dialog.Cancel - - closePolicy: Dialog.CloseOnPressOutside - onAboutToShow: { - textFieldFilterContact.forceActiveFocus() - } - - function filterByText(text) { - myDisplayAddrsModel.clear() - if (text === "") { - for(var i = 0; i < listAddrsModel.count; i++){ - myDisplayAddrsModel.append(listAddrsModel.get(i)) - } - return - } - for(var i = 0; i < listAddrsModel.count; i++) { - if (listAddrsModel.get(i).name.toLowerCase().includes(text.toLowerCase()) || listAddrsModel.get(i).address.toLowerCase().includes(text.toLowerCase())) { - myDisplayAddrsModel.append(listAddrsModel.get(i)) - } - } - } - - ColumnLayout { - anchors.fill: parent - - TextField { - id: textFieldFilterContact - - Layout.fillWidth: true - Layout.leftMargin: 10 - Layout.rightMargin: 10 - - placeholderText: qsTr("Filter address") - focus: true - selectByMouse: true - - onTextChanged: { - filterByText(textFieldFilterContact.text) - } - } - - ListView { - id: listView - model: myDisplayAddrsModel - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - currentIndex: -1 - section.property: "name" - section.criteria: ViewSection.FullString - section.delegate: SectionDelegate { - width: parent.width - } - delegate: ItemDelegate { - width: parent.width - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - focusPolicy: Qt.NoFocus - text:coinType + "-" + address - font.family: "Code New Roman" - Material.foreground: hovered ? parent.Material.accent : parent.Material.foreground - highlighted: hovered - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - - onHighlightedChanged: { - ListView.view.currentIndex = highlighted ? index : -1 - } - - onClicked: { - selectedAddress = address - accept() - } - } - - ScrollIndicator.vertical: ScrollIndicator { } - } // ListView - } // ColumnLayout - - ListModel{ - id: myDisplayAddrsModel - } - -} \ No newline at end of file diff --git a/src/ui/Dialogs/DialogSelectAddressByWallet.qml b/src/ui/Dialogs/DialogSelectAddressByWallet.qml deleted file mode 100644 index 8525fc44..00000000 --- a/src/ui/Dialogs/DialogSelectAddressByWallet.qml +++ /dev/null @@ -1,93 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogSelectAddressByWallet - - property alias model: listView.model - property alias filterString: textFieldFilterWallet.text - property string selectedAddress - - padding: 0 - standardButtons: Dialog.Cancel - - closePolicy: Dialog.CloseOnPressOutside - onAboutToShow: { - textFieldFilterWallet.forceActiveFocus() - } - - ColumnLayout { - anchors.fill: parent - - TextField { - id: textFieldFilterWallet - - Layout.fillWidth: true - Layout.leftMargin: 10 - Layout.rightMargin: 10 - placeholderText: qsTr("Filter by wallet name") - focus: true - selectByMouse: true - } - - ListView { - id: listView - - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - currentIndex: -1 - - delegate: MenuItem { - readonly property string parentWallet: wallet - readonly property bool matchFilter: !filterString || wallet.toLowerCase().includes(filterString.toLowerCase()) - - width: parent.width - height: matchFilter ? implicitHeight : 0 - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - focusPolicy: Qt.NoFocus - text: address - font.family: "Code New Roman" - Material.foreground: hovered ? parent.Material.accent : parent.Material.foreground - highlighted: hovered - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - - onHighlightedChanged: { - ListView.view.currentIndex = highlighted ? index : -1 - } - - onTriggered: { - selectedAddress = address - accept() - } - } - - section.property: "wallet" - section.criteria: ViewSection.FullString - section.delegate: Label { - readonly property color textColor: (ListView.view.currentItem && ListView.view.currentItem.parentWallet === text) ? Material.accent : Material.foreground - readonly property bool matchFilter: !filterString || section.toLowerCase().includes(filterString.toLowerCase()) - - height: matchFilter ? contentHeight * 1.5 : 0 - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - verticalAlignment: Text.AlignBottom - text: section - clip: true - leftPadding: 12 - font.bold: true - font.pointSize: Qt.application.font.pointSize * 1.5 - color: textColor - Behavior on color { ColorAnimation { duration: 150 } } - } - - ScrollIndicator.vertical: ScrollIndicator { } - } // ListView - } // ColumnLayout -} diff --git a/src/ui/Dialogs/DialogSelectSecType.qml b/src/ui/Dialogs/DialogSelectSecType.qml deleted file mode 100644 index 16274954..00000000 --- a/src/ui/Dialogs/DialogSelectSecType.qml +++ /dev/null @@ -1,77 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "../Delegates" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogCreateAddressBook - - enum SecurityType { LowSecurity, MediumSecurity, StrongSecurity } - - property alias select: listViewSecurityType.currentIndex - - standardButtons: Dialog.Ok | Dialog.Cancel - - ScrollView { - id: scrollView - anchors.fill: parent - contentWidth: width - clip: true - - ColumnLayout { - anchors.fill: parent - - Label { - Layout.topMargin: 10 - Layout.leftMargin: 20 - Layout.rightMargin: 20 - Layout.fillWidth: true - - text: qsTr("Select the security type for your Address Book") - wrapMode: Text.Wrap - font.bold: true - } - - ListView { - id: listViewSecurityType - - Layout.fillWidth: true - Layout.leftMargin: 20 - Layout.rightMargin: 20 - height: contentHeight - - spacing: -6 - interactive: false - currentIndex: DialogSelectSecType.SecurityType.MediumSecurity - model: [ qsTr("Low (plain text)"), qsTr("Medium (recommended)"), qsTr("Hard (with password)") ] - delegate: RadioButton { - width: parent.width - text: modelData - checked: index === ListView.view.currentIndex - - onCheckedChanged: { - if (checked) { - ListView.view.currentIndex = index - } - } - } // RadioButton (delegate) - } // ListView (log output) - - Label { - Layout.leftMargin: 20 - Layout.rightMargin: 20 - Layout.fillWidth: true - - visible: select === DialogSelectSecType.SecurityType.StrongSecurity - text: "" + qsTr("Note:") + " " + qsTr("Accessing a password-protected address book can slowdown your device") - wrapMode: Text.Wrap - Material.foreground: Material.Red - font.italic: true - } - } // ColumnLayout - } // ScrollView -} \ No newline at end of file diff --git a/src/ui/Dialogs/DialogSendTransaction.qml b/src/ui/Dialogs/DialogSendTransaction.qml deleted file mode 100644 index 8b7dcde7..00000000 --- a/src/ui/Dialogs/DialogSendTransaction.qml +++ /dev/null @@ -1,98 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogSendTransaction - - property alias expanded: transactionDetails.expanded - property bool showPasswordField: false - property string passwordText - - property alias previewDate: transactionDetails.date - property alias previewType: transactionDetails.type - property alias previewAmount: transactionDetails.amount - property alias previewHoursReceived: transactionDetails.hoursReceived - property alias previewHoursBurned: transactionDetails.hoursBurned - property alias previewtransactionID: transactionDetails.transactionID - property alias inputs : transactionDetails.modelInputs - property alias outputs : transactionDetails.modelOutputs - - title: qsTr("Confirm transaction") - standardButtons: Dialog.Ok | Dialog.Cancel - - onOpened: { - forceActiveFocus() - passwordRequester.forceTextFocus() - standardButton(Dialog.Ok).enabled = passwordRequester.text !== "" || !showPasswordField - } - - onClosed: { - passwordRequester.clear() - } - - Flickable { - id: flickable - anchors.fill: parent - clip: true - contentHeight: columnLayoutRoot.height - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 20 - - TransactionDetails { - id: transactionDetails - - Layout.fillWidth: true - } - - Rectangle { - visible: expanded - height: 1 - color: Material.color(Material.Grey) - Layout.fillWidth: true - } - - ColumnLayout { - id: columnLayoutPasswordField - - Layout.fillWidth: true - opacity: showPasswordField ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation {} } - visible: opacity > 0 - - Label { - text: qsTr("Enter the password to confirm the transaction") - font.bold: true - } - - PasswordRequester { - id: passwordRequester - - Layout.topMargin: -10 - Layout.fillWidth: true - - onTextChanged: { - dialogSendTransaction.standardButton(Dialog.Ok).enabled = text !== "" || !showPasswordField - passwordText = text - } - } - } // ColumnLayout - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: dialogSendTransaction.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -dialogSendTransaction.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/DialogSetPassword.qml b/src/ui/Dialogs/DialogSetPassword.qml deleted file mode 100644 index 80fcd114..00000000 --- a/src/ui/Dialogs/DialogSetPassword.qml +++ /dev/null @@ -1,72 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogSetPassword - - property alias headerMessage: labelHeaderMessage.text - property alias headerMessageColor: labelHeaderMessage.color - property alias password: textFieldPassword.text - readonly property bool acceptablePassword: password && textFieldPassword.text === textFieldPasswordConfirmation.text - onAcceptablePasswordChanged: { - standardButton(Dialog.Ok).enabled = acceptablePassword - } - - function clear() { - textFieldPassword.clear() - textFieldPasswordConfirmation.clear() - standardButton(Dialog.Ok).enabled = acceptablePassword - } - - onAboutToShow: { - clear() - textFieldPassword.forceActiveFocus() - } - - title: qsTr("Set a password") - standardButtons: Dialog.Ok | Dialog.Cancel - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 10 - clip: true - - Label { - id: labelHeaderMessage - - Layout.fillWidth: true - wrapMode: Text.Wrap - visible: text - } - - TextField { - id: textFieldPassword - - Layout.fillWidth: true - placeholderText: qsTr("Password") - selectByMouse: true - echoMode: TextField.Password - focus: true - } - - TextField { - id: textFieldPasswordConfirmation - - Layout.fillWidth: true - placeholderText: qsTr("Confirm password") - selectByMouse: true - echoMode: TextField.Password - enabled: textFieldPassword.text - opacity: textFieldPassword.text ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: 200 } } - Material.accent: text === textFieldPassword.text ? parent.Material.accent : Material.color(Material.Red) - } - } // ColumnLayout (root) -} diff --git a/src/ui/Dialogs/DialogShowContact.qml b/src/ui/Dialogs/DialogShowContact.qml deleted file mode 100644 index 646e85c3..00000000 --- a/src/ui/Dialogs/DialogShowContact.qml +++ /dev/null @@ -1,56 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 - -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "../Delegates" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogShowContact - - property alias name: labelName.text - property AddrsBkAddressModel addressModel - - standardButtons: Dialog.Close - - header: ColumnLayout { - Image { - Layout.topMargin: 20 - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - source: "qrc:/images/resources/images/icons/user.svg" - sourceSize: "128x128" - } - - Label { - id: labelName - Layout.fillWidth: true - Layout.topMargin: 20 - horizontalAlignment: Qt.AlignHCenter - font.bold: true - } - } - - ScrollView { - anchors.fill: parent - clip: true - - ListView { - id: addresses - - model: addressModel - delegate: ItemDelegate { - id: addressdelegate - width: parent.width - text: value - } - section.property: "coinType" - section.criteria: ViewSection.FullString - section.delegate: SectionDelegate { - width: addresses.width - } - } - } // ScrollView -} \ No newline at end of file diff --git a/src/ui/Dialogs/DialogTransactionDetails.qml b/src/ui/Dialogs/DialogTransactionDetails.qml deleted file mode 100644 index 15834c86..00000000 --- a/src/ui/Dialogs/DialogTransactionDetails.qml +++ /dev/null @@ -1,33 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/" -import "../" // For quick UI development, switch back to resources when making a release - -Dialog { - id: dialogTransactionsDetails - - property alias date: transactionDetails.date - property alias status: transactionDetails.status - property alias type: transactionDetails.type - property alias amount: transactionDetails.amount - property alias hoursReceived: transactionDetails.hoursReceived - property alias hoursBurned: transactionDetails.hoursBurned - property alias transactionID: transactionDetails.transactionID - property alias modelInputs: transactionDetails.modelInputs - property alias modelOutputs: transactionDetails.modelOutputs - - property alias expanded: transactionDetails.expanded - - title: qsTr("Transaction details") - standardButtons: Dialog.Ok - - TransactionDetails { - id: transactionDetails - anchors.fill: parent - clip: true - } -} diff --git a/src/ui/Dialogs/DialogUnconfiguredWallet.qml b/src/ui/Dialogs/DialogUnconfiguredWallet.qml deleted file mode 100644 index 3e652186..00000000 --- a/src/ui/Dialogs/DialogUnconfiguredWallet.qml +++ /dev/null @@ -1,78 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Dialog { - id: dialogUnconfiguredWallet - - title: qsTr("Unconfigured wallet") - standardButtons: Dialog.Abort - closePolicy: Dialog.NoAutoClose - - Flickable { - id: flickable - clip: true - anchors.fill: parent - contentHeight: columnLayoutRoot.height - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 50 - - RowLayout { - spacing: 50 - - Image { - id: icon - source: "qrc:/images/resources/images/icons/cpu.svg" - sourceSize: "64x64" - Layout.alignment: Qt.AlignTop - } - - Label { - id: msg - text: qsTr("A seedless hardware wallet has been detected. " + - "Select Configure automatically " + - "if you want to configure it as a brand new wallet " + - "and start using it inmediately, " + - "or select Restore backup " + - "if you want to configure it with a previously created " + - "seed backup and thus be able to access your funds again.") - wrapMode: Text.WordWrap - Layout.fillWidth: true - Layout.alignment: Qt.AlignTop - } - } // RowLayout (icon + message) - - ColumnLayout { - Label { - id: options - text: qsTr("Options:") - font.bold: true - Layout.fillWidth: true - } - ItemDelegate { - id: buttonAutoConf - text: qsTr("Configure automatically") - Layout.fillWidth: true - } - ItemDelegate { - id: buttonBackupConf - text: qsTr("Restore backup") - Layout.fillWidth: true - - } - } - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: dialogUnconfiguredWallet.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -dialogUnconfiguredWallet.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/MsgDialog.qml b/src/ui/Dialogs/MsgDialog.qml deleted file mode 100644 index db056c97..00000000 --- a/src/ui/Dialogs/MsgDialog.qml +++ /dev/null @@ -1,79 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Dialog { - id: msgDialog - - property alias text: msg.text - property alias imagePath: icon.source - property alias confirmationCheckBoxVisible: checkBoxConfirmation.visible - property alias confirmationCheckBoxText: checkBoxConfirmation.text - property alias confirmationCheckBoxChecked: checkBoxConfirmation.checked - property int buttonToConnectWithConfirmationCheckBox: Dialog.Ok - - title: Qt.application.name - standardButtons: Dialog.Ok - - Component.onCompleted: { - if (confirmationCheckBoxVisible && standardButton(buttonToConnectWithConfirmationCheckBox)) { - standardButton(buttonToConnectWithConfirmationCheckBox).enabled = confirmationCheckBoxChecked - } - } - - onConfirmationCheckBoxCheckedChanged: { - if (confirmationCheckBoxVisible && standardButton(buttonToConnectWithConfirmationCheckBox)) { - standardButton(buttonToConnectWithConfirmationCheckBox).enabled = confirmationCheckBoxChecked - } else if (standardButton(buttonToConnectWithConfirmationCheckBox)) { - standardButton(buttonToConnectWithConfirmationCheckBox).enabled = true - } - } - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 30 - - RowLayout { - spacing: 30 - Layout.fillWidth: true - - Image { - id: icon - source: "qrc:/images/resources/images/icons/appIcon/appIcon.png" - sourceSize: "64x64" - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - } - Label { - id: msg - text: qsTr("Your message goes here.") - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - wrapMode: Text.WordWrap - } - } - - CheckBox { - id: checkBoxConfirmation - visible: false - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - } - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: msgDialog.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -msgDialog.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/NumPadDialog.qml b/src/ui/Dialogs/NumPadDialog.qml deleted file mode 100644 index 03991f31..00000000 --- a/src/ui/Dialogs/NumPadDialog.qml +++ /dev/null @@ -1,189 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: numPadDialog - - standardButtons: Dialog.Ok | Dialog.Cancel - closePolicy: Popup.NoAutoClose - title: Qt.application.name - - readonly property string numPadButtonText: "#" - readonly property real numPadButtonImplicitSideSize: 50 - readonly property real numPadButtonPointSize: 18 - - Component.onCompleted: { - standardButton(Dialog.Ok).enabled = textInput.length >= 4 - } - - onAboutToShow: { - textInput.forceActiveFocus() - } - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - - Label { - id: labelInstructions - text: qsTr("Enter a hard-to-guess PIN of between 4 and 8 digits. " + - "The PIN layout is displayed in the hardware wallet screen.") - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Label.AlignHCenter - wrapMode: Label.WordWrap - } - - TextField { - id: textInput - - placeholderText: qsTr("12345678") - selectByMouse: true - validator: IntValidator { - bottom: 11111111 - top: 99999999 - } - - inputMethodHints: Qt.ImhDigitsOnly - Layout.fillWidth: true - readOnly: true - maximumLength: 8 - - onTextChanged: { - standardButton(Dialog.Ok).enabled = textInput.length >= 4 - } - } - - Rectangle { - id: numPad - Layout.alignment: Qt.AlignHCenter - border.width: 1 - border.color: "#20000000" - color: Material.background - implicitWidth: Math.max(gridNumPad.implicitWidth, backspace.implicitWidth) + 16 - implicitHeight: gridNumPad.implicitHeight + backspace.implicitHeight + 20 - - ColumnLayout { - id: columnLayoutNumPad - anchors.centerIn: parent - - GridLayout { - id: gridNumPad - Layout.alignment: Qt.AlignCenter - columns: 3 - - readonly property var sequences: [ 7, 8, 9, 4, 5, 6, 1, 2, 3 ] - readonly property var positionsStrings: [ "Top left", "Top center", "Top right", "Center left", "Center", "Center right", "Bottom left", "Bottom center", "Bottom right" ] - - Repeater { - model: 9 - - delegate: ItemDelegate { - id: itemDelegateNumPadButton - - text: numPadButtonText - font.pointSize: numPadButtonPointSize - implicitWidth: numPadButtonImplicitSideSize - implicitHeight: numPadButtonImplicitSideSize - - Shortcut { - sequence: gridNumPad.sequences[index].toString() - enabled: numPadDialog.visible - onActivated: { - itemDelegateNumPadButton.clicked() - numPadButtonAnimation.start() - } - } - onClicked: { - console.log(gridNumPad.positionsStrings[index], "clicked") - } - - SequentialAnimation { - id: numPadButtonAnimation - loops: 1 - PropertyAction { target: itemDelegateNumPadButton; property: "downSym"; value: true } - PauseAnimation { duration: 350 } - PropertyAction { target: itemDelegateNumPadButton; property: "downSym"; value: false } - } - - property bool downSym: down - property color color: (down || downSym) ? Material.color(Material.Amber) : hovered ? numPadDialog.Material.accent : numPadDialog.Material.foreground - Material.foreground: color - - Behavior on color { ColorAnimation {} } - } // ItemDelegate (delegate) - } // Repeater - } // GridLayout - - ItemDelegate { - id: backspace - icon.source: "qrc:/images/resources/images/icons/backspace.svg" - display: ItemDelegate.IconOnly - font.pointSize: numPadButtonPointSize - Layout.fillWidth: true - Layout.alignment: Qt.AlignCenter - - Shortcut { - sequence: "Backspace" - onActivated: { - backspace.clicked() - backspaceAnimation.start() - } - } - onClicked: { - console.log("Backspace clicked") - } - - SequentialAnimation { - id: backspaceAnimation - loops: 1 - PropertyAction { target: backspace; property: "downSym"; value: true } - PauseAnimation { duration: 350 } - PropertyAction { target: backspace; property: "downSym"; value: false } - } - - property bool downSym: down - property color color: (down || downSym) ? Material.color(Material.Amber) : hovered ? numPadDialog.Material.accent : numPadDialog.Material.foreground - Material.foreground: color - - Behavior on color { ColorAnimation {} } - } // GridLayout (numpad) - } // ColumnLayout (numpad) - } // Rectangle (numpad) - - Label { - id: labelInstructionsNotes - text: qsTr("NOTE: You can use the numpad, but the number entered " + - "will be the corresponding number in the hardware wallet screen.") - font.pointSize: 9 - font.italic: true - - Layout.fillWidth: true - wrapMode: Label.WordWrap - color: Material.color(Material.Red) - } - - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: msgDialog.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -msgDialog.rightPadding + 1 - } - } // Flickable - -} diff --git a/src/ui/Dialogs/RestoreBackupWordsDialog.qml b/src/ui/Dialogs/RestoreBackupWordsDialog.qml deleted file mode 100644 index a64bb62d..00000000 --- a/src/ui/Dialogs/RestoreBackupWordsDialog.qml +++ /dev/null @@ -1,89 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: restoreBackupWordsDialog - - property bool finalEntry: false - - title: Qt.application.name - standardButtons: Dialog.YesToAll | Dialog.Cancel - closePolicy: Dialog.NoAutoClose - - Component.onCompleted: { - standardButton(Dialog.YesToAll).text = finalEntry ? qsTr("Finish") : qsTr("Next") - standardButton(Dialog.YesToAll).enabled = wordInput.text !== "" - } - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 50 - - RowLayout { - id: rowLayoutIconMessage - spacing: 30 - - Image { - id: icon - source: "qrc:/images/resources/images/icons/backup.svg" - sourceSize: "64x64" - Layout.alignment: Qt.AlighLeft | Qt.AlignTop - } - - ColumnLayout { - id: columnLayoutMessage - Label { - id: msgTitle - text: "" + qsTr("Enter the word indicated in the device") + "" - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - - Label { - id: msg - text: qsTr("You will be asked to enter the words " + - "of your backup seed in random order, " + - "plus a few additinal words.") - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - } // ColumnLayout (message) - } // RowLayout (icon + message) - - TextField { - id: wordInput - placeholderText: qsTr("Requested word") - Layout.fillWidth: true - focus: restoreBackupWordsDialog.focus - selectByMouse: true - - onTextChanged: { - standardButton(Dialog.YesToAll).enabled = text !== "" - } - } - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: restoreBackupWordsDialog.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -restoreBackupWordsDialog.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/SecureWalletDialog.qml b/src/ui/Dialogs/SecureWalletDialog.qml deleted file mode 100644 index 2a7b9b79..00000000 --- a/src/ui/Dialogs/SecureWalletDialog.qml +++ /dev/null @@ -1,145 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -Dialog { - id: secureWalletDialog - - property string deviceName: "" - property bool enableBackupWarning: true - property bool enablePINWarning: true - - focus: true - modal: true - title: Qt.application.name - standardButtons: Dialog.Abort - closePolicy: Dialog.NoAutoClose - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 50 - - RowLayout { - id: rowLayoutIconMessage - Layout.fillWidth: true - spacing: 50 - - Image { - id: icon - source: "qrc:/images/resources/images/icons/security.svg" - sourceSize: "72x72" - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - } - ColumnLayout { - Label { - id: msgTitle - text: qsTr("Secure hardware wallet") - font.bold: true - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - Label { - id: msg - text: qsTr("Hardware wallet detected.
The device is identified in the " + - "wallets list as: ") + "" + deviceName + "" - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - } // ColumnLayout (message) - } // RowLayout (icon + message) - - ColumnLayout { - id: columnLayoutWarningsOptions - spacing: 30 - - ColumnLayout { - id: columnLayoutWarnings - visible: enableBackupWarning || enablePINWarning - - Label { - id: securityWarningsTitle - text: qsTr("Security warnings") - font.pointSize: 14 - font.bold: true - color: Material.color(Material.Pink) - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - Label { - id: securityWarningBackup - visible: enableBackupWarning - text: "1) " + - qsTr("You should secure the hardware seed or you could lose " + - "access to the funds in case of problems. " + - "To do this, select Create a backup.") - color: Material.color(Material.Pink) - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - Label { - id: securityWarningPIN - visible: enablePINWarning - text: "" + (enableBackupWarning ? 2 : 1) + ") " + - qsTr("The connected hardware wallet does not have a PIN. " + - "The PIN code protects the hardware wallet in case of " + - "loss, theft and hacks. " + - "To do this, select Create PIN code.") - color: Material.color(Material.Pink) - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - } // ColumnLayout (warnings) - - ColumnLayout { - id: columnLayoutOptions - - Label { - id: options - text: qsTr("Options:") - font.bold: true - Layout.fillWidth: true - } - ItemDelegate { - id: buttonCreateBackup - visible: enableBackupWarning - text: qsTr("Create a backup") - Layout.fillWidth: true - } - ItemDelegate { - id: buttonCreatePIN - visible: enablePINWarning - text: qsTr("Create PIN code") - Layout.fillWidth: true - } - ItemDelegate { - id: buttonWipeDevice - text: qsTr("Wipe device") - Layout.fillWidth: true - Material.foreground: Material.Pink - } - } // ColumnLayout (options) - } // ColumnLayouts (warnings + options) - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: secureWalletDialog.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -secureWalletDialog.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/Dialogs/WalletCreatedDialog.qml b/src/ui/Dialogs/WalletCreatedDialog.qml deleted file mode 100644 index b48780a7..00000000 --- a/src/ui/Dialogs/WalletCreatedDialog.qml +++ /dev/null @@ -1,88 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "../Controls" // For quick UI development, switch back to resources when making a release - -Dialog { - id: walletCreateDialog - - title: Qt.application.name - standardButtons: Dialog.Ok - closePolicy: Dialog.NoAutoClose - - Component.onCompleted: { - standardButton(Dialog.Ok).enabled = name.text !== "" - } - - onAboutToShow: { - name.forceActiveFocus() - } - - Flickable { - id: flickable - anchors.fill: parent - contentHeight: columnLayoutRoot.height - clip: true - - ColumnLayout { - id: columnLayoutRoot - width: parent.width - spacing: 30 - - RowLayout { - spacing: 30 - - Image { - id: icon - source: "qrc:/images/resources/images/icons/check.svg" - sourceSize: "64x64" - Layout.alignment: Qt.AlignTop - } - - ColumnLayout { - Label { - text: qsTr("The connected hardware wallet will be added " + - "to the wallets list with the following name:") - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - - TextField { - id: name - placeholderText: qsTr("New hardware wallet") - Layout.fillWidth: true - focus: walletCreateDialog.focus - selectByMouse: true - - onTextChanged: { - standardButton(Dialog.Ok).enabled = text !== "" - } - } - } // ColumnLayout (message) - } // RowLayout (icon + message) - - Label { - text: qsTr("Now you can check the balance and the address of the " + - "hardware wallet even when it is not connected. " + - "Additionally, you can change the name of the wallet " + - "or remove it from the wallets list, if you wish.") - Layout.fillWidth: true - wrapMode: Text.WordWrap - Layout.alignment: Qt.AlignTop - } - } // ColumnLayout (root) - - ScrollIndicator.vertical: ScrollIndicator { - parent: walletCreateDialog.contentItem - anchors.top: flickable.top - anchors.bottom: flickable.bottom - anchors.right: parent.right - anchors.rightMargin: -walletCreateDialog.rightPadding + 1 - } - } // Flickable -} diff --git a/src/ui/FilterComboBoxPopup.qml b/src/ui/FilterComboBoxPopup.qml deleted file mode 100755 index 35ac3dc9..00000000 --- a/src/ui/FilterComboBoxPopup.qml +++ /dev/null @@ -1,48 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.12 - -Popup { - - property ComboBox comboBox: null - property alias filterText: textFieldFilter.text - property alias filterPlaceholderText: textFieldFilter.placeholderText - - y: comboBox.editable ? comboBox.height - 5 : 0 - width: comboBox.width - height: Math.min(contentItem.implicitHeight + topPadding + bottomPadding, Overlay.overlay.height - topMargin - bottomMargin) - transformOrigin: Item.Top - topMargin: 12 - bottomMargin: 12 - padding: 0 - topPadding: 6 - - onAboutToShow: { - textFieldFilter.forceActiveFocus() - } - - contentItem: ColumnLayout { - - TextField { - id: textFieldFilter - - Layout.fillWidth: true - Layout.leftMargin: 12 - Layout.rightMargin: 12 - placeholderText: qsTr("Filter") - focus: true - } - - ListView { - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - implicitHeight: contentHeight - model: comboBox.delegateModel - currentIndex: comboBox.highlightedIndex - highlightMoveDuration: 0 - - ScrollIndicator.vertical: ScrollIndicator { } - } - } // ColumnLayout (contentItem) -} diff --git a/src/ui/GeneralStackView.qml b/src/ui/GeneralStackView.qml deleted file mode 100644 index a85ca248..00000000 --- a/src/ui/GeneralStackView.qml +++ /dev/null @@ -1,202 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import BlockchainModels 1.0 -import WalletsManager 1.0 - -Item { - id: generalStackView - - property alias depth: stackView.depth - property alias busy: stackView.busy - - signal backRequested() - - function openOutputsPage() { - if (stackView.depth > 1) { - stackView.replace(componentOutputs) - } else { - stackView.push(componentOutputs) - } - } - - function openPendingTransactionsPage() { - if (stackView.depth > 1) { - stackView.replace(componentPendingTransactions) - } else { - stackView.push(componentPendingTransactions) - } - } - - - WalletManager { - id: walletManager - } - - WalletModel { - id: walletModel - - Component.onCompleted: { - walletModel.loadModel(walletManager.getWallets()) - if (walletModel.count) { - if (stackView.depth > 1) { - stackView.replace(componentGeneralSwipeView) - } else { - stackView.push(componentGeneralSwipeView) - } - } else{ - if (stackView.depth > 1) { - stackView.replace(componentPageCreateLoadWallet) - } else { - stackView.push(componentPageCreateLoadWallet) - } - - } - } - } - - BlockchainStatusModel { - id: blockchainModel - } - - function openBlockchainPage() { - if (stackView.depth > 1) { - stackView.replace(componentBlockchain) - } else { - stackView.push(componentBlockchain) - } - } - - function openNetworkingPage() { - if (stackView.depth > 1) { - stackView.replace(componentNetworking) - } else { - stackView.push(componentNetworking) - } - } - - function openSettingsPage() { - if (stackView.depth > 1) { - stackView.replace(componentSettings) - } else { - stackView.push(componentSettings) - } - } - - function openSettingsAddressBookPage() { - stackView.push(componentSettingsAddressBook) - } - - function openAddressBookPage() { - if (stackView.depth > 1) { - stackView.replace(componentAddressBook) - } else { - stackView.push(componentAddressBook) - } - } - - function pop() { - stackView.pop() - } - - - StackView { - id: stackView - anchors.fill: parent - } - - Component { - id: componentPageCreateLoadWallet - - Item { - PageCreateLoadWallet { - id: pageCreateLoadWallet - anchors.centerIn: parent - width: 400 - height: 400 - - onWalletCreationRequested: { - stackView.replace(componentGeneralSwipeView) - walletManager.createUnencryptedWallet(pageCreateLoadWallet.seed, pageCreateLoadWallet.name, walletManager.getDefaultWalletType() ,0) - } - - onWalletLoadingRequested:{ - stackView.replace(componentGeneralSwipeView) - walletManager.createUnencryptedWallet(pageCreateLoadWallet.seed, pageCreateLoadWallet.name, walletManager.getDefaultWalletType(), 10) - } - } - } - } - - Component { - id: componentGeneralSwipeView - - GeneralSwipeView { - id: generalSwipeView - } - } - - Component { - id: componentOutputs - - Outputs { - id: outputs - } - } - - Component { - id: componentPendingTransactions - - PendingTransactions { - id: pendingTransactions - } - } - - Component { - id: componentBlockchain - - Blockchain { - id: blockchain - - Component.onCompleted: { - model = blockchainModel - model.update() - } - } - } - - Component { - id: componentNetworking - - Networking { - id: networking - } - } - - Component { - id: componentAddressBook - - AddressBook { - id: addressBook - - onCanceled: { - backRequested() - } - } - } - - Component { - id: componentSettings - - Settings { - id: settings - } - } - - Component { - id: componentSettingsAddressBook - - SettingsAddressBook { - id: settingsAddressBook - } - } -} diff --git a/src/ui/GeneralSwipeView.qml b/src/ui/GeneralSwipeView.qml deleted file mode 100644 index 21b655d2..00000000 --- a/src/ui/GeneralSwipeView.qml +++ /dev/null @@ -1,35 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -Page { - id: root - header: TabBar { - id: tabBar - currentIndex: swipeView.currentIndex - - TabButton { - text: qsTr("Wallets") - } - TabButton { - text: qsTr("Send") - } - TabButton { - text: qsTr("History") - } - } - - SwipeView { - id: swipeView - anchors.fill: parent - currentIndex: tabBar.currentIndex - - PageWallets { - } - - PageSend { - } - - PageHistory { - } - } -} diff --git a/src/ui/HistoryFilterList.qml b/src/ui/HistoryFilterList.qml deleted file mode 100644 index d0e562af..00000000 --- a/src/ui/HistoryFilterList.qml +++ /dev/null @@ -1,47 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "Delegates/" // For quick UI development, switch back to resources when making a release - -ScrollView { - id: historyFilterDelegate - signal loadWallets() - ListView { - id: listViewFilters - - width: parent.width - spacing: 10 - - model: modelFilters - delegate: HistoryFilterListDelegate { - property var listAddresses - width: parent.width - } - - ModelManager { - id: modelManager - - Component.onCompleted: { - setWalletManager(walletManager) - } - } - Connections{ - target: historyFilterDelegate - onLoadWallets:{ - modelFilters.loadModel(walletManager.getWallets()) - } - } - - WalletModel { - id: modelFilters - - Component.onCompleted: { - loadModel(walletManager.getWallets()) - } - } - } -} \ No newline at end of file diff --git a/src/ui/MenuThemeAccent.qml b/src/ui/MenuThemeAccent.qml deleted file mode 100644 index d5c15560..00000000 --- a/src/ui/MenuThemeAccent.qml +++ /dev/null @@ -1,129 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Layouts 1.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 - -Menu { - id: menuThemeAccent - - readonly property int currentTheme: applicationWindow.Material.theme - readonly property color currentAccent: applicationWindow.accentColor - property int currentSelectedIndex // initialized when the component is completed (see bellow) - readonly property var materialPredefinedColors: [ - Material.Pink, - Material.Purple, - Material.DeepPurple, - Material.Indigo, - Material.Blue, - Material.LightBlue, - Material.Cyan, - Material.Teal, - Material.Green, - Material.LightGreen, - Material.Lime, - Material.Yellow, - Material.Amber, - Material.Orange, - Material.DeepOrange, - Material.Brown, - Material.Grey, - Material.BlueGrey - ] - - function saveConfiguration(theme, accent) { - settings.setValue("style/material/theme", theme) - settings.setValue("style/material/accent", accent) - } - - // Initialize `currentSelectedIndex`: - onAboutToShow: { - for (var i = 0; i < gridAccents.children.length; i++) { - if (gridAccents.children[i].checked) { - currentSelectedIndex = i - } - } - } - - title: qsTr("Style configuration") - width: gridAccents.width - - SwitchDelegate { - id: switchDelegateTheme - - width: parent.width - text: qsTr("Night theme") - icon.source: "qrc:/images/resources/images/icons/moon.svg" - icon.color: "transparent" - checked: currentTheme === Material.Dark - - onClicked: { - applicationWindow.flash() - applicationWindow.Material.theme = (currentTheme === Material.Light ? Material.Dark : Material.Light) - applicationWindow.skipAccentColorAnimation = true - applicationWindow.accentColor = gridAccents.children[currentSelectedIndex].Material.accent // needed for accent color transitions - skipAccentColorAnimation = false - saveConfiguration(Material.theme, Material.accentColor) - } - } - - MenuSeparator {} - - Grid { - id: gridAccents - - property int markedIndex: 5 - - width: columns * (48 + columnSpacing) + columnSpacing - - columns: 4 - columnSpacing: 10 - rowSpacing: 10 - leftPadding: 10 - rightPadding: leftPadding - bottomPadding: 4 - - Repeater { - model: materialPredefinedColors.length - - delegate: Rectangle { - id: rectangleDelegate - - property bool checked: applicationWindow.accentColor === Material.accent - - width: 48 - height: width - radius: width/2 - color: Material.accent - border { width: 3; color: Qt.darker(rectangleDelegate.color) } - Material.accent: materialPredefinedColors[index] - - Rectangle { - id: rectangleCheckIndicator - - anchors.centerIn: parent - width: rectangleDelegate.width - 16 - height: width - radius: width/2 - color: rectangleDelegate.border.color - opacity: parent.checked ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation { duration: 150; easing.type: Easing.OutQuint } } - scale: 0.5 + 0.5*opacity - } - - ToolButton { - id: toolButtonChangeAccent - - anchors.fill: parent - anchors.margins: -6 - z: 10 - - onClicked: { - currentSelectedIndex = index - applicationWindow.accentColor = Material.accent - saveConfiguration(Material.theme, Material.accentColor) - } - } // ToolButton - } // Rectangle - } // Repeater - } // Grid -} diff --git a/src/ui/MultiplePasswordRequester.qml b/src/ui/MultiplePasswordRequester.qml deleted file mode 100644 index bbace1d2..00000000 --- a/src/ui/MultiplePasswordRequester.qml +++ /dev/null @@ -1,56 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "Controls" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - property alias text: textFieldPassword.text - property alias placeholderText: textFieldPassword.placeholderText - property alias allowPasswordRecovery: buttonForgot.visible - - signal passwordForgotten() - - function forceTextFocus() { - textFieldPassword.forceActiveFocus() - } - - function clear() { - textFieldPassword.clear() - } - - implicitHeight: textFieldPassword.implicitHeight + buttonForgot.implicitHeight - - ColumnLayout { - anchors.fill: parent - - TextField { - id: textFieldPassword - - placeholderText: qsTr("Password") - selectByMouse: true - echoMode: TextField.Password - focus: true - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - } - - Button { - id: buttonForgot - text: qsTr("I forgot my password") - flat: true - highlighted: hovered - Layout.alignment: Qt.AlignHCenter | Qt.AlignTop - Layout.fillWidth: true - - onClicked: { - passwordForgotten() - } - } - } -} diff --git a/src/ui/NetworkSettings.qml b/src/ui/NetworkSettings.qml deleted file mode 100644 index b2834aee..00000000 --- a/src/ui/NetworkSettings.qml +++ /dev/null @@ -1,27 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "Controls" // For quick UI development, switch back to resources when making a release - -RowLayout { - property alias nodeUrl: nodeUrlField.text - width: parent.width - height: 40 - Label { - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - Layout.alignment: Qt.AlignCenter - text: "Node Url:" - } - TextField { - id: nodeUrlField - Layout.fillWidth: true - Layout.alignment: Qt.AlignCenter - placeholderText: qsTr("http://127.0.0.1:6420") - selectByMouse: true - } -} diff --git a/src/ui/Networking.qml b/src/ui/Networking.qml deleted file mode 100644 index 588c2220..00000000 --- a/src/ui/Networking.qml +++ /dev/null @@ -1,113 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import NetworkingManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "Delegates/" // For quick UI development, switch back to resources when making a release - -Page { - id: root - - Frame { - anchors.fill: parent - anchors.margins: 20 - clip: true - - - ColumnLayout { - id: columnLayoutFrame - anchors.fill: parent - - ColumnLayout { - id: columnLayoutHeader - - RowLayout { - Layout.topMargin: 30 - - Label { - text: qsTr("IP address and port") - font.pointSize: 9 - Layout.leftMargin: 75 // Empirically obtained - Layout.fillWidth: true - } - Label { - text: qsTr("Source") - font.pointSize: 9 - Layout.rightMargin: 75 - } - Label { - text: qsTr("Block") - font.pointSize: 9 - Layout.rightMargin: 65 - } - Label { - text: qsTr("Last seen") - font.pointSize: 9 - Layout.rightMargin: 90 - } - } - - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#DDDDDD" - } - } // ColumnLayout (header) - - ScrollView { - id: scrollItem - Layout.fillWidth: true - Layout.fillHeight: true - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: listNetworking - anchors.fill: parent - clip: true - - model: modelNetworking - delegate: NetworkingListDelegate { - modelIp: ip - modelPort: port - modelSource: source - modelBlock: block - modelLastSeenIn: lastSeenIn - modelLastSeenOut: lastSeenOut - } - } // ListView - } // ScrollView - } // ColumnLayout (frame) - - } // Frame - - NetworkingModel { - id: modelNetworking - } - - NetworkManager { - id: networkManager - property Timer timer: Timer{ - id: networkTimer - repeat: true - running: true - interval: 3000 - onTriggered: { - modelNetworking.cleanNetworks() - modelNetworking.addMultipleNetworks(networkManager.getNetworks()) - } - - } - } - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - // Create a `busy` property in the backend and bind it to `running` here: - running: modelNetworking.networks.length === 0 - - } -} diff --git a/src/ui/Outputs.qml b/src/ui/Outputs.qml deleted file mode 100644 index 4ba130e0..00000000 --- a/src/ui/Outputs.qml +++ /dev/null @@ -1,98 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import OutputsModels 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "Delegates/" // For quick UI development, switch back to resources when making a release - -Page { - id: outputs - - readonly property real listOutputsLeftMargin: 20 - readonly property real listOutputsRightMargin: 50 - readonly property real listOutputsSpacing: 20 - readonly property real internalLabelsWidth: 60 - - Frame { - id: frame - anchors.fill: parent - anchors.margins: 20 - clip: true - - ColumnLayout { - id: columnLayoutFrame - anchors.fill: parent - - ColumnLayout { - id: columnLayoutHeader - - RowLayout { - spacing: listOutputsSpacing - Layout.topMargin: 30 - - Label { - text: qsTr("Output ID") - font.pointSize: 9 - Layout.leftMargin: 38 - Layout.fillWidth: true - } - Label { - text: qsTr("Sky") - font.pointSize: 9 - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth/2 - } - Label { - text: qsTr("Coin hours") - font.pointSize: 9 - horizontalAlignment: Text.AlignRight - Layout.rightMargin: listOutputsRightMargin - Layout.preferredWidth: internalLabelsWidth - } - } - - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#DDDDDD" - } - } // ColumnLayout (header) - - ScrollView { - id: scrollView - Layout.fillWidth: true - Layout.fillHeight: true - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - id: listViewWallets - anchors.fill: parent - clip: true - - model: modelWallets - - delegate: OutputsListDelegate { - width: listViewWallets.width - } - } // ListView - } // ScrollView - } // ColumnLayout (frame) - } // Frame - - // Roles: name - // Implement the model in the backend (a more recommendable approach) - QWallets { - id: modelWallets - } - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - // Create a `busy` property in the backend and bind it to `running` here: - running: modelWallets.loading - } -} diff --git a/src/ui/PageCreateLoadWallet.qml b/src/ui/PageCreateLoadWallet.qml deleted file mode 100644 index 1dde6b28..00000000 --- a/src/ui/PageCreateLoadWallet.qml +++ /dev/null @@ -1,95 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - - -Item { - id: root - - implicitWidth: 400 - implicitHeight: 400 - - signal walletCreationRequested() - signal walletLoadingRequested() - property alias name: createLoadWallet.name - property alias seed: createLoadWallet.seed - property alias confirmedSeed: createLoadWallet.seedConfirm - - Column { - anchors.fill: parent - spacing: 30 - - ControlCustomSwitch { - id: switchNewLoadWallet - width: parent.width - height: 70 - - leftText: qsTr("New wallet") - rightText: qsTr("Load wallet") - - backgroundColor: Material.accent - - textColor: Material.accent - - onToggled: { - createLoadWallet.mode = isInLeftSide ? CreateLoadWallet.Create : CreateLoadWallet.Load - } - } - - CreateLoadWallet { - id: createLoadWallet - width: parent.width - } - - Button { - id: buttonCreateLoadWallet - anchors.horizontalCenter: parent.horizontalCenter - width: 120 - height: 60 - font.bold: true - font.pointSize: Qt.application.font.pointSize * 1.2 - Connections{ - target: createLoadWallet - onModeChanged:{ - if( createLoadWallet.mode === CreateLoadWallet.Load){ - buttonCreateLoadWallet.enabled = true - } - - } - onSeedChanged:{ - if (createLoadWallet.mode === CreateLoadWallet.Create){ - - if (createLoadWallet.seed != createLoadWallet.seedConfirm){ - buttonCreateLoadWallet.enabled = false - } else{ - buttonCreateLoadWallet.enabled = true - } - } - - } - onSeedConfirmChanged:{ - if (createLoadWallet.mode === CreateLoadWallet.Create){ - if (createLoadWallet.seed != createLoadWallet.seedConfirm){ - buttonCreateLoadWallet.enabled = false - } else{ - buttonCreateLoadWallet.enabled = true - } - } - - - } - } - text: createLoadWallet.mode === CreateLoadWallet.Create ? qsTr("Create") : qsTr("Load") - highlighted: true - - onClicked: { - if (createLoadWallet.mode === CreateLoadWallet.Create) { - walletCreationRequested() - } else { - walletLoadingRequested() - } - } - } - } // Column -} diff --git a/src/ui/PageHistory.qml b/src/ui/PageHistory.qml deleted file mode 100644 index 32fbf8b0..00000000 --- a/src/ui/PageHistory.qml +++ /dev/null @@ -1,135 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import HistoryModels 1.0 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -// import "qrc:/ui/src/ui/Delegates" -import "Dialogs/" // For quick UI development, switch back to resources when making a release -import "Delegates/" // For quick UI development, switch back to resources when making a release - -Page { - id: root - - GroupBox { - anchors.fill: parent - anchors.margins: 20 - clip: true - - label: RowLayout { - SwitchDelegate { - id: switchFilters - text: qsTr("Filters") - onClicked:{ - if (!checked) { - modelTransactions.clear() - modelTransactions.addMultipleTransactions(historyManager.getTransactions()) - } - else { - modelTransactions.clear() - modelTransactions.addMultipleTransactions(historyManager.getTransactionsWithFilters()) - } - } - } - Button { - id: buttonFilters - flat: true - enabled: switchFilters.checked - highlighted: true - text: qsTr("Select filters") - - onClicked: { - toolTipFilters.open() - } - } - } // RowLayout (GroupBox label) - - ScrollView { - anchors.fill: parent - clip: true - ListView { - id: listTransactions - - model: modelTransactions - delegate: HistoryListDelegate { - onClicked: { - dialogTransactionDetails.open() - listTransactions.currentIndex = index - } - } - } - } - } // GroupBox - - - Dialog { - id: toolTipFilters - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 440 ? 440 - 40 : applicationWindow.width - 40 - height: Math.min(applicationWindow.height - 40, filter.contentHeight + header.height + footer.height + topPadding + bottomPadding) - - modal: true - standardButtons: Dialog.Close - closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside - title: qsTr("Available filters") - - onClosed: { - modelTransactions.clear() - modelTransactions.addMultipleTransactions(historyManager.getTransactionsWithFilters()) - } - - onOpened:{ - filter.loadWallets() - } - - HistoryFilterList { - id: filter - anchors.fill: parent - } - } // Dialog - - DialogTransactionDetails { - id: dialogTransactionDetails - - readonly property real maxHeight: expanded ? 590 : 370 - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 640 ? 640 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > maxHeight ? maxHeight - 40 : applicationWindow.height - 40 - Behavior on height { NumberAnimation { duration: 1000; easing.type: Easing.OutQuint } } - - modal: true - focus: true - - date: listTransactions.currentItem ? listTransactions.currentItem.modelDate : "" - status: listTransactions.currentItem ? listTransactions.currentItem.modelStatus : 0 - type: listTransactions.currentItem ? listTransactions.currentItem.modelType : 0 - amount: listTransactions.currentItem ? listTransactions.currentItem.modelAmount : "" - hoursReceived: listTransactions.currentItem ? listTransactions.currentItem.modelHoursReceived : 1 - hoursBurned: listTransactions.currentItem ? listTransactions.currentItem.modelHoursBurned : 1 - transactionID: listTransactions.currentItem ? listTransactions.currentItem.modelTransactionID : "" - modelInputs: listTransactions.currentItem ? listTransactions.currentItem.modelInputs : null - modelOutputs: listTransactions.currentItem ? listTransactions.currentItem.modelOutputs : null - } - - QTransactionList { - id: modelTransactions - } - - HistoryManager { - id: historyManager - onNewTransactions: { - if (!switchFilters.checked) { - modelTransactions.addMultipleTransactions(historyManager.getNewTransactions()) - } - else { - modelTransactions.addMultipleTransactions(historyManager.getNewTransactionsWithFilters()) - } - } - } - -} diff --git a/src/ui/PageSend.qml b/src/ui/PageSend.qml deleted file mode 100644 index 09f64be8..00000000 --- a/src/ui/PageSend.qml +++ /dev/null @@ -1,214 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import Transactions 1.0 -import Utils 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -import "Dialogs/" // For quick UI development, switch back to resources when making a release - -Page { - id: root - - property alias advancedMode: switchAdvancedMode.checked - property string walletSelected - property string signerSelected - property string walletEncrypted - property string destinationAddress - property string amount - property QTransaction txn - - footer: ToolBar { - id: tabBarSend - Material.theme: applicationWindow.Material.theme - Material.primary: applicationWindow.accentColor - Material.foreground: applicationWindow.Material.background - Material.elevation: 0 - - ToolButton { - id: buttonAddWallet - anchors.fill: parent - text: qsTr("Send") - icon.source: "qrc:/images/resources/images/icons/send.svg" - - onClicked: { - - var isEncrypted - var walletSelected - var walletSelecteds - if (advancedMode){ - var outs = stackView.currentItem.advancedPage.getSelectedOutputsWithWallets() - var addrs = stackView.currentItem.advancedPage.getSelectedAddressesWithWallets() - //walletSelecteds = stackView.currentItem.advancedPage.getSelectedWallet() - var destinationSummary = stackView.currentItem.advancedPage.getDestinationsSummary() - var changeAddress = stackView.currentItem.advancedPage.getChangeAddress() - var automaticCoinHours = stackView.currentItem.advancedPage.getAutomaticCoinHours() - var burnFactor = stackView.currentItem.advancedPage.getBurnFactor() - if (outs[0].length > 0){ - txn = walletManager.sendFromOutputs(outs[1], outs[0], destinationSummary[0], destinationSummary[1], destinationSummary[2], changeAddress, automaticCoinHours, burnFactor) - } else { - if (addrs[0].length == 0){ - addrs = stackView.currentItem.advancedPage.getAllAddressesWithWallets() - } - txn = walletManager.sendFromAddresses(addrs[1], addrs[0], destinationSummary[0], destinationSummary[1], destinationSummary[2], changeAddress, automaticCoinHours, burnFactor) - } - - isEncrypted = stackView.currentItem.advancedPage.walletIsEncrypted() - } else{ - walletSelected = stackView.currentItem.simplePage.getSelectedWallet() - isEncrypted = stackView.currentItem.simplePage.walletIsEncrypted() - var addrs = [] - addrs.push([]) - addrs.push([]) - addrs[0].push(stackView.currentItem.simplePage.getDestinationAddress()) - addrs[1].push(walletSelected) - txn = walletManager.sendTo(walletSelected, stackView.currentItem.simplePage.getDestinationAddress(), stackView.currentItem.simplePage.getAmount()) - } - dialogSendTransaction.showPasswordField = false//isEncrypted// get if the current wallet is encrypted - //dialogSendTransaction.previewDate = "2019-02-26 15:27" - dialogSendTransaction.previewType = TransactionDetails.Type.Send - dialogSendTransaction.previewAmount = txn.amount - dialogSendTransaction.previewHoursReceived = txn.hoursTraspassed - dialogSendTransaction.previewHoursBurned = txn.hoursBurned - dialogSendTransaction.previewtransactionID = txn.transactionId - dialogSendTransaction.inputs = txn.inputs - dialogSendTransaction.outputs = txn.outputs - dialogSendTransaction.walletsAddresses = addrs - dialogSendTransaction.open() - - - } - } - } - - GroupBox { - id: groupBox - - readonly property real margins: 50 - - anchors.fill: parent - anchors.topMargin: 10 - anchors.leftMargin: margins - anchors.rightMargin: margins - anchors.bottomMargin: margins - implicitWidth: stackView.width - clip: true - - label: SwitchDelegate { - id: switchAdvancedMode - - text: qsTr("Advanced mode") - - onToggled: { - if (checked) { - stackView.push(componentAdvanced) - } else { - stackView.pop() - } - } - } - - StackView { - id: stackView - - property string walletSelected - property string destinationAddress - property string amount - - anchors.fill: parent - initialItem: componentSimple - clip: true - - Component { - id: componentSimple - - ScrollView { - id: scrollViewSimple - property alias simplePage: simple - contentWidth: simple.width - contentHeight: simple.height - clip: true - - SubPageSendSimple { - id: simple - - width: stackView.width - onWalletSelectedChanged: { - root.walletSelected = walletSelected - } - onAmountChanged: { - root.amount = amount - } - onDestinationAddressChanged: { - root.destinationAddress = destinationAddress - } - onWalletEncryptedChanged: { - root.walletEncrypted = walletEncrypted - } - } - } - } - - Component { - id: componentAdvanced - - ScrollView { - id: scrollViewAdvanced - property alias advancedPage: advanced - contentWidth: advanced.width - contentHeight: advanced.height - clip: true - - SubPageSendAdvanced { - id: advanced - width: stackView.width - } - } - } - } // StackView - } // GroupBox - - DialogSendTransaction { - id: dialogSendTransaction - anchors.centerIn: Overlay.overlay - property var walletsAddresses - readonly property real maxHeight: (expanded ? 490 : 340) + (showPasswordField ? 140 : 0) - width: applicationWindow.width > 640 - 40 ? 640 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > maxHeight - 40 ? maxHeight - 40 : applicationWindow.height - 40 - Behavior on height { NumberAnimation { duration: 1000; easing.type: Easing.OutQuint } } - - modal: true - focus: true - onAccepted: { - signerSelected = stackView.currentItem.simplePage.getSignerSelected() - walletManager.signAndBroadcastTxnAsync(walletsAddresses[1], walletsAddresses[0],signerSelected, bridgeForPassword, [], txn) - } - } - - DialogGetPassword{ - id: getPasswordDialog - anchors.centerIn: Overlay.overlay - property int nAddress - width: applicationWindow.width > 540 ? 540 - 120 : applicationWindow.width - 40 - height: applicationWindow.height > 570 ? 570 - 180 : applicationWindow.height - 40 - - focus: true - modal: true - onClosed:{ - bridgeForPassword.setResult(getPasswordDialog.password) - bridgeForPassword.unlock() - } - } - - QBridge{ - id: bridgeForPassword - - onGetPassword:{ - getPasswordDialog.title = message - getPasswordDialog.clear() - getPasswordDialog.open() - } - } -} diff --git a/src/ui/PageWallets.qml b/src/ui/PageWallets.qml deleted file mode 100644 index 60fc95e1..00000000 --- a/src/ui/PageWallets.qml +++ /dev/null @@ -1,181 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import WalletsManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -// import "qrc:/ui/src/ui/Dialogs" -import "Delegates/" // For quick UI development, switch back to resources when making a release -import "Dialogs/" // For quick UI development, switch back to resources when making a release - -Page { - id: root - - property string statusIcon; // an empty string for no icon - readonly property real listWalletLeftMargin: 20 - readonly property real listWalletRightMargin: 50 - readonly property real listWalletSpacing: 20 - readonly property real internalLabelsWidth: 70 - - header: ColumnLayout { - - RowLayout { - spacing: listWalletSpacing - Layout.topMargin: 30 - - Label { - text: qsTr("Name") - font.pointSize: 9 - Layout.leftMargin: listWalletLeftMargin - Layout.fillWidth: true - } - Label { - text: qsTr("SKY") - font.pointSize: 9 - horizontalAlignment: Text.AlignRight - Layout.preferredWidth: internalLabelsWidth - } - Label { - text: qsTr("Coin hours") - font.pointSize: 9 - horizontalAlignment: Text.AlignRight - Layout.rightMargin: listWalletRightMargin - Layout.preferredWidth: internalLabelsWidth - } - } // RowLayout - - Rectangle { - id: rect - Layout.fillWidth: true - height: 1 - color: "#DDDDDD" - } - } // ColumnLayout (header) - - footer: ToolBar { - id: tabBarCreateUpload - Material.theme: applicationWindow.Material.theme - Material.primary: applicationWindow.accentColor - Material.foreground: applicationWindow.Material.background - Material.elevation: 0 - - RowLayout { - anchors.fill: parent - ToolButton { - id: buttonAddWallet - text: qsTr("Add wallet") - icon.source: "qrc:/images/resources/images/icons/add.svg" - Layout.fillWidth: true - - onClicked: { - dialogAddLoadWallet.mode = CreateLoadWallet.Create - dialogAddLoadWallet.open() - } - - } - ToolButton { - id: buttonLoadWallet - text: qsTr("Load wallet") - icon.source: "qrc:/images/resources/images/icons/upload.svg" - Layout.fillWidth: true - - onClicked: { - dialogAddLoadWallet.mode = CreateLoadWallet.Load - dialogAddLoadWallet.open() - } - } - } // RowLayout - } // ToolBar (footer) - - ScrollView { - id: scrollItem - - anchors.fill: parent - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - - ListView { - Timer { - interval: 4000 - repeat: false - running: true - onTriggered: { - walletModel.sniffHw() - } - } - - id: walletList - anchors.fill: parent - clip: true // limit the painting to it's bounding rectangle - model: walletModel - delegate: WalletListDelegate {} - - populate: Transition { - id: transitionPopulate - - SequentialAnimation { - PropertyAction { property: "opacity"; value: 0.0 } - PauseAnimation { - duration: transitionPopulate.ViewTransition.index === 0 ? 150 : 150 + (transitionPopulate.ViewTransition.index - transitionPopulate.ViewTransition.targetIndexes[0]) * 50 - } - ParallelAnimation { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 250; easing.type: Easing.OutCubic } - NumberAnimation { property: "scale"; from: 0.8; to: 1.0; duration: 250; easing.type: Easing.OutCubic } - } - } - } - } - } - - WalletModel { - id: walletModel - - Component.onCompleted: { - walletModel.loadModel(walletManager.getWallets()) - } - //property Timer timer: Timer { - // id: walletListTimer - // interval: 5000 - // repeat: true - // running: true - // onTriggered: { - // walletModel.updateModel(walletManager.getWallets()) - // } - //} - } - - DialogAddLoadWallet { - id: dialogAddLoadWallet - anchors.centerIn: Overlay.overlay - - modal: true - focus: true - - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 640 ? 640 - 40 : applicationWindow.height - 40 - } - - - // Roles: name, encryptionEnabled, sky, coinHours - // Use listModel.append( { "name": value, "encryptionEnabled": value, "sky": value, "coinHours": value } ) - // Or implement the model in the backend (a more recommendable approach) - ListModel { - id: listWallets - ListElement { name: "My first wallet"; encryptionEnabled: true; sky: 5; coinHours: 10 } - ListElement { name: "My second wallet"; encryptionEnabled: true; sky: 300; coinHours: 1049 } - ListElement { name: "My third wallet"; encryptionEnabled: false; sky: 13; coinHours: 201 } - - ListElement { name: "My first wallet"; encryptionEnabled: false; sky: 5; coinHours: 10 } - ListElement { name: "My second wallet"; encryptionEnabled: true; sky: 300; coinHours: 1049 } - ListElement { name: "My third wallet"; encryptionEnabled: true; sky: 13; coinHours: 201 } - - ListElement { name: "My first wallet"; encryptionEnabled: true; sky: 5; coinHours: 10 } - ListElement { name: "My second wallet"; encryptionEnabled: false; sky: 300; coinHours: 1049 } - ListElement { name: "My third wallet"; encryptionEnabled: false; sky: 13; coinHours: 201 } - - ListElement { name: "My first wallet"; encryptionEnabled: true; sky: 5; coinHours: 10 } - ListElement { name: "My second wallet"; encryptionEnabled: false; sky: 300; coinHours: 1049 } - ListElement { name: "My third wallet"; encryptionEnabled: true; sky: 13; coinHours: 201 } - } -} diff --git a/src/ui/PasswordRequester.qml b/src/ui/PasswordRequester.qml deleted file mode 100644 index bbace1d2..00000000 --- a/src/ui/PasswordRequester.qml +++ /dev/null @@ -1,56 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Controls" -import "Controls" // For quick UI development, switch back to resources when making a release - -Item { - id: root - - property alias text: textFieldPassword.text - property alias placeholderText: textFieldPassword.placeholderText - property alias allowPasswordRecovery: buttonForgot.visible - - signal passwordForgotten() - - function forceTextFocus() { - textFieldPassword.forceActiveFocus() - } - - function clear() { - textFieldPassword.clear() - } - - implicitHeight: textFieldPassword.implicitHeight + buttonForgot.implicitHeight - - ColumnLayout { - anchors.fill: parent - - TextField { - id: textFieldPassword - - placeholderText: qsTr("Password") - selectByMouse: true - echoMode: TextField.Password - focus: true - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - } - - Button { - id: buttonForgot - text: qsTr("I forgot my password") - flat: true - highlighted: hovered - Layout.alignment: Qt.AlignHCenter | Qt.AlignTop - Layout.fillWidth: true - - onClicked: { - passwordForgotten() - } - } - } -} diff --git a/src/ui/PendingTransactions.qml b/src/ui/PendingTransactions.qml deleted file mode 100644 index c74141bd..00000000 --- a/src/ui/PendingTransactions.qml +++ /dev/null @@ -1,124 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import PendingModels 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "Delegates/" // For quick UI development, switch back to resources when making a release - -Page { - id: root - - property bool showOnlyMine: false - - GroupBox { - anchors.fill: parent - anchors.margins: 20 - clip: true - - label: CheckDelegate { - text: qsTr("Show only mine") - checked: showOnlyMine - onCheckedChanged: { - showOnlyMine = checked - modelPendingTransactions.recoverTransactions(showOnlyMine) - } - } - - ColumnLayout { - id: columnLayoutFrame - anchors.fill: parent - - ColumnLayout { - id: columnLayoutHeader - - RowLayout { - Layout.topMargin: 30 - - Label { - text: qsTr("Transaction ID") - font.pointSize: 9 - Layout.leftMargin: 10 // Empirically obtained - Layout.fillWidth: true - } - Label { - text: qsTr("Sky") - font.pointSize: 9 - Layout.rightMargin: 92 - } - Label { - text: qsTr("Coin hours") - font.pointSize: 9 - Layout.rightMargin: 33 - } - Label { - text: qsTr("Timestamp") - font.pointSize: 9 - Layout.rightMargin: 98 - } - } // RowLayout - - Rectangle { - Layout.fillWidth: true - height: 1 - color: "#DDDDDD" - } - } // ColumnLayout (header) - - ListView { - id: listPendingTransactions - - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - model: modelPendingTransactions.recoverTransactions(showOnlyMine) - delegate: PendingTransactionsDelegate { - property bool hide: false - - width: parent.width - - modelMine: modelData.mine - modelTransactionID: modelData.transactionID - modelSky: modelData.sky - modelCoinHours: modelData.coinHours - modelTimestamp: modelData.timeStamp - - height: hide ? 0 : implicitHeight - Behavior on height { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } - opacity: hide ? 0 : 1 - Behavior on opacity { NumberAnimation { duration: 100 } } - - clip: true - } // PendingTransactionsDelegate (delegate) - - ScrollBar.vertical: ScrollBar { } - } // ListView - } // ColumnLayout (frame) - } // GroupBox - - QPendingList { - id: modelPendingTransactions - property Timer timer: Timer{ - id: pendingTxnTimer - repeat: true - running: true - interval: 3000 - onTriggered: { - modelPendingTransactions.cleanPendingTxns() - modelPendingTransactions.recoverTransactions(showOnlyMine) - } - - } - - } - - BusyIndicator { - id: busyIndicator - - anchors.centerIn: parent - - running: modelPendingTransactions.loading - } -} diff --git a/src/ui/Settings.qml b/src/ui/Settings.qml deleted file mode 100644 index 6f07d514..00000000 --- a/src/ui/Settings.qml +++ /dev/null @@ -1,399 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -// import "qrc:/ui/src/ui/Controls" -import "Dialogs/" // For quick UI development, switch back to resources when making a release -import "Controls/" // For quick UI development, switch back to resources when making a release - -Page { - id: settings - - enum LogLevel { Debug, Information, Warning, Error, FatalError, Panic } - enum LogOutput { Stdout, Stderr, None, File } - - // BUG: About the wallet path: What happens on Windows? - // TODO: Consider using `StandardPaths.standardLocations(StandardPaths.AppDataLocation)` - - // These are defaults. Will be restored when the "DEFAULT" button is clicked - // TODO: How to get the defaults from the config manager - readonly property string defaultWalletPath: configManager.getDefaultValue("skycoin/walletSource/1/Source") - readonly property bool defaultIsLocalWalletEnv: configManager.getDefaultValue("skycoin/walletSource/1/SourceType") === "local" - readonly property string defaultNodeUrl: configManager.getDefaultValue("skycoin/node/address") - readonly property int defaultLogLevel: ~~configManager.getDefaultValue("skycoin/log/level") - readonly property int defaultLogOutput: ~~configManager.getDefaultValue("skycoin/log/output") - readonly property string defaultLogOutputFile: configManager.getDefaultValue("skycoin/log/outputFile") - readonly property var defaultCacheLifeTime: configManager.getDefaultValue("global/cache/lifeTime") - readonly property var defaultCacheUpdateTime: configManager.getDefaultValue("global/cache/updateTime") - - // These are the saved settings, must be applied when the settings are opened or when - // the user clicks "RESET" and updated when the user clicks "APPLY" - // TODO: This should be binded to backend properties - property string savedWalletPath: configManager.getValue("skycoin/walletSource/1/Source") - property bool savedIsLocalWalletEnv: configManager.getValue("skycoin/walletSource/1/SourceType") === "local" - property url savedNodeUrl: configManager.getValue("skycoin/node/address") - property int savedLogLevel: ~~configManager.getValue("skycoin/log/level") - property int savedLogOutput: ~~configManager.getValue("skycoin/log/output") - property string savedLogOutputFile: configManager.getDefaultValue("skycoin/log/outputFile") - property var savedLifeTime: configManager.getValue("global/cache/lifeTime") - property var savedUpdateTime: configManager.getValue("global/cache/updateTime") - - // QtObject{ - // id: logLevel - // property string modifier - // property string old - // } - - // These are the properties that are actually set, so they are aliases of the respective - // control's properties - property alias walletPath: textFieldWalletPath.text - property alias isLocalWalletEnv: switchLocalWalletEnv.checked - property alias nodeUrl: textFieldNodeUrl.text - property alias logLevel: comboBoxLogLevel.currentIndex - property alias logOutput: listViewLogOutput.currentIndex - property alias logOutputFile: listViewLogOutput.outputFile - property alias cacheLifeTime: textFieldCacheLifeTime.text - property alias cacheUpdateTime: textFieldCacheUpdateTime.text - - Component.onCompleted: { - loadSavedSettings() - } - - function saveCurrentSettings() { - configManager.setValue("skycoin/walletSource/1/Source", walletPath) - configManager.setValue("skycoin/walletSource/1/SourceType", isLocalWalletEnv ? "local" : "remote") - configManager.setValue("skycoin/node/address", nodeUrl) - configManager.setValue("skycoin/log/level", logLevel) - configManager.setValue("skycoin/log/output", logOutput) - configManager.setValue("global/cache/updateTime", cacheUpdateTime) - configManager.setValue("skycoin/log/outputFile", logOutputFile) - configManager.setValue("global/cache/lifeTime", cacheLifeTime) - loadSavedSettings() - } - - function loadSavedSettings() { - walletPath = savedWalletPath = configManager.getValue("skycoin/walletSource/1/Source") - isLocalWalletEnv = savedIsLocalWalletEnv = configManager.getValue("skycoin/walletSource/1/SourceType") === "local" - nodeUrl = savedNodeUrl = configManager.getValue("skycoin/node/address") - logLevel = savedLogLevel = ~~configManager.getValue("skycoin/log/level") - logOutput = savedLogOutput = ~~configManager.getValue("skycoin/log/output") - logOutputFile = savedLogOutputFile = configManager.getValue("skycoin/log/outputFile") - cacheLifeTime = savedLifeTime = configManager.getValue("global/cache/lifeTime") - cacheUpdateTime = savedUpdateTime = configManager.getValue("global/cache/updateTime") - - walletManager.updateAll() - updateFooterButtonsStatus() - } - - function restoreDefaultSettings() { - walletPath = defaultWalletPath - isLocalWalletEnv = defaultIsLocalWalletEnv - nodeUrl = defaultNodeUrl - cacheLifeTime = defaultCacheLifeTime - logLevel = defaultLogLevel - logOutput = defaultLogOutput - - saveCurrentSettings() - } - - function updateFooterButtonsStatus() { - if (Component.status === Component.Ready) { - var configChanged = (walletPath !== savedWalletPath || isLocalWalletEnv !== savedIsLocalWalletEnv || nodeUrl != savedNodeUrl || logLevel != savedLogLevel || logOutput != savedLogOutput || logOutputFile != savedLogOutputFile || cacheLifeTime != savedLifeTime) - var noDefaultConfig = (walletPath !== defaultWalletPath || isLocalWalletEnv !== defaultIsLocalWalletEnv || nodeUrl !== defaultNodeUrl || logLevel !== defaultLogLevel || logOutput !== defaultLogOutput || logOutputFile !== defaultLogOutputFile || cacheLifeTime !== defaultCacheLifeTime) - footer.standardButton(Dialog.Apply).enabled = configChanged - footer.standardButton(Dialog.Discard).enabled = configChanged - footer.standardButton(Dialog.RestoreDefaults).enabled = noDefaultConfig - } - } - - footer: DialogButtonBox { - standardButtons: Dialog.Apply | Dialog.Discard | Dialog.RestoreDefaults - - onApplied: { - saveCurrentSettings() - } - - onDiscarded: { - dialogConfirmation.onlyDiscard = true - dialogConfirmation.open() - } - - onReset: { - dialogConfirmation.onlyDiscard = false - dialogConfirmation.open() - } - } - - ScrollView { - id: scrollView - anchors.fill: parent - contentWidth: width - - ColumnLayout { - id: columnLayout - width: parent.width - spacing: 20 - - GroupBox { - id: groupBoxWalletEnvironment - Layout.fillWidth: true - Layout.topMargin: 10 - Layout.leftMargin: 20 - Layout.rightMargin: 20 - title: qsTr("Wallet environment settings") - - RowLayout { - anchors.fill: parent - - Label { - text: qsTr("Remote") - font.bold: true - color: Material.hintTextColor - } - Switch { - id: switchLocalWalletEnv - - checked: savedIsLocalWalletEnv - font.bold: true - - onToggled: { - updateFooterButtonsStatus() - } - } - Label { - text: qsTr("Local") - font.bold: true - color: Material.accent - } - - Rectangle { - Layout.fillHeight: true - Layout.leftMargin: 10 - Layout.rightMargin: 10 - width: 1 - color: Material.hintTextColor - } - - TextField { - id: textFieldWalletPath - - Layout.fillWidth: true - enabled: isLocalWalletEnv - selectByMouse: true - placeholderText: qsTr("Local wallet path") - - onTextChanged: { - updateFooterButtonsStatus() - } - } - } // RowLayout - } // GroupBox (wallet settings) - - GroupBox { - id: groupBoxNetworkSettings - - Layout.fillWidth: true - Layout.leftMargin: 20 - Layout.rightMargin: 20 - - title: qsTr("Network settings") - - TextField { - id: textFieldNodeUrl - - anchors.fill: parent - selectByMouse: true - placeholderText: qsTr("Node URL") - - onTextChanged: { - updateFooterButtonsStatus() - } - } - } // GroupBox (network settings) - - GroupBox { - id: groupBoxGlobalSettings - - Layout.fillWidth: true - Layout.leftMargin: 20 - Layout.rightMargin: 20 - Layout.bottomMargin: 10 // The Last `GroupBox` must have this set - - title: qsTr("Global settings") - - ColumnLayout { - id: columnLayoutGlobalSettings - anchors.fill: parent - - spacing: 20 - - TextField { - id: textFieldCacheLifeTime - Layout.fillWidth: true - selectByMouse: true - placeholderText: qsTr("Cache lifetime") - onTextChanged: { - updateFooterButtonsStatus(); - } - validator: IntValidator { - bottom: 0 - top: 99999999 - } - } - - TextField { - - id: textFieldCacheUpdateTime - - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - selectByMouse: true - placeholderText: qsTr("Time to update") - - onTextChanged: { - updateFooterButtonsStatus(); - } - validator: IntValidator { - bottom: 0 - top: 99999999 - } - } - - Label { text: qsTr("Log level") } - - ComboBox { - id: comboBoxLogLevel - Layout.fillWidth: true - Layout.topMargin: -20 - - readonly property var logLevelString: [ "debug", "info", "warn", "error", "fatal", "panic" ] - readonly property var logLevelColor: [ Material.Teal, Material.Blue, Material.Amber, Material.DeepOrange, Material.Red, Material.primaryTextColor ] - - currentIndex: savedLogLevel < 0 || savedLogLevel >= count ? defaultLogLevel : savedLogLevel - onCurrentIndexChanged: { - updateFooterButtonsStatus() - } - model: [ qsTr("Debug"), qsTr("Informations"), qsTr("Warnings"), qsTr("Errors"), qsTr("Fatal errors"), qsTr("Panics") ] - delegate: MenuItem { - width: parent.width - text: comboBoxLogLevel.textRole ? (Array.isArray(comboBoxLogLevel.model) ? modelData[comboBoxLogLevel.textRole] : model[comboBoxLogLevel.textRole]) : modelData - icon.source: "qrc:/images/resources/images/icons/log_level_" + comboBoxLogLevel.logLevelString[index] + ".svg" - icon.color: Material.accent - Material.accent: comboBoxLogLevel.logLevelColor[index] - Material.foreground: comboBoxLogLevel.currentIndex === index ? parent.Material.accent : parent.Material.foreground - highlighted: comboBoxLogLevel.highlightedIndex === index - hoverEnabled: comboBoxLogLevel.hoverEnabled - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - } // MenuItem (delegate) - } // ComboBox - - Label { text: qsTr("Log output") } - - ListView { - id: listViewLogOutput - - property alias outputFile: textFieldLogOutputFile.text - readonly property var logOutputString: [ "stdout", "stderr", "none", "file" ] - - Layout.fillWidth: true - Layout.topMargin: -20 - height: contentHeight - - onCurrentIndexChanged: { - updateFooterButtonsStatus() - } - - spacing: -6 - interactive: false - model: [ qsTr("Standard output"), qsTr("Standard error output"), qsTr("None"), qsTr("File") ] - delegate: RadioButton { - width: index === Settings.LogOutput.File && textFieldLogOutputFile.enabled ? implicitWidth : parent.width - text: modelData - checked: savedLogOutput < 0 || savedLogOutput >= ListView.view.count ? index === defaultLogLevel : index === savedLogOutput - - onCheckedChanged: { - if (checked) { - ListView.view.currentIndex = index - if (index === Settings.LogOutput.File) { - textFieldLogOutputFile.forceActiveFocus() - } - } - } - } // RadioButton (delegate) - - Component.onCompleted: { - textFieldLogOutputFile.anchors.leftMargin = listViewLogOutput.itemAtIndex(3).implicitWidth - } - - TextField { - id: textFieldLogOutputFile - - anchors.bottom: parent.bottom - anchors.bottomMargin: 6 - anchors.left: parent.left - anchors.right: parent.right - - enabled: listViewLogOutput.currentIndex === Settings.LogOutput.File - placeholderText: qsTr("Output file") - selectByMouse: true - } - } // ListView (log output) - } // ColumnLayout (global settings) - } // GroupBox (global settings) - } // ColumnLayout - } // ScrollView - - // Confirm the discard or reset action: - Dialog { - id: dialogConfirmation - - property bool onlyDiscard: true - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 300 ? 300 - 40 : applicationWindow.width - 40 - - standardButtons: Dialog.Ok | Dialog.Cancel - title: qsTr("Confirm action") - modal: true - focus: visible - - ColumnLayout { - width: parent.width - - Label { - id: labelQuestion - - Layout.fillWidth: true - text: (dialogConfirmation.onlyDiscard ? qsTr("Discard all changes?") : qsTr("Restore defaults?")) - font.bold: true - } - Label { - id: labelDescription - - Layout.fillWidth: true - text: qsTr("This action will set the settings to the") + " " + (dialogConfirmation.onlyDiscard ? qsTr("last saved values.") : qsTr("default values.")) - font.italic: true - wrapMode: Text.Wrap - } - } - - Component.onCompleted: { - standardButton(Dialog.Ok).Material.accent = Material.Red - standardButton(Dialog.Ok).highlighted = true - standardButton(Dialog.Ok).text = Qt.binding(function() { return dialogConfirmation.onlyDiscard ? qsTr("Discard") : qsTr("Restore defaults") }) - } - - onAccepted: { - if (onlyDiscard) { - loadSavedSettings() - } else { - restoreDefaultSettings() - } - } - } // Dialog -} diff --git a/src/ui/SettingsAddressBook.qml b/src/ui/SettingsAddressBook.qml deleted file mode 100644 index 1144ed42..00000000 --- a/src/ui/SettingsAddressBook.qml +++ /dev/null @@ -1,160 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -// import "qrc:/ui/src/ui/Controls" -import "Dialogs/" // For quick UI development, switch back to resources when making a release -import "Controls/" // For quick UI development, switch back to resources when making a release - -Page { - id: settingsAddressBook - - enum SecurityType { LowSecurity, MediumSecurity, StrongSecurity } - - property bool enableButtonChangePassword: addrsBookModel.getSecType() === SettingsAddressBook.SecurityType.StrongSecurity - - signal canceled() - - footer: DialogButtonBox { - id: footer - standardButtons: Dialog.Apply | Dialog.Cancel - - onApplied: { - if (addrsBookModel.getSecType() === SettingsAddressBook.SecurityType.StrongSecurity) { - dialogGetPassword.open() - } else { - if (listViewSecurityType.currentIndex === SettingsAddressBook.SecurityType.StrongSecurity) { - dialogSetPassword.open() - } else { - footer.standardButton(Dialog.Apply).enabled = !addrsBookModel.changeSecType(listViewSecurityType.currentIndex, "", "") - enableButtonChangePassword = false - } - } - } - - onRejected: { - canceled() - } - } - - ScrollView { - id: scrollView - anchors.fill: parent - contentWidth: width - clip: true - - ColumnLayout { - anchors.fill: parent - - Label { - Layout.topMargin: 10 - Layout.leftMargin: 20 - Layout.rightMargin: 20 - Layout.fillWidth: true - - text: qsTr("Security type") - wrapMode: Text.Wrap - font.bold: true - } - - ListView { - id: listViewSecurityType - - Layout.fillWidth: true - Layout.leftMargin: 20 - Layout.rightMargin: 20 - height: contentHeight - - spacing: -6 - interactive: false - currentIndex: addrsBookModel.getSecType() - model: [ qsTr("Low (plain text)"), qsTr("Medium (recommended)"), qsTr("Hard (with password)") ] - delegate: RadioButton { - width: parent.width - text: modelData - checked: index === ListView.view.currentIndex - - onCheckedChanged: { - if (checked) { - ListView.view.currentIndex = index - footer.standardButton(Dialog.Apply).enabled = index !== addrsBookModel.getSecType() - } - } - - Button { - id: buttonChangePassword - - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - - visible: index === SettingsAddressBook.SecurityType.StrongSecurity - enabled: visible && enableButtonChangePassword - text: qsTr("Change password") - highlighted: true - - onClicked: { - dialogGetPassword.open() - } - } - } // RadioButton (delegate) - } // ListView (log output) - - Label { - Layout.leftMargin: 20 - Layout.rightMargin: 20 - Layout.fillWidth: true - - visible: listViewSecurityType.currentIndex === DialogSelectSecType.SecurityType.StrongSecurity - text: "" + qsTr("Note:") + " " + qsTr("Accessing a password-protected address book can slowdown your device") - wrapMode: Text.Wrap - Material.foreground: Material.Red - font.italic: true - } - } // ColumnLayout - } // ScrollView - - AddrsBookModel { - id: addrsBookModel - } - - DialogGetPassword { - id: dialogGetPassword - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 280 ? 280 - 40 : applicationWindow.height - 40 - - modal: true - focus: visible - - onAccepted: { - if(!addrsBookModel.authenticate(dialogGetPassword.password)) { - dialogGetPassword.open() - } else { - if (listViewSecurityType.currentIndex === SettingsAddressBook.SecurityType.StrongSecurity) { - dialogSetPassword.open() - } else { - footer.standardButton(Dialog.Apply).enabled = !addrsBookModel.changeSecType(listViewSecurityType.currentIndex, dialogGetPassword.password, "") - enableButtonChangePassword = false - } - } - } - } - - DialogSetPassword { - id: dialogSetPassword - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 400 ? 400 - 40 : applicationWindow.width - 40 - - modal: true - focus: visible - - onAccepted: { - footer.standardButton(Dialog.Apply).enabled = !addrsBookModel.changeSecType(SettingsAddressBook.SecurityType.StrongSecurity, dialogGetPassword.password, dialogSetPassword.password) - enableButtonChangePassword = true - } - } -} diff --git a/src/ui/SubPageSendAdvanced.qml b/src/ui/SubPageSendAdvanced.qml deleted file mode 100644 index 09abf32b..00000000 --- a/src/ui/SubPageSendAdvanced.qml +++ /dev/null @@ -1,635 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import WalletsManager 1.0 -import OutputsModels 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -// import "qrc:/ui/src/ui/Dialogs" -// import "qrc:/ui/src/ui/Controls" -import "Delegates" // For quick UI development, switch back to resources when making a release -import "Dialogs" // For quick UI development, switch back to resources when making a release -import "Controls" // For quick UI development, switch back to resources when making a release - -Page { - id: subPageSendAdvanced - - property int upperCoinBound: 0 - property int upperAltCointBound: 0 - property int minFeeAmount: 0 - - function updateInfo() { - subPageSendAdvanced.updateOutputs() - upperCoinBound = 0; - upperAltCointBound = 0; - minFeeAmount = 0; - var valCH = 0; - if (comboBoxWalletsUnspentOutputsSendFrom.enabled) { - for (var i = 0; i < comboBoxWalletsUnspentOutputsSendFrom.checkedElements.length; i++) { - upperCoinBound += parseFloat(comboBoxWalletsUnspentOutputsSendFrom.model.outputs[comboBoxWalletsUnspentOutputsSendFrom.checkedElements[i]].addressSky, 10) - var s = comboBoxWalletsUnspentOutputsSendFrom.model.outputs[comboBoxWalletsUnspentOutputsSendFrom.checkedElements[i]].addressCoinHours - valCH += parseInt(comboBoxWalletsUnspentOutputsSendFrom.model.outputs[comboBoxWalletsUnspentOutputsSendFrom.checkedElements[i]].addressCoinHours.replace('\,',''), 10) - } - } else if (comboBoxWalletsAddressesSendFrom.enabled) { - for (var i = 0; i < comboBoxWalletsAddressesSendFrom.checkedElements.length; i++) { - upperCoinBound += parseFloat(comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].addressSky, 10) - valCH += parseInt(comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].addressCoinHours.replace('\,',''), 10) - } - } else { - for(var i = 0; i < comboBoxWalletsAddressesSendFrom.model.addresses.length; i++) { - upperCoinBound += parseFloat(comboBoxWalletsAddressesSendFrom.model.addresses[i].addressSky, 10) - valCH += parseInt(comboBoxWalletsAddressesSendFrom.model.addresses[i].addressCoinHours.replace('\,',''), 10) - } - } - upperAltCointBound = valCH * 9/10 - minFeeAmount = valCH/10 - } - - function getSelectedAddressesWithWallets() { - var indexs = comboBoxWalletsAddressesSendFrom.getCheckedDelegates() - var addresses = [] - addresses.push([]) - addresses.push([]) - for (var i =0;i< indexs.length; i++) { - addresses[0].push(comboBoxWalletsAddressesSendFrom.model.addresses[indexs[i]].address) - addresses[1].push(comboBoxWalletsAddressesSendFrom.model.addresses[indexs[i]].walletId) - // addresses.push(comboBoxWalletsAddressesSendFrom.model.addresses[indexs[i]].address) - } - return addresses - } - - function getSelectedOutputsWithWallets() { - var indexs = comboBoxWalletsUnspentOutputsSendFrom.getCheckedDelegates() - var outputs = [] - outputs.push([]) - outputs.push([]) - for (var i =0;i< indexs.length; i++) { - outputs[0].push(comboBoxWalletsUnspentOutputsSendFrom.model.outputs[indexs[i]].outputID) - outputs[1].push(comboBoxWalletsUnspentOutputsSendFrom.model.outputs[indexs[i]].walletOwner) - // outputs.push(comboBoxWalletsUnspentOutputsSendFrom.model.outputs[indexs[i]].outputID) - } - return outputs - } - - function getSelectedWallet() { - - var indexs = comboBoxWalletsSendFrom.getCheckedDelegates() - var files = [] - for (var i=0; i < indexs.length; i++) { - files.push(comboBoxWalletsSendFrom.model.wallets[indexs[i]].fileName) - } - return files - } - - function walletIsEncrypted() { - var indexs = comboBoxWalletsSendFrom.getCheckedDelegates() - var enc = [] - for (var i = 0; i < indexs.length; i++){ - var walletEncrypted = [] - walletEncrypted.push(comboBoxWalletsSendFrom.model.wallets[indexs[i]].fileName) - walletEncrypted.push(comboBoxWalletsSendFrom.model.wallets[indexs[i]].name) - walletEncrypted.push(comboBoxWalletsSendFrom.model.wallets[indexs[i]].encryptionEnabled) - enc.push(walletEncrypted) - } - return enc - } - - function getDestinationsSummary() { - var addrs = [] - var skyAmounts = [] - var coinHoursAmount = [] - for (var i = 0; i < listModelDestinations.count; i++) { - addrs.push(listModelDestinations.get(i).address) - skyAmounts.push(listModelDestinations.get(i).sky) - coinHoursAmount.push(listModelDestinations.get(i).coinHours) - } - return [addrs, skyAmounts, coinHoursAmount] - } - - function getChangeAddress() { - return textFieldCustomChangeAddress.text - } - - function getAutomaticCoinHours() { - return checkBoxAutomaticCoinHoursAllocation.checked - } - function getBurnFactor() { - return sliderCoinHoursShareFactor.value - } - - function getAllAddressesWithWallets() { - var addrs = [] - addrs.push([]) - addrs.push([]) - for (var i = 0; i < listAddresses.count; i++) { - addrs[0].push(listAddresses.addresses[i].address) - addrs[1].push(listAddresses.addresses[i].walletId) - // addrs.push(listAddresses.addresses[i].address) - } - return addrs - } - function updateOutputs() { - listOutputs.cleanModel() - if (checkBoxAllAddresses.checked) { - for (var i = 0; i < comboBoxWalletsSendFrom.checkedElements.length; i++) { - walletManager.updateAddresses(comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.checkedElements[i]].fileName) - var addresses = walletManager.getAddresses(comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.checkedElements[i]].fileName) - for(var j = 0; j < addresses.length; j++) { - walletManager.updateOutputs(comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.checkedElements[i]].fileName, addresses[j].address) - listOutputs.insertOutputs(walletManager.getOutputs(comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.checkedElements[i]].fileName, addresses[j].address)) - } - } - } else { - for (var j = 0; j < comboBoxWalletsSendFrom.checkedElements.length; j++) { - walletManager.updateAddresses(comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.checkedElements[j]].fileName) - } - for (var i = 0; i < comboBoxWalletsAddressesSendFrom.checkedElements.length; i++) { - walletManager.updateOutputs(comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].walletId, comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].address) - listOutputs.insertOutputs(walletManager.getOutputs(comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].walletId, comboBoxWalletsAddressesSendFrom.model.addresses[comboBoxWalletsAddressesSendFrom.checkedElements[i]].address)) - } - } - } - - ColumnLayout { - id: columnLayoutRoot - anchors.fill: parent - anchors.leftMargin: 10 - anchors.rightMargin: 10 - spacing: 20 - - ColumnLayout { - id: columnLayoutSendFrom - - Layout.alignment: Qt.AlignTop - - RowLayout { - - Label { text: qsTr("Wallet") } - - ToolButton { - id: toolButtonWalletPopupHelp - icon.source: "qrc:/images/resources/images/icons/help.svg" - icon.color: Material.color(Material.Grey) - } - } - - ComboBox { - id: comboBoxWalletsSendFrom - function getCheckedDelegates() { - return checkedElements - } - - property var checkedElements: [] - property var checkedElementsText: [] - property int numberOfCheckedElements: checkedElements.length - property alias filterString: filterPopupWallets.filterText - - Layout.fillWidth: true - Layout.topMargin: -12 - textRole: "name" - displayText: numberOfCheckedElements > 1 ? (numberOfCheckedElements + ' ' + qsTr("address selected")) : numberOfCheckedElements === 1 ? checkedElementsText[0] : qsTr("No address selected") - model: WalletModel { - Component.onCompleted: { - loadModel(walletManager.getWallets()) - } - } - - popup: FilterComboBoxPopup { - id: filterPopupWallets - comboBox: comboBoxWalletsSendFrom - filterPlaceholderText: qsTr("Filter wallets by name") - } - - // Taken from Qt 5.13.0 source code: - delegate: Item { - id: rootDelegate - - property alias checked: checkDelegate.checked - property alias text: checkDelegate.text - readonly property bool matchFilter: !comboBoxWalletsSendFrom.filterString || text.toLowerCase().includes(comboBoxWalletsSendFrom.filterString.toLowerCase()) - - width: parent.width - height: matchFilter ? checkDelegate.height : 0 - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - clip: true - - CheckDelegate { - id: checkDelegate - - // Update the states saved in `checkedElements` - onClicked: { - if (checked) { - var pos = comboBoxWalletsSendFrom.checkedElements.indexOf(index) - if (pos < 0) { - comboBoxWalletsSendFrom.checkedElements.push(index) - comboBoxWalletsSendFrom.checkedElementsText.push(text) - } - listAddresses.addAddresses(walletManager.getAddresses(comboBoxWalletsSendFrom.model.wallets[index].fileName)) - listOutputs.insertOutputs(walletManager.getOutputsFromWallet(comboBoxWalletsSendFrom.model.wallets[index].fileName)) - } else { - var pos = comboBoxWalletsSendFrom.checkedElements.indexOf(index) - if (pos >= 0) { - comboBoxWalletsSendFrom.checkedElements.splice(pos, 1) - comboBoxWalletsSendFrom.checkedElementsText.splice(pos, 1) - } - // Update Outputs and Addresses Model - listAddresses.removeAddressesFromWallet(comboBoxWalletsSendFrom.model.wallets[index].fileName) - listOutputs.removeOutputsFromWallet(comboBoxWalletsSendFrom.model.wallets[index].fileName) - } - subPageSendAdvanced.updateInfo(); - comboBoxWalletsSendFrom.numberOfCheckedElements = comboBoxWalletsSendFrom.checkedElements.length - } - - width: parent.width - text: comboBoxWalletsSendFrom.textRole ? (Array.isArray(comboBoxWalletsSendFrom.model) ? modelData[comboBoxWalletsSendFrom.textRole] + " - " + modelData["sky"] + " SKY (" + modelData["coinHours"] + " CoinHours)" : model[comboBoxWalletsSendFrom.textRole] + " - " + model["sky"] + " SKY (" + model["coinHours"] + " CoinHours)") : " --- " + modelData - // Load the saved state when the delegate is recicled: - checked: comboBoxWalletsSendFrom.checkedElements.indexOf(index) >= 0 - hoverEnabled: comboBoxWalletsSendFrom.hoverEnabled - highlighted: hovered - Material.foreground: checked ? parent.Material.accent : parent.Material.foreground - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - - LayoutMirroring.enabled: true - contentItem: Label { - leftPadding: comboBoxWalletsSendFrom.indicator.width + comboBoxWalletsSendFrom.spacing - text: checkDelegate.text - verticalAlignment: Qt.AlignVCenter - color: checkDelegate.enabled ? checkDelegate.Material.foreground : checkDelegate.Material.hintTextColor - } - } // CheckDelegate - } // Item (delegate) - } // ComboBox (wallets, send from) - - RowLayout { - - Label { text: qsTr("Address") } - - ToolButton { - id: toolButtonAddressPopupHelp - icon.source: "qrc:/images/resources/images/icons/help.svg" - icon.color: Material.color(Material.Grey) - } - CheckBox { - id: checkBoxAllAddresses - text: qsTr("All Addresses of the selected addresses") - checked: true - onClicked: { - subPageSendAdvanced.updateInfo() - } - } - } - - ComboBox { - id: comboBoxWalletsAddressesSendFrom - function getCheckedDelegates() { - return checkedElements - } - property var checkedElements: [] - property var checkedElementsText: [] - property int numberOfCheckedElements: checkedElements.length - property alias filterString: filterPopupAddresses.filterText - - popup: FilterComboBoxPopup { - id: filterPopupAddresses - comboBox: comboBoxWalletsAddressesSendFrom - filterPlaceholderText: qsTr("Filter Addresses") - } - - Layout.fillWidth: true - Layout.topMargin: -12 - - onModelChanged: { - if (!model) { - checkedElements = [] - checkedElementsText = [] - numberOfCheckedElements = 0 - } - } - - model: AddressModel{ - id: listAddresses - } - - textRole: "address" - displayText: !checkBoxAllAddresses.checked ? (numberOfCheckedElements > 1 ? (numberOfCheckedElements + ' ' + qsTr("addresses selected")) : numberOfCheckedElements === 1 ? checkedElementsText[0] : qsTr("No addresses selected")): "All address selected" - enabled: !checkBoxAllAddresses.checked - delegate: Item { - - property alias checked: checkDelegate.checked - property alias text: checkDelegate.text - readonly property bool matchFilter: !comboBoxWalletsAddressesSendFrom.filterString || text.toLowerCase().includes(comboBoxWalletsAddressesSendFrom.filterString.toLowerCase()) - - width: parent.width - height: matchFilter ? checkDelegate.height : 0 - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - clip: true - - - CheckDelegate { - id: checkDelegate - - width: parent.width - text: comboBoxWalletsAddressesSendFrom.textRole ? (Array.isArray(comboBoxWalletsAddressesSendFrom.model) ? modelData["addressSky"] + " --- " + modelData[comboBoxWalletsAddressesSendFrom.textRole] + " - " + modelData["addressSky"] + " SKY (" + modelData["addressCoinHours"] + " CoinHours)" : model[comboBoxWalletsAddressesSendFrom.textRole] + " - " + model["addressSky"] + " SKY (" + model["addressCoinHours"] + " CoinHours)") : modelData - font.family: "Code New Roman" - - LayoutMirroring.enabled: true - contentItem: Label { - leftPadding: comboBoxWalletsAddressesSendFrom.indicator.width + comboBoxWalletsAddressesSendFrom.spacing - text: checkDelegate.text - verticalAlignment: Qt.AlignVCenter - color: checkDelegate.enabled ? checkDelegate.Material.foreground : checkDelegate.Material.hintTextColor - } - onClicked: { - if (checked) { - var addrText = comboBoxWalletsAddressesSendFrom.textRole ? (Array.isArray(comboBoxWalletsAddressesSendFrom.model) ? modelData[comboBoxWalletsAddressesSendFrom.textRole] : model[comboBoxWalletsAddressesSendFrom.textRole]) : modelData; - if (comboBoxWalletsAddressesSendFrom.getCheckedDelegates().length > 1){ - listOutputs.insertOutputs(walletManager.getOutputs(comboBoxWalletsAddressesSendFrom.model.addresses[index].walletId, addrText)) - } else{ - listOutputs.loadModel(walletManager.getOutputs(comboBoxWalletsAddressesSendFrom.model.addresses[index].walletId, addrText)) - } - var pos = comboBoxWalletsAddressesSendFrom.checkedElements.indexOf(index) - if (pos < 0) { - comboBoxWalletsAddressesSendFrom.checkedElements.push(index) - comboBoxWalletsAddressesSendFrom.checkedElementsText.push(text) - } - } else { - listOutputs.removeOutputsFromAddress(text) - if (comboBoxWalletsAddressesSendFrom.getCheckedDelegates().length == 0){ - var indexs = comboBoxWalletsSendFrom.getCheckedDelegates() - for (var i = 0; i < indexs.length; i++){ - listOutputs.insertOutputs(walletManager.getOutputsFromWallet(comboBoxWalletsSendFrom.model.wallets[indexs[i]].fileName)) - } - } - var pos = comboBoxWalletsAddressesSendFrom.checkedElements.indexOf(index) - if (pos >= 0) { - comboBoxWalletsAddressesSendFrom.checkedElements.splice(pos, 1) - comboBoxWalletsAddressesSendFrom.checkedElementsText.splice(pos, 1) - } - } - subPageSendAdvanced.updateInfo(); - comboBoxWalletsAddressesSendFrom.numberOfCheckedElements = comboBoxWalletsAddressesSendFrom.checkedElements.length - } - - } // CheckDelegate - } // Item (delegate) - } // ComboBox (addresses, send from) - - RowLayout { - - Label { text: qsTr("Unspent outputs") } - - ToolButton { - id: toolButtonUnspentOutputsPopupHelp - icon.source: "qrc:/images/resources/images/icons/help.svg" - icon.color: Material.color(Material.Grey) - } - - CheckBox { - id: checkBoxUnspentOutputsUseAllOutputs - text: qsTr("All outputs of the selected addresses") - checked: true - onClicked: { - subPageSendAdvanced.updateInfo() - } - } - } - - ComboBox { - id: comboBoxWalletsUnspentOutputsSendFrom - - function getCheckedDelegates() { - return checkedElements - } - property var checkedElements: [] - property var checkedElementsText: [] - property int numberOfCheckedElements: checkedElements.length - property alias filterString: filterPopupOutputs.filterText - - Layout.fillWidth: true - Layout.topMargin: -12 - textRole: "outputID" - displayText: checkBoxUnspentOutputsUseAllOutputs.checked ? qsTr("All outputs selected") : numberOfCheckedElements > 1 ? (numberOfCheckedElements + ' ' + qsTr("outputs selected")) : numberOfCheckedElements === 1 ? checkedElementsText[0] : qsTr("No output selected") - - enabled: !checkBoxUnspentOutputsUseAllOutputs.checked - model: QOutputs { - id: listOutputs - } - - onModelChanged: { - if (!model) { - checkedElements = [] - checkedElementsText = [] - numberOfCheckedElements = 0 - } - } - - popup: FilterComboBoxPopup { - id: filterPopupOutputs - comboBox: comboBoxWalletsUnspentOutputsSendFrom - filterPlaceholderText: qsTr("Filter outputs") - } - - delegate: Item { - - property alias checked: checkDelegate.checked - property alias text: checkDelegate.text - readonly property bool matchFilter: !comboBoxWalletsUnspentOutputsSendFrom.filterString || text.toLowerCase().includes(comboBoxWalletsUnspentOutputsSendFrom.filterString.toLowerCase()) - - width: parent.width - height: matchFilter ? checkDelegate.height : 0 - Behavior on height { NumberAnimation { easing.type: Easing.OutQuint } } - clip: true - - CheckDelegate { - id: checkDelegate - - // Update the states saved in `checkedElements` - onClicked: { - if (checked) { - var pos = comboBoxWalletsUnspentOutputsSendFrom.checkedElements.indexOf(index) - if (pos < 0) { - comboBoxWalletsUnspentOutputsSendFrom.checkedElements.push(index) - comboBoxWalletsUnspentOutputsSendFrom.checkedElementsText.push(text) - } - } else { - var pos = comboBoxWalletsUnspentOutputsSendFrom.checkedElements.indexOf(index) - if (pos >= 0) { - comboBoxWalletsUnspentOutputsSendFrom.checkedElements.splice(pos, 1) - comboBoxWalletsUnspentOutputsSendFrom.checkedElementsText.splice(pos, 1) - } - } - comboBoxWalletsUnspentOutputsSendFrom.numberOfCheckedElements = comboBoxWalletsUnspentOutputsSendFrom.checkedElements.length - subPageSendAdvanced.updateInfo(); - } - - width: parent.width - text: comboBoxWalletsUnspentOutputsSendFrom.textRole ? (Array.isArray(comboBoxWalletsUnspentOutputsSendFrom.model) ? modelData[comboBoxWalletsUnspentOutputsSendFrom.textRole] + " - " + modelData["addressSky"] + " SKY (" + modelData["addressCoinHours"] + " CoinHours)" :model[comboBoxWalletsUnspentOutputsSendFrom.textRole] + " - " + model["addressSky"] + " SKY (" + model["addressCoinHours"] + " CoinHours)") : modelData - font.family: "Code New Roman" - // Load the saved state when the delegate is recicled: - checked: comboBoxWalletsUnspentOutputsSendFrom.checkedElements.indexOf(index) >= 0 - hoverEnabled: comboBoxWalletsSendFrom.hoverEnabled - highlighted: hovered - Material.foreground: checked ? parent.Material.accent : parent.Material.foreground - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - - LayoutMirroring.enabled: true - contentItem: Label { - leftPadding: comboBoxWalletsUnspentOutputsSendFrom.indicator.width + comboBoxWalletsUnspentOutputsSendFrom.spacing - text: checkDelegate.text - verticalAlignment: Qt.AlignVCenter - color: checkDelegate.enabled ? checkDelegate.Material.foreground : checkDelegate.Material.hintTextColor - } - } // CheckDelegate - } // Item (delegate) - } // ComboBox (outputs, send from) - - } // ColumnLayout (send from) - - - Label { - Layout.fillWidth: true - Layout.preferredHeight: 30 - text: "With your current selection you can send up to " + subPageSendAdvanced.upperCoinBound + " SKY and " + subPageSendAdvanced.upperAltCointBound + " Coin Hours (at least " + subPageSendAdvanced.minFeeAmount + " Coin Hours must be used for the transaction fee)" - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignHCenter - } - - ColumnLayout { - id: columnLayoutDestinations - - Layout.alignment: Qt.AlignTop - - RowLayout { - - Label { text: qsTr("Destinations") } - - ToolButton { - id: toolButtonDestinationPopupHelp - icon.source: "qrc:/images/resources/images/icons/help.svg" - icon.color: Material.color(Material.Grey) - } - } - - ListView { - id: listViewDestinations - - Layout.fillWidth: true - Layout.topMargin: -16 - implicitHeight: contentItem.height - Behavior on implicitHeight { NumberAnimation { duration: 250; easing.type: Easing.OutQuint } } - - interactive: false - clip: true - - model: listModelDestinations - - delegate: DestinationListDelegate { - width: listViewDestinations.width - } - } // ListView - } // ColumnLayout (destinations) - - ColumnLayout { - id: columnLayoutCustomChangeAddress - - Layout.alignment: Qt.AlignTop - - RowLayout { - - Label { text: qsTr("Custom change address") } - - ToolButton { - id: toolButtonCustomChangeAddressPopupHelp - icon.source: "qrc:/images/resources/images/icons/help.svg" - icon.color: Material.color(Material.Grey) - } - - Button { - id: buttonSelectCustomChangeAddress - text: qsTr("Select") - flat: true - highlighted: true - - onClicked: { - modelAddressesByWallet.loadModel(walletManager.getAllAddresses()) - dialogSelectAddressByWallet.open() - } - } - } - - TextField { - id: textFieldCustomChangeAddress - - Layout.fillWidth: true - Layout.topMargin: -16 - placeholderText: qsTr("Address to receive change") - selectByMouse: true - font.family: "Code New Roman" - } - } // ColumnLayout (custom change address) - - ColumnLayout { - id: columnLayoutAutomaticCoinHoursAllocation - - Layout.fillWidth: true - - Layout.alignment: Qt.AlignTop - - CheckBox { - id: checkBoxAutomaticCoinHoursAllocation - text: qsTr("Automatic coin hours allocation") - checked: true - } - - Slider { - id: sliderCoinHoursShareFactor - - Layout.preferredWidth: parent.width < 500 ? 500 : parent.width - - opacity: checkBoxAutomaticCoinHoursAllocation.checked ? 1.0 : 0.0 - Behavior on opacity { NumberAnimation {} } - from: 0.01 - to: 1.00 - value: 0.50 - stepSize: 0.01 - - ToolTip { - parent: sliderCoinHoursShareFactor.handle - visible: sliderCoinHoursShareFactor.pressed - text: sliderCoinHoursShareFactor.value.toFixed(2) - font.pointSize: Qt.application.font.pointSize * 1.2 - } - } - } // ColumnLayout (automatic coin hours allocation) - } // ColumnLayout (root) - - DialogSelectAddressByWallet { - id: dialogSelectAddressByWallet - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height - 40 - - model: modelAddressesByWallet - - focus: true - modal: true - - onAccepted: { - textFieldCustomChangeAddress.text = selectedAddress - } - } - - AddressModel{ - id: modelAddressesByWallet - } - - ListModel { - id: listModelDestinations - ListElement { address: ""; sky: "0.0"; coinHours: "0.0" } - } -} diff --git a/src/ui/SubPageSendSimple.qml b/src/ui/SubPageSendSimple.qml deleted file mode 100644 index 59f03cf8..00000000 --- a/src/ui/SubPageSendSimple.qml +++ /dev/null @@ -1,259 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import WalletsManager 1.0 -import AddrsBookManager 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -// import "qrc:/ui/src/ui/Controls" -import "Dialogs" // For quick UI development, switch back to resources when making a release -import "Controls" // For quick UI development, switch back to resources when making a release - -Page { - id: root - property string walletSelected - property string walletSelectedName - property string signerSelected - property bool walletEncrypted: false - property string amount - property string destinationAddress - function getSelectedWallet(){ - return walletSelected - } - function getSignerSelected() { - return signerSelected; - } - - function getAmount(){ - return amount - } - function getDestinationAddress(){ - return destinationAddress - } - function walletIsEncrypted(){ - return [walletSelected, walletSelectedName, walletEncrypted] - } - signal qrCodeRequested(var data) - -function getAddressList(){ -addressList.clear() -for(var i=0;i 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height - 40 - - listAddrsModel: addressList - - focus: true - modal: true - -onAboutToShow:{ -getAddressList() -} - - onAccepted: { - textFieldWalletsSendTo.text = selectedAddress - } - } - - DialogGetPassword{ - id:getpass - anchors.centerIn: Overlay.overlay - height:180 - onAccepted:{ - if(!abm.authenticate(getpass.password)){ - getpass.open() - }else{ - abm.loadContacts() - dialogSelectAddressByAddressBook.open() - } - } - } - - ColumnLayout { - id: columnLayoutRoot - anchors.fill: parent - anchors.leftMargin: 10 - anchors.rightMargin: 10 - spacing: 20 - - RowLayout { - spacing: 20 - ColumnLayout { - id: columnLayoutSendFrom - - Layout.alignment: Qt.AlignTop - - Label { text: qsTr("Send from") } - - ComboBox { - Layout.fillWidth: true - id: comboBoxWalletsSendFrom - textRole: "name" - displayText: comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex] && comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].sky ? comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].name + " - " + comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].sky + " SKY (" + comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].coinHours + " CoinHours)" : "Select a wallet" - model: WalletModel { - Component.onCompleted: { - loadModel(walletManager.getWallets()) - } - } - - // Taken from Qt 5.13.0 source code: - delegate: MenuItem { - width: parent.width - text: comboBoxWalletsSendFrom.textRole ? (Array.isArray(comboBoxWalletsSendFrom.model) ? modelData[comboBoxWalletsSendFrom.textRole] : model[comboBoxWalletsSendFrom.textRole] + " - "+model["sky"] + " SKY (" + model["coinHours"] + " CoinHours)") : " --- " + modelData - Material.foreground: comboBoxWalletsSendFrom.currentIndex === index ? parent.Material.accent : parent.Material.foreground - highlighted: comboBoxWalletsSendFrom.highlightedIndex === index - hoverEnabled: comboBoxWalletsSendFrom.hoverEnabled - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - } - onPressedChanged: { - comboBoxWalletsSendFrom.model.updateModel(walletManager.getWallets()) - } - onActivated: { - root.walletSelected = comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].fileName - root.walletSelectedName = comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].name - root.walletEncrypted = comboBoxWalletsSendFrom.model.wallets[comboBoxWalletsSendFrom.currentIndex].encryptionEnabled - signerSelector.reset(root.walletSelected); - } - } // ComboBox - } // ColumnLayout (send from) - ColumnLayout { - id: signerSelectorId - Layout.alignment: Qt.AlignTop - visible: false - - Label { text: qsTr("Change signer") } - ComboBox { - Layout.fillWidth: true - id: signerSelector - textRole: "description" - model: SignerModel { - id: signerModelId - } - // Taken from Qt 5.13.0 source code: - delegate: MenuItem { - id: selectedSignerDelegateId - width: parent.width - text: signerSelector.textRole ? - (Array.isArray(signerSelector.model) - ? modelData[signerSelector.textRole] - : model[signerSelector.textRole]) - : modelData - Material.foreground: signerSelector.currentIndex === index ? parent.Material.accent : parent.Material.foreground - highlighted: signerSelector.highlightedIndex === index - hoverEnabled: signerSelector.hoverEnabled - leftPadding: highlighted ? 2*padding : padding // added - Behavior on leftPadding { NumberAnimation { duration: 500; easing.type: Easing.OutQuint } } // added - onClicked: { - root.signerSelected = - Array.isArray(signerSelector.model) - ? modelData["id"] : model["id"]; - } - } - function reset(wltId) { - currentIndex = 0; - signerModelId.loadModel(wltId) - signerSelectorId.visible = signerModelId.rowCount() > 1 - } - } - } - } - - - ColumnLayout { - id: columnLayoutSendTo - - Layout.alignment: Qt.AlignTop - - Label { text: qsTr("Send to") } - - Button { - id: buttonSelectCustomChangeAddress - text: qsTr("Select") - flat: true - highlighted: true - - onClicked: { - if(abm.getSecType()!=2){ - abm.loadContacts() - dialogSelectAddressByAddressBook.open() - }else{ - getpass.open() - } - } - } - - RowLayout { - Layout.fillWidth: true - spacing: 8 - - ToolButtonQR { - id: toolButtonQR - Layout.bottomMargin: 4 - - iconSize: "24x24" - - onClicked: { - qrCodeRequested(textFieldWalletsSendTo.text) - } - } - - TextField { - id: textFieldWalletsSendTo - font.family: "Code New Roman" - placeholderText: qsTr("Destination address") - selectByMouse: true - Layout.fillWidth: true - Layout.topMargin: -5 - Material.accent: abm.addressIsValid(text) ? parent.Material.accent : Material.color(Material.Red) - onTextChanged:{ - root.destinationAddress = text - - } - } - } // RowLayout - } // ColumnLayout (send to) - - TextField { - id: textFieldAmount - placeholderText: qsTr("Amount to send") - selectByMouse: true - Layout.fillWidth: true - Layout.topMargin: -10 - validator: DoubleValidator { - notation: DoubleValidator.StandardNotation - } - onTextChanged:{ - root.amount = text - } - } - } // ColumnLayout (root) - - ListModel{ - id:addressList - } -} diff --git a/src/ui/ToolButtonQR.qml b/src/ui/ToolButtonQR.qml deleted file mode 100644 index d1761ead..00000000 --- a/src/ui/ToolButtonQR.qml +++ /dev/null @@ -1,16 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 - -ToolButton { - id: toolButtonQR - - property size iconSize: "16x16" - - icon.source: "qrc:/images/resources/images/icons/qr.svg" - icon.width: iconSize.width - icon.height: iconSize.height - - ToolTip.text: qsTr("Show QR code") - ToolTip.visible: hovered // TODO: pressed when mobile? - ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval -} diff --git a/src/ui/TransactionDetails.qml b/src/ui/TransactionDetails.qml deleted file mode 100644 index a93fd0bc..00000000 --- a/src/ui/TransactionDetails.qml +++ /dev/null @@ -1,256 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 -import HistoryModels 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Delegates" -import "Delegates/" // For quick UI development, switch back to resources when making a release - -// Backend imports -import HistoryModels 1.0 - -Item { - id: root - - property date date: "2000-01-01 00:00" - property int type: TransactionDetails.Type.Send - property int status: TransactionDetails.Status.Preview - property var statusString: [ qsTr("Confirmed"), qsTr("Pending"), qsTr("Preview") ] - property real amount: 0 - property string hoursReceived - property string hoursBurned - property string transactionID - property QAddressList modelInputs - property QAddressList modelOutputs - - readonly property bool expanded: buttonMoreDetails.checked - - enum Status { - Confirmed, - Pending, - Preview - } - enum Type { - Send, - Receive, - Internal - } - - readonly property real basicHeight: 80 + rowLayoutBasicDetails.height - implicitHeight: Math.min(basicHeight + (expanded ? Math.max(listViewInputs.height, listViewOutputs.height) : 0), maxHeight) - Behavior on implicitHeight { NumberAnimation { duration: 1000; easing.type: Easing.OutQuint } } - - clip: true - - ColumnLayout { - id: columnLayoutRoot - anchors.fill: parent - spacing: 20 - - RowLayout { - id: rowLayoutBasicDetails - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - ColumnLayout { - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - Label { - text: qsTr("Transaction") - font.bold: true - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - } - - GridLayout { - id: gridLayoutBasicInfo - Material.foreground: Material.Grey - columns: 2 - columnSpacing: 10 - - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - Label { - text: qsTr("Date:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: Qt.formatDateTime(root.date, Qt.DefaultLocaleShortDate) - font.pointSize: Qt.application.font.pointSize * 0.9 - } - - Label { - text: qsTr("Status:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: statusString[root.status] - font.pointSize: Qt.application.font.pointSize * 0.9 - } - - Label { - text: qsTr("Hours:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: root.hoursReceived + ' ' + qsTr("received") + ' | ' + hoursBurned + ' ' + qsTr("burned") - font.pointSize: Qt.application.font.pointSize * 0.9 - } - - Label { - text: qsTr("Tx ID:") - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - } - Label { - text: root.transactionID - font.pointSize: Qt.application.font.pointSize * 0.9 - Layout.fillWidth: true - } - } // GridLayout - } - - ColumnLayout { - Layout.alignment: Qt.AlignTop - Layout.topMargin: -10 - Layout.rightMargin: 20 - Image { - source: "qrc:/images/resources/images/icons/send-" + (type === TransactionDetails.Type.Receive ? "blue" : "amber") + ".svg" - sourceSize: "72x72" - fillMode: Image.PreserveAspectFit - mirror: type === TransactionDetails.Type.Receive - Layout.fillWidth: true - } - Label { - text: (type === TransactionDetails.Type.Receive ? qsTr("Receive") : qsTr("Send")) + ' ' + amount + ' ' + qsTr("SKY") - font.bold: true - font.pointSize: Qt.application.font.pointSize * 1.15 - horizontalAlignment: Label.AlignHCenter - Layout.fillWidth: true - } - } - } // RowLayout - - RowLayout { - id: rowLayoutDetailsSeparator - - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - Button { - id: buttonMoreDetails - implicitWidth: 200 - flat: true - checkable: true - text: checked ? qsTr("Less details") : qsTr("More details") - } - - Rectangle { - height: 1 - color: Material.color(Material.Grey) - Layout.alignment: Qt.AlignVCenter - Layout.fillWidth: true - } - } - - RowLayout { - id: rowLayoutMoreDetails - - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - Layout.fillHeight: true - - opacity: expanded ? 1 : 0 - Behavior on opacity { NumberAnimation { duration: 1000; easing.type: Easing.OutQuint } } - - ColumnLayout { - id: columnLayoutInputs - Layout.fillWidth: true - Layout.fillHeight: true - - Label { - text: qsTr("Inputs") - font.bold: true - font.italic: true - Layout.fillWidth: true - } - - ScrollView { - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - id: listViewInputs - - Material.foreground: Material.Grey - model: modelInputs - clip: true - delegate: InputOutputDelegate { - width: parent.width - } - } - } // ScrollView - } // ColumnLayout (inputs) - - ColumnLayout { - id: columnLayoutOutputs - Layout.fillWidth: true - Layout.fillHeight: true - - Label { - text: qsTr("Outputs") - font.bold: true - font.italic: true - Layout.fillWidth: true - } - - ScrollView { - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - Layout.fillHeight: true - - ListView { - id: listViewOutputs - - Material.foreground: Material.Grey - model: modelOutputs - clip: true - delegate: InputOutputDelegate { - width: parent.width - } - } - } // ScrollView - } // ColumnLayout (outputs) - } // RowLayout (details) - } // ColumnLayout (root) - - // Roles: address, addressSky, addressCoinHours - // Use listModel.append( { "address": value, "addressSky": value, "addressCoinHours": value } ) - // Or implement the model in the backend (a more recommendable approach) - // ListModel { - // id: listModelInputs - // ListElement { address: "qrxw7364w8xerusftaxkw87ues"; addressSky: 30; addressCoinHours: 1049 } - // ListElement { address: "8745yuetsrk8tcsku4ryj48ije"; addressSky: 12; addressCoinHours: 16011 } - // } - // ListModel { - // id: listModelOutputs - // ListElement { address: "734irweaweygtawieta783cwyc"; addressSky: 38; addressCoinHours: 5048 } - // ListElement { address: "ekq03i3qerwhjqoqh9823yurig"; addressSky: 61; addressCoinHours: 9456 } - // ListElement { address: "1kjher73yiner7wn32nkuwe94v"; addressSky: 1; addressCoinHours: 24 } - // ListElement { address: "oopfwwklfd34iuhjwe83w3h28r"; addressSky: 111; addressCoinHours: 13548 } - // } - // QAddressList{ - // id: listModelInputs - // } - // QAddressList{ - // id: listModelOutputs - // } -} diff --git a/src/ui/Utils/QRCode.qml b/src/ui/Utils/QRCode.qml deleted file mode 100644 index 82f35494..00000000 --- a/src/ui/Utils/QRCode.qml +++ /dev/null @@ -1,51 +0,0 @@ -import QtQuick 2.0 - -import "qqr.js" as QRCodeBackend // For quick UI development, switch back to resources when making a release - -Canvas { - id: canvas - // background colour to be used - property color background : "white" - // foreground colour to be used - property color foreground : "black" - // ECC level to be applied (e.g. L, M, Q, H) - property string level : "L" - // value to be encoded in the generated QR code - property string value : "" - - onPaint : { - var qr = QRCodeBackend.get_qr() - qr.canvas({ - background : canvas.background, - canvas : canvas, - value: canvas.value, - foreground : canvas.foreground, - level : canvas.level, - side : Math.min(canvas.width, canvas.height), - value : canvas.value - }) - } - onHeightChanged : { - requestPaint() - } - - onWidthChanged : { - requestPaint() - } - - onBackgroundChanged : { - requestPaint() - } - - onForegroundChanged : { - requestPaint() - } - - onLevelChanged : { - requestPaint() - } - - onValueChanged : { - requestPaint() - } -} diff --git a/src/ui/Utils/qqr.js b/src/ui/Utils/qqr.js deleted file mode 100644 index 8fe3a623..00000000 --- a/src/ui/Utils/qqr.js +++ /dev/null @@ -1,1198 +0,0 @@ -// [qr.js](http://neocotic.com/qr.js) -// (c) 2014 Alasdair Mercer -// Licensed under the GPL Version 3 license. -// Based on [jsqrencode](http://code.google.com/p/jsqrencode/) -// (c) 2010 tz@execpc.com -// Licensed under the GPL Version 3 license. -// For all details and documentation: -// - -.pragma library - -var _qr_instance - -(function (root) { - - 'use strict'; - - // Private constants - // ----------------- - - // Alignment pattern. - var ALIGNMENT_DELTA = [ - 0, 11, 15, 19, 23, 27, 31, - 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, - 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 - ]; - // Default MIME type. - var DEFAULT_MIME = 'image/png'; - // MIME used to initiate a browser download prompt when `qr.save` is called. - var DOWNLOAD_MIME = 'image/octet-stream'; - // There are four elements per version. The first two indicate the number of blocks, then the - // data width, and finally the ECC width. - var ECC_BLOCKS = [ - 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, - 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, - 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, - 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, - 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, - 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, - 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, - 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, - 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, - 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, - 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, - 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, - 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, - 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, - 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, - 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, - 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, - 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, - 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, - 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, - 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, - 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, - 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, - 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, - 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, - 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, - 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, - 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, - 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, - 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, - 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, - 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, - 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, - 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, - 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, - 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, - 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, - 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, - 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, - 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 - ]; - // Map of human-readable ECC levels. - var ECC_LEVELS = { - L: 1, - M: 2, - Q: 3, - H: 4 - }; - // Final format bits with mask (level << 3 | mask). - var FINAL_FORMAT = [ - 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, /* L */ - 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, /* M */ - 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, /* Q */ - 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b /* H */ - ]; - // Galois field exponent table. - var GALOIS_EXPONENT = [ - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, - 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, - 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, - 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, - 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, - 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, - 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, - 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, - 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, - 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, - 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, - 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, - 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, - 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, - 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, - 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 - ]; - // Galois field log table. - var GALOIS_LOG = [ - 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, - 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, - 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, - 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, - 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, - 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, - 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, - 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, - 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, - 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, - 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, - 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, - 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, - 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, - 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, - 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf - ]; - // *Badness* coefficients. - var N1 = 3; - var N2 = 3; - var N3 = 40; - var N4 = 10; - // Version pattern. - var VERSION_BLOCK = [ - 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532, - 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5, - 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69 - ]; - // Mode for node.js file system file writes. - var WRITE_MODE = parseInt('0666', 8); - - // Private variables - // ----------------- - - // Run lengths for badness. - var badBuffer = []; - // Constructor for `canvas` elements in the node.js environment. - var Canvas; - // Data block. - var dataBlock; - // ECC data blocks and tables. - var eccBlock, neccBlock1, neccBlock2; - // ECC buffer. - var eccBuffer = []; - // ECC level (defaults to **L**). - var eccLevel = 1; - // Image buffer. - var frameBuffer = []; - // Fixed part of the image. - var frameMask = []; - // File system within the node.js environment. - var fs; - // Constructor for `img` elements in the node.js environment. - var Image; - // Indicates whether or not this script is running in node.js. - var inNode = false; - // Generator polynomial. - var polynomial = []; - // Save the previous value of the `qr` variable. - var previousQr = root.qr; - // Data input buffer. - var stringBuffer = []; - // Version for the data. - var version; - // Data width is based on `version`. - var width; - - // Private functions - // ----------------- - - // Create a new canvas using `document.createElement` unless script is running in node.js, in - // which case the `canvas` module is used. - function createCanvas() { - return inNode ? new Canvas() : root.document.createElement('canvas'); - } - - // Create a new image using `document.createElement` unless script is running in node.js, in - // which case the `canvas` module is used. - function createImage() { - return inNode ? new Image() : root.document.createElement('img'); - } - - // Force the canvas image to be downloaded in the browser. - // Optionally, a `callback` function can be specified which will be called upon completed. Since - // this is not an asynchronous operation, this is merely convenient and helps simplify the - // calling code. - function download(cvs, data, callback) { - var mime = data.mime || DEFAULT_MIME; - - root.location.href = cvs.toDataURL(mime).replace(mime, DOWNLOAD_MIME); - - if (typeof callback === 'function') callback(); - } - - // Normalize the `data` that is provided to the main API. - function normalizeData(data) { - if (typeof data === 'string') data = { value: data }; - return data || {}; - } - - // Override the `qr` API methods that require HTML5 canvas support to throw a relevant error. - function overrideAPI(qr) { - var methods = [ 'canvas', 'image', 'save', 'saveSync', 'toDataURL' ]; - var i; - - function overrideMethod(name) { - qr[name] = function () { - throw new Error(name + ' requires HTML5 canvas element support'); - }; - } - - for (i = 0; i < methods.length; i++) { - overrideMethod(methods[i]); - } - } - - // Asynchronously write the data of the rendered canvas to a given file path. - function writeFile(cvs, data, callback) { - if (typeof data.path !== 'string') { - return callback(new TypeError('Invalid path type: ' + typeof data.path)); - } - - var fd, buff; - - // Write the buffer to the open file stream once both prerequisites are met. - function writeBuffer() { - fs.write(fd, buff, 0, buff.length, 0, function (error) { - fs.close(fd); - - callback(error); - }); - } - - // Create a buffer of the canvas' data. - cvs.toBuffer(function (error, _buff) { - if (error) return callback(error); - - buff = _buff; - if (fd) { - writeBuffer(); - } - }); - - // Open a stream for the file to be written. - fs.open(data.path, 'w', WRITE_MODE, function (error, _fd) { - if (error) return callback(error); - - fd = _fd; - if (buff) { - writeBuffer(); - } - }); - } - - // Write the data of the rendered canvas to a given file path. - function writeFileSync(cvs, data) { - if (typeof data.path !== 'string') { - throw new TypeError('Invalid path type: ' + typeof data.path); - } - - var buff = cvs.toBuffer(); - var fd = fs.openSync(data.path, 'w', WRITE_MODE); - - try { - fs.writeSync(fd, buff, 0, buff.length, 0); - } finally { - fs.closeSync(fd); - } - } - - // Set bit to indicate cell in frame is immutable (symmetric around diagonal). - function setMask(x, y) { - var bit; - - if (x > y) { - bit = x; - x = y; - y = bit; - } - - bit = y; - bit *= y; - bit += y; - bit >>= 1; - bit += x; - - frameMask[bit] = 1; - } - - // Enter alignment pattern. Foreground colour to frame, background to mask. Frame will be merged - // with mask later. - function addAlignment(x, y) { - var i; - - frameBuffer[x + width * y] = 1; - - for (i = -2; i < 2; i++) { - frameBuffer[(x + i) + width * (y - 2)] = 1; - frameBuffer[(x - 2) + width * (y + i + 1)] = 1; - frameBuffer[(x + 2) + width * (y + i)] = 1; - frameBuffer[(x + i + 1) + width * (y + 2)] = 1; - } - - for (i = 0; i < 2; i++) { - setMask(x - 1, y + i); - setMask(x + 1, y - i); - setMask(x - i, y - 1); - setMask(x + i, y + 1); - } - } - - // Exponentiation mod N. - function modN(x) { - while (x >= 255) { - x -= 255; - x = (x >> 8) + (x & 255); - } - - return x; - } - - // Calculate and append `ecc` data to the `data` block. If block is in the string buffer the - // indices to buffers are used. - function appendData(data, dataLength, ecc, eccLength) { - var bit, i, j; - - for (i = 0; i < eccLength; i++) { - stringBuffer[ecc + i] = 0; - } - - for (i = 0; i < dataLength; i++) { - bit = GALOIS_LOG[stringBuffer[data + i] ^ stringBuffer[ecc]]; - - if (bit !== 255) { - for (j = 1; j < eccLength; j++) { - stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^ - GALOIS_EXPONENT[modN(bit + polynomial[eccLength - j])]; - } - } else { - for (j = ecc; j < ecc + eccLength; j++) { - stringBuffer[j] = stringBuffer[j + 1]; - } - } - - stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 : - GALOIS_EXPONENT[modN(bit + polynomial[0])]; - } - } - - // Check mask since symmetricals use half. - function isMasked(x, y) { - var bit; - - if (x > y) { - bit = x; - x = y; - y = bit; - } - - bit = y; - bit += y * y; - bit >>= 1; - bit += x; - - return frameMask[bit] === 1; - } - - // Apply the selected mask out of the 8 options. - function applyMask(mask) { - var x, y, r3x, r3y; - - switch (mask) { - case 0: - for (y = 0; y < width; y++) { - for (x = 0; x < width; x++) { - if (!((x + y) & 1) && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 1: - for (y = 0; y < width; y++) { - for (x = 0; x < width; x++) { - if (!(y & 1) && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 2: - for (y = 0; y < width; y++) { - for (r3x = 0, x = 0; x < width; x++, r3x++) { - if (r3x === 3) r3x = 0; - - if (!r3x && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 3: - for (r3y = 0, y = 0; y < width; y++, r3y++) { - if (r3y === 3) r3y = 0; - - for (r3x = r3y, x = 0; x < width; x++, r3x++) { - if (r3x === 3) r3x = 0; - - if (!r3x && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 4: - for (y = 0; y < width; y++) { - for (r3x = 0, r3y = ((y >> 1) & 1), x = 0; x < width; x++, r3x++) { - if (r3x === 3) { - r3x = 0; - r3y = !r3y; - } - - if (!r3y && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 5: - for (r3y = 0, y = 0; y < width; y++, r3y++) { - if (r3y === 3) r3y = 0; - - for (r3x = 0, x = 0; x < width; x++, r3x++) { - if (r3x === 3) r3x = 0; - - if (!((x & y & 1) + !(!r3x | !r3y)) && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 6: - for (r3y = 0, y = 0; y < width; y++, r3y++) { - if (r3y === 3) r3y = 0; - - for (r3x = 0, x = 0; x < width; x++, r3x++) { - if (r3x === 3) r3x = 0; - - if (!(((x & y & 1) + (r3x && (r3x === r3y))) & 1) && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - case 7: - for (r3y = 0, y = 0; y < width; y++, r3y++) { - if (r3y === 3) r3y = 0; - - for (r3x = 0, x = 0; x < width; x++, r3x++) { - if (r3x === 3) r3x = 0; - - if (!(((r3x && (r3x === r3y)) + ((x + y) & 1)) & 1) && !isMasked(x, y)) { - frameBuffer[x + y * width] ^= 1; - } - } - } - - break; - } - } - - // Using the table for the length of each run, calculate the amount of bad image. Long runs or - // those that look like finders are called twice; once for X and Y. - function getBadRuns(length) { - var badRuns = 0; - var i; - - for (i = 0; i <= length; i++) { - if (badBuffer[i] >= 5) { - badRuns += N1 + badBuffer[i] - 5; - } - } - - // FBFFFBF as in finder. - for (i = 3; i < length - 1; i += 2) { - if (badBuffer[i - 2] === badBuffer[i + 2] && - badBuffer[i + 2] === badBuffer[i - 1] && - badBuffer[i - 1] === badBuffer[i + 1] && - badBuffer[i - 1] * 3 === badBuffer[i] && - // Background around the foreground pattern? Not part of the specs. - (badBuffer[i - 3] === 0 || i + 3 > length || - badBuffer[i - 3] * 3 >= badBuffer[i] * 4 || - badBuffer[i + 3] * 3 >= badBuffer[i] * 4)) { - badRuns += N3; - } - } - - return badRuns; - } - - // Calculate how bad the masked image is (e.g. blocks, imbalance, runs, or finders). - function checkBadness() { - var b, b1, bad, big, bw, count, h, x, y; - bad = bw = count = 0; - - // Blocks of same colour. - for (y = 0; y < width - 1; y++) { - for (x = 0; x < width - 1; x++) { - // All foreground colour. - if ((frameBuffer[x + width * y] && - frameBuffer[(x + 1) + width * y] && - frameBuffer[x + width * (y + 1)] && - frameBuffer[(x + 1) + width * (y + 1)]) || - // All background colour. - !(frameBuffer[x + width * y] || - frameBuffer[(x + 1) + width * y] || - frameBuffer[x + width * (y + 1)] || - frameBuffer[(x + 1) + width * (y + 1)])) { - bad += N2; - } - } - } - - // X runs. - for (y = 0; y < width; y++) { - badBuffer[0] = 0; - - for (h = b = x = 0; x < width; x++) { - if ((b1 = frameBuffer[x + width * y]) === b) { - badBuffer[h]++; - } else { - badBuffer[++h] = 1; - } - - b = b1; - bw += b ? 1 : -1; - } - - bad += getBadRuns(h); - } - - if (bw < 0) bw = -bw; - - big = bw; - big += big << 2; - big <<= 1; - - while (big > width * width) { - big -= width * width; - count++; - } - - bad += count * N4; - - // Y runs. - for (x = 0; x < width; x++) { - badBuffer[0] = 0; - - for (h = b = y = 0; y < width; y++) { - if ((b1 = frameBuffer[x + width * y]) === b) { - badBuffer[h]++; - } else { - badBuffer[++h] = 1; - } - - b = b1; - } - - bad += getBadRuns(h); - } - - return bad; - } - - // Generate the encoded QR image for the string provided. - function generateFrame(str) { - var i, j, k, m, t, v, x, y; - - // Find the smallest version that fits the string. - t = str.length; - - version = 0; - - do { - version++; - - k = (eccLevel - 1) * 4 + (version - 1) * 16; - - neccBlock1 = ECC_BLOCKS[k++]; - neccBlock2 = ECC_BLOCKS[k++]; - dataBlock = ECC_BLOCKS[k++]; - eccBlock = ECC_BLOCKS[k]; - - k = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2 - 3 + (version <= 9); - - if (t <= k) break; - } while (version < 40); - - // FIXME: Ensure that it fits insted of being truncated. - width = 17 + 4 * version; - - // Allocate, clear and setup data structures. - v = dataBlock + (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2; - - for (t = 0; t < v; t++) { - eccBuffer[t] = 0; - } - - stringBuffer = str.slice(0); - - for (t = 0; t < width * width; t++) { - frameBuffer[t] = 0; - } - - for (t = 0; t < (width * (width + 1) + 1) / 2; t++) { - frameMask[t] = 0; - } - - // Insert finders: Foreground colour to frame and background to mask. - for (t = 0; t < 3; t++) { - k = y = 0; - - if (t === 1) k = (width - 7); - if (t === 2) y = (width - 7); - - frameBuffer[(y + 3) + width * (k + 3)] = 1; - - for (x = 0; x < 6; x++) { - frameBuffer[(y + x) + width * k] = 1; - frameBuffer[y + width * (k + x + 1)] = 1; - frameBuffer[(y + 6) + width * (k + x)] = 1; - frameBuffer[(y + x + 1) + width * (k + 6)] = 1; - } - - for (x = 1; x < 5; x++) { - setMask(y + x, k + 1); - setMask(y + 1, k + x + 1); - setMask(y + 5, k + x); - setMask(y + x + 1, k + 5); - } - - for (x = 2; x < 4; x++) { - frameBuffer[(y + x) + width * (k + 2)] = 1; - frameBuffer[(y + 2) + width * (k + x + 1)] = 1; - frameBuffer[(y + 4) + width * (k + x)] = 1; - frameBuffer[(y + x + 1) + width * (k + 4)] = 1; - } - } - - // Alignment blocks. - if (version > 1) { - t = ALIGNMENT_DELTA[version]; - y = width - 7; - - for (;;) { - x = width - 7; - - while (x > t - 3) { - addAlignment(x, y); - - if (x < t) break; - - x -= t; - } - - if (y <= t + 9) break; - - y -= t; - - addAlignment(6, y); - addAlignment(y, 6); - } - } - - // Single foreground cell. - frameBuffer[8 + width * (width - 8)] = 1; - - // Timing gap (mask only). - for (y = 0; y < 7; y++) { - setMask(7, y); - setMask(width - 8, y); - setMask(7, y + width - 7); - } - - for (x = 0; x < 8; x++) { - setMask(x, 7); - setMask(x + width - 8, 7); - setMask(x, width - 8); - } - - // Reserve mask, format area. - for (x = 0; x < 9; x++) { - setMask(x, 8); - } - - for (x = 0; x < 8; x++) { - setMask(x + width - 8, 8); - setMask(8, x); - } - - for (y = 0; y < 7; y++) { - setMask(8, y + width - 7); - } - - // Timing row/column. - for (x = 0; x < width - 14; x++) { - if (x & 1) { - setMask(8 + x, 6); - setMask(6, 8 + x); - } else { - frameBuffer[(8 + x) + width * 6] = 1; - frameBuffer[6 + width * (8 + x)] = 1; - } - } - - // Version block. - if (version > 6) { - t = VERSION_BLOCK[version - 7]; - k = 17; - - for (x = 0; x < 6; x++) { - for (y = 0; y < 3; y++, k--) { - if (1 & (k > 11 ? version >> (k - 12) : t >> k)) { - frameBuffer[(5 - x) + width * (2 - y + width - 11)] = 1; - frameBuffer[(2 - y + width - 11) + width * (5 - x)] = 1; - } else { - setMask(5 - x, 2 - y + width - 11); - setMask(2 - y + width - 11, 5 - x); - } - } - } - } - - // Sync mask bits. Only set above for background cells, so now add the foreground. - for (y = 0; y < width; y++) { - for (x = 0; x <= y; x++) { - if (frameBuffer[x + width * y]) { - setMask(x, y); - } - } - } - - // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanum, or kanji - // not supported). - v = stringBuffer.length; - - // String to array. - for (i = 0; i < v; i++) { - eccBuffer[i] = stringBuffer.charCodeAt(i); - } - - stringBuffer = eccBuffer.slice(0); - - // Calculate max string length. - x = dataBlock * (neccBlock1 + neccBlock2) + neccBlock2; - - if (v >= x - 2) { - v = x - 2; - - if (version > 9) v--; - } - - // Shift and re-pack to insert length prefix. - i = v; - - if (version > 9) { - stringBuffer[i + 2] = 0; - stringBuffer[i + 3] = 0; - - while (i--) { - t = stringBuffer[i]; - - stringBuffer[i + 3] |= 255 & (t << 4); - stringBuffer[i + 2] = t >> 4; - } - - stringBuffer[2] |= 255 & (v << 4); - stringBuffer[1] = v >> 4; - stringBuffer[0] = 0x40 | (v >> 12); - } else { - stringBuffer[i + 1] = 0; - stringBuffer[i + 2] = 0; - - while (i--) { - t = stringBuffer[i]; - - stringBuffer[i + 2] |= 255 & (t << 4); - stringBuffer[i + 1] = t >> 4; - } - - stringBuffer[1] |= 255 & (v << 4); - stringBuffer[0] = 0x40 | (v >> 4); - } - - // Fill to end with pad pattern. - i = v + 3 - (version < 10); - - while (i < x) { - stringBuffer[i++] = 0xec; - stringBuffer[i++] = 0x11; - } - - // Calculate generator polynomial. - polynomial[0] = 1; - - for (i = 0; i < eccBlock; i++) { - polynomial[i + 1] = 1; - - for (j = i; j > 0; j--) { - polynomial[j] = polynomial[j] ? polynomial[j - 1] ^ - GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[j]] + i)] : polynomial[j - 1]; - } - - polynomial[0] = GALOIS_EXPONENT[modN(GALOIS_LOG[polynomial[0]] + i)]; - } - - // Use logs for generator polynomial to save calculation step. - for (i = 0; i <= eccBlock; i++) { - polynomial[i] = GALOIS_LOG[polynomial[i]]; - } - - // Append ECC to data buffer. - k = x; - y = 0; - - for (i = 0; i < neccBlock1; i++) { - appendData(y, dataBlock, k, eccBlock); - - y += dataBlock; - k += eccBlock; - } - - for (i = 0; i < neccBlock2; i++) { - appendData(y, dataBlock + 1, k, eccBlock); - - y += dataBlock + 1; - k += eccBlock; - } - - // Interleave blocks. - y = 0; - - for (i = 0; i < dataBlock; i++) { - for (j = 0; j < neccBlock1; j++) { - eccBuffer[y++] = stringBuffer[i + j * dataBlock]; - } - - for (j = 0; j < neccBlock2; j++) { - eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))]; - } - } - - for (j = 0; j < neccBlock2; j++) { - eccBuffer[y++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))]; - } - - for (i = 0; i < eccBlock; i++) { - for (j = 0; j < neccBlock1 + neccBlock2; j++) { - eccBuffer[y++] = stringBuffer[x + i + j * eccBlock]; - } - } - - stringBuffer = eccBuffer; - - // Pack bits into frame avoiding masked area. - x = y = width - 1; - k = v = 1; - - // inteleaved data and ECC codes. - m = (dataBlock + eccBlock) * (neccBlock1 + neccBlock2) + neccBlock2; - - for (i = 0; i < m; i++) { - t = stringBuffer[i]; - - for (j = 0; j < 8; j++, t <<= 1) { - if (0x80 & t) { - frameBuffer[x + width * y] = 1; - } - - // Find next fill position. - do { - if (v) { - x--; - } else { - x++; - - if (k) { - if (y !== 0) { - y--; - } else { - x -= 2; - k = !k; - - if (x === 6) { - x--; - y = 9; - } - } - } else { - if (y !== width - 1) { - y++; - } else { - x -= 2; - k = !k; - - if (x === 6) { - x--; - y -= 8; - } - } - } - } - - v = !v; - } while (isMasked(x, y)); - } - } - - // Save pre-mask copy of frame. - stringBuffer = frameBuffer.slice(0); - - t = 0; - y = 30000; - - // Using `for` instead of `while` since in original Arduino code if an early mask was *good - // enough* it wouldn't try for a better one since they get more complex and take longer. - for (k = 0; k < 8; k++) { - // Returns foreground-background imbalance. - applyMask(k); - - x = checkBadness(); - - // Is current mask better than previous best? - if (x < y) { - y = x; - t = k; - } - - // Don't increment `i` to a void redoing mask. - if (t === 7) break; - - // Reset for next pass. - frameBuffer = stringBuffer.slice(0); - } - - // Redo best mask as none were *good enough* (i.e. last wasn't `t`). - if (t !== k) { - applyMask(t); - } - - // Add in final mask/ECC level bytes. - y = FINAL_FORMAT[t + ((eccLevel - 1) << 3)]; - - // Low byte. - for (k = 0; k < 8; k++, y >>= 1) { - if (y & 1) { - frameBuffer[(width - 1 - k) + width * 8] = 1; - - if (k < 6) { - frameBuffer[8 + width * k] = 1; - } else { - frameBuffer[8 + width * (k + 1)] = 1; - } - } - } - - // High byte. - for (k = 0; k < 7; k++, y >>= 1) { - if (y & 1) { - frameBuffer[8 + width * (width - 7 + k)] = 1; - - if (k) { - frameBuffer[(6 - k) + width * 8] = 1; - } else { - frameBuffer[7 + width * 8] = 1; - } - } - } - - // Finally, return the image data. - return frameBuffer; - } - - // qr.js setup - // ----------- - - // Build the publicly exposed API. - var qr = { - - // Constants - // --------- - - // Current version of `qr`. - VERSION: '1.1.3', - - // QR functions - // ------------ - - // Generate the QR code using the data provided and render it on to a `` element. - // If no `` element is specified in the argument provided a new one will be created and - // used. - // ECC (error correction capacity) determines how many intential errors are contained in the QR - // code. - canvas: function(data) { - data = normalizeData(data); - - // Module size of the generated QR code (i.e. 1-10). - var size = data.side - - // `` element used to render the QR code. - var cvs = data.canvas || createCanvas(); - // Retreive the 2D context of the canvas. - var c2d = cvs.getContext('2d'); - // Ensure the canvas has the correct dimensions. - //c2d.canvas.width = size; - //c2d.canvas.height = size; - // Fill the canvas with the correct background colour. - c2d.fillStyle = data.background || '#fff'; - c2d.fillRect(0, 0, size, size); - - // Determine the ECC level to be applied. - eccLevel = ECC_LEVELS[(data.level && data.level.toUpperCase()) || 'L']; - - // Generate the image frame for the given `value`. - var frame = generateFrame(data.value || ''); - - c2d.lineWidth = 1; - - // Determine the *pixel* size. - var px = size; - px /= width; - px = Math.floor(px); - - // Draw the QR code. - c2d.clearRect(0, 0, size, size); - c2d.fillStyle = data.background || '#fff'; - c2d.fillRect(0, 0, px * (width + 8), px * (width + 8)); - c2d.fillStyle = data.foreground || '#000'; - - var i, j; - - for (i = 0; i < width; i++) { - for (j = 0; j < width; j++) { - if (frame[j * width + i]) { - c2d.fillRect(px * i, px * j, px, px); - } - } - } - - return cvs; - }, - - // Generate the QR code using the data provided and render it on to a `` element. - // If no `` element is specified in the argument provided a new one will be created and - // used. - // ECC (error correction capacity) determines how many intential errors are contained in the QR - // code. - image: function(data) { - data = normalizeData(data); - - // `` element only which the QR code is rendered. - var cvs = this.canvas(data); - // `` element used to display the QR code. - var img = data.image || createImage(); - - // Apply the QR code to `img`. - img.src = cvs.toDataURL(data.mime || DEFAULT_MIME); - img.height = cvs.height; - img.width = cvs.width; - - return img; - }, - - // Generate the QR code using the data provided and render it on to a `` element and - // save it as an image file. - // If no `` element is specified in the argument provided a new one will be created and - // used. - // ECC (error correction capacity) determines how many intential errors are contained in the QR - // code. - // If called in a browser the `path` property/argument is ignored and will simply prompt the - // user to choose a location and file name. However, if called within node.js the file will be - // saved to specified path. - // A `callback` function must be provided which will be called once the saving process has - // started. If an error occurs it will be passed as the first argument to this function, - // otherwise this argument will be `null`. - save: function(data, path, callback) { - data = normalizeData(data); - - switch (typeof path) { - case 'function': - callback = path; - path = null; - break; - case 'string': - data.path = path; - break; - } - - // Callback function is required. - if (typeof callback !== 'function') { - throw new TypeError('Invalid callback type: ' + typeof callback); - } - - var completed = false; - // `` element only which the QR code is rendered. - var cvs = this.canvas(data); - - // Simple function to try and ensure that the `callback` function is only called once. - function done(error) { - if (!completed) { - completed = true; - - callback(error); - } - } - - if (inNode) { - writeFile(cvs, data, done); - } else { - download(cvs, data, done); - } - }, - - // Generate the QR code using the data provided and render it on to a `` element and - // save it as an image file. - // If no `` element is specified in the argument provided a new one will be created and - // used. - // ECC (error correction capacity) determines how many intential errors are contained in the QR - // code. - // If called in a browser the `path` property/argument is ignored and will simply prompt the - // user to choose a location and file name. However, if called within node.js the file will be - // saved to specified path. - saveSync: function(data, path) { - data = normalizeData(data); - - if (typeof path === 'string') data.path = path; - - // `` element only which the QR code is rendered. - var cvs = this.canvas(data); - - if (inNode) { - writeFileSync(cvs, data); - } else { - download(cvs, data); - } - }, - - // Generate the QR code using the data provided and render it on to a `` element before - // returning its data URI. - // If no `` element is specified in the argument provided a new one will be created and - // used. - // ECC (error correction capacity) determines how many intential errors are contained in the QR - // code. - toDataURL: function(data) { - data = normalizeData(data); - - return this.canvas(data).toDataURL(data.mime || DEFAULT_MIME); - }, - - // Utility functions - // ----------------- - - // Run qr.js in *noConflict* mode, returning the `qr` variable to its previous owner. - // Returns a reference to `qr`. - noConflict: function() { - root.qr = previousQr; - return this; - } - - }; - - // Support - // ------- - - // Export `qr` for QtQuick - _qr_instance = qr - -})(this); - -function get_qr() { - return _qr_instance -} diff --git a/src/ui/WalletSettings.qml b/src/ui/WalletSettings.qml deleted file mode 100644 index 208f014d..00000000 --- a/src/ui/WalletSettings.qml +++ /dev/null @@ -1,44 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Layouts 1.12 - -ColumnLayout { - id: walletSettings - width: parent.width - property alias isSetWalletEnvLocal: walletEnvSwitch.checked - property alias walletPath: walletPathTextEdit.text - - RowLayout { - width: parent.width - height: 40 - Label { - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - Layout.alignment: Qt.AlignCenter - text: "Wallet Path:" - } - TextField { - id: walletPathTextEdit - Layout.fillWidth: true - Layout.alignment: Qt.AlignCenter - placeholderText: "$HOME/.skycoin/wallets" - selectByMouse: true - } - } - - RowLayout { - width: parent.width - height: 40 - Label { - font.pointSize: Qt.application.font.pointSize * 0.9 - font.bold: true - Layout.alignment: Qt.AlignCenter - text: "Wallet Enviroment (Local/Remote):" - } - Switch { - id: walletEnvSwitch - checked: false - } - } -} diff --git a/src/ui/main.qml b/src/ui/main.qml deleted file mode 100644 index 57082290..00000000 --- a/src/ui/main.qml +++ /dev/null @@ -1,343 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Window 2.12 -import Qt.labs.settings 1.0 -import WalletsManager 1.0 -import Config 1.0 - -// Resource imports -// import "qrc:/ui/src/ui/Dialogs" -import "Dialogs/" // For quick UI development, switch back to resources when making a release - -ApplicationWindow { - id: applicationWindow - - property bool skipAccentColorAnimation: false - property bool accentColorAnimationActive: false - property color accentColor: settings.value("style/material/accent", Material.accent) - Behavior on accentColor { - SequentialAnimation { - PropertyAction { target: applicationWindow; property: "accentColorAnimationActive"; value: true } - ColorAnimation { duration: skipAccentColorAnimation ? 0 : 200 } - PropertyAction { target: applicationWindow; property: "accentColorAnimationActive"; value: false } - } - } - - width: 680 - height: 580 - title: Qt.application.name + ' v' + Qt.application.version - Material.theme: ~~settings.value("style/material/theme", Material.Light) - Material.accent: accentColor - - function flash() { - flasher.flash() - } - - menuBar: CustomMenuBar { - id: customMenuBar - - ConfigManager{ - id: configManager - } - - onOutputsRequested: { - generalStackView.openOutputsPage() - customHeader.text = qsTr("Outputs") - - enableOutputs = false - enablePendingTransactions = true - enableBlockchain = true - enableNetworking = true - enableSettings = true - enableSettingsAddressBook = false - enableAddrsBook = true - } - - onPendingTransactionsRequested: { - generalStackView.openPendingTransactionsPage() - customHeader.text = qsTr("Pending transactions") - - enableOutputs = true - enablePendingTransactions = false - enableBlockchain = true - enableNetworking = true - enableSettings = true - enableSettingsAddressBook = false - enableAddrsBook = true - - } - - onBlockchainRequested: { - generalStackView.openBlockchainPage() - customHeader.text = qsTr("Blockchain") - - enableOutputs = true - enablePendingTransactions = true - enableBlockchain = false - enableNetworking = true - enableSettings = true - enableSettingsAddressBook = false - enableAddrsBook = true - - } - - onNetworkingRequested: { - generalStackView.openNetworkingPage() - customHeader.text = qsTr("Networking") - - enableOutputs = true - enablePendingTransactions = true - enableBlockchain = true - enableNetworking = false - enableSettings = true - enableSettingsAddressBook = false - enableAddrsBook = true - } - - onAddressBookRequested: { - generalStackView.openAddressBookPage() - customHeader.text = qsTr("Address book") - - enableOutputs = true - enablePendingTransactions = true - enableBlockchain = true - enableNetworking = true - enableSettings = true - enableSettingsAddressBook = true - enableAddrsBook = false - } - - onSettingsRequested: { - generalStackView.openSettingsPage() - customHeader.text = qsTr("Settings") - - enableOutputs = true - enablePendingTransactions = true - enableBlockchain = true - enableNetworking = true - enableSettings = false - enableSettingsAddressBook = false - enableAddrsBook = true - } - - onSettingsAddressBookRequested: { - generalStackView.openSettingsAddressBookPage() - customHeader.text = qsTr("Address Book Settings") - - // The back button must be used to go back to the Address Book - enableOutputs = enablePendingTransactions = enableBlockchain = enableNetworking = enableSettings = enableSettingsAddressBook = enableAddrsBook = false - } - - onAboutRequested: { - dialogAbout.open() - } - - onAboutQtRequested: { - dialogAboutQt.open() - } - - onLicenseRequested: { - dialogAboutLicense.open() - } - } // CustomMenuBar - - Action { - id: actionFullScreen - - property int previous: applicationWindow.visibility - - shortcut: StandardKey.FullScreen - onTriggered: { - if (applicationWindow.visibility !== Window.FullScreen) { - previous = applicationWindow.visibility - } - if (applicationWindow.visibility === Window.FullScreen) { - applicationWindow.showNormal() // Cannot show maximized directly due to a bug in some X11 managers - if (previous === Window.Maximized) { - applicationWindow.showMaximized() - } - } else { - applicationWindow.showFullScreen() - } - } - } - - CustomHeader { - id: customHeader - } - - GeneralStackView { - id: generalStackView - anchors.fill: parent - - onBackRequested: { - customMenuBar.back() - } - - WalletManager { - id: walletManager - } - } - - //! Settings - Settings { - id: settings - } - - //! Dialogs - - // Message dialogs - - MsgDialog { - id: msgDialog - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 440 ? 440 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 280 ? 280 - 40 : applicationWindow.height - 40 - - focus: true - modal: true - - text: qsTr("Lorem ipsum dolor sit amet, consectetur adipiscing elit, " - + "sed eiusmod tempor incidunt ut labore et dolore magna aliqua. " - + "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris " - + "nisi ut aliquid ex ea commodi consequat. " - + "Quis aute iure reprehenderit in voluptate velit esse cillum dolore " - + "eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, " - + "sunt in culpa qui officia deserunt mollit anim id est laborum.") - } - - // QR - DialogQR { - id: dialogQR - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 570 ? 570 - 40 : applicationWindow.height - 40 - - focus: true - modal: true - } - - // Hardware dialogs - - DialogUnconfiguredWallet { - id: dialogUnconfiguredWallet - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 690 ? 690 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 420 ? 420 - 40 : applicationWindow.height - 40 - - focus: true - modal: true - } - - NumPadDialog { - id: numPadDialog - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 440 ? 440 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 540 ? 540 - 40 : applicationWindow.height - 40 - - focus: visible - modal: true - } - - RestoreBackupWordsDialog { - id: restoreBackupWordsDialog - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 460 ? 460 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 340 ? 340 - 40 : applicationWindow.height - 40 - - focus: visible - modal: true - } - - SecureWalletDialog { - id: secureWalletDialog - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 640 ? 640 - 40 : applicationWindow.width - 40 - height: (applicationWindow.height > 590 ? 590 - 40 : applicationWindow.height - 40) - (enableBackupWarning ^ enablePINWarning ? 100 : 0) - (!enableBackupWarning && !enablePINWarning ? 240 : 0) - - focus: visible - modal: true - } - - - - WalletCreatedDialog { - id: walletCreatedDialog - anchors.centerIn: Overlay.overlay - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 360 ? 360 - 40 : applicationWindow.height - 40 - - focus: visible - modal: true - } - - - // Help dialogs - - DialogAbout { - id: dialogAbout - - parent: Overlay.overlay - anchors.centerIn: parent - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 640 ? 640 - 40 : applicationWindow.height - 40 - - onLicenseRequested: { - close() - dialogAboutLicense.open() - } - } - - DialogAboutQt { - id: dialogAboutQt - - parent: Overlay.overlay - anchors.centerIn: parent - width: applicationWindow.width > 540 ? 540 - 40 : applicationWindow.width - 40 - height: applicationWindow.height > 640 ? 640 - 40 : applicationWindow.height - 40 - } - - DialogAboutLicense { - id: dialogAboutLicense - - anchors.centerIn: Overlay.overlay - width: applicationWindow.width - 40 - height: applicationWindow.height - 40 - - focus: visible - modal: true - } - - //! This must be the last object (i.e. the one with the greater `z` value) - Rectangle { - id: flasher - - property int duration: 500 - - function flash() { - if (flashAnimation.running) { - flashAnimation.restart() - } else { - flashAnimation.start() - } - } - - y: -customMenuBar.height - width: applicationWindow.width - height: applicationWindow.height - color: "white" - opacity: 0.0 - z: customMenuBar.z + 1 - - NumberAnimation { - id: flashAnimation - - target: flasher - property: "opacity" - from: 1.0; to: 0.0 - duration: flasher.duration - easing.type: Easing.InQuad - } - } // Rectangle (flasher) -} diff --git a/src/ui/splash.qml b/src/ui/splash.qml deleted file mode 100755 index 6a46519d..00000000 --- a/src/ui/splash.qml +++ /dev/null @@ -1,104 +0,0 @@ -import QtQuick 2.12 -import QtQuick.Controls 2.12 -import QtQuick.Controls.Material 2.12 -import QtQuick.Window 2.12 -import QtQuick.Layouts 1.12 -import Qt.labs.settings 1.0 - -Window { - id: windowSplash - - width: dialogSplash.width + 100 - height: dialogSplash.height + 140 - visible: true - flags: Qt.SplashScreen | Qt.BypassWindowManagerHint | Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint - color: "transparent" - x: (Screen.width - width)/2 - y: (Screen.height - height)/2 - - Material.theme: ~~settings.value("style/material/theme", Material.Light) - - Dialog { - id: dialogSplash - anchors.centerIn: Overlay.overlay - visible: true - closePolicy: Dialog.NoAutoClose - standardButtons: Dialog.Abort - - Component.onCompleted: { - standardButton(Dialog.Abort).Material.accent = Material.Red - standardButton(Dialog.Abort).highlighted = true - } - - onRejected: Qt.exit(-1) - onClosed: windowSplash.visible = false - - width: implicitWidth + (implicitWidth % 2) - height: implicitHeight + (implicitHeight % 2) - - ColumnLayout { - anchors.fill: parent - - Image { - id: imageLogo - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - fillMode: Image.PreserveAspectFit - source: "qrc:/images/resources/images/icons/appIcon/appIcon.png" - sourceSize: "128x128" - } - - Label { - id: labelApplicationName - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - text: "FiberCrypto Wallet" - font.family: "Hemi Head" - font.pointSize: Qt.application.font.pointSize * 2.2 - } - - Label { - id: labelApplicationDescription - Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter - text: qsTr("Multi-coin cryptocurrency wallet") - font.bold: true - } - - RowLayout { - clip: true - Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter - - BusyIndicator { - running: visible - implicitWidth: 32 - implicitHeight: implicitWidth - } - Label { - text: qsTr("Loading...") - font.italic: true - } - } - } // ColumnLayout - } // Dialog - - Loader { - id: loader - source: "main.qml" - asynchronous: true - - onLoaded: { - dialogSplash.standardButton(Dialog.Abort).enabled = false - item.visible = true - timer.start() - } - } - - Timer { - id: timer - interval: 200 - repeat: false - onTriggered: dialogSplash.close() - } - - Settings { - id: settings - } -}