# http://pytricity.com/qt-artificial-horizon-custom-widget/
import math
-from PyQt4 import QtCore, QtGui
+import argparse
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+from PyQt5.QtCore import pyqtSlot
import serialfpv
+import qtosd_ui
try:
_fromUtf8 = QtCore.QString.fromUtf8
return s
try:
- _encoding = QtGui.QApplication.UnicodeUTF8
+ _encoding = QtWidgets.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
- return QtGui.QApplication.translate(context, text, disambig, _encoding)
+ return QtWidgets.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
- return QtGui.QApplication.translate(context, text, disambig)
+ return QtWidgets.QApplication.translate(context, text, disambig)
-class OSDWidget(QtGui.QWidget):
- def __init__(self, roundWidget = False):
+class OSDWidget(QtWidgets.QWidget):
+ def __init__(self, roundWidget = False, filename = None):
super(OSDWidget, self).__init__()
# init parameters
self.roundWidget = roundWidget
+ self.fpv = None
# parameters that will be modified by the user
self.user_pitch = 0
self.user_roll = 0
self.ALT_REFLINES_NUM_LINES)
self.ALT_REFLINES_SIZE_FACTOR = 0.7
+ if filename:
+ self.fpv = serialfpv.SerialFPV()
+ self.fpv.open_file(filename)
+
self.FPS = 50.
self.timer = QtCore.QTimer(self)
- self.connect(self.timer, QtCore.SIGNAL("timeout()"), self.frameTimerCb)
+ self.timer.timeout.connect(self.frameTimerCb)
self.timer.start(1000. / self.FPS)
+ @pyqtSlot(name = "paintEvent")
def paintEvent(self, evt):
"""Paint callback, this is the entry point for all drawings."""
painter = QtGui.QPainter()
self.draw(painter)
painter.end()
+ @pyqtSlot(name = "frameTimerCb")
def frameTimerCb(self):
- """called periodically, every frame, it calls the user_frame_cb function,
- updates the filter and updates the widget"""
- if self.user_frame_cb != None:
- self.user_frame_cb()
+ # read from SerialFPV object
+ if self.fpv:
+ self.fpv.update_state()
+ self.user_speed = self.user_speed + 1
+ self.setRoll(self.fpv.roll)
+ self.setPitch(self.fpv.pitch)
+ self.setYaw(self.fpv.yaw)
# avoid filter bugs when changing between 180 and -180
self.pitch += round((self.user_pitch - self.pitch) / 360.) * 360
sz = metrics.size(QtCore.Qt.TextSingleLine, disp_val)
lefttxt = QtCore.QRect(QtCore.QPoint(0, 0), sz)
lefttxt.moveCenter(pt1 - QtCore.QPoint(0.2 * r, 0))
+ # XXX
#pen.setWidth(1);
#brush = QtGui.QBrush(QtCore.Qt.white)
#painter.setBrush(brush)
"""set the left text"""
self.right_txt = txt
- def setFrameCb(self, user_frame_cb):
- """set a function that is called every frame, before updating the widget"""
- self.user_frame_cb = user_frame_cb
+class Ui_MainWindow(QtWidgets.QMainWindow):
+ def __init__(self, parent = None, roundWidget = False, filename = None):
+ super(Ui_MainWindow, self).__init__(parent)
+ self.ui = qtosd_ui.Ui_MainWindow()
+ self.ui.setupUi(self)
-class Ui_MainWindow(object):
- def __init__(self, filename = None, roundWidget = False):
self.roundWidget = roundWidget
self.filename = filename
- def update_fpv_info(self):
- self.fpv.update()
- self.osd.user_speed = self.osd.user_speed + 1
- self.osd.setRoll(self.fpv.roll)
- self.osd.setPitch(self.fpv.pitch)
- self.osd.setYaw(self.fpv.yaw)
-
- def setupUi(self, MainWindow):
- MainWindow.setObjectName(_fromUtf8("MainWindow"))
- MainWindow.resize(400, 300)
- self.centralWidget = QtGui.QWidget(MainWindow)
- self.centralWidget.setObjectName(_fromUtf8("centralWidget"))
- self.gridLayout = QtGui.QGridLayout(self.centralWidget)
- self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
-
- self.pitchSlider = QtGui.QSlider(self.centralWidget)
- self.pitchSlider.setMinimum(-180)
- self.pitchSlider.setMaximum(180)
- self.pitchSlider.setOrientation(QtCore.Qt.Vertical)
- self.pitchSlider.setObjectName(_fromUtf8("pitchSlider"))
- self.pitchSlider.valueChanged[int].connect(self.changePitch)
- self.gridLayout.addWidget(self.pitchSlider, 0, 0)
-
- self.osd = OSDWidget(self.roundWidget)
- if self.filename:
- self.fpv = serialfpv.SerialFPV()
- self.fpv.open_file(self.filename)
- self.osd.setFrameCb(self.update_fpv_info)
- self.gridLayout.addWidget(self.osd, 0, 1)
-
- self.rollSlider = QtGui.QSlider(self.centralWidget)
- self.rollSlider.setMinimum(-180)
- self.rollSlider.setMaximum(180)
- self.rollSlider.setOrientation(QtCore.Qt.Horizontal)
- self.rollSlider.setObjectName(_fromUtf8("rollSlider"))
- self.rollSlider.valueChanged[int].connect(self.changeRoll)
- self.gridLayout.addWidget(self.rollSlider, 1, 1)
-
- self.yawSlider = QtGui.QSlider(self.centralWidget)
- self.yawSlider.setMaximum(360)
- self.yawSlider.setProperty("value", 180)
- self.osd.setYaw(180)
- self.yawSlider.setOrientation(QtCore.Qt.Horizontal)
- self.yawSlider.setObjectName(_fromUtf8("yawSlider"))
- self.yawSlider.valueChanged[int].connect(self.changeYaw)
- self.gridLayout.addWidget(self.yawSlider, 2, 1)
-
- MainWindow.setCentralWidget(self.centralWidget)
- self.menuBar = QtGui.QMenuBar(MainWindow)
- self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 23))
- self.menuBar.setObjectName(_fromUtf8("menuBar"))
- MainWindow.setMenuBar(self.menuBar)
- self.mainToolBar = QtGui.QToolBar(MainWindow)
- self.mainToolBar.setObjectName(_fromUtf8("mainToolBar"))
- MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
- self.statusBar = QtGui.QStatusBar(MainWindow)
- self.statusBar.setObjectName(_fromUtf8("statusBar"))
- MainWindow.setStatusBar(self.statusBar)
-
- self.retranslateUi(MainWindow)
- QtCore.QMetaObject.connectSlotsByName(MainWindow)
+ self.osd = OSDWidget(roundWidget = self.roundWidget,
+ filename = self.filename)
+ self.ui.gridLayout.addWidget(self.osd, 0, 1)
+ self.ui.pitchSlider.valueChanged[int].connect(self.changePitch)
+ self.ui.rollSlider.valueChanged[int].connect(self.changeRoll)
+ self.ui.yawSlider.valueChanged[int].connect(self.changeYaw)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
+ @pyqtSlot(int, name = "changePitch")
def changePitch(self, value):
self.osd.setPitch(value)
- self.osd.update()
+ @pyqtSlot(int, name = "changeRoll")
def changeRoll(self, value):
self.osd.setRoll(value)
- self.osd.update()
+ @pyqtSlot(int, name = "changeYaw")
def changeYaw(self, value):
self.osd.setYaw(value)
- self.osd.update()
if __name__ == "__main__":
import sys
- app = QtGui.QApplication(sys.argv)
- if "round" in sys.argv:
- roundWidget = True
- else:
- roundWidget = False
- MainWindow = QtGui.QMainWindow()
- if len(sys.argv) > 1:
- ui = Ui_MainWindow(sys.argv[1], roundWidget)
- else:
- ui = Ui_MainWindow(roundWidget = roundWidget)
- ui.setupUi(MainWindow)
- MainWindow.show()
+
+ parser = argparse.ArgumentParser(description='OSD written in Qt.')
+ parser.add_argument('--round', '-r', action="store_true",
+ help='display the widget as a round attitude meter')
+ parser.add_argument('--filename', '-f',
+ help='specify the log file')
+ args = parser.parse_args()
+
+ app = QtWidgets.QApplication(sys.argv)
+ ui = Ui_MainWindow(filename = args.filename, roundWidget = args.round)
+ ui.show()
sys.exit(app.exec_())
--- /dev/null
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'qtosd.ui'
+#
+# Created: Tue Jun 2 19:36:00 2015
+# by: PyQt5 UI code generator 5.3.2
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(400, 300)
+ self.centralWidget = QtWidgets.QWidget(MainWindow)
+ self.centralWidget.setObjectName("centralWidget")
+ self.gridLayout = QtWidgets.QGridLayout(self.centralWidget)
+ self.gridLayout.setObjectName("gridLayout")
+ self.pitchSlider = QtWidgets.QSlider(self.centralWidget)
+ self.pitchSlider.setMinimum(-180)
+ self.pitchSlider.setMaximum(180)
+ self.pitchSlider.setOrientation(QtCore.Qt.Vertical)
+ self.pitchSlider.setObjectName("pitchSlider")
+ self.gridLayout.addWidget(self.pitchSlider, 0, 0, 1, 1)
+ self.rollSlider = QtWidgets.QSlider(self.centralWidget)
+ self.rollSlider.setMinimum(-180)
+ self.rollSlider.setMaximum(180)
+ self.rollSlider.setOrientation(QtCore.Qt.Horizontal)
+ self.rollSlider.setObjectName("rollSlider")
+ self.gridLayout.addWidget(self.rollSlider, 1, 1, 1, 1)
+ self.yawSlider = QtWidgets.QSlider(self.centralWidget)
+ self.yawSlider.setMaximum(360)
+ self.yawSlider.setProperty("value", 180)
+ self.yawSlider.setOrientation(QtCore.Qt.Horizontal)
+ self.yawSlider.setObjectName("yawSlider")
+ self.gridLayout.addWidget(self.yawSlider, 2, 1, 1, 1)
+ MainWindow.setCentralWidget(self.centralWidget)
+ self.menuBar = QtWidgets.QMenuBar(MainWindow)
+ self.menuBar.setGeometry(QtCore.QRect(0, 0, 400, 23))
+ self.menuBar.setObjectName("menuBar")
+ MainWindow.setMenuBar(self.menuBar)
+ self.mainToolBar = QtWidgets.QToolBar(MainWindow)
+ self.mainToolBar.setObjectName("mainToolBar")
+ MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
+ self.statusBar = QtWidgets.QStatusBar(MainWindow)
+ self.statusBar.setObjectName("statusBar")
+ MainWindow.setStatusBar(self.statusBar)
+
+ self.retranslateUi(MainWindow)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+
+
+if __name__ == "__main__":
+ import sys
+ app = QtWidgets.QApplication(sys.argv)
+ MainWindow = QtWidgets.QMainWindow()
+ ui = Ui_MainWindow()
+ ui.setupUi(MainWindow)
+ MainWindow.show()
+ sys.exit(app.exec_())
+