mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 14:55:36 +08:00
AFV initial commit
This commit is contained in:
committed by
Mat Sutcliffe
parent
7030302e73
commit
b5a2f2ad13
74
samples/afvclient/qml/AtcRing.qml
Normal file
74
samples/afvclient/qml/AtcRing.qml
Normal file
@@ -0,0 +1,74 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtLocation 5.12
|
||||
import QtPositioning 5.12
|
||||
|
||||
MapItemGroup {
|
||||
id: atcRing
|
||||
|
||||
signal selected(real latitude, real longitude, string frequency)
|
||||
|
||||
property alias position: mainCircle.center
|
||||
property alias radius: mainCircle.radius
|
||||
property alias cs: idCallsignText.text
|
||||
property alias freqAsString: idFrequency.text
|
||||
property int freqKhz: 122800
|
||||
|
||||
MapCircle {
|
||||
id: mainCircle
|
||||
color: 'green'
|
||||
border.width: 3
|
||||
border.color: 'green'
|
||||
opacity: 0.3
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
idCallsign.visible = !idCallsign.visible
|
||||
}
|
||||
onDoubleClicked: {
|
||||
atcRing.selected(mainCircle.center.latitude, mainCircle.center.longitude, atcRing.freqKhz)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MapQuickItem {
|
||||
id: circleCenter
|
||||
sourceItem: Rectangle { width: 6; height: 6; color: "#000000"; border.width: 2; border.color: "#000000"; smooth: true; radius: 3 }
|
||||
coordinate: mainCircle.center
|
||||
opacity:1.0
|
||||
anchorPoint: Qt.point(sourceItem.width/2, sourceItem.height/2)
|
||||
}
|
||||
|
||||
MapQuickItem {
|
||||
id: idCallsign
|
||||
visible: false
|
||||
coordinate: mainCircle.center
|
||||
anchorPoint: Qt.point(-circleCenter.sourceItem.width * 0.5, circleCenter.sourceItem.height * -1.5)
|
||||
|
||||
sourceItem: Item {
|
||||
|
||||
Rectangle {
|
||||
color: "#FFFFFF"
|
||||
width: idCallsignText.width * 1.3
|
||||
height: (idCallsignText.height + idFrequency.height) * 1.3
|
||||
border.width: 2
|
||||
border.color: "#000000"
|
||||
radius: 5
|
||||
}
|
||||
|
||||
Text {
|
||||
id: idCallsignText
|
||||
color:"#000000"
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
id: idFrequency
|
||||
color:"#000000"
|
||||
anchors.top: idCallsignText.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
samples/afvclient/qml/Transceiver.qml
Normal file
74
samples/afvclient/qml/Transceiver.qml
Normal file
@@ -0,0 +1,74 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Row {
|
||||
property int transceiverId: 0
|
||||
property alias frequency: sbFrequency.value
|
||||
|
||||
spacing: 10
|
||||
Label {
|
||||
id: lblRadio
|
||||
text: 'Radio ' + transceiverId
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
id: sbFrequency
|
||||
width: 150
|
||||
height: 40
|
||||
editable: true
|
||||
stepSize: 25
|
||||
to: 140000
|
||||
from: 110000
|
||||
value: 122800
|
||||
|
||||
property int decimals: 3
|
||||
property real realValue: value / 1000
|
||||
|
||||
validator: DoubleValidator {
|
||||
bottom: Math.min(sbFrequency.from, sbFrequency.to)
|
||||
top: Math.max(sbFrequency.from, sbFrequency.to)
|
||||
}
|
||||
|
||||
textFromValue: function(value, locale) {
|
||||
return Number(value / 1000).toLocaleString(locale, 'f', sbFrequency.decimals)
|
||||
}
|
||||
|
||||
valueFromText: function(text, locale) {
|
||||
return Number.fromLocaleString(locale, text) * 1000
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0)
|
||||
{
|
||||
sbFrequency.value += sbFrequency.stepSize
|
||||
}
|
||||
else
|
||||
{
|
||||
sbFrequency.value -= sbFrequency.stepSize
|
||||
}
|
||||
wheel.accepted=true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: cbTxOn
|
||||
height: 25
|
||||
text: qsTr("TX")
|
||||
checked: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: cbEnabled
|
||||
height: 25
|
||||
text: qsTr("Enabled")
|
||||
checked: true
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
336
samples/afvclient/qml/main.qml
Normal file
336
samples/afvclient/qml/main.qml
Normal file
@@ -0,0 +1,336 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtLocation 5.12
|
||||
import QtPositioning 5.12
|
||||
|
||||
ApplicationWindow {
|
||||
id: window
|
||||
width: 1200
|
||||
height: 520
|
||||
visible: true
|
||||
title: "Audio For Vatsim"
|
||||
|
||||
Plugin {
|
||||
id: mapPlugin
|
||||
name: "osm" // "mapboxgl", "esri", ...
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: leftGrid
|
||||
columns: 2
|
||||
rows: 6
|
||||
spacing: 10
|
||||
padding: 10
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 5
|
||||
anchors.leftMargin: 10
|
||||
|
||||
Label {
|
||||
id: lblUsername
|
||||
width: 100
|
||||
text: qsTr("Username")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: tfUsername
|
||||
width: 350
|
||||
height: 25
|
||||
text: qsTr("1234567")
|
||||
selectByMouse: true
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblPassword
|
||||
width: 100
|
||||
text: qsTr("Password")
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: false
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: tfPassword
|
||||
width: 350
|
||||
height: 25
|
||||
text: qsTr("123456")
|
||||
selectByMouse: true
|
||||
echoMode: TextInput.PasswordEchoOnEdit
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblCallsign
|
||||
width: 100
|
||||
text: qsTr("Callsign")
|
||||
Layout.fillWidth: false
|
||||
Layout.fillHeight: false
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: tfCallsign
|
||||
width: 350
|
||||
height: 25
|
||||
text: qsTr("DECHK")
|
||||
selectByMouse: true
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblInputDevice
|
||||
width: 100
|
||||
text: qsTr("Input Device")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: cbInputDevices
|
||||
width: 350
|
||||
height: 25
|
||||
model: voiceClient.availableInputDevices()
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblOutputDevice
|
||||
width: 100
|
||||
text: qsTr("Output Device")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
Layout.fillHeight: false
|
||||
Layout.fillWidth: false
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: cbOutputDevices
|
||||
width: 350
|
||||
height: 25
|
||||
model: voiceClient.availableOutputDevices()
|
||||
}
|
||||
|
||||
Frame {
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: 10
|
||||
|
||||
Button {
|
||||
id: btConnect
|
||||
|
||||
property bool connected: false
|
||||
width: 170
|
||||
height: 25
|
||||
text: qsTr("Connect")
|
||||
onClicked: {
|
||||
if (btConnect.connected) {
|
||||
btConnect.connected = false;
|
||||
btConnect.text = qsTr("Connect")
|
||||
voiceClient.disconnectFrom()
|
||||
} else {
|
||||
btConnect.connected = true
|
||||
btConnect.text = qsTr("Disconnect")
|
||||
voiceClient.connectTo(tfUsername.text, tfPassword.text, tfCallsign.text)
|
||||
afvMapReader.setOwnCallsign(tfCallsign.text)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: btStartAudio
|
||||
|
||||
property bool started: false
|
||||
width: 170
|
||||
height: 25
|
||||
text: qsTr("Start Audio")
|
||||
onClicked: {
|
||||
btStartAudio.enabled = false
|
||||
cbInputDevices.enabled = false
|
||||
cbOutputDevices.enabled = false
|
||||
voiceClient.start(cbInputDevices.currentText, cbOutputDevices.currentText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: rightGrid
|
||||
padding: 10
|
||||
anchors.top: parent.top
|
||||
anchors.left: leftGrid.right
|
||||
anchors.right: parent.right
|
||||
spacing: 10
|
||||
rows: 2
|
||||
columns: 3
|
||||
|
||||
Transceiver { id: transceiver1; transceiverId: 0 }
|
||||
|
||||
SpinBox {
|
||||
id: sbAltitude
|
||||
width: 150
|
||||
height: 40
|
||||
stepSize: 500
|
||||
to: 50000
|
||||
from: 0
|
||||
value: 1000
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblReceivingCom1
|
||||
height: 40
|
||||
text: qsTr("Receiving:")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Transceiver { id: transceiver2; transceiverId: 1 }
|
||||
|
||||
Button {
|
||||
id: btUpdateStack
|
||||
width: 150
|
||||
height: 40
|
||||
text: qsTr("Update Stack")
|
||||
onClicked: {
|
||||
voiceClient.updateComFrequency(0, transceiver1.frequency * 1000)
|
||||
voiceClient.updateComFrequency(1, transceiver2.frequency * 1000)
|
||||
voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value)
|
||||
voiceClient.updateTransceivers()
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: lblReceivingCom2
|
||||
height: 40
|
||||
text: qsTr("Receiving:")
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
// anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
padding: 10
|
||||
spacing: 10
|
||||
anchors.top: rightGrid.bottom
|
||||
anchors.left: leftGrid.right
|
||||
anchors.right: parent.right
|
||||
|
||||
ProgressBar {
|
||||
id: pbAudioInput
|
||||
width: 500
|
||||
height: 25
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
value: voiceClient.inputVolumePeakVU
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: pbAudioOutput
|
||||
width: 500
|
||||
height: 25
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
value: voiceClient.outputVolumePeakVU
|
||||
}
|
||||
}
|
||||
|
||||
//// CheckBox {
|
||||
//// id: cbVhfEffects
|
||||
//// anchors.topMargin: 5
|
||||
//// anchors.leftMargin: 10
|
||||
//// anchors.left: sbAltitude.right
|
||||
//// anchors.top: parent.top
|
||||
//// anchors.verticalCenter: sbAltitude.verticalCenter
|
||||
//// height: 25
|
||||
//// text: qsTr("VHF Effects")
|
||||
//// checked: true
|
||||
//// }
|
||||
|
||||
Map {
|
||||
id: map
|
||||
anchors.topMargin: 5
|
||||
anchors.top: leftGrid.bottom
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
plugin: mapPlugin
|
||||
center: QtPositioning.coordinate(48.50, 11.50) // Oslo
|
||||
zoomLevel: 3
|
||||
|
||||
// MapCircle {
|
||||
// center {
|
||||
// latitude: map.center.latitude
|
||||
// longitude: map.center.longitude
|
||||
// }
|
||||
// radius: 500000.0
|
||||
// color: 'blue'
|
||||
// border.width: 3
|
||||
// border.color: 'blue'
|
||||
// opacity: 0.3
|
||||
// }
|
||||
|
||||
MapItemView {
|
||||
model: afvMapReader.atcStationModel
|
||||
delegate: atcDelegate
|
||||
}
|
||||
|
||||
Component {
|
||||
id: atcDelegate
|
||||
AtcRing {
|
||||
position {
|
||||
latitude: latitude
|
||||
longitude: longitude
|
||||
}
|
||||
radius: radioDistanceM
|
||||
cs: callsign
|
||||
freqAsString: frequencyAsString
|
||||
freqKhz: frequencyKhz
|
||||
onSelected: {
|
||||
map.center = QtPositioning.coordinate(latitude, longitude)
|
||||
transceiver1.frequency = frequency
|
||||
voiceClient.updateComFrequency(0, transceiver1.frequency * 1000)
|
||||
voiceClient.updateComFrequency(1, transceiver2.frequency * 1000)
|
||||
voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 3
|
||||
height: 15
|
||||
color: "blue"
|
||||
anchors.verticalCenter: map.verticalCenter
|
||||
anchors.horizontalCenter: map.horizontalCenter
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 15
|
||||
height: 3
|
||||
color: "blue"
|
||||
anchors.verticalCenter: map.verticalCenter
|
||||
anchors.horizontalCenter: map.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: 5000; running: true; repeat: true
|
||||
onTriggered: {
|
||||
voiceClient.updateComFrequency(0, transceiver1.frequency * 1000)
|
||||
voiceClient.updateComFrequency(1, transceiver2.frequency * 1000)
|
||||
voiceClient.updatePosition(map.center.latitude, map.center.longitude, sbAltitude.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
7
samples/afvclient/qml/qml.qrc
Normal file
7
samples/afvclient/qml/qml.qrc
Normal file
@@ -0,0 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>main.qml</file>
|
||||
<file>AtcRing.qml</file>
|
||||
<file>Transceiver.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
Reference in New Issue
Block a user