├── ConnectPage.qml ├── CustomPushButton.qml ├── CustomTextEdit.qml ├── HistoryPage.qml ├── MainForm.ui.qml ├── ScrollBarVertical.qml ├── SettingsPage.qml ├── TerminalPage.qml ├── android ├── AndroidManifest.xml ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libs │ ├── android-support-v4.jar │ └── d2xx.jar ├── res │ ├── drawable-hdpi │ │ └── icon.png │ ├── drawable-ldpi │ │ └── icon.png │ ├── drawable-mdpi │ │ └── icon.png │ ├── values │ │ └── libs.xml │ └── xml │ │ └── device_filter.xml └── src │ ├── QtFtDev.java │ └── TestClass.java ├── customproxy4qmlmodel.cpp ├── customproxy4qmlmodel.h ├── deployment.pri ├── ftdimanager.cpp ├── ftdimanager.h ├── katynko ├── .directory ├── android_ft232.png ├── clear_left.png ├── dashed_elmnt.png ├── dashed_elmnt_red.png ├── fontsizedefault_koffice.png ├── fontsizedown_koffice.png ├── fontsizeup_koffice.png ├── history.png ├── key_enter.png └── settings.png ├── main.cpp ├── main.qml ├── qml.qrc ├── qmlitemmodel.cpp ├── qmlitemmodel.h ├── res.qrc ├── screenshot ├── .directory ├── Screenshot_2016-02-29-17-12-55.png ├── Screenshot_2016-02-29-17-13-02.png ├── Screenshot_2016-02-29-17-15-32.png ├── Screenshot_2016-02-29-17-33-36.png ├── android settings1.png └── qt settings.png ├── untitled.pro └── untitled.pro.user /ConnectPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Controls.Styles 1.2 4 | Item { 5 | id: root 6 | signal connectPageSettt(int dataIndx, int stopIndx, int parityIndx, int flowIndx, int baudIndx); 7 | signal setCurrntPortIndx(int portIndx); 8 | 9 | onConnectPageSettt: { 10 | cmbxDataBits.currentIndex = dataIndx 11 | cmbxStopBits.currentIndex = stopIndx 12 | cmbxParity.currentIndex = parityIndx 13 | cmbxFlow.currentIndex = flowIndx 14 | cmbxBaud.currentIndex = baudIndx 15 | } 16 | 17 | onSetCurrntPortIndx: { 18 | cmbxCurrentDevice.currentIndex = portIndx 19 | } 20 | 21 | property int defHeightPushButtonL: (root.height / 10) > defHeightPushButton ? defHeightPushButton : (root.height / 10) 22 | 23 | Column{ 24 | anchors.fill: parent 25 | anchors.margins: defMargins 26 | spacing: defMargins 27 | 28 | Item { 29 | height: defHeightPushButtonL 30 | 31 | } 32 | 33 | ComboBox{ 34 | id: cmbxDataBits 35 | height: defHeightPushButtonL 36 | width: parent.width - 2 * defMargins 37 | currentIndex: 0 38 | activeFocusOnPress: true 39 | style: comboboxStyle 40 | model: ListModel{ 41 | ListElement{ value: qsTrId("Data 8")} 42 | ListElement{ value: qsTrId("Data 7")} 43 | } 44 | } 45 | 46 | ComboBox{ 47 | id: cmbxStopBits 48 | height: defHeightPushButtonL 49 | width: cmbxDataBits.width 50 | currentIndex: 0 51 | activeFocusOnPress: true 52 | style: comboboxStyle 53 | model: ListModel{ 54 | ListElement{ value: qsTrId("Stop 1")} 55 | ListElement{ value: qsTrId("Stop 2")} 56 | } 57 | } 58 | 59 | ComboBox{ 60 | id: cmbxParity 61 | height: defHeightPushButtonL 62 | currentIndex: 0 63 | width: cmbxDataBits.width 64 | activeFocusOnPress: true 65 | style: comboboxStyle 66 | model: ListModel{ 67 | ListElement{ value: qsTrId("Parity None")} 68 | ListElement{ value: qsTrId("Parity Odd")} 69 | ListElement{ value: qsTrId("Parity Even")} 70 | ListElement{ value: qsTrId("Parity Mark")} 71 | ListElement{ value: qsTrId("Parity Space")} 72 | 73 | } 74 | } 75 | 76 | ComboBox{ 77 | id: cmbxFlow 78 | height: defHeightPushButtonL 79 | currentIndex: 0 80 | width: cmbxDataBits.width 81 | activeFocusOnPress: true 82 | style: comboboxStyle 83 | model: ListModel{ 84 | ListElement{ value: qsTrId("None")} 85 | ListElement{ value: qsTrId("CTS/RTS")} 86 | ListElement{ value: qsTrId("DTR/DSR")} 87 | ListElement{ value: qsTrId("XOFF/XON")} 88 | 89 | } 90 | } 91 | 92 | ComboBox{ 93 | id: cmbxBaud 94 | height: defHeightPushButtonL 95 | currentIndex: 3 96 | width: cmbxDataBits.width 97 | activeFocusOnPress: true 98 | style: comboboxStyle 99 | model: ListModel{ 100 | ListElement{ value: qsTrId("1200")} 101 | ListElement{ value: qsTrId("2400")} 102 | ListElement{ value: qsTrId("4800")} 103 | ListElement{ value: qsTrId("9600")} 104 | ListElement{ value: qsTrId("19200")} 105 | ListElement{ value: qsTrId("38400")} 106 | ListElement{ value: qsTrId("57600")} 107 | ListElement{ value: qsTrId("115200")} 108 | 109 | } 110 | } 111 | 112 | ComboBox{ 113 | id: cmbxCurrentDevice 114 | height: defHeightPushButtonL 115 | currentIndex: 0 116 | width: cmbxDataBits.width 117 | activeFocusOnPress: true 118 | style: comboboxStyle 119 | model: deviceModel 120 | } 121 | 122 | CustomPushButton{ 123 | id: cpbConnect 124 | text: ftdiIsConnected ? qsTr("Disconnect") : qsTr("Connect") 125 | fillColor: defColorButtonFill; 126 | color: defColorBackground 127 | radius: defRadiusButton 128 | textSize: defHeightFontPixel 129 | width: cmbxDataBits.width 130 | height: defHeightPushButtonL * 2 131 | 132 | enabled: (cmbxCurrentDevice.currentIndex >= 0 && cmbxCurrentDevice.currentText.length) 133 | 134 | onAnimationDone: { 135 | if(ftdiIsConnected) 136 | ftdiManager.disconnectFromPort(); 137 | else 138 | ftdiManager.connectToOnePort(cmbxCurrentDevice.currentIndex, 139 | cmbxBaud.currentIndex, 140 | cmbxDataBits.currentIndex, 141 | cmbxStopBits.currentIndex, 142 | cmbxParity.currentIndex, 143 | cmbxFlow.currentIndex); 144 | } 145 | 146 | } 147 | 148 | CustomPushButton{ 149 | id: cpbUpdate 150 | text: qsTr("Update List") 151 | fillColor: defColorButtonFill; 152 | color: defColorBackground 153 | radius: defRadiusButton 154 | textSize: defHeightFontPixel 155 | width: cmbxDataBits.width 156 | height: defHeightPushButtonL 157 | 158 | onAnimationDone: { 159 | ftdiManager.createDeviceInfoList(true) 160 | } 161 | 162 | } 163 | 164 | 165 | 166 | } 167 | Component{ 168 | id: comboboxStyle 169 | ComboBoxStyle { 170 | id: comboBox 171 | textColor: defColorText 172 | // selectedTextColor: 173 | // selectionColor: 174 | 175 | background: Rectangle { 176 | id: rectCategory 177 | radius: defRadiusButton 178 | color: defColorButtonFill 179 | 180 | // Image { 181 | // source: "qrc:/mainform/katynko/ComboImg.png" 182 | // anchors.verticalCenter: parent.verticalCenter 183 | // // anchors.bottom: parent.bottom 184 | // anchors.right: parent.right 185 | // // anchors.bottomMargin: 5 186 | // anchors.rightMargin: mainLeftMargin 187 | // height: parent.height * 0.8 188 | // width: height 189 | // fillMode: Image.Stretch 190 | // } 191 | } 192 | label: Text { 193 | verticalAlignment: Text.AlignVCenter 194 | horizontalAlignment: Text.AlignHCenter 195 | font.pixelSize: defHeightFontPixel 196 | 197 | color: defColorBackground 198 | text: control.currentText 199 | } 200 | } 201 | } 202 | 203 | } 204 | 205 | -------------------------------------------------------------------------------- /CustomPushButton.qml: -------------------------------------------------------------------------------- 1 | //import QtQuick 2.0 2 | 3 | import QtQuick 2.4 4 | import QtQuick.Controls 1.3 5 | import QtQuick.Layouts 1.1 6 | 7 | 8 | FocusScope { 9 | id: container 10 | signal clicked 11 | signal iAmReleased 12 | signal animationDone 13 | signal iAmPressAndHold 14 | property string imgSource: "" 15 | property string text: "" 16 | property string color: "#ffffff" 17 | property string fillColor: "#00000000" 18 | property int textSize: height * 0.6 19 | property string borderColor: "#00000000" 20 | property int borderWidth: 0 21 | property int radius: 6 22 | property int marginss: 0 23 | // property bool checable: false 24 | width: 40 25 | height: 20 26 | 27 | onEnabledChanged: enabled ? opacity = 1 : opacity = 0.4 28 | 29 | Rectangle { 30 | id: buttonRectangle 31 | anchors.fill: parent 32 | color: fillColor 33 | radius: container.radius 34 | border.width: container.borderWidth 35 | border.color: container.borderColor 36 | 37 | Image { 38 | id: image 39 | smooth: true 40 | 41 | // fillMode: Image.PreserveAspectFit 42 | anchors.right: parent.right 43 | anchors.verticalCenter: parent.verticalCenter 44 | height: parent.height * 0.8 45 | width: (imgSource.length > 0) ? height : 0 46 | anchors.margins: container.marginss 47 | 48 | anchors.rightMargin: (container.text.length < 1) ? (parent.height - height) / 2 : container.marginss 49 | 50 | source: imgSource 51 | 52 | } 53 | 54 | Item { 55 | anchors.left: parent.left 56 | anchors.right: image.left 57 | anchors.top: parent.top 58 | anchors.bottom: parent.bottom 59 | anchors.leftMargin: container.marginss * 2 60 | 61 | Text { 62 | color: container.color 63 | anchors.centerIn: parent 64 | font.pixelSize: container.textSize 65 | text: container.text 66 | font.bold: true 67 | } 68 | } 69 | 70 | MouseArea { 71 | id: mouseArea; 72 | anchors.fill: parent 73 | 74 | onPressed:{ 75 | buttonRectangle.state = "pressed" 76 | container.clicked() 77 | } 78 | 79 | onClicked: { 80 | buttonRectangle.state = "pressed" 81 | 82 | clkTmr.start() 83 | // container.clicked() 84 | } 85 | onReleased: { 86 | stateTimer.start() 87 | container.iAmReleased() 88 | } 89 | 90 | onPressAndHold: { 91 | buttonRectangle.state = "pressed" 92 | container.iAmPressAndHold() 93 | stateTimer.start() 94 | 95 | } 96 | } 97 | 98 | states: State { 99 | name: "pressed" 100 | PropertyChanges { target: /*image*/buttonRectangle; scale: 0.85 } 101 | } 102 | 103 | Timer{ 104 | id: clkTmr 105 | interval: stateTimer.interval 106 | repeat: false 107 | onTriggered: container.animationDone() 108 | } 109 | 110 | Timer { 111 | id: stateTimer 112 | interval: 150; 113 | repeat: false 114 | onTriggered:{ buttonRectangle.state = 'State0'; 115 | 116 | } 117 | } 118 | 119 | transitions: Transition { 120 | NumberAnimation { properties: "scale"; duration: 100; easing.type: Easing.InOutQuad /*InCubic*/} //.InOutQuad } 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /CustomTextEdit.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Controls.Styles 1.1 4 | 5 | Rectangle{ 6 | id: root 7 | property bool firstValBool: false 8 | signal customTextChanged 9 | signal cteEnter() 10 | signal cteEsc() 11 | property bool _readOnly: false 12 | 13 | property string placeholderText: qsTr("Type Here") 14 | property string imgSource: "qrc:/img/katynko/dashed_elmnt.png" 15 | property string imgSourceTextNotValid: "qrc:/img/katynko/dashed_elmnt_red.png" 16 | 17 | property string text: textField1.text 18 | property int cursorPosition: 0 19 | property int length: textField1.length 20 | property bool isValid: true 21 | property real scaleCoef: 1 22 | 23 | 24 | 25 | onEnabledChanged: enabled ? opacity = 1 : opacity = 0.4 26 | 27 | 28 | function setTextIsValid(_isValid){ 29 | isValid = _isValid 30 | } 31 | 32 | function setText(txt){ 33 | textField1.text = txt 34 | if(textField1.text.length) 35 | pbClearTextField1.state = "State0" 36 | else 37 | pbClearTextField1.state = "clear" 38 | } 39 | 40 | function setFocus(isTrue){ 41 | textField1.focus = isTrue 42 | } 43 | 44 | color: defColorBackground 45 | 46 | 47 | height: 22 48 | width: 50 49 | x: 5 50 | y: 5 51 | 52 | TextField { 53 | id: textField1 54 | anchors.left: parent.left 55 | anchors.top: parent.top 56 | height: parent.height * 0.9 57 | width: _readOnly ? parent.width : parent.width - height 58 | 59 | placeholderText: root.placeholderText 60 | text: root.text 61 | readOnly: _readOnly 62 | cursorPosition: root.cursorPosition 63 | 64 | onTextChanged: { 65 | root.text = text 66 | if(textField1.text.length > 0 && !_readOnly){ 67 | if(!pbClearTextField1.visible){ 68 | firstValBool = true 69 | pbClearTextField1.state = "State0" 70 | } 71 | }else{ 72 | if(pbClearTextField1.visible) 73 | pbClearTextField1.state = "clear" 74 | } 75 | if(!_readOnly) 76 | root.customTextChanged() 77 | } 78 | 79 | Keys.onEscapePressed: cteEsc() 80 | 81 | Keys.onReturnPressed: cteEnter() 82 | 83 | style: customTextEditStyle 84 | 85 | } 86 | 87 | Rectangle{ 88 | id: pbClearTextField1 89 | anchors.top: parent.top 90 | anchors.right: parent.right 91 | anchors.bottom: parent.bottom 92 | anchors.bottomMargin: parent.height - textField1.height 93 | 94 | width: (!firstValBool) ? 0 : parent.height 95 | visible: firstValBool 96 | color: defColorBackground//"transparent" 97 | 98 | MouseArea{ 99 | id: maPbClearTextField1 100 | anchors.fill: parent 101 | 102 | Image{ 103 | id: image111 104 | anchors.fill: parent 105 | source: "qrc:/img/katynko/clear_left.png"; 106 | } 107 | 108 | onClicked: { 109 | Qt.inputMethod.hide() 110 | 111 | textField1.text = ""; 112 | textField1.cursorPosition = 0 113 | textField1.focus = true 114 | 115 | } 116 | } 117 | states: State { 118 | name: "clear" 119 | PropertyChanges { target: pbClearTextField1; visible: false; width: 0 } 120 | } 121 | 122 | transitions: Transition { 123 | NumberAnimation { properties: "width"; duration: 150; easing.type: Easing.Linear } 124 | 125 | } 126 | 127 | } 128 | 129 | Rectangle{ 130 | anchors.left: parent.left 131 | anchors.right: parent.right 132 | anchors.bottom: parent.bottom 133 | anchors.rightMargin: pbClearTextField1.width 134 | color: "transparent" 135 | height: parent.height - textField1.height 136 | 137 | Image{id: imgValid; source: (isValid) ? imgSource : imgSourceTextNotValid; fillMode: Image.Tile; anchors.fill: parent; scale: scaleCoef } 138 | 139 | } 140 | 141 | Component{ 142 | id: customTextEditStyle 143 | TextFieldStyle{ 144 | textColor: defColorText 145 | // selectedTextColor: mainSelectedTextColor 146 | // selectionColor: mainSelectionColor 147 | // font.pixelSize: mainDefaultFontPixelSize 148 | background: Rectangle{ 149 | color: defColorBackground 150 | } 151 | } 152 | } 153 | } 154 | 155 | 156 | -------------------------------------------------------------------------------- /HistoryPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Controls.Styles 1.2 4 | import QtQuick.Dialogs 1.2 5 | 6 | 7 | Item { 8 | 9 | property int lastDeleteIndx: -1; 10 | Item { 11 | id: itmTop 12 | anchors.left: parent.left 13 | anchors.right: parent.right 14 | anchors.top: parent.top 15 | height: defHeightPushButton * 1.3 16 | 17 | 18 | CustomPushButton{ 19 | id: cpbHistory 20 | anchors.top: parent.top 21 | anchors.left: parent.left 22 | anchors.bottom: parent.bottom 23 | anchors.margins: defMargins 24 | width: defHeightFontPixel * text.length * 0.7 25 | imgSource: ""; 26 | 27 | text: qsTrId("Back") 28 | radius: defRadiusButton; 29 | color: defColorButtonText 30 | fillColor: defColorButtonFill 31 | 32 | onAnimationDone: { 33 | changeStackViewPage(1); 34 | } 35 | 36 | } 37 | 38 | CustomTextEdit{ 39 | id: cteFilter 40 | anchors.left: cpbHistory.right 41 | anchors.top: parent.top 42 | anchors.right: parent.right 43 | anchors.bottom: parent.bottom 44 | anchors.margins: defMargins 45 | placeholderText: qsTr("Enter command") 46 | 47 | onCteEnter: { 48 | Qt.inputMethod.hide() 49 | 50 | } 51 | 52 | onCteEsc: { 53 | Qt.inputMethod.hide() 54 | } 55 | 56 | onTextChanged: { 57 | ftdiManager.setThisHistoryFilter(cteFilter.text) 58 | } 59 | 60 | 61 | } 62 | 63 | } 64 | 65 | ListView{ 66 | id: lvHistory 67 | anchors.left: parent.left 68 | anchors.top: itmTop.bottom 69 | anchors.right: parent.right 70 | anchors.bottom: parent.bottom 71 | clip: true 72 | 73 | delegate: Item{ 74 | 75 | signal onPress(); 76 | id: emnt1 77 | anchors.left: parent.left 78 | anchors.right: parent.right 79 | anchors.margins: defMargins 80 | height: defHeightPushButton 81 | 82 | Text{ 83 | id: txtElmnt 84 | anchors.verticalCenter: parent.verticalCenter 85 | anchors.bottomMargin: defHeightLine 86 | anchors.leftMargin: defMargins 87 | anchors.left: parent.left 88 | color: defColorText //defColorBackground 89 | text: value 90 | elide: Text.ElideMiddle 91 | } 92 | 93 | Rectangle{ 94 | anchors.left: parent.left 95 | anchors.right: parent.right 96 | anchors.bottom: parent.bottom 97 | anchors.leftMargin: defMargins 98 | anchors.rightMargin: defMargins 99 | height: defHeightLine 100 | color: defColorLine 101 | } 102 | 103 | MouseArea{ 104 | anchors.fill: parent 105 | 106 | onClicked: { 107 | changeStackViewPage(1); 108 | tpPage.setThisCommandLine(txtElmnt.text) 109 | 110 | } 111 | 112 | 113 | onPressAndHold: { 114 | lastDeleteIndx = index; 115 | messageDialog.show(qsTr("Delete: ") + txtElmnt.text + "?"); 116 | } 117 | } 118 | 119 | 120 | } 121 | model: historyModel 122 | 123 | Behavior on height { 124 | 125 | NumberAnimation { 126 | id: animateHeight 127 | property: "height" 128 | from: 0.9 129 | to: 1.0 130 | loops: Animation.Infinite 131 | duration: 200 132 | easing {type: Easing.OutInQuart } 133 | } 134 | } 135 | 136 | states: State { 137 | name: "ShowBars" 138 | when: lstUsrView.movingVertically 139 | PropertyChanges { target: verticalScrollBar; opacity: 1 } 140 | } 141 | 142 | transitions: Transition { 143 | NumberAnimation { properties: "opacity"; duration: 400 } 144 | } 145 | } 146 | 147 | 148 | ScrollBarVertical { 149 | target: lvHistory 150 | } 151 | MessageDialog { 152 | id: messageDialog 153 | title: qsTr("Delete") 154 | 155 | function show(caption) { 156 | 157 | messageDialog.text = caption; 158 | messageDialog.open(); 159 | 160 | } 161 | 162 | standardButtons: StandardButton.Yes | 163 | StandardButton.No 164 | 165 | onYes: { 166 | ftdiManager.delThisHistoryIndx(lastDeleteIndx); 167 | lastDeleteIndx = -1; 168 | } 169 | 170 | onNo: { 171 | lastDeleteIndx = -1; 172 | } 173 | } 174 | 175 | } 176 | 177 | -------------------------------------------------------------------------------- /MainForm.ui.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Layouts 1.1 4 | 5 | Item { 6 | width: 640 7 | height: 480 8 | 9 | property alias button3: button3 10 | property alias button2: button2 11 | property alias button1: button1 12 | 13 | RowLayout { 14 | anchors.centerIn: parent 15 | 16 | Button { 17 | id: button1 18 | text: qsTr("Press Me 1") 19 | } 20 | 21 | Button { 22 | id: button2 23 | text: qsTr("Press Me 2") 24 | } 25 | 26 | Button { 27 | id: button3 28 | text: qsTr("Press Me 3") 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ScrollBarVertical.qml: -------------------------------------------------------------------------------- 1 | 2 | import QtQuick 2.4 3 | import QtQuick.Controls 1.3 4 | import QtQuick.Layouts 1.1 5 | 6 | 7 | Rectangle { 8 | id: scrollBar 9 | property variant target 10 | 11 | clip: true 12 | width: defHeightFontPixel * 0.5 13 | radius: defRadiusButton 14 | smooth: true 15 | 16 | anchors.top: target.top 17 | anchors.bottom: target.bottom 18 | anchors.right: target.right 19 | anchors.rightMargin: 0 20 | 21 | states: [ 22 | State { name: "nothing"; }, 23 | State { name: "disabled"; when: (track.height == slider.height || target.width <= slider.width || target.contentHeight <= track.height) } 24 | ] 25 | transitions: [ 26 | Transition { to: "disabled"; 27 | ParallelAnimation { 28 | NumberAnimation { target: scrollBar; property: "opacity"; to: 0; duration: 500; } 29 | PropertyAction { target: scrollBar; property: "visible"; value: false; } 30 | } 31 | }, 32 | Transition { to: "*"; 33 | PropertyAction { target: scrollBar; property: "visible"; value: true; } 34 | NumberAnimation { target: scrollBar; property: "opacity"; to: 0.6; duration: 500; } 35 | } 36 | ] 37 | 38 | Timer { 39 | property int scrollAmount 40 | 41 | id: timer 42 | repeat: true 43 | interval: 20 44 | onTriggered: { 45 | target.contentY = Math.max(0, Math.min(target.contentY + scrollAmount, 46 | target.contentHeight - target.height)); 47 | } 48 | } 49 | 50 | Item { 51 | id: track 52 | anchors.top: parent.top 53 | anchors.bottom: parent.bottom; 54 | width: parent.width 55 | 56 | MouseArea { 57 | anchors.fill: parent 58 | onPressed: { 59 | timer.scrollAmount = target.height * (mouseY < slider.y ? -1 : 1) // scroll by a page 60 | timer.running = true; 61 | } 62 | onReleased: { 63 | timer.running = false; 64 | } 65 | } 66 | 67 | Rectangle { 68 | id:slider 69 | color: defColorButtonFill 70 | smooth: true 71 | width: parent.width 72 | radius: 6 73 | 74 | anchors.bottom: (target.visibleArea.yPosition > 1)? parent.bottom: undefined 75 | height: { 76 | if(visible && target.contentHeight > 0 && target.height > 0 && target.visibleArea.yPosition > 0){ 77 | if (target.visibleArea.yPosition < 0){ // Oberer Rand 78 | Math.max(30, Math.min(target.height / target.contentHeight * track.height, track.height-y) +target.height * target.visibleArea.yPosition) 79 | 80 | }else { // Mittelbereich 81 | Math.min(target.height / target.contentHeight * track.height, track.height-y) 82 | 83 | } 84 | } 85 | } 86 | 87 | y: Math.max(0,Math.min(track.height-30, target.visibleArea.yPosition * track.height)); 88 | 89 | 90 | MouseArea { 91 | anchors.fill: parent 92 | drag.target: parent 93 | drag.axis: Drag.YAxis 94 | drag.minimumY: 0 95 | drag.maximumY: track.height - height 96 | hoverEnabled: true 97 | onPositionChanged: { 98 | if (pressedButtons == Qt.LeftButton) { 99 | target.contentY = slider.y * target.contentHeight / track.height 100 | } 101 | } 102 | onPressed: { 103 | scrollBar.opacity = 1 104 | } 105 | 106 | onEntered: { 107 | scrollBar.opacity = 1 108 | } 109 | 110 | onReleased: { 111 | scrollBar.opacity = 0.6 112 | } 113 | 114 | onExited: { 115 | if(pressedButtons == Qt.LeftButton) 116 | scrollBar.opacity = 1 117 | else 118 | scrollBar.opacity = 0.6 119 | } 120 | onWheel: { 121 | if(slider.y + slider.height +20 >= track.height){ 122 | // flickTextLog.ensureVisible(textLog.cursorRectangle) 123 | console.log("down1") 124 | } 125 | } 126 | } 127 | } 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /SettingsPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Window 2.2 3 | 4 | Item { 5 | Column{ 6 | anchors.fill: parent 7 | anchors.margins: defMargins 8 | 9 | spacing: defMargins 10 | 11 | Row{ 12 | height: defHeightPushButton 13 | spacing: defMargins 14 | Text{ text: qsTrId("Scale"); color: defColorText; font.pixelSize: defHeightFontPixel; height: defHeightPushButton } 15 | 16 | CustomPushButton{ 17 | height: defHeightPushButton 18 | width: height; 19 | imgSource: "qrc:/img/katynko/fontsizedown_koffice.png"; 20 | 21 | text: ""; 22 | fillColor: defColorButtonFill; 23 | color: defColorText 24 | radius: defRadiusButton 25 | textSize: defHeightFontPixel 26 | enabled: (defHeightFontPixel > Screen.logicalPixelDensity) 27 | onAnimationDone: { 28 | defHeightFontPixel = defHeightFontPixel * 0.95 29 | console.log("minus = " + defHeightFontPixel) 30 | ftdiManager.saveQmlSettRealVal(defHeightFontPixel,0) 31 | } 32 | } 33 | 34 | CustomPushButton{ 35 | height: defHeightPushButton 36 | width: height; 37 | imgSource: "qrc:/img/katynko/fontsizeup_koffice.png"; 38 | 39 | text: ""; 40 | fillColor: defColorButtonFill; 41 | color: defColorText 42 | radius: defRadiusButton 43 | textSize: defHeightFontPixel 44 | 45 | enabled: Screen.width < Screen.height ? 46 | width < (Screen.width * 0.25) : 47 | height < (Screen.height * 0.25) 48 | onAnimationDone: { 49 | defHeightFontPixel = defHeightFontPixel * 1.05 50 | console.log("plus = " + defHeightFontPixel) 51 | ftdiManager.saveQmlSettRealVal(defHeightFontPixel,0) 52 | 53 | 54 | } 55 | } 56 | 57 | CustomPushButton{ 58 | height: defHeightPushButton 59 | width: height; 60 | imgSource: "qrc:/img/katynko/fontsizedefault_koffice.png"; 61 | 62 | text: ""; 63 | fillColor: defColorButtonFill; 64 | color: defColorText 65 | radius: defRadiusButton 66 | textSize: defHeightFontPixel 67 | 68 | onAnimationDone: { 69 | defHeightFontPixel = Screen.pixelDensity * 3.8; 70 | ftdiManager.saveQmlSettRealVal(defHeightFontPixel,0) 71 | 72 | } 73 | } 74 | } 75 | 76 | 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /TerminalPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Controls.Styles 1.2 4 | import QtQuick.Window 2.2 5 | 6 | Item { 7 | 8 | 9 | signal appendPlainText(string plainTxt); 10 | signal terminalPageSettt(int endLineIndx, bool _hexOut); 11 | signal setThisCommandLine(string line) 12 | signal sendLineHexIsValid(bool isValid); 13 | 14 | property bool hexOut: false 15 | 16 | 17 | 18 | onAppendPlainText: { 19 | textArea1.append(plainTxt /*+ "\r\n"*/); 20 | } 21 | 22 | onTerminalPageSettt: { 23 | cmbxEndSymb.currentIndex = endLineIndx 24 | hexOut = _hexOut 25 | if(hexOut) 26 | ftdiManager.sendLineHexValidator(cteSend.text) 27 | } 28 | 29 | onSetThisCommandLine: { 30 | cteSend.setText(line) 31 | } 32 | 33 | onSendLineHexIsValid: { 34 | if(hexOut){ 35 | cteSend.setTextIsValid(isValid) 36 | } 37 | } 38 | 39 | function sendLineNow(){ 40 | if(hexOut && !cteSend.isValid) 41 | return; 42 | 43 | ftdiManager.sendDataToPort(cteSend.text , hexOut, cmbxEndSymb.currentIndex); 44 | cteSend.setText(""); 45 | 46 | } 47 | 48 | Row{ 49 | id: rwTop 50 | anchors.left: parent.left 51 | anchors.top: parent.top 52 | anchors.right: parent.right 53 | spacing: defMargins 54 | 55 | height: defHeightPushButtonSmll 56 | 57 | ComboBox{ 58 | id: cmbxEndSymb 59 | width: parent.width * 0.27 60 | height: defHeightPushButtonSmll 61 | currentIndex: 0 62 | activeFocusOnPress: true 63 | style: comboboxStyle 64 | model: lstModelDN 65 | 66 | ListModel{ 67 | id: lstModelDN 68 | ListElement{ value: qsTrId("CR+LF")} 69 | ListElement{ value: qsTrId("CR")} 70 | ListElement{ value: qsTrId("LF")} 71 | ListElement{ value: qsTrId("None")} 72 | 73 | } 74 | 75 | onCurrentIndexChanged: { 76 | ftdiManager.saveQmlSett(currentIndex, 0) 77 | } 78 | } 79 | 80 | CustomPushButton{ 81 | id: cpbHex 82 | width: parent.width * 0.25 83 | height: defHeightPushButtonSmll 84 | radius: defRadiusButton 85 | color: defColorButtonText 86 | fillColor: defColorButtonFill 87 | textSize: defHeightFontPixel 88 | text: hexOut ? "Hex" : "String" 89 | onAnimationDone: { 90 | if(hexOut) 91 | cteSend.setTextIsValid(true) 92 | hexOut = !hexOut 93 | ftdiManager.saveQmlSett(hexOut,0); 94 | 95 | if(hexOut) 96 | ftdiManager.sendLineHexValidator(cteSend.text) 97 | } 98 | } 99 | 100 | CustomPushButton{ 101 | id: cpbConnectPage 102 | height: defHeightPushButtonSmll 103 | 104 | width: text.length * defHeightFontPixel * 0.7 105 | text: qsTr("Clear") 106 | 107 | radius: defRadiusButton 108 | color: defColorButtonText 109 | fillColor: defColorButtonFill 110 | textSize: defHeightFontPixel 111 | onAnimationDone: { 112 | textArea1.text = ""; 113 | } 114 | enabled: true 115 | } 116 | } 117 | 118 | 119 | 120 | TextArea { 121 | id: textArea1 122 | text: "" 123 | readOnly: true 124 | textColor: defColorText 125 | frameVisible: true 126 | font.pixelSize: defHeightFontPixelLog 127 | anchors.bottom: itmBottom.top 128 | anchors.right: parent.right 129 | anchors.left: parent.left 130 | anchors.top: rwTop.bottom 131 | anchors.margins: defMargins 132 | 133 | } 134 | 135 | Item { 136 | id: itmBottom 137 | anchors.left: parent.left 138 | anchors.right: parent.right 139 | anchors.bottom: parent.bottom 140 | height: defHeightPushButton * 1.3 141 | CustomPushButton{ 142 | id: cpbSend 143 | anchors.top: parent.top 144 | anchors.right: parent.right 145 | anchors.bottom: parent.bottom 146 | anchors.margins: defMargins 147 | width: height 148 | imgSource: "qrc:/img/katynko/key_enter.png"; 149 | 150 | text: "" 151 | radius: defRadiusButton; 152 | 153 | enabled: (ftdiIsConnected && !sendTmr.running && cteSend.isValid) 154 | 155 | color: defColorButtonText 156 | fillColor: defColorButtonFill 157 | 158 | onAnimationDone: { 159 | Qt.inputMethod.hide() 160 | sendTmr.start(); 161 | } 162 | 163 | } 164 | 165 | CustomPushButton{ 166 | id: cpbHistory 167 | anchors.top: parent.top 168 | anchors.left: parent.left 169 | anchors.bottom: parent.bottom 170 | anchors.margins: defMargins 171 | width: height 172 | imgSource: "qrc:/img/katynko/history.png"; 173 | 174 | text: "" 175 | radius: defRadiusButton; 176 | color: defColorButtonText 177 | fillColor: defColorButtonFill 178 | 179 | onAnimationDone: { 180 | changeStackViewPage(3); 181 | } 182 | 183 | } 184 | 185 | CustomTextEdit{ 186 | id: cteSend 187 | anchors.left: cpbHistory.right 188 | anchors.top: parent.top 189 | anchors.right: cpbSend.left 190 | anchors.bottom: parent.bottom 191 | anchors.margins: defMargins 192 | enabled: ftdiIsConnected 193 | 194 | text: "+++" 195 | placeholderText: qsTr("Enter command") 196 | 197 | // scaleCoef: defHeightFontPixel / (Screen.pixelDensity ) 198 | 199 | onCteEnter: { 200 | Qt.inputMethod.hide() 201 | sendTmr.restart(); 202 | // sendLineNow(); 203 | } 204 | 205 | onCteEsc: { 206 | Qt.inputMethod.hide() 207 | } 208 | 209 | onTextChanged: { 210 | if(hexOut) 211 | ftdiManager.sendLineHexValidator(cteSend.text) 212 | 213 | } 214 | 215 | 216 | } 217 | 218 | 219 | Timer{ 220 | id: sendTmr 221 | repeat: false 222 | interval: 50 223 | onTriggered: { 224 | sendLineNow(); 225 | 226 | } 227 | } 228 | } 229 | 230 | Component{ 231 | id: comboboxStyle 232 | ComboBoxStyle { 233 | id: comboBox 234 | textColor: defColorText 235 | // selectedTextColor: 236 | // selectionColor: 237 | 238 | background: Rectangle { 239 | id: rectCategory 240 | radius: defRadiusButton 241 | color: defColorButtonFill 242 | 243 | // Image { 244 | // source: "qrc:/mainform/katynko/ComboImg.png" 245 | // anchors.verticalCenter: parent.verticalCenter 246 | // // anchors.bottom: parent.bottom 247 | // anchors.right: parent.right 248 | // // anchors.bottomMargin: 5 249 | // anchors.rightMargin: mainLeftMargin 250 | // height: parent.height * 0.8 251 | // width: height 252 | // fillMode: Image.Stretch 253 | // } 254 | } 255 | label: Text { 256 | verticalAlignment: Text.AlignVCenter 257 | horizontalAlignment: Text.AlignHCenter 258 | font.pixelSize: defHeightFontPixel 259 | 260 | color: defColorBackground 261 | text: control.currentText 262 | } 263 | } 264 | } 265 | } 266 | 267 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 62 | 63 | 64 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:1.1.0' 8 | } 9 | } 10 | 11 | allprojects { 12 | repositories { 13 | jcenter() 14 | } 15 | } 16 | 17 | apply plugin: 'com.android.application' 18 | 19 | dependencies { 20 | compile fileTree(dir: 'libs', include: ['*.jar']) 21 | } 22 | 23 | android { 24 | /******************************************************* 25 | * The following variables: 26 | * - androidBuildToolsVersion, 27 | * - androidCompileSdkVersion 28 | * - qt5AndroidDir - holds the path to qt android files 29 | * needed to build any Qt application 30 | * on Android. 31 | * 32 | * are defined in gradle.properties file. This file is 33 | * updated by QtCreator and androiddeployqt tools. 34 | * Changing them manually might break the compilation! 35 | *******************************************************/ 36 | 37 | compileSdkVersion androidCompileSdkVersion.toInteger() 38 | 39 | buildToolsVersion androidBuildToolsVersion 40 | 41 | sourceSets { 42 | main { 43 | manifest.srcFile 'AndroidManifest.xml' 44 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] 45 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] 46 | res.srcDirs = [qt5AndroidDir + '/res', 'res'] 47 | resources.srcDirs = ['src'] 48 | renderscript.srcDirs = ['src'] 49 | assets.srcDirs = ['assets'] 50 | jniLibs.srcDirs = ['libs'] 51 | } 52 | } 53 | 54 | lintOptions { 55 | abortOnError false 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip 7 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /android/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/libs/android-support-v4.jar -------------------------------------------------------------------------------- /android/libs/d2xx.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/libs/d2xx.jar -------------------------------------------------------------------------------- /android/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /android/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /android/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/android/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /android/res/values/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://download.qt-project.org/ministro/android/qt5/qt-5.4 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /android/res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /android/src/QtFtDev.java: -------------------------------------------------------------------------------- 1 | // Java class 2 | package org.qtproject.qt5; 3 | 4 | //import android.app.Activity; 5 | import com.ftdi.j2xx.D2xxManager; 6 | import com.ftdi.j2xx.FT_Device; 7 | 8 | import android.content.Context; 9 | 10 | //import android.os.Handler; 11 | 12 | 13 | 14 | import java.io.IOException; 15 | 16 | 17 | public class QtFtDev //extends org.qtproject.qt5.android.bindings.QtActivity//extends Activity 18 | { 19 | // j2xx 20 | public static D2xxManager ftD2xx = null; 21 | public Context global_context; 22 | 23 | FT_Device ftDev; 24 | int DevCount = -1; 25 | int currentPortIndex = -1; 26 | int portIndex = -1; 27 | 28 | enum DeviceStatus{ 29 | DEV_NOT_CONNECT, 30 | DEV_NOT_CONFIG, 31 | DEV_CONFIG 32 | } 33 | boolean uart_configured = false; 34 | 35 | int lastReadLen; 36 | 37 | int baudRate; /* baud rate */ 38 | byte stopBit; /* 1:1stop bits, 2:2 stop bits */ 39 | byte dataBit; /* 8:8bit, 7: 7bit */ 40 | byte parity; /* 0: none, 1: odd, 2: even, 3: mark, 4: space */ 41 | byte flowControl; /* 0:none, 1: CTS/RTS, 2:DTR/DSR, 3:XOFF/XON */ 42 | 43 | final byte XON = 0x11; /* Resume transmission */ 44 | final byte XOFF = 0x13; /* Pause transmission */ 45 | // ReadThread readThread; // read data from USB 46 | 47 | final int MAX_NUM_BYTES = 65536; 48 | final int USB_DATA_BUFFER = 8192; 49 | 50 | byte[] writeBuffer; 51 | 52 | 53 | 54 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 55 | static int fromNumber(int x, int y) { 56 | return x + y; 57 | } 58 | 59 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 60 | 61 | static String fromNumberOne(int x) { 62 | return "Hello Qt from Java " + x; 63 | } 64 | 65 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 66 | 67 | String fromNumberTwo(int x){ 68 | return "from number two " + x; 69 | } 70 | 71 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 72 | 73 | //init lib 74 | int getInstance(Context parentContext) 75 | { 76 | int retVal = 1; 77 | writeBuffer = new byte[512]; 78 | global_context = parentContext; 79 | 80 | try{ 81 | ftD2xx = D2xxManager.getInstance(parentContext); 82 | retVal = 2; 83 | } 84 | catch (D2xxManager.D2xxException e) { 85 | retVal = 3; 86 | } 87 | return retVal; 88 | } 89 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 90 | 91 | //ftdev list 92 | int createDeviceList() 93 | { 94 | int tempDevCount = ftD2xx.createDeviceInfoList(global_context); 95 | if (tempDevCount > 0) { 96 | if( DevCount != tempDevCount ) 97 | DevCount = tempDevCount; 98 | }else 99 | DevCount = -1; 100 | 101 | return DevCount; 102 | 103 | } 104 | 105 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 106 | 107 | int checkDeviceStatus() 108 | { 109 | 110 | int retVal = 0; 111 | 112 | switch(checkDevice()){ 113 | case DEV_NOT_CONNECT: retVal = 0; 114 | case DEV_NOT_CONFIG: retVal = 1; 115 | case DEV_CONFIG: retVal = 2; 116 | } 117 | return retVal; 118 | } 119 | 120 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 121 | 122 | DeviceStatus checkDevice() 123 | { 124 | if(ftDev == null || false == ftDev.isOpen()) { 125 | //"Need to connect to cable" 126 | return DeviceStatus.DEV_NOT_CONNECT; 127 | }else{ 128 | if(false == uart_configured){ 129 | //midToast("CHECK: uart_configured == false", Toast.LENGTH_SHORT); 130 | //"Need to configure UART. 131 | return DeviceStatus.DEV_NOT_CONFIG; 132 | } 133 | } 134 | return DeviceStatus.DEV_CONFIG; 135 | } 136 | 137 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 138 | 139 | int connToOneDevice(int connIndx, int baudR, int dataB, int stopB, int partt, int flowCtrl) 140 | { 141 | lastReadLen = 0; 142 | portIndex = connIndx; 143 | int connF = 10; 144 | createDeviceList(); 145 | if(DevCount > 0) 146 | connF = connectFunction(); 147 | 148 | if(DeviceStatus.DEV_NOT_CONNECT == checkDevice()) 149 | return connF; //dev not connect 150 | 151 | baudRate = baudR; 152 | stopBit = (byte)stopB ; /* 0:1stop bits, 1:2 stop bits */ 153 | dataBit = (byte)dataB; /* 8:8bit, 7: 7bit */ 154 | parity = (byte)partt; /* 0: none, 1: odd, 2: even, 3: mark, 4: space */ 155 | flowControl = (byte)flowCtrl; /* 0:none, 1: CTS/RTS, 2:DTR/DSR, 3:XOFF/XON */ 156 | 157 | 158 | setConfig(baudRate, dataBit, stopBit, parity, flowControl); 159 | 160 | uart_configured = true; 161 | 162 | if(true == ftDev.isOpen()) 163 | return 0; 164 | else 165 | return 11; 166 | } 167 | 168 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 169 | 170 | void setConfig(int baud, byte dataBits, byte stopBits, byte parity, byte flowControl) 171 | { 172 | // configure port 173 | // reset to UART mode for 232 devices 174 | ftDev.setBitMode((byte) 0, D2xxManager.FT_BITMODE_RESET); 175 | 176 | ftDev.setBaudRate(baud); 177 | 178 | switch (dataBits){ 179 | case 7: dataBits = D2xxManager.FT_DATA_BITS_7; break; 180 | case 8: dataBits = D2xxManager.FT_DATA_BITS_8; break; 181 | default: dataBits = D2xxManager.FT_DATA_BITS_8; break; 182 | } 183 | 184 | switch (stopBits){ 185 | case 0: stopBits = D2xxManager.FT_STOP_BITS_1; break; 186 | case 1: stopBits = D2xxManager.FT_STOP_BITS_2; break; 187 | default: stopBits = D2xxManager.FT_STOP_BITS_1; break; 188 | } 189 | 190 | switch (parity){ 191 | case 0: parity = D2xxManager.FT_PARITY_NONE; break; 192 | case 1: parity = D2xxManager.FT_PARITY_ODD; break; 193 | case 2: parity = D2xxManager.FT_PARITY_EVEN; break; 194 | case 3: parity = D2xxManager.FT_PARITY_MARK; break; 195 | case 4: parity = D2xxManager.FT_PARITY_SPACE; break; 196 | default: parity = D2xxManager.FT_PARITY_NONE; break; 197 | } 198 | 199 | ftDev.setDataCharacteristics(dataBits, stopBits, parity); 200 | 201 | short flowCtrlSetting; 202 | switch (flowControl){ 203 | case 0: flowCtrlSetting = D2xxManager.FT_FLOW_NONE; break; 204 | case 1: flowCtrlSetting = D2xxManager.FT_FLOW_RTS_CTS; break; 205 | case 2: flowCtrlSetting = D2xxManager.FT_FLOW_DTR_DSR; break; 206 | case 3: flowCtrlSetting = D2xxManager.FT_FLOW_XON_XOFF; break; 207 | default: flowCtrlSetting = D2xxManager.FT_FLOW_NONE; break; 208 | } 209 | 210 | ftDev.setFlowControl(flowCtrlSetting, XON, XOFF); 211 | uart_configured = true; 212 | } 213 | 214 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 215 | 216 | int connectFunction() 217 | { 218 | 219 | if( portIndex + 1 > DevCount) 220 | portIndex = 0; 221 | 222 | 223 | if( currentPortIndex == portIndex && ftDev != null && true == ftDev.isOpen() ) 224 | return 1; 225 | 226 | 227 | if(null == ftDev) 228 | ftDev = ftD2xx.openByIndex(global_context, portIndex); 229 | else 230 | ftDev = ftD2xx.openByIndex(global_context, portIndex); 231 | 232 | uart_configured = false; 233 | 234 | if(ftDev == null) 235 | return 2; 236 | 237 | if (true == ftDev.isOpen()){ 238 | currentPortIndex = portIndex; 239 | return 0; 240 | }else 241 | return 3; 242 | 243 | } 244 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 245 | 246 | int sendData(String writeHex/*, byte[] buffer*/) 247 | { 248 | int numBytes = -1; 249 | try { 250 | String atemp = hexToAscii(writeHex); 251 | numBytes = atemp.length(); 252 | for (int i = 0; i < numBytes; i++){ 253 | writeBuffer[i] = (byte) atemp.charAt(i); 254 | } 255 | }catch(IllegalArgumentException e){ 256 | return -2; 257 | } 258 | 259 | if (ftDev.isOpen() == false) 260 | return -3; 261 | 262 | if (numBytes > 0) 263 | return ftDev.write(writeBuffer, numBytes); 264 | return 0; 265 | 266 | } 267 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 268 | int readDataArrLen() 269 | { 270 | return USB_DATA_BUFFER; 271 | } 272 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 273 | int readDataLastReadLen() 274 | { 275 | return lastReadLen; 276 | } 277 | 278 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 279 | int bytesAvailable() 280 | { 281 | if (ftDev.isOpen() == false){ 282 | lastReadLen = -1; 283 | return lastReadLen; 284 | }else{ 285 | return ftDev.getQueueStatus(); 286 | } 287 | 288 | } 289 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 290 | String readData() 291 | { 292 | byte[] usbdata = new byte[USB_DATA_BUFFER]; 293 | 294 | if (ftDev.isOpen() == false){ 295 | lastReadLen = -1; 296 | return new StringBuilder(0).toString(); 297 | } 298 | int readcount = ftDev.getQueueStatus(); 299 | 300 | if (readcount > 0){ 301 | if(readcount > USB_DATA_BUFFER){ 302 | readcount = USB_DATA_BUFFER; 303 | } 304 | ftDev.read(usbdata, readcount); 305 | } 306 | lastReadLen = readcount; 307 | 308 | return byteArrayToHex(usbdata); 309 | } 310 | 311 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 312 | 313 | int disconnectFunction() 314 | { 315 | DevCount = -1; 316 | currentPortIndex = -1; 317 | 318 | if(ftDev != null){ 319 | if( true == ftDev.isOpen()) { 320 | ftDev.close(); 321 | } 322 | } 323 | return 0; 324 | } 325 | 326 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 327 | 328 | String hexToAscii(String s) throws IllegalArgumentException 329 | { 330 | int n = s.length(); 331 | StringBuilder sb = new StringBuilder(n / 2); 332 | for (int i = 0; i < n; i += 2) 333 | { 334 | char a = s.charAt(i); 335 | char b = s.charAt(i + 1); 336 | sb.append((char) ((hexToInt(a) << 4) | hexToInt(b))); 337 | } 338 | return sb.toString(); 339 | } 340 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 341 | int hexToInt(char ch) 342 | { 343 | if ('a' <= ch && ch <= 'f') { return ch - 'a' + 10; } 344 | if ('A' <= ch && ch <= 'F') { return ch - 'A' + 10; } 345 | if ('0' <= ch && ch <= '9') { return ch - '0'; } 346 | throw new IllegalArgumentException(String.valueOf(ch)); 347 | } 348 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 349 | 350 | String byteArrayToHex(byte[] a) { 351 | StringBuilder sb = new StringBuilder(a.length * 2); 352 | for(byte b: a) 353 | sb.append(String.format("%02x", b & 0xff)); 354 | return sb.toString(); 355 | } 356 | 357 | //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 358 | } 359 | 360 | -------------------------------------------------------------------------------- /android/src/TestClass.java: -------------------------------------------------------------------------------- 1 | // Java class 2 | package org.qtproject.qt5; 3 | class TestClass 4 | { 5 | static int fromNumber(int x) { 6 | return x + 2; 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /customproxy4qmlmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "customproxy4qmlmodel.h" 2 | //======================================================================================== 3 | CustomProxy4QmlModel::CustomProxy4QmlModel(const QList &sortCols, QObject *parent) : 4 | QSortFilterProxyModel(parent), sortCols(sortCols) 5 | { 6 | 7 | } 8 | 9 | //======================================================================================== 10 | bool CustomProxy4QmlModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const 11 | { 12 | 13 | QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); 14 | 15 | bool retVal = false; 16 | if(sortCols.isEmpty()){ 17 | retVal = true; 18 | }else{ 19 | for( int i = 0, iMax = sortCols.size(); i < iMax && !retVal; i++) 20 | retVal = index.data(sortCols.at(i)).toString().contains(filterRegExp()); 21 | 22 | } 23 | 24 | return retVal; 25 | } 26 | //======================================================================================== 27 | void CustomProxy4QmlModel::setNewFileterStr(QString str) 28 | { 29 | if(str.contains("'")){ 30 | str.replace("'", " "); 31 | } 32 | 33 | QRegExp regExp(str, Qt::CaseInsensitive, QRegExp::RegExp); 34 | this->setFilterRegExp(regExp); 35 | } 36 | //======================================================================================== 37 | -------------------------------------------------------------------------------- /customproxy4qmlmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOMPROXY4QMLMODEL_H 2 | #define CUSTOMPROXY4QMLMODEL_H 3 | 4 | #include 5 | #include 6 | #include "qmlitemmodel.h" 7 | 8 | class CustomProxy4QmlModel : public QSortFilterProxyModel 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit CustomProxy4QmlModel(const QList &sortCols, QObject *parent = 0); 13 | 14 | signals: 15 | 16 | protected: 17 | bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; 18 | 19 | public slots: 20 | void setNewFileterStr(QString str); 21 | 22 | private: 23 | QList sortCols; 24 | 25 | }; 26 | 27 | #endif // CUSTOMPROXY4QMLMODEL_H 28 | -------------------------------------------------------------------------------- /deployment.pri: -------------------------------------------------------------------------------- 1 | android-no-sdk { 2 | target.path = /data/user/qt 3 | export(target.path) 4 | INSTALLS += target 5 | } else:android { 6 | x86 { 7 | target.path = /libs/x86 8 | } else: armeabi-v7a { 9 | target.path = /libs/armeabi-v7a 10 | } else { 11 | target.path = /libs/armeabi 12 | } 13 | export(target.path) 14 | INSTALLS += target 15 | } else:unix { 16 | isEmpty(target.path) { 17 | qnx { 18 | target.path = /tmp/$${TARGET}/bin 19 | } else { 20 | target.path = /opt/$${TARGET}/bin 21 | } 22 | export(target.path) 23 | } 24 | INSTALLS += target 25 | } 26 | 27 | export(INSTALLS) 28 | -------------------------------------------------------------------------------- /ftdimanager.cpp: -------------------------------------------------------------------------------- 1 | #include "ftdimanager.h" 2 | #include 3 | #include 4 | 5 | //============================================================================================================================= 6 | FtdiManager::FtdiManager(QObject *parent) : QObject(parent) 7 | { 8 | QTimer *readTmr = new QTimer; 9 | readTmr->setInterval(150); 10 | readTmr->setSingleShot(true); 11 | 12 | connect(this, SIGNAL(startReadTmr()), readTmr, SLOT(start()) ); 13 | connect(this, SIGNAL(stopReadTmr()), readTmr, SLOT(stop()) ); 14 | connect(readTmr, SIGNAL(timeout()), this, SLOT(onReadTmr()) ); 15 | 16 | deviceModel = new QmlItemModel(QString("value").split(",") ); 17 | historyModel = new QmlItemModel(QString("value").split(",") ); 18 | 19 | QList listInt; 20 | listInt.append(Qt::UserRole + 1); 21 | proxy_historyModel = new CustomProxy4QmlModel(listInt); 22 | proxy_historyModel->setDynamicSortFilter(true); 23 | proxy_historyModel->setSourceModel(historyModel); 24 | 25 | this->adnrActivity = QtAndroid::androidActivity(); 26 | 27 | } 28 | //============================================================================================================================= 29 | void FtdiManager::startJar() 30 | { 31 | qtFtDev2xxManager = QAndroidJniObject(QByteArray("org/qtproject/qt5/QtFtDev").constData()); 32 | 33 | // qDebug() << "context is valid = " <ExceptionCheck()) { 37 | // Handle exception here. 38 | qDebug() << "1 env =================================================== "; 39 | env->ExceptionClear(); 40 | } 41 | qDebug() << "getInstance = " << qtFtDev2xxManager.callMethod(QByteArray("getInstance").constData(), QByteArray("(Landroid/content/Context;)I").constData(), adnrActivity.object()); 42 | // QByteArray("(I)Ljava/lang/Object;").constData(), adnrActivity.object()); 43 | 44 | if (env->ExceptionCheck()) { 45 | // Handle exception here. 46 | qDebug() << "2 env =================================================== "; 47 | env->ExceptionClear(); 48 | } 49 | 50 | QTimer::singleShot(200, this, SLOT(createDeviceInfoList())); 51 | loadSettings(0); 52 | 53 | historyModel->clearAllData(); 54 | for(int i = 0, iMax = listHistoryCommand.size(); i < iMax; i++) 55 | historyModel->addCustomDevice(QList() << listHistoryCommand.at(i)); 56 | 57 | } 58 | //============================================================================================================================= 59 | void FtdiManager::onBtnPrssd() 60 | { 61 | QAndroidJniObject strhello = QAndroidJniObject::callStaticObjectMethod(QByteArray("org/qtproject/qt5/QtFtDev").constData(), 62 | QByteArray("fromNumberOne").constData(), 63 | QByteArray("(I)Ljava/lang/String;").constData(), 64 | QTime::currentTime().second()); 65 | QAndroidJniEnvironment env; 66 | if (env->ExceptionCheck()) { 67 | // Handle exception here. 68 | qDebug() << "4env =================================================== "; 69 | env->ExceptionClear(); 70 | } 71 | 72 | // jstring strJ = strhello.object(); 73 | 74 | qDebug() << "stringNumber=" << strhello.toString(); // <clearAllData(); 82 | 83 | jint devCount = qtFtDev2xxManager.callMethod(QByteArray("createDeviceList").constData()); 84 | 85 | QAndroidJniEnvironment env; 86 | if (env->ExceptionCheck()) { 87 | // Handle exception here. 88 | qDebug() << "11 env =================================================== "; 89 | env->ExceptionClear(); 90 | } 91 | 92 | for(int i = 0; i < devCount; i++) 93 | deviceModel->addCustomDevice(QList() << QString("ttyUSB%1").arg(i)); 94 | 95 | if(devCount > 0){ 96 | emit setCurrntPortIndx(devCount - 1); 97 | }else 98 | emit setCurrntPortIndx(-1); 99 | if(devCount > 0 && !onlyUpdate) 100 | connectToOnePort(); 101 | } 102 | //============================================================================================================================= 103 | void FtdiManager::deviceStatus() 104 | { 105 | jint devCount = qtFtDev2xxManager.callMethod(QByteArray("checkDeviceStatus").constData()); 106 | 107 | QString devStts(""); 108 | switch(devCount){ 109 | case 0: devStts = "DEV_NOT_CONNECT"; break; 110 | case 1: devStts = "DEV_NOT_CONFIG"; break; 111 | case 2: devStts = "DEV_CONFIG"; break; 112 | default: devStts = "unknown"; break; 113 | } 114 | 115 | QAndroidJniEnvironment env; 116 | if (env->ExceptionCheck()) { 117 | // Handle exception here. 118 | qDebug() << "11 env =================================================== "; 119 | env->ExceptionClear(); 120 | } 121 | emit addLineToLog("devStts= " + devStts + " retVal=" + QString::number(devCount)); 122 | } 123 | //============================================================================================================================= 124 | void FtdiManager::connectToOnePort() 125 | { 126 | QList list = loadSettings(1); 127 | while(list.size() < 4) 128 | list.append(0); 129 | 130 | if(list.size() < 5) 131 | list.append(3); 132 | 133 | connectToOnePort(0, list.at(4).toInt(), list.at(0).toInt(), list.at(1).toInt(), list.at(2).toInt(), list.at(3).toInt()); 134 | } 135 | //============================================================================================================================= 136 | void FtdiManager::connectToOnePort(int indx, int baudIndx, int dataIndx, int stopIndx, int parityIndx, int flowIndx) 137 | { 138 | 139 | QList listVar; 140 | listVar.append(dataIndx); 141 | listVar.append(stopIndx); 142 | listVar.append(parityIndx); 143 | listVar.append(flowIndx); 144 | listVar.append(baudIndx); 145 | saveSettings(listVar, 1); 146 | 147 | jint baudRate ; 148 | 149 | switch (baudIndx) { 150 | case 0: baudRate = 1200; break; 151 | case 1: baudRate = 2400; break; 152 | case 2: baudRate = 4800; break; 153 | case 3: baudRate = 9600; break; 154 | case 4: baudRate = 19200; break; 155 | case 5: baudRate = 38400; break; 156 | case 6: baudRate = 57600; break; 157 | case 7: baudRate = 115200; break; 158 | 159 | default: baudRate = 9600; break; 160 | } 161 | 162 | jint devIndx = indx; 163 | jint devDataIndx = dataIndx; 164 | jint devStopIndx = stopIndx ; 165 | jint devParityIndx = parityIndx; 166 | jint devFlowIndx = flowIndx; 167 | 168 | jint retVal = qtFtDev2xxManager.callMethod(QByteArray("connToOneDevice").constData(), 169 | QByteArray("(IIIIII)I").constData(), devIndx, 170 | baudRate, 171 | devDataIndx, 172 | devStopIndx, 173 | devParityIndx, 174 | devFlowIndx ); 175 | 176 | QAndroidJniEnvironment env; 177 | if (env->ExceptionCheck()) { 178 | // Handle exception here. 179 | qDebug() << "11 env =================================================== "; 180 | env->ExceptionClear(); 181 | } 182 | 183 | QString openStts(""); 184 | switch (retVal) { 185 | case 0: openStts = tr("Opened ttyUSB%1!").arg(indx) ; emit onFtdiStateChanged(true); emit startReadTmr(); break; 186 | case 1: openStts = tr("Already opened ttyUSB%1!").arg(indx); emit onFtdiStateChanged(true); emit startReadTmr(); break; 187 | case 2: openStts = tr("Device not valid ttyUSB%1!").arg(indx); break; 188 | case 3: openStts = tr("Can't open ttyUSB%1!").arg(indx); break; 189 | 190 | default: openStts = "unkonown error"; break; 191 | } 192 | 193 | emit addLineToLog(openStts ); 194 | } 195 | //============================================================================================================================= 196 | void FtdiManager::disconnectFromPort() 197 | { 198 | emit stopReadTmr(); 199 | emit onFtdiStateChanged(false); 200 | emit addLineToLog("Device disconected"); 201 | qtFtDev2xxManager.callMethod(QByteArray("disconnectFunction").constData()); 202 | 203 | createDeviceInfoList(true); 204 | } 205 | //============================================================================================================================= 206 | void FtdiManager::sendDataToPort(QString line, bool hexOut, int endLineIndx) 207 | { 208 | QString tmpStr(line); 209 | emit startReadTmr(); 210 | 211 | if(hexOut){ 212 | switch(endLineIndx){ 213 | case 0: line.append("0D0A"); break; 214 | case 1: line.append("0D"); break; 215 | case 2: line.append("0A"); break; 216 | default: break; 217 | } 218 | }else{ 219 | 220 | switch(endLineIndx){ 221 | case 0: line.append("\r\n"); break; 222 | case 1: line.append("\r"); break; 223 | case 2: line.append("\n"); break; 224 | default: break; 225 | } 226 | } 227 | 228 | 229 | QAndroidJniEnvironment env; 230 | if(!hexOut) 231 | line = line.toLocal8Bit().toHex(); 232 | 233 | if((line.size() % 2)) 234 | line.prepend("0"); 235 | 236 | QAndroidJniObject string2 = QAndroidJniObject::fromString(line); 237 | 238 | jint retVal = qtFtDev2xxManager.callMethod(QByteArray("sendData").constData(), 239 | QByteArray("(Ljava/lang/String;)I").constData(), 240 | string2.object()/*, arr*/); 241 | if (env->ExceptionCheck()) { 242 | // Handle exception here. 243 | emit addLineToLog("write exeption"); 244 | qDebug() << "11 env =================================================== "; 245 | env->ExceptionClear(); 246 | } 247 | 248 | if(!listHistoryCommand.contains(tmpStr.simplified().trimmed(), Qt::CaseInsensitive)){ 249 | listHistoryCommand.prepend(tmpStr.simplified().trimmed()); 250 | historyModel->prependCustomDevice(QList() << listHistoryCommand.first()); 251 | saveSettings(QList(), 4); //save list last command 252 | } 253 | 254 | if(retVal >= 0){ 255 | emit addLineToLog(tmpStr); 256 | }else{ 257 | emit addLineToLog("line error write\r\n" + QString::number(retVal)); 258 | disconnectFromPort(); 259 | } 260 | } 261 | //============================================================================================================================= 262 | void FtdiManager::setThisHistoryFilter(const QString &str) 263 | { 264 | proxy_historyModel->setNewFileterStr(str); 265 | } 266 | //============================================================================================================================= 267 | void FtdiManager::delThisHistoryIndx(const int &indx) 268 | { 269 | int row = proxy_historyModel->mapToSource(proxy_historyModel->index(indx,0)).row(); 270 | if(row < 0 || row > listHistoryCommand.size()) 271 | return; 272 | historyModel->removeThisRow(row); 273 | listHistoryCommand.removeAt(row); 274 | saveSettings(QList(), 4); 275 | } 276 | //============================================================================================================================= 277 | void FtdiManager::saveQmlSett(const int &intVal, const int &key) 278 | { 279 | QSettings settings("Hello_ZB", "QtAndroidFtdiTerminal"); 280 | 281 | switch(key){ 282 | case 0: { settings.beginGroup("terminal"); settings.setValue("endSymb", intVal); break;} 283 | } 284 | settings.endGroup(); 285 | } 286 | //============================================================================================================================= 287 | void FtdiManager::saveQmlSett(const bool &boolVal, const int &key) 288 | { 289 | QSettings settings("Hello_ZB", "QtAndroidFtdiTerminal"); 290 | 291 | switch(key){ 292 | case 0: { settings.beginGroup("terminal"); settings.setValue("hexOut", boolVal); break;} 293 | 294 | } 295 | settings.endGroup(); 296 | 297 | } 298 | //============================================================================================================================= 299 | void FtdiManager::saveQmlSettRealVal(const qreal &realVal, const int &key) 300 | { 301 | QSettings settings("Hello_ZB", "QtAndroidFtdiTerminal"); 302 | 303 | switch(key){ 304 | case 0: { settings.beginGroup("sett"); settings.setValue("fontSize", realVal); break;} 305 | 306 | } 307 | settings.endGroup(); 308 | 309 | } 310 | //============================================================================================================================= 311 | void FtdiManager::sendLineHexValidator( QString line) 312 | { 313 | line = line.simplified().trimmed().remove(" "); 314 | bool isValid = false; 315 | if(line.isEmpty()){ 316 | isValid = true; 317 | }else{ 318 | if(line.size()%2){ 319 | isValid = false; 320 | }else{ 321 | 322 | QString tmpStr = QByteArray::fromHex(line.toLocal8Bit()).toHex(); 323 | isValid = (tmpStr.length() == line.length()); 324 | } 325 | } 326 | 327 | emit sendLineHexIsValid(isValid); 328 | } 329 | //============================================================================================================================= 330 | void FtdiManager::onReadTmr() 331 | { 332 | if(readData()) 333 | emit startReadTmr(); 334 | else{ 335 | disconnectFromPort(); 336 | 337 | } 338 | } 339 | //============================================================================================================================= 340 | bool FtdiManager::readData() 341 | { 342 | jint bytesAvailable = qtFtDev2xxManager.callMethod(QByteArray("bytesAvailable").constData()); 343 | QAndroidJniEnvironment env; 344 | if (env->ExceptionCheck()) { 345 | // Handle exception here. 346 | qDebug() << "11 env =================================================== "; 347 | emit addLineToLog("read errror"); 348 | 349 | env->ExceptionClear(); 350 | return false; 351 | } 352 | 353 | if(bytesAvailable < 0){ 354 | return false; 355 | } 356 | 357 | if(bytesAvailable < 1) 358 | return true; 359 | 360 | QAndroidJniObject stringArray = qtFtDev2xxManager.callObjectMethod(QByteArray("readData").constData()); 361 | if (env->ExceptionCheck()) { 362 | // Handle exception here. 363 | qDebug() << "11 env =================================================== "; 364 | emit addLineToLog("read errror"); 365 | 366 | env->ExceptionClear(); 367 | disconnectFromPort(); 368 | return false; 369 | } 370 | QString readStr = stringArray.toString(); 371 | if(readStr.isEmpty()) 372 | return true; 373 | 374 | if((readStr.length()%2)) 375 | readStr.prepend("0"); 376 | 377 | readStr = QByteArray::fromHex(readStr.toLocal8Bit()); 378 | 379 | if(!readStr.isEmpty()) 380 | emit addLineToLog(readStr); 381 | 382 | return true; 383 | } 384 | //============================================================================================================================= 385 | QList FtdiManager::loadSettings(int key) 386 | { 387 | QSettings settings("Hello_ZB", "QtAndroidFtdiTerminal"); 388 | QList list; 389 | switch(key){ 390 | case 0: { //load all settings 391 | settings.beginGroup("uart"); 392 | emit onConnectPageSettt(settings.value("dataBits", 0).toInt(), 393 | settings.value("stopBits", 0).toInt(), 394 | settings.value("parity", 0).toInt(), 395 | settings.value("flowCtrl", 0).toInt(), 396 | settings.value("baudRate", 3).toInt() ); 397 | 398 | settings.endGroup(); 399 | 400 | settings.beginGroup("terminal"); 401 | emit onTerminalPageSettt(settings.value("endSymb", 0).toInt(), settings.value("hexOut", false).toBool()); 402 | settings.endGroup(); 403 | 404 | settings.beginGroup("sett"); 405 | emit onSettPage(settings.value("fontSize", 0).toReal()); 406 | settings.endGroup(); 407 | 408 | settings.beginGroup("app"); 409 | listHistoryCommand = settings.value("listHistoryCommand").toStringList(); 410 | if(listHistoryCommand.isEmpty()) 411 | listHistoryCommand = QString("+++ ATAD ATBD ATCH ATID ATNI ATSL ATSH ATVR ATHV ATAP ATSM ATND ATBD").split(' '); 412 | settings.endGroup(); 413 | 414 | return list; } 415 | 416 | case 1:{ 417 | settings.beginGroup("uart"); 418 | list.append(settings.value("dataBits", 0)); 419 | list.append(settings.value("stopBits", 0)); 420 | list.append(settings.value("parity", 0)); 421 | list.append(settings.value("flowCtrl", 0)); 422 | list.append(settings.value("baudRate", 3)); 423 | 424 | settings.endGroup(); 425 | return list;} 426 | } 427 | return list; 428 | } 429 | //============================================================================================================================= 430 | void FtdiManager::saveSettings(QList list, int key) 431 | { 432 | QSettings settings("Hello_ZB", "QtAndroidFtdiTerminal"); 433 | switch(key){ 434 | case 0: { //save all settings 435 | settings.beginGroup("uart"); 436 | if(list.size() != 8) 437 | return; 438 | settings.setValue("dataBits", list.at(0)); 439 | settings.setValue("stopBits", list.at(1)); 440 | settings.setValue("parity", list.at(2)); 441 | settings.setValue("flowCtrl", list.at(3)); 442 | settings.setValue("baudRate", list.at(4)); 443 | settings.endGroup(); 444 | 445 | settings.beginGroup("terminal"); 446 | settings.setValue("endSymb", list.at(5)); 447 | settings.setValue("hexOut", list.at(6)); 448 | settings.endGroup(); 449 | 450 | settings.beginGroup("sett"); 451 | settings.setValue("fontSize", list.at(7)); 452 | settings.endGroup(); 453 | 454 | while(listHistoryCommand.size() > 1000) 455 | listHistoryCommand.removeLast(); 456 | 457 | settings.beginGroup("app"); 458 | settings.setValue("listHistoryCommand",listHistoryCommand); 459 | settings.endGroup(); 460 | 461 | return ; } 462 | 463 | case 1:{ 464 | settings.beginGroup("uart"); 465 | if(list.size() != 5) 466 | return; 467 | settings.setValue("dataBits", list.at(0)); 468 | settings.setValue("stopBits", list.at(1)); 469 | settings.setValue("parity", list.at(2)); 470 | settings.setValue("flowCtrl", list.at(3)); 471 | settings.setValue("baudRate", list.at(4)); 472 | 473 | settings.endGroup(); 474 | return ;} 475 | 476 | case 2:{ 477 | if(list.size() != 2) 478 | return; 479 | settings.beginGroup("terminal"); 480 | settings.setValue("endSymb", list.at(0)); 481 | settings.setValue("hexOut", list.at(1)); 482 | settings.endGroup(); 483 | return; } 484 | 485 | case 3:{ 486 | if(list.size() != 1) 487 | return; 488 | settings.beginGroup("sett"); 489 | settings.setValue("fontSize", list.at(0)); 490 | settings.endGroup(); 491 | return; } 492 | 493 | case 4:{ 494 | while(listHistoryCommand.size() > 1000) 495 | listHistoryCommand.removeLast(); 496 | 497 | settings.beginGroup("app"); 498 | settings.setValue("listHistoryCommand",listHistoryCommand); 499 | settings.endGroup(); 500 | return;} 501 | } 502 | } 503 | //============================================================================================================================= 504 | -------------------------------------------------------------------------------- /ftdimanager.h: -------------------------------------------------------------------------------- 1 | #ifndef FTDIMANAGER_H 2 | #define FTDIMANAGER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "qmlitemmodel.h" 11 | #include "customproxy4qmlmodel.h" 12 | 13 | class FtdiManager : public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit FtdiManager(QObject *parent = 0); 18 | QmlItemModel *deviceModel; 19 | QmlItemModel *historyModel; 20 | 21 | CustomProxy4QmlModel *proxy_historyModel; 22 | 23 | 24 | signals: 25 | void addLineToLog(QString); 26 | 27 | void startReadTmr(); 28 | 29 | void stopReadTmr(); 30 | 31 | void onFtdiStateChanged(bool); 32 | 33 | void onConnectPageSettt(int, int,int ,int,int); 34 | 35 | void onTerminalPageSettt(int,bool); 36 | 37 | void onSettPage(qreal); 38 | 39 | void setCurrntPortIndx(int); 40 | 41 | void sendLineHexIsValid(bool); 42 | 43 | public slots: 44 | void startJar(); 45 | 46 | 47 | void onBtnPrssd(); 48 | 49 | void createDeviceInfoList(bool onlyUpdate = false); 50 | 51 | void deviceStatus(); 52 | 53 | void connectToOnePort(); 54 | 55 | void connectToOnePort(int indx , int baudIndx, int dataIndx, int stopIndx, int parityIndx, int flowIndx); 56 | 57 | void disconnectFromPort(); 58 | 59 | void sendDataToPort(QString line, bool hexOut, int endLineIndx); 60 | 61 | void setThisHistoryFilter(const QString &str); 62 | 63 | void delThisHistoryIndx(const int &indx); 64 | 65 | void saveQmlSett(const int &intVal, const int &key); 66 | 67 | void saveQmlSett(const bool &boolVal, const int &key); 68 | 69 | 70 | void saveQmlSettRealVal(const qreal &realVal, const int &key); 71 | 72 | void sendLineHexValidator(QString line); 73 | 74 | private slots: 75 | void onReadTmr(); 76 | 77 | private: 78 | bool readData(); 79 | 80 | QList loadSettings(int key); 81 | void saveSettings(QList list, int key); 82 | 83 | 84 | 85 | int bufLen; 86 | 87 | QAndroidJniObject qtFtDev2xxManager; 88 | QAndroidJniObject adnrActivity; 89 | 90 | QAndroidJniObject ftD2xx; 91 | 92 | QStringList listHistoryCommand; 93 | 94 | }; 95 | 96 | #endif // FTDIMANAGER_H 97 | -------------------------------------------------------------------------------- /katynko/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | PreviewsShown=true 3 | Timestamp=2015,9,3,16,23,56 4 | Version=3 5 | ViewMode=1 6 | -------------------------------------------------------------------------------- /katynko/android_ft232.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/android_ft232.png -------------------------------------------------------------------------------- /katynko/clear_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/clear_left.png -------------------------------------------------------------------------------- /katynko/dashed_elmnt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/dashed_elmnt.png -------------------------------------------------------------------------------- /katynko/dashed_elmnt_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/dashed_elmnt_red.png -------------------------------------------------------------------------------- /katynko/fontsizedefault_koffice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/fontsizedefault_koffice.png -------------------------------------------------------------------------------- /katynko/fontsizedown_koffice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/fontsizedown_koffice.png -------------------------------------------------------------------------------- /katynko/fontsizeup_koffice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/fontsizeup_koffice.png -------------------------------------------------------------------------------- /katynko/history.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/history.png -------------------------------------------------------------------------------- /katynko/key_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/key_enter.png -------------------------------------------------------------------------------- /katynko/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/katynko/settings.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "ftdimanager.h" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | QApplication app(argc, argv); 11 | 12 | FtdiManager ftdiManager; 13 | 14 | QQmlApplicationEngine engine; 15 | 16 | engine.rootContext()->setContextProperty("ftdiManager", &ftdiManager); 17 | engine.rootContext()->setContextProperty("deviceModel", ftdiManager.deviceModel); 18 | engine.rootContext()->setContextProperty("historyModel", ftdiManager.proxy_historyModel); 19 | 20 | //QtAndroid::androidActivity().callMethod() 21 | engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 22 | 23 | if(!engine.rootObjects().isEmpty()){ 24 | 25 | qDebug() << "one line"; 26 | QObject *item = engine.rootObjects().first(); 27 | 28 | if(item) 29 | qDebug() << "item done"; 30 | else 31 | return 100; 32 | 33 | QObject::connect(&ftdiManager, SIGNAL(addLineToLog(QString)), item, SIGNAL(addToLog(QString))); 34 | QObject::connect(&ftdiManager, SIGNAL(onFtdiStateChanged(bool)), item, SIGNAL(connStateChanged(bool))); 35 | QObject::connect(&ftdiManager, SIGNAL(onConnectPageSettt(int,int, int,int ,int)), item, SIGNAL(connectPageSettt(int, int,int ,int, int))); 36 | QObject::connect(&ftdiManager, SIGNAL(onTerminalPageSettt(int,bool)), item, SIGNAL(terminalPageSettt(int,bool))); 37 | QObject::connect(&ftdiManager, SIGNAL(onSettPage(qreal)), item, SIGNAL(settPage(qreal))); 38 | QObject::connect(&ftdiManager, SIGNAL(setCurrntPortIndx(int)), item, SIGNAL(setCurrntPortIndx(int))); 39 | QObject::connect(&ftdiManager, SIGNAL(sendLineHexIsValid(bool)), item, SIGNAL( sendLineHexIsValid(bool))); 40 | 41 | ftdiManager.startJar(); 42 | return app.exec(); 43 | }else{ 44 | QMessageBox::critical(0,"AndroidFtdi", "Can't load qml content. Check your installation dir."); 45 | return 3; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import QtQuick.Controls 1.3 3 | import QtQuick.Window 2.2 4 | import QtQuick.Dialogs 1.2 5 | 6 | ApplicationWindow { 7 | title: qsTr("QtAndroidFTDI Terminal") 8 | width: 640 9 | height: 480 10 | visible: true 11 | property bool ftdiIsConnected: false 12 | 13 | signal addToLog(string mess) 14 | signal connStateChanged(bool isConnected) 15 | 16 | signal connectPageSettt(int dataIndx, int stopIndx, int parityIndx, int flowIndx, int baudIndx); 17 | 18 | signal terminalPageSettt(int endLineIndx, bool hexOut); 19 | 20 | signal settPage(real defH); 21 | 22 | signal setCurrntPortIndx(int portIndx); 23 | 24 | signal sendLineHexIsValid(bool isValid); 25 | 26 | 27 | onSetCurrntPortIndx: { 28 | cpPage.setCurrntPortIndx(portIndx); 29 | } 30 | 31 | 32 | onConnectPageSettt: { 33 | cpPage.connectPageSettt(dataIndx, stopIndx, parityIndx, flowIndx, baudIndx); 34 | } 35 | 36 | onTerminalPageSettt: { 37 | tpPage.terminalPageSettt(endLineIndx, hexOut); 38 | } 39 | 40 | onSettPage: { 41 | if(defH > Screen.logicalPixelDensity && (Screen.width < Screen.height ? 42 | width < (Screen.width * 0.25) : 43 | height < (Screen.height * 0.25))) 44 | defHeightFontPixel = defH 45 | } 46 | 47 | onSendLineHexIsValid: { 48 | tpPage.sendLineHexIsValid(isValid); 49 | } 50 | 51 | property real defHeightFontPixel: Screen.pixelDensity * 3.8; 52 | property real defHeightPushButton: defHeightFontPixel * 1.6 53 | property real defHeightPushButtonSmll: defHeightFontPixel * 1.4 54 | property real defHeightFontPixelLog: defHeightFontPixel * 0.6; 55 | property real defHeightLine: defHeightFontPixel * 0.1 56 | 57 | 58 | property string defColorBackground: "#efefef" 59 | property string defColorTop: "#aaaaaa" 60 | property string defColorText: "black" 61 | property string defColorButtonFill: "#0d670d" 62 | property string defColorButtonText: defColorBackground 63 | property string defColorLine: "#gray" 64 | 65 | property int defRadiusButton: 4; 66 | 67 | property real defMargins: defHeightFontPixel * 0.2 68 | 69 | 70 | onConnStateChanged: { 71 | ftdiIsConnected = isConnected 72 | if(isConnected){ 73 | changeStackViewPage(1) 74 | } 75 | } 76 | 77 | onAddToLog: { 78 | tpPage.appendPlainText(mess) 79 | } 80 | 81 | 82 | function changeStackViewPage(indx){ 83 | switch(indx){ 84 | case 0: stackView.push({item: cpPage, visible: true}); break; 85 | case 1: stackView.push({item: tpPage, visible: true}); break; 86 | case 2: stackView.push({item: spPage, visible: true});break; 87 | case 3: stackView.push({item: hpPage, visible: true});break; 88 | 89 | default: break; 90 | } 91 | } 92 | 93 | Rectangle { 94 | id: root 95 | anchors.fill: parent 96 | color: defColorBackground 97 | 98 | 99 | Row{ 100 | id: rtTop 101 | 102 | anchors.left: parent.left 103 | anchors.top: parent.top 104 | anchors.right: parent.right 105 | height: defHeightPushButton 106 | 107 | anchors.margins: defMargins 108 | 109 | spacing: defMargins 110 | 111 | CustomPushButton{ 112 | id: cpbConnectPage 113 | height: parent.height 114 | text: qsTr("Device") 115 | 116 | width: (parent.width / 3 ) - parent.spacing 117 | 118 | radius: defRadiusButton 119 | color: defColorButtonText 120 | fillColor: defColorButtonFill 121 | textSize: defHeightFontPixel 122 | onAnimationDone: { 123 | changeStackViewPage(0); 124 | } 125 | enabled: false 126 | } 127 | 128 | CustomPushButton{ 129 | id: cpbTerminalPage 130 | height: parent.height 131 | text: qsTr("Terminal") 132 | width: cpbConnectPage.width 133 | radius: defRadiusButton 134 | color: defColorButtonText 135 | fillColor: defColorButtonFill 136 | textSize: defHeightFontPixel 137 | onAnimationDone: { 138 | changeStackViewPage(1) 139 | } 140 | enabled: true 141 | } 142 | 143 | Item{ 144 | height: parent.height 145 | width: parent.width - cpbConnectPage.width * 2 - cpbSettingsPage.width - 3 * parent.spacing - 2 * defMargins 146 | } 147 | 148 | CustomPushButton{ 149 | id: cpbSettingsPage 150 | height: parent.height 151 | text: "" 152 | imgSource: "qrc:/img/katynko/settings.png" 153 | radius: defRadiusButton 154 | color: defColorButtonText 155 | fillColor: defColorButtonFill 156 | textSize: defHeightFontPixel 157 | width: height//cpbConnectPage.width 158 | // onIAmReleased: videoS.refreshDevList(); 159 | onAnimationDone: { 160 | changeStackViewPage(2) 161 | } 162 | enabled: true 163 | } 164 | 165 | } 166 | 167 | 168 | StackView{ 169 | id: stackView 170 | anchors.left: parent.left 171 | anchors.top: rtTop.bottom 172 | anchors.right: parent.right 173 | anchors.bottom: parent.bottom 174 | visible: true 175 | anchors.margins: defMargins 176 | initialItem: cpPage; 177 | 178 | focus: true 179 | Keys.onReleased: if (event.key === Qt.Key_Back && stackView.depth > 1) { 180 | stackView.pop(); 181 | event.accepted = true; 182 | } 183 | 184 | onCurrentItemChanged: { 185 | cpbSettingsPage.enabled = !(currentItem === spPage); 186 | cpbTerminalPage.enabled = !((currentItem === tpPage) || (currentItem === hpPage)); 187 | cpbConnectPage.enabled = !(currentItem === cpPage); 188 | 189 | 190 | } 191 | 192 | } 193 | 194 | ConnectPage{ 195 | id: cpPage 196 | visible: true 197 | } 198 | 199 | TerminalPage{ 200 | id: tpPage 201 | visible: false 202 | } 203 | 204 | SettingsPage{ 205 | id: spPage 206 | visible: false 207 | } 208 | 209 | HistoryPage{ 210 | id: hpPage 211 | visible: false 212 | } 213 | 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | CustomTextEdit.qml 5 | ConnectPage.qml 6 | TerminalPage.qml 7 | SettingsPage.qml 8 | CustomPushButton.qml 9 | HistoryPage.qml 10 | ScrollBarVertical.qml 11 | 12 | 13 | -------------------------------------------------------------------------------- /qmlitemmodel.cpp: -------------------------------------------------------------------------------- 1 | #include "qmlitemmodel.h" 2 | 3 | //============================================================================= 4 | CustomDevice::CustomDevice(const int &firstRole, const int &maxCount, const QList &list) 5 | { 6 | this->firtsRole = firstRole; 7 | for(int i = firstRole, j = 0, jMax = list.size(); i < 0xffff && j < maxCount && j < jMax; i++, j++){ 8 | hashIntVar.insert(i,list.at(j)); 9 | } 10 | } 11 | 12 | //============================================================================= 13 | QVariant CustomDevice::roleData(int role) const 14 | { 15 | if(role < firtsRole) 16 | return QVariant(); 17 | return hashIntVar.value(role, QVariant()); 18 | } 19 | //============================================================================= 20 | QHash CustomDevice::rolesData() const 21 | { 22 | return hashIntVar; 23 | } 24 | //============================================================================= 25 | 26 | QmlItemModel::QmlItemModel(QStringList listRoleName, int firstRole, QObject *parent) : 27 | QAbstractListModel(parent), firstRole(firstRole) 28 | { 29 | 30 | maxCount = listRoleName.size(); 31 | for(int j = firstRole, i = 0; i < maxCount; i++ ) 32 | m_roleNames.insert(j++,listRoleName.at(i).toLocal8Bit()); 33 | } 34 | //============================================================================= 35 | void QmlItemModel::addCustomDevice(const QList &list) 36 | { 37 | beginInsertRows(QModelIndex(), rowCount(), rowCount()); 38 | m_device.append(CustomDevice(firstRole,maxCount, list)); 39 | endInsertRows(); 40 | } 41 | //============================================================================= 42 | void QmlItemModel::prependCustomDevice(const QList &list) 43 | { 44 | beginInsertRows(QModelIndex(), 0, 0); 45 | m_device.prepend(CustomDevice(firstRole,maxCount, list)); 46 | endInsertRows(); 47 | } 48 | //============================================================================= 49 | int QmlItemModel::rowCount(const QModelIndex &parent) const 50 | { 51 | Q_UNUSED(parent); 52 | return m_device.count(); 53 | } 54 | //============================================================================= 55 | QVariant QmlItemModel::data(const QModelIndex &index, int role) const 56 | { 57 | if(index.row() < 0 || index.row() >= m_device.count()) 58 | return QVariant(); 59 | 60 | const CustomDevice dev = m_device.at(index.row()); 61 | return dev.roleData(role); 62 | } 63 | //============================================================================= 64 | QVariant QmlItemModel::dataRow(const int &row, int role) const 65 | { 66 | if(row < 0 || row >= m_device.count()) 67 | return QVariant(); 68 | 69 | const CustomDevice dev = m_device.at(row); 70 | return dev.roleData(role); 71 | 72 | // const VideoDevice &videoDev = m_device.at(row); 73 | 74 | // switch(role){ 75 | // case IpRole: return videoDev.ipStr(); 76 | // case TcpPortRole: return videoDev.tcpPort(); 77 | // case UsrNameRole: return videoDev.usrName(); 78 | // case PasswdRole: return videoDev.passwd(); 79 | // case DeviceFirmwareRole: return videoDev.deviceFirmware(); 80 | // } 81 | // return QVariant(); 82 | 83 | } 84 | //============================================================================= 85 | void QmlItemModel::removeThisRow(const int &row) 86 | { 87 | if(row < 0 || row >= m_device.count()) 88 | return; 89 | beginRemoveRows(QModelIndex(),row,row); 90 | m_device.removeAt(row); 91 | endRemoveRows(); 92 | } 93 | //============================================================================= 94 | void QmlItemModel::clearAllData() 95 | { 96 | // qDebug() << "m_device size = " << m_device.size(); 97 | beginRemoveRows(QModelIndex(), 0, rowCount()); 98 | m_device.clear(); 99 | endRemoveRows(); 100 | } 101 | //============================================================================= 102 | void QmlItemModel::replaceData(const int &row, const int &role, const QVariant &dataVar) 103 | { 104 | if(row < 0 || row >= m_device.count()) 105 | return; 106 | 107 | beginRemoveRows(QModelIndex(),row,row); 108 | CustomDevice dev = m_device.takeAt(row); 109 | endRemoveRows(); 110 | 111 | QHash devHash = dev.rolesData(); 112 | 113 | if(devHash.contains(role)) 114 | devHash.insert(role,dataVar); 115 | 116 | QList listKeys = devHash.keys(); 117 | qSort(listKeys); 118 | 119 | QList listVar; 120 | 121 | while(!listKeys.isEmpty()) 122 | listVar.append(devHash.value(listKeys.takeFirst())); 123 | 124 | beginInsertRows(QModelIndex(), row,row); 125 | m_device.insert(row, CustomDevice(firstRole,maxCount, listVar)); 126 | endInsertRows(); 127 | 128 | } 129 | //============================================================================= 130 | QList QmlItemModel::dataRowInList(const int &row) 131 | { 132 | QList retList; 133 | if(row < 0 || row >= m_device.count()) 134 | return retList; 135 | 136 | for(int role = firstRole, i = 0; i < maxCount ; i++, role++){ 137 | const CustomDevice dev = m_device.at(row); 138 | retList.append(dev.roleData(role)); 139 | } 140 | 141 | return retList; 142 | } 143 | //============================================================================= 144 | QHash QmlItemModel::roleNames() const 145 | { 146 | // QHash roles; 147 | // roles[IpRole] = "deviceIp"; 148 | // roles[TcpPortRole] = "devPort"; 149 | // roles[UsrNameRole] = "usrName"; 150 | // roles[PasswdRole] = "psswrd"; 151 | // roles[DeviceFirmwareRole] = "deviceFirmware"; 152 | // return roles; 153 | return m_roleNames; 154 | } 155 | //============================================================================= 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /qmlitemmodel.h: -------------------------------------------------------------------------------- 1 | #ifndef QMLITEMMODEL_H 2 | #define QMLITEMMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class CustomDevice 9 | { 10 | public: 11 | CustomDevice(const int &firstRole, const int &maxCount, const QList &list); 12 | 13 | QVariant roleData(int role) const; 14 | 15 | QHash rolesData() const; 16 | 17 | private: 18 | QHash hashIntVar; 19 | int firtsRole; 20 | }; 21 | 22 | class QmlItemModel : public QAbstractListModel 23 | { 24 | Q_OBJECT 25 | public: 26 | 27 | 28 | QmlItemModel(QStringList listRoleName, int firstRole = Qt::UserRole + 1, QObject *parent = 0); 29 | 30 | void addCustomDevice(const QList &list); 31 | 32 | void prependCustomDevice(const QList &list); 33 | 34 | 35 | int rowCount(const QModelIndex &parent = QModelIndex()) const; 36 | 37 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 38 | 39 | QVariant dataRow(const int &row, int role = Qt::DisplayRole) const; 40 | 41 | void removeThisRow(const int &row); 42 | 43 | void clearAllData(); 44 | 45 | void replaceData(const int &row, const int &role , const QVariant &dataVar); 46 | 47 | QList dataRowInList(const int &row); 48 | 49 | 50 | protected: 51 | QHash roleNames() const; 52 | 53 | private: 54 | QList m_device; 55 | QHash m_roleNames; 56 | int firstRole; 57 | int maxCount; 58 | 59 | }; 60 | 61 | #endif // QMLITEMMODEL_H 62 | -------------------------------------------------------------------------------- /res.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | katynko/clear_left.png 4 | katynko/dashed_elmnt_red.png 5 | katynko/dashed_elmnt.png 6 | katynko/settings.png 7 | katynko/key_enter.png 8 | katynko/fontsizedefault_koffice.png 9 | katynko/fontsizedown_koffice.png 10 | katynko/fontsizeup_koffice.png 11 | katynko/history.png 12 | 13 | 14 | -------------------------------------------------------------------------------- /screenshot/.directory: -------------------------------------------------------------------------------- 1 | [Dolphin] 2 | PreviewsShown=true 3 | Timestamp=2016,2,29,17,38,5 4 | Version=3 5 | ViewMode=1 6 | -------------------------------------------------------------------------------- /screenshot/Screenshot_2016-02-29-17-12-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/Screenshot_2016-02-29-17-12-55.png -------------------------------------------------------------------------------- /screenshot/Screenshot_2016-02-29-17-13-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/Screenshot_2016-02-29-17-13-02.png -------------------------------------------------------------------------------- /screenshot/Screenshot_2016-02-29-17-15-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/Screenshot_2016-02-29-17-15-32.png -------------------------------------------------------------------------------- /screenshot/Screenshot_2016-02-29-17-33-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/Screenshot_2016-02-29-17-33-36.png -------------------------------------------------------------------------------- /screenshot/android settings1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/android settings1.png -------------------------------------------------------------------------------- /screenshot/qt settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloZB/QtAndroidFTDI/d3ee9c7e51aafa4962a5bb6f3148faa352b4aa5b/screenshot/qt settings.png -------------------------------------------------------------------------------- /untitled.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += qml quick widgets androidextras 4 | 5 | TARGET = Terminalko 6 | 7 | SOURCES += main.cpp \ 8 | ftdimanager.cpp \ 9 | qmlitemmodel.cpp \ 10 | customproxy4qmlmodel.cpp 11 | 12 | RESOURCES += qml.qrc \ 13 | res.qrc 14 | 15 | # Additional import path used to resolve QML modules in Qt Creator's code model 16 | QML_IMPORT_PATH = 17 | 18 | # Default rules for deployment. 19 | include(deployment.pri) 20 | 21 | 22 | HEADERS += \ 23 | ftdimanager.h \ 24 | qmlitemmodel.h \ 25 | customproxy4qmlmodel.h 26 | 27 | DISTFILES += \ 28 | android/AndroidManifest.xml \ 29 | android/gradle/wrapper/gradle-wrapper.jar \ 30 | android/gradlew \ 31 | android/res/values/libs.xml \ 32 | android/build.gradle \ 33 | android/gradle/wrapper/gradle-wrapper.properties \ 34 | android/gradlew.bat\ 35 | android/src/* 36 | 37 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 38 | -------------------------------------------------------------------------------- /untitled.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {2cc0458a-0814-4662-a33c-093d765b2485} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | 0 45 | 8 46 | true 47 | 1 48 | true 49 | true 50 | true 51 | false 52 | 53 | 54 | 55 | ProjectExplorer.Project.PluginSettings 56 | 57 | 58 | 59 | ProjectExplorer.Project.Target.0 60 | 61 | Android for armeabi-v7a (GCC 4.9, Qt 5.5.0) 62 | Android for armeabi-v7a (GCC 4.9, Qt 5.5.0) 63 | {a5e2cca9-5124-4751-b990-0a15b1378ec7} 64 | 1 65 | 0 66 | 0 67 | 68 | /home/hello_zb/My_Prog/Qt5_progs/TESTS/SerialPort/AndroidFTDI/build-untitled-Android_for_armeabi_v7a_GCC_4_9_Qt_5_5_0-Debug 69 | 70 | 71 | true 72 | qmake 73 | 74 | QtProjectManager.QMakeBuildStep 75 | true 76 | 77 | false 78 | false 79 | false 80 | 81 | 82 | true 83 | Make 84 | 85 | Qt4ProjectManager.MakeStep 86 | 87 | -w 88 | -r 89 | 90 | false 91 | 92 | 93 | 94 | 95 | true 96 | Copy application data 97 | 98 | Qt4ProjectManager.AndroidPackageInstallationStep 99 | 100 | 101 | android-22 102 | 103 | true 104 | Build Android APK 105 | 106 | QmakeProjectManager.AndroidBuildApkStep 107 | 2 108 | false 109 | false 110 | 111 | 4 112 | Build 113 | 114 | ProjectExplorer.BuildSteps.Build 115 | 116 | 117 | 118 | true 119 | Make 120 | 121 | Qt4ProjectManager.MakeStep 122 | 123 | -w 124 | -r 125 | 126 | true 127 | clean 128 | 129 | 130 | 1 131 | Clean 132 | 133 | ProjectExplorer.BuildSteps.Clean 134 | 135 | 2 136 | false 137 | 138 | Debug 139 | 140 | Qt4ProjectManager.Qt4BuildConfiguration 141 | 2 142 | true 143 | 144 | 145 | /home/hello_zb/My_Prog/Qt5_progs/TESTS/SerialPort/AndroidFTDI/build-untitled-Android_for_armeabi_v7a_GCC_4_9_Qt_5_5_0-Release 146 | 147 | 148 | true 149 | qmake 150 | 151 | QtProjectManager.QMakeBuildStep 152 | false 153 | 154 | false 155 | false 156 | false 157 | 158 | 159 | true 160 | Make 161 | 162 | Qt4ProjectManager.MakeStep 163 | 164 | -w 165 | -r 166 | 167 | false 168 | 169 | 170 | 171 | 172 | true 173 | Copy application data 174 | 175 | Qt4ProjectManager.AndroidPackageInstallationStep 176 | 177 | 178 | android-22 179 | /home/hello_zb/Dropbox/AndroidIntekKlu4yk.keystore 180 | true 181 | Build Android APK 182 | 183 | QmakeProjectManager.AndroidBuildApkStep 184 | 2 185 | false 186 | false 187 | 188 | 4 189 | Build 190 | 191 | ProjectExplorer.BuildSteps.Build 192 | 193 | 194 | 195 | true 196 | Make 197 | 198 | Qt4ProjectManager.MakeStep 199 | 200 | -w 201 | -r 202 | 203 | true 204 | clean 205 | 206 | 207 | 1 208 | Clean 209 | 210 | ProjectExplorer.BuildSteps.Clean 211 | 212 | 2 213 | false 214 | 215 | Release 216 | 217 | Qt4ProjectManager.Qt4BuildConfiguration 218 | 0 219 | true 220 | 221 | 2 222 | 223 | 224 | 225 | true 226 | Deploy to Android device 227 | 228 | Qt4ProjectManager.AndroidDeployQtStep 229 | false 230 | 231 | 1 232 | Deploy 233 | 234 | ProjectExplorer.BuildSteps.Deploy 235 | 236 | 1 237 | Deploy to Android device 238 | Deploy to Android device 239 | Qt4ProjectManager.AndroidDeployConfiguration2 240 | 241 | 1 242 | 243 | ZX1D322LVT 244 | 245 | 246 | false 247 | 1000 248 | 249 | true 250 | 251 | false 252 | false 253 | false 254 | false 255 | true 256 | 0.01 257 | 10 258 | true 259 | 1 260 | 25 261 | 262 | 1 263 | true 264 | false 265 | true 266 | valgrind 267 | 268 | 0 269 | 1 270 | 2 271 | 3 272 | 4 273 | 5 274 | 6 275 | 7 276 | 8 277 | 9 278 | 10 279 | 11 280 | 12 281 | 13 282 | 14 283 | 284 | untitled 285 | 286 | Qt4ProjectManager.AndroidRunConfiguration:/home/hello_zb/My_Prog/Qt5_progs/TESTS/SerialPort/AndroidFTDI/untitled/untitled.pro 287 | untitled.pro 288 | 3768 289 | false 290 | true 291 | false 292 | false 293 | true 294 | 295 | 1 296 | 297 | 298 | 299 | ProjectExplorer.Project.TargetCount 300 | 1 301 | 302 | 303 | ProjectExplorer.Project.Updater.FileVersion 304 | 18 305 | 306 | 307 | Version 308 | 18 309 | 310 | 311 | --------------------------------------------------------------------------------