move views & logic into their respective folders; add initial tab for node management

This commit is contained in:
Iuri Matias 2020-05-15 17:10:00 -04:00
parent 5710ad8079
commit bc6d1f1623
17 changed files with 636 additions and 219 deletions

View File

@ -0,0 +1,22 @@
import NimQml
# Probably all QT classes will look like this:
QtObject:
type ApplicationView* = ref object of QObject
app: QApplication
# Constructor
proc newApplicationView*(app: QApplication): ApplicationView =
new(result)
result.app = app
result.setup()
proc setup(self: ApplicationView) =
self.QObject.setup
proc delete*(self: ApplicationView) =
self.QObject.delete
proc onExitTriggered(self: ApplicationView) {.slot.} =
echo "exiting..."
self.app.quit

View File

@ -1,76 +0,0 @@
import NimQml
# Probably all QT classes will look like this:
QtObject:
type ApplicationView* = ref object of QObject
app: QApplication
callResult: string
accountResult: string
sendMessage: proc (msg: string): string
# Constructor
proc newApplicationView*(app: QApplication, sendMessage: proc): ApplicationView =
new(result)
result.app = app
result.sendMessage = sendMessage
result.callResult = "Use this tool to call JSONRPC methods"
result.setup()
# ¯\_(ツ)_/¯ dunno what is this
proc setup(self: ApplicationView) =
self.QObject.setup
# ¯\_(ツ)_/¯ seems to be a method for garbage collection
proc delete*(self: ApplicationView) =
self.QObject.delete
# Read more about slots and signals here: https://doc.qt.io/qt-5/signalsandslots.html
# This is an EventHandler
proc onExitTriggered(self: ApplicationView) {.slot.} =
self.app.quit
# Accesors
proc callResult*(self: ApplicationView): string {.slot.} =
result = self.callResult
proc callResultChanged*(self: ApplicationView, callResult: string) {.signal.}
proc setCallResult(self: ApplicationView, callResult: string) {.slot.} =
if self.callResult == callResult: return
self.callResult = callResult
self.callResultChanged(callResult)
proc `callResult=`*(self: ApplicationView, callResult: string) = self.setCallResult(callResult)
# Binding between a QML variable and accesors is done here
QtProperty[string] callResult:
read = callResult
write = setCallResult
notify = callResultChanged
proc onSend*(self: ApplicationView, inputJSON: string) {.slot.} =
self.setCallResult(self.sendMessage(inputJSON))
echo "Done!: ", self.callResult
proc onMessage*(self: ApplicationView, message: string) {.slot.} =
self.setCallResult(message)
echo "Received message: ", message
proc accountResultChanged*(self: ApplicationView, callResult: string) {.signal.}
proc accountResult*(self: ApplicationView): string {.slot.} =
result = self.accountResult
proc setAccountResult(self: ApplicationView, accountResult: string) {.slot.} =
if self.accountResult == accountResult: return
self.accountResult = accountResult
self.accountResultChanged(accountResult)
QtProperty[string] accountResult:
read = accountResult
write = setAccountResult
notify = callResultChanged
# This class has the metaObject property available which lets
# access all the QProperties which are stored as QVariants

View File

@ -1,6 +1,6 @@
import NimQml
import Tables
import core as chat
# import core as chat
type
RoleNames {.pure.} = enum
@ -10,6 +10,8 @@ QtObject:
type
ChatsModel* = ref object of QAbstractListModel
names*: seq[string]
callResult: string
sendMessage: proc (msg: string): string
proc delete(self: ChatsModel) =
self.QAbstractListModel.delete
@ -17,17 +19,18 @@ QtObject:
proc setup(self: ChatsModel) =
self.QAbstractListModel.setup
proc newChatsModel*(): ChatsModel =
proc newChatsModel*(sendMessage: proc): ChatsModel =
new(result, delete)
result.sendMessage = sendMessage
result.names = @[]
result.setup
proc addNameTolist*(self: ChatsModel, chatId: string) {.slot.} =
chat.join(chatId)
# chat.join(chatId)
self.beginInsertRows(newQModelIndex(), self.names.len, self.names.len)
self.names.add(chatId)
self.endInsertRows()
method rowCount(self: ChatsModel, index: QModelIndex = nil): int =
return self.names.len
@ -40,3 +43,30 @@ QtObject:
method roleNames(self: ChatsModel): Table[int, string] =
{ RoleNames.Name.int:"name"}.toTable
# Accesors
proc callResult*(self: ChatsModel): string {.slot.} =
result = self.callResult
proc callResultChanged*(self: ChatsModel, callResult: string) {.signal.}
proc setCallResult(self: ChatsModel, callResult: string) {.slot.} =
if self.callResult == callResult: return
self.callResult = callResult
self.callResultChanged(callResult)
proc `callResult=`*(self: ChatsModel, callResult: string) = self.setCallResult(callResult)
# Binding between a QML variable and accesors is done here
QtProperty[string] callResult:
read = callResult
write = setCallResult
notify = callResultChanged
proc onSend*(self: ChatsModel, inputJSON: string) {.slot.} =
self.setCallResult(self.sendMessage(inputJSON))
echo "Done!: ", self.callResult
proc onMessage*(self: ChatsModel, message: string) {.slot.} =
self.setCallResult(message)
echo "Received message: ", message

View File

@ -1,15 +1,39 @@
import NimQml
import "../status/chat" as status_chat
import chatView
proc join*(chatId: string) =
var sendMessage = proc (msg: string): string =
echo "sending public message"
status_chat.sendPublicChatMessage("test", msg)
type Chat* = ref object
chatsModel*: ChatsModel
chatsVariant*: QVariant
proc newChat*(): Chat =
result = Chat()
result.chatsModel = newChatsModel(sendMessage)
result.chatsModel.names = @[]
result.chatsVariant = newQVariant(result.chatsModel)
proc delete*(self: Chat) =
delete self.chatsModel
delete self.chatsVariant
proc init*(self: Chat) =
discard
proc join*(self: Chat, chatId: string) =
# TODO: check whether we have joined a chat already or not
# TODO: save chat list in the db
echo "Joining chat: ", chatId
status_chat.loadFilters(chatId)
status_chat.saveChat(chatId)
status_chat.chatMessages(chatId)
proc load*(): seq[string] =
# TODO: retrieve chats from DB
join("test")
result = @["test"]
# self.chatsModel.addNameTolist(channel.name)
self.chatsModel.addNameTolist(chatId)
proc load*(self: Chat): seq[string] =
# TODO: retrieve chats from DB
self.join("test")
result = @["test"]

View File

@ -1,18 +1,14 @@
import NimQml
import applicationView
import chat/chatView
import wallet/assetsView
import json
import application/applicationView
import chat/core as chat
import wallet/core as wallet
import node/core as node
import state
import status/utils
import strformat
import strutils
import status/core as status
import status/chat as status_chat
# import status/chat as status_chat
import status/test as status_test
import status/types as types
import status/wallet as status_wallet
import status/types
proc mainProc() =
# From QT docs:
@ -23,78 +19,48 @@ proc mainProc() =
var app = newQApplication()
defer: app.delete() # Defer will run this just before mainProc() function ends
var appState = state.newAppState()
echo appState.title
var chatsModel = newChatsModel();
defer: chatsModel.delete
var assetsModel = newAssetsModel();
defer: assetsModel.delete
var engine = newQQmlApplicationEngine()
defer: engine.delete()
var appState = state.newAppState()
echo appState.title
status.init(appState)
status_test.setupNewAccount()
discard status_test.addPeer("enode://2c8de3cbb27a3d30cbb5b3e003bc722b126f5aef82e2052aaef032ca94e0c7ad219e533ba88c70585ebd802de206693255335b100307645ab5170e88620d2a81@47.244.221.14:443")
echo status.callPrivateRPC("{\"jsonrpc\":\"2.0\", \"method\":\"wakuext_requestMessages\", \"params\":[{\"topics\": [\"0x7998f3c8\"]}], \"id\": 1}")
# 1. get balance of an address
var balance = status_wallet.getBalance("0x0000000000000000000000000000000000000000")
echo(fmt"balance in hex: {balance}")
# 2. convert balance to eth
var eth_value = status_wallet.hex2Eth(balance)
echo(fmt"balance in eth: {eth_value}")
# 3. get usd price of 1 eth
var usd_eth_price = status_wallet.getPrice("ETH", "USD")
echo(fmt"usd_price: {usd_eth_price}")
# 4. convert balance to usd
var usd_balance = parseFloat(eth_value) * parseFloat(usd_eth_price)
echo(fmt"balance in usd: {usd_balance}")
# result.accountResult = status.queryAccounts()
var sendMessage = proc (msg: string): string =
status_chat.sendPublicChatMessage("test", msg)
let logic = newApplicationView(app, sendMessage)
defer: logic.delete
let logicVariant = newQVariant(logic)
defer: logicVariant.delete
let chatsVariant = newQVariant(chatsModel)
defer: chatsVariant.delete
appState.subscribe(proc () =
chatsModel.names = @[]
for channel in appState.channels:
echo channel.name
chatsModel.addNameTolist(channel.name)
)
let assetsVariant = newQVariant(assetsModel)
defer: chatsVariant.delete
let applicationView = newApplicationView(app)
defer: applicationView.delete
status.startMessenger()
var wallet = wallet.newWallet()
wallet.init()
engine.setRootContextProperty("assetsModel", wallet.assetsVariant)
var chat = chat.newChat()
chat.init()
engine.setRootContextProperty("chatsModel", chat.chatsVariant)
var node = node.newNode()
node.init()
engine.setRootContextProperty("nodeModel", node.nodeVariant)
engine.load("../ui/main.qml")
appState.subscribe(proc () =
# chatsModel.names = @[]
for channel in appState.channels:
echo channel.name
# chatsModel.addNameTolist(channel.name)
chat.join(channel.name)
)
appState.addChannel("test")
appState.addChannel("test2")
engine.setRootContextProperty("logic", logicVariant)
engine.setRootContextProperty("chatsModel", chatsVariant)
engine.setRootContextProperty("assetsModel", assetsVariant)
let symbol = "ETH"
assetsModel.addAssetToList("Ethereum", symbol, fmt"{eth_value:.6}", "$" & fmt"{usd_balance:.6}", fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg")
engine.load("../ui/main.qml")
# EXAMPLE: this will be triggered once a message is received
appState.onSignal(SignalType.Message, proc(myMessage: string): void =
echo "I received a message: ", myMessage
@ -104,14 +70,11 @@ proc mainProc() =
var signalWorker: Thread[AppState]
signalWorker.createThread(proc(s:AppState) = s.processSignals, appState)
defer: signalWorker.joinThread()
# Qt main event loop is entered here
# The termination of the loop will be performed when exit() or quit() is called
app.exec()
when isMainModule:
mainProc()
GC_fullcollect()

23
src/node/core.nim Normal file
View File

@ -0,0 +1,23 @@
import NimQml
import "../status/core" as status
import nodeView
type Node* = ref object
nodeModel*: NodeView
nodeVariant*: QVariant
var sendRPCMessage = proc (msg: string): string =
echo "sending RPC message"
status.callPrivateRPC(msg)
proc newNode*(): Node =
result = Node()
result.nodeModel = newNodeView(sendRPCMessage)
result.nodeVariant = newQVariant(result.nodeModel)
proc delete*(self: Node) =
delete self.nodeModel
delete self.nodeVariant
proc init*(self: Node) =
discard

43
src/node/nodeView.nim Normal file
View File

@ -0,0 +1,43 @@
import NimQml
QtObject:
type NodeView* = ref object of QObject
callResult: string
sendRPCMessage: proc (msg: string): string
proc setup(self: NodeView) =
self.QObject.setup
proc newNodeView*(sendRPCMessage: proc): NodeView =
new(result)
result.sendRPCMessage = sendRPCMessage
result.callResult = "Use this tool to call JSONRPC methods"
result.setup
proc delete*(self: NodeView) =
self.QObject.delete
proc callResult*(self: NodeView): string {.slot.} =
result = self.callResult
proc callResultChanged*(self: NodeView, callResult: string) {.signal.}
proc setCallResult(self: NodeView, callResult: string) {.slot.} =
if self.callResult == callResult: return
self.callResult = callResult
self.callResultChanged(callResult)
proc `callResult=`*(self: NodeView, callResult: string) = self.setCallResult(callResult)
QtProperty[string] callResult:
read = callResult
write = setCallResult
notify = callResultChanged
proc onSend*(self: NodeView, inputJSON: string) {.slot.} =
self.setCallResult(self.sendRPCMessage(inputJSON))
echo "Done!: ", self.callResult
proc onMessage*(self: NodeView, message: string) {.slot.} =
self.setCallResult(message)
echo "Received message: ", message

View File

@ -2,7 +2,7 @@ import os
import core
import libstatus
import json
import chat
# import chat
# THIS FILE IS FOR TESTING STATUS FUNCTIONALITY
# ONCE TEST IS DONE, SPLIT THE CODE TO INDIVIDUAL NIM FILES

View File

@ -1,6 +1,6 @@
import core as status
import json
import utils
# import utils
import httpclient, json
import strformat
import stint

View File

@ -40,7 +40,7 @@ QtObject:
fiatValue: fiatValue,
image: image))
self.endInsertRows()
method rowCount(self: AssetsModel, index: QModelIndex = nil): int =
return self.assets.len

40
src/wallet/core.nim Normal file
View File

@ -0,0 +1,40 @@
import NimQml
import strformat
import strutils
import assetsView
import ../status/wallet as status_wallet
type Wallet* = ref object
assetsModel*: AssetsModel
assetsVariant*: QVariant
proc newWallet*(): Wallet =
echo "new wallet"
result = Wallet()
result.assetsModel = newAssetsModel()
result.assetsVariant = newQVariant(result.assetsModel)
proc delete*(self: Wallet) =
delete self.assetsModel
delete self.assetsVariant
proc init*(self: Wallet) =
# 1. get balance of an address
var balance = status_wallet.getBalance("0x0000000000000000000000000000000000000000")
echo(fmt"balance in hex: {balance}")
# 2. convert balance to eth
var eth_value = status_wallet.hex2Eth(balance)
echo(fmt"balance in eth: {eth_value}")
# 3. get usd price of 1 eth
var usd_eth_price = status_wallet.getPrice("ETH", "USD")
echo(fmt"usd_price: {usd_eth_price}")
# 4. convert balance to usd
var usd_balance = parseFloat(eth_value) * parseFloat(usd_eth_price)
echo(fmt"balance in usd: {usd_balance}")
let symbol = "ETH"
self.assetsModel.addAssetToList("Ethereum", symbol, fmt"{eth_value:.6}", "$" & fmt"{usd_balance:.6}", fmt"../../img/token-icons/{toLowerAscii(symbol)}.svg")

View File

@ -301,67 +301,55 @@ SplitView {
}
}
RowLayout {
id: separator
height: 16
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
// RowLayout {
// id: separator
// height: 16
// Layout.fillWidth: true
// Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Item {
id: separatorContent
width: 200
height: 16
Layout.fillHeight: false
Layout.fillWidth: true
// Item {
// id: separatorContent
// width: 200
// height: 16
// Layout.fillHeight: false
// Layout.fillWidth: true
Rectangle {
id: lineSeparator1
height: 1
color: "#00000000"
border.color: "#eef2f5"
anchors.top: parent.top
anchors.topMargin: 8
anchors.right: separatorText.left
anchors.rightMargin: 14
anchors.left: parent.left
anchors.leftMargin: 16
}
// Rectangle {
// id: lineSeparator1
// height: 1
// color: "#00000000"
// border.color: "#eef2f5"
// anchors.top: parent.top
// anchors.topMargin: 8
// anchors.right: separatorText.left
// anchors.rightMargin: 14
// anchors.left: parent.left
// anchors.leftMargin: 16
// }
Text {
id: separatorText
color: Theme.darkGrey
text: qsTr("Yesterday")
font.pixelSize: 12
anchors.centerIn: parent
}
// Text {
// id: separatorText
// color: Theme.darkGrey
// text: qsTr("Yesterday")
// font.pixelSize: 12
// anchors.centerIn: parent
// }
Rectangle {
id: lineSeparator2
height: 1
color: "#00000000"
anchors.right: parent.right
anchors.rightMargin: 16
anchors.left: separatorText.right
border.color: "#eef2f5"
anchors.top: parent.top
anchors.leftMargin: 14
anchors.topMargin: 8
}
}
// Rectangle {
// id: lineSeparator2
// height: 1
// color: "#00000000"
// anchors.right: parent.right
// anchors.rightMargin: 16
// anchors.left: separatorText.right
// border.color: "#eef2f5"
// anchors.top: parent.top
// anchors.leftMargin: 14
// anchors.topMargin: 8
// }
// }
}
RowLayout {
id: resultContainer
Layout.fillHeight: true
TextArea { id: callResult; Layout.fillWidth: true; text: logic.callResult; readOnly: true }
}
RowLayout {
id: accountResultContainer
Layout.fillHeight: true
TextArea { id: accountResult; Layout.fillWidth: true; text: logic.accountResult; readOnly: true }
}
// }
RowLayout {
id: chatInputContainer
@ -396,7 +384,7 @@ SplitView {
anchors.right: parent.right
anchors.rightMargin: 16
onClicked: {
logic.onSend(txtData.text)
chatsModel.onSend(txtData.text)
txtData.text = ""
}
enabled: txtData.text !== ""
@ -420,11 +408,11 @@ SplitView {
anchors.left: parent.left
anchors.leftMargin: 24
Keys.onEnterPressed: {
logic.onSend(txtData.text)
chatsModel.onSend(txtData.text)
txtData.text = ""
}
Keys.onReturnPressed: {
logic.onSend(txtData.text)
chatsModel.onSend(txtData.text)
txtData.text = ""
}
background: Rectangle {

View File

@ -0,0 +1,124 @@
import QtQuick 2.3
import QtQuick.Controls 1.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import "../../imports"
SplitView {
id: nodeView
x: 0
y: 0
Layout.fillHeight: true
Layout.fillWidth: true
// Those anchors show a warning too, but whithout them, there is a gap on the right
anchors.right: parent.right
anchors.rightMargin: 0
anchors.left: parent.left
anchors.leftMargin: 0
ColumnLayout {
id: rpcColumn
spacing: 0
// anchors.left: contactsColumn.right
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
RowLayout {
id: resultContainer
Layout.fillHeight: true
TextArea { id: callResult; Layout.fillWidth: true; text: nodeModel.callResult; readOnly: true }
}
RowLayout {
id: rpcInputContainer
height: 70
Layout.fillWidth: true
Layout.bottomMargin: 0
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
transformOrigin: Item.Bottom
Item {
id: element2
width: 200
height: 70
Layout.fillWidth: true
Rectangle {
id: rectangle
color: "#00000000"
border.color: Theme.grey
anchors.fill: parent
Button {
id: rpcSendBtn
x: 100
width: 30
height: 30
text: "\u2191"
font.bold: true
font.pointSize: 12
anchors.top: parent.top
anchors.topMargin: 20
anchors.right: parent.right
anchors.rightMargin: 16
onClicked: {
nodeModel.onSend(txtData.text)
txtData.text = ""
}
enabled: txtData.text !== ""
background: Rectangle {
color: parent.enabled ? Theme.blue : Theme.grey
radius: 50
}
}
TextField {
id: txtData
text: ""
leftPadding: 0
padding: 0
font.pixelSize: 14
placeholderText: qsTr("Type json-rpc message... e.g {\"method\": \"eth_accounts\"}")
anchors.right: rpcSendBtn.left
anchors.rightMargin: 16
anchors.top: parent.top
anchors.topMargin: 24
anchors.left: parent.left
anchors.leftMargin: 24
Keys.onEnterPressed: {
nodeModel.onSend(txtData.text)
txtData.text = ""
}
Keys.onReturnPressed: {
nodeModel.onSend(txtData.text)
txtData.text = ""
}
background: Rectangle {
color: "#00000000"
}
}
MouseArea {
id: mouseArea1
anchors.rightMargin: 50
anchors.fill: parent
onClicked : {
txtData.forceActiveFocus(Qt.MouseFocusReason)
}
}
}
}
}
}
}
/*##^##
Designer {
D{i:0;formeditorZoom:0.5;height:770;width:1152}
}
##^##*/

View File

@ -1,2 +1,3 @@
ChatLayout 1.0 ChatLayout.qml
NodeLayout 1.0 NodeLayout.qml
WalletLayout 1.0 Wallet/WalletLayout.qml

View File

@ -122,6 +122,29 @@ RowLayout {
source: parent.checked ? "img/profileActive.svg" : "img/profile.svg"
}
}
TabButton {
id: nodeBtn
width: 40
height: 40
text: ""
anchors.topMargin: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: profileBtn.top
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image4
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/list.svg" : "img/profile.svg"
}
}
}
StackLayout {
@ -148,6 +171,21 @@ RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
}
Item {
// browser
}
Item {
// profile
}
NodeLayout {
id: nodeLayoutContainer
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
}
}
}

196
ui/app/AppMain.qml.autosave Normal file
View File

@ -0,0 +1,196 @@
import QtQuick 2.3
import QtQuick.Controls 1.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import "../imports"
import "./AppLayouts"
RowLayout {
id: rowLayout
Layout.fillHeight: true
Layout.fillWidth: true
TabBar {
id: tabBar
width: 80
Layout.maximumWidth: 80
Layout.preferredWidth: 80
Layout.minimumWidth: 80
currentIndex: 0
topPadding: 57
rightPadding: 19
leftPadding: 19
transformOrigin: Item.Top
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
spacing: 5
background: Rectangle {
color: "#00000000"
border.color: Theme.grey
}
TabButton {
id: chatBtn
x: 0
width: 40
height: 40
text: ""
padding: 0
transformOrigin: Item.Center
anchors.horizontalCenter: parent.horizontalCenter
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/messageActive.svg" : "img/message.svg"
}
}
TabButton {
id: walletBtn
width: 40
height: 40
text: ""
anchors.topMargin: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: chatBtn.top
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image1
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/walletActive.svg" : "img/wallet.svg"
}
}
TabButton {
id: browserBtn
width: 40
height: 40
text: ""
anchors.topMargin: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: walletBtn.top
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image2
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/compassActive.svg" : "img/compass.svg"
}
}
TabButton {
id: profileBtn
width: 40
height: 40
text: ""
anchors.topMargin: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: browserBtn.top
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image3
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/profileActive.svg" : "img/profile.svg"
}
}
TabButton {
id: nodeBtn
width: 40
height: 40
text: ""
anchors.topMargin: 50
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: profileBtn.top
background: Rectangle {
color: Theme.lightBlue
opacity: parent.checked ? 1 : 0
radius: 50
}
Image {
id: image4
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: parent.checked ? "img/list.svg" : "img/profile.svg"
}
}
}
StackLayout {
currentIndex: 4
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
// Those anchors show a warning, but they are the only way to have QT Creator show correctly
anchors.left: tabBar.right
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 0
ChatLayout {
id: chatLayoutContainer
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
}
WalletLayout {
id: walletLayoutContainer
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
}
Item {
// browser
}
Item {
// profile
}
NodeLayout {
id: nodeLayoutContainer
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
Layout.fillHeight: true
}
}
}
/*##^##
Designer {
D{i:0;formeditorZoom:0.33000001311302185;height:770;width:1232}
}
##^##*/

View File

@ -50,6 +50,7 @@ DISTFILES += \
Inter-V.otf \
Theme.qml \
app/AppLayouts/ChatLayout.qml \
app/AppLayouts/NodeLayout.qml \
app/AppLayouts/Wallet/LeftTab.qml \
app/AppLayouts/Wallet/WalletLayout.qml \
app/AppLayouts/Wallet/qmldir \