From cd10b6cd8f70ff70b8227d34843fc6a6e8db14e3 Mon Sep 17 00:00:00 2001 From: Kuba Sawulski Date: Fri, 18 Oct 2019 16:08:08 +0200 Subject: [PATCH] Point Editor --- car/__init__.py | 3 +- car/guiConnector.py | 69 +++++++++++++++++++++++ car/motion.py | 130 ++++++++++++++++++++++---------------------- gui/about.ui | 121 ----------------------------------------- gui/mainWindow.py | 34 ++++++------ gui/mainWindow.ui | 63 +++++++++++++-------- main.py | 40 ++++++++------ mainWindow.py | 9 +++ 8 files changed, 224 insertions(+), 245 deletions(-) create mode 100644 car/guiConnector.py delete mode 100644 gui/about.ui create mode 100644 mainWindow.py diff --git a/car/__init__.py b/car/__init__.py index 86e47df..6d5d824 100644 --- a/car/__init__.py +++ b/car/__init__.py @@ -1,2 +1,3 @@ from .motion import motion, track -from .util import * \ No newline at end of file +from .util import * +from .guiConnector import * \ No newline at end of file diff --git a/car/guiConnector.py b/car/guiConnector.py new file mode 100644 index 0000000..bacf0f9 --- /dev/null +++ b/car/guiConnector.py @@ -0,0 +1,69 @@ +from PyQt5 import QtCore + + +class tableGuiConnector(QtCore.QAbstractTableModel): + def __init__(self, myTab): + self.__internalTable = myTab + super().__init__() + + def rowCount(self, parent): + return len(self.__internalTable) + + def columnCount(self, parent): + return int(2) + + def data(self, index, role): + if role != QtCore.Qt.DisplayRole: + return QtCore.QVariant() + + return self.__internalTable[index.row()][index.column()] + + def headerData(self, section, orientation, role): + if role != QtCore.Qt.DisplayRole: + return QtCore.QVariant() + + if orientation == QtCore.Qt.Horizontal: + if section == 0: + return "Position" + else: + return "Height" + if orientation == QtCore.Qt.Vertical: + return section + + def flags(self,index): + return QtCore.Qt.ItemIsEnabled|QtCore.Qt.ItemIsSelectable|QtCore.Qt.ItemIsEditable + + def setData(self,index,value,role): + if role!=QtCore.Qt.EditRole: + return False + try: + self.__internalTable[index.row()][index.column()]=float(value) + except: + return False + return True + + def insertRows(self, row, count=1, parent=QtCore.QModelIndex()): + self.beginInsertRows(parent,row,row+count-1) + + for i in range(0,count): + self.__internalTable.insert(row,[0]*2) + + self.endInsertRows() + + return True + + def removeRows(self, row, count=1, parent=QtCore.QModelIndex()): + self.beginRemoveRows(parent,row,row+count-1) + + for i in range(row,row+count): + self.__internalTable.pop(i) + + self.endRemoveRows() + + return True + + + + + + diff --git a/car/motion.py b/car/motion.py index 575dfea..dea35ff 100644 --- a/car/motion.py +++ b/car/motion.py @@ -28,71 +28,71 @@ class track: """ def __init__(self): - self.__verticalProfile = [(0, 9.529), - (50, 9.870), - (100, 10.04), - (150, 10.22), - (155, 10.182), - (200, 9.471), - (250, 8.576), - (255, 8.476), - (280, 7.885), - (300, 7.392), - (315, 7.118), - (345, 6.675), - (350, 6.650), - (375, 6.300), - (400, 6.070), - (415, 5.878), - (450, 5.707), - (455, 5.722), - (500, 5.670), - (540, 5.572), - (550, 5.570), - (590, 5.627), - (600, 5.626), - (625, 5.651), - (650, 5.658), - (655, 5.603), - (680, 5.953), - (700, 6.130), - (750, 6.070), - (785, 6.026), - (800, 5.818), - (813, 5.755), - (836, 5.577), - (850, 5.509), - (870, 5.494), - (900, 5.282), - (930, 5.235), - (950, 5.030), - (975, 4.883), - (1000, 4.786), - (1025, 4.647), - (1050, 4.482), - (1100, 4.276), - (1150, 4.038), - (1165, 3.946), - (1200, 3.697), - (1220, 3.539), - (1250, 3.369), - (1270, 3.761), - (1300, 4.975), - (1335, 6.691), - (1350, 7.451), - (1395, 9.695), - (1400, 9.945), - (1450, 12.069), - (1455, 12.17), - (1500, 11.903), - (1505, 11.739), - (1550, 9.721), - (1553, 9.621), - (1580, 9.515), - (1600, 9.508), - (1630, 9.438), - (1650, 9.466), - (1659, 9.529)] + self.__verticalProfile = [[0, 9.529], + [50, 9.870], + [100, 10.04], + [150, 10.22], + [155, 10.182], + [200, 9.471], + [250, 8.576], + [255, 8.476], + [280, 7.885], + [300, 7.392], + [315, 7.118], + [345, 6.675], + [350, 6.650], + [375, 6.300], + [400, 6.070], + [415, 5.878], + [450, 5.707], + [455, 5.722], + [500, 5.670], + [540, 5.572], + [550, 5.570], + [590, 5.627], + [600, 5.626], + [625, 5.651], + [650, 5.658], + [655, 5.603], + [680, 5.953], + [700, 6.130], + [750, 6.070], + [785, 6.026], + [800, 5.818], + [813, 5.755], + [836, 5.577], + [850, 5.509], + [870, 5.494], + [900, 5.282], + [930, 5.235], + [950, 5.030], + [975, 4.883], + [1000, 4.786], + [1025, 4.647], + [1050, 4.482], + [1100, 4.276], + [1150, 4.038], + [1165, 3.946], + [1200, 3.697], + [1220, 3.539], + [1250, 3.369], + [1270, 3.761], + [1300, 4.975], + [1335, 6.691], + [1350, 7.451], + [1395, 9.695], + [1400, 9.945], + [1450, 12.069], + [1455, 12.17], + [1500, 11.903], + [1505, 11.739], + [1550, 9.721], + [1553, 9.621], + [1580, 9.515], + [1600, 9.508], + [1630, 9.438], + [1650, 9.466], + [1659, 9.529]] self.__trackLength = max(pos[0] for pos in self.__verticalProfile) self.__interpolantFunction = interp1d([pos[0] for pos in self.__verticalProfile], [ pos[1] for pos in self.__verticalProfile], kind='cubic', bounds_error=True, copy=False, assume_sorted=True) diff --git a/gui/about.ui b/gui/about.ui deleted file mode 100644 index bc95dc3..0000000 --- a/gui/about.ui +++ /dev/null @@ -1,121 +0,0 @@ - - - AboutDialog - - - - 0 - 0 - 378 - 210 - - - - About - - - - - - - - 10 - 10 - 271 - 191 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Car Motion Simulator </span><span style=" font-size:10pt; font-weight:600;">carSim</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">© by Kuba Sawulski 2019</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">carSim is licensed under the</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">GNU General Public License v3.0</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works and modifications, which include larger works using a licensed work, under the same license. Copyright and license notices must be preserved. Contributors provide an express grant of patent rights.</span></p></body></html> - - - - - - 290 - 90 - 80 - 80 - - - - - - - :/logos/skap_logo.png - - - true - - - Qt::AlignCenter - - - - - - 290 - 10 - 80 - 66 - - - - - - - :/logos/ia_logo.png - - - true - - - Qt::AlignCenter - - - - - - 290 - 175 - 80 - 25 - - - - OK - - - - - - - - - okButton - clicked() - AboutDialog - close() - - - 329 - 187 - - - 188 - 104 - - - - - diff --git a/gui/mainWindow.py b/gui/mainWindow.py index a777b68..bd9a3a4 100644 --- a/gui/mainWindow.py +++ b/gui/mainWindow.py @@ -78,21 +78,21 @@ def setupUi(self, MainWindow): self.tabWidget.addTab(self.Car, "") self.Track = QtWidgets.QWidget() self.Track.setObjectName("Track") - self.trackVerticalProfileField = QtWidgets.QPlainTextEdit(self.Track) - self.trackVerticalProfileField.setGeometry(QtCore.QRect(10, 30, 261, 281)) - self.trackVerticalProfileField.setObjectName("trackVerticalProfileField") self.trackVerticalProfileLabel = QtWidgets.QLabel(self.Track) - self.trackVerticalProfileLabel.setGeometry(QtCore.QRect(10, 10, 251, 16)) + self.trackVerticalProfileLabel.setGeometry(QtCore.QRect(10, 10, 121, 16)) self.trackVerticalProfileLabel.setObjectName("trackVerticalProfileLabel") - self.trackVerticalProfileTab = QtWidgets.QTableWidget(self.Track) - self.trackVerticalProfileTab.setGeometry(QtCore.QRect(280, 30, 371, 281)) + self.trackVerticalProfileTab = QtWidgets.QTableView(self.Track) + self.trackVerticalProfileTab.setGeometry(QtCore.QRect(10, 30, 231, 281)) + self.trackVerticalProfileTab.setFocusPolicy(QtCore.Qt.WheelFocus) + self.trackVerticalProfileTab.setAlternatingRowColors(True) + self.trackVerticalProfileTab.setSortingEnabled(True) self.trackVerticalProfileTab.setObjectName("trackVerticalProfileTab") - self.trackVerticalProfileTab.setColumnCount(2) - self.trackVerticalProfileTab.setRowCount(0) - item = QtWidgets.QTableWidgetItem() - self.trackVerticalProfileTab.setHorizontalHeaderItem(0, item) - item = QtWidgets.QTableWidgetItem() - self.trackVerticalProfileTab.setHorizontalHeaderItem(1, item) + self.rowInsertButton = QtWidgets.QPushButton(self.Track) + self.rowInsertButton.setGeometry(QtCore.QRect(250, 30, 75, 23)) + self.rowInsertButton.setObjectName("rowInsertButton") + self.rowDeleteButton = QtWidgets.QPushButton(self.Track) + self.rowDeleteButton.setGeometry(QtCore.QRect(250, 60, 75, 23)) + self.rowDeleteButton.setObjectName("rowDeleteButton") self.tabWidget.addTab(self.Track, "") MainWindow.setCentralWidget(self.centralwidget) self.menuBar = QtWidgets.QMenuBar(MainWindow) @@ -123,7 +123,7 @@ def setupUi(self, MainWindow): self.menuBar.addAction(self.menuAbout.menuAction()) self.retranslateUi(MainWindow) - self.tabWidget.setCurrentIndex(0) + self.tabWidget.setCurrentIndex(2) self.actionClose.triggered.connect(MainWindow.close) QtCore.QMetaObject.connectSlotsByName(MainWindow) @@ -138,11 +138,9 @@ def retranslateUi(self, MainWindow): self.engineLabel.setText(_translate("MainWindow", "Engine")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Simulation), _translate("MainWindow", "Simulation")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Car), _translate("MainWindow", "Car")) - self.trackVerticalProfileLabel.setText(_translate("MainWindow", "Track Profile (Python format)+table view")) - item = self.trackVerticalProfileTab.horizontalHeaderItem(0) - item.setText(_translate("MainWindow", "Position [m]")) - item = self.trackVerticalProfileTab.horizontalHeaderItem(1) - item.setText(_translate("MainWindow", "Height [m a.s.l.]")) + self.trackVerticalProfileLabel.setText(_translate("MainWindow", "Track Profile (table view)")) + self.rowInsertButton.setText(_translate("MainWindow", "Add point")) + self.rowDeleteButton.setText(_translate("MainWindow", "Remove point")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Track), _translate("MainWindow", "Track")) self.menuMain.setTitle(_translate("MainWindow", "Main")) self.menuAbout.setTitle(_translate("MainWindow", "About")) diff --git a/gui/mainWindow.ui b/gui/mainWindow.ui index 1589623..ba3c68a 100644 --- a/gui/mainWindow.ui +++ b/gui/mainWindow.ui @@ -33,7 +33,7 @@ 0 - 0 + 2 @@ -149,48 +149,63 @@ Track - + + + + 10 + 10 + 121 + 16 + + + + Track Profile (table view) + + + 10 30 - 261 + 231 281 + + Qt::WheelFocus + + + true + + + true + - + - 10 - 10 - 251 - 16 + 250 + 30 + 75 + 23 - Track Profile (Python format)+table view + Add point - + - 280 - 30 - 371 - 281 + 250 + 60 + 75 + 23 - - - Position [m] - - - - - Height [m a.s.l.] - - + + Remove point + diff --git a/main.py b/main.py index 9712c2c..c997a74 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ from PyQt5 import QtWidgets -from PyQt5.QtCore import pyqtSlot, Qt +from PyQt5.QtCore import pyqtSlot, Qt, QSortFilterProxyModel, QRect, QItemSelectionModel import sys @@ -15,8 +15,27 @@ def __init__(self): self.__car = car.motion() self.populateFields() self.engineField.setText("0") - self.trackVerticalProfileField.setPlainText( - str(self.__car.track.getTrackProfile())) + self.proxyTrackModel = QSortFilterProxyModel() + self.proxyTrackModel.setSourceModel( + car.guiConnector.tableGuiConnector(self.__car.track.getTrackProfile())) + self.trackVerticalProfileTab.setModel(self.proxyTrackModel) + #self.trackVerticalProfileTab.sortByColumn(0,Qt.AscendingOrder) + #self.trackVerticalProfileTab.reset() + + @pyqtSlot() + def on_rowInsertButton_clicked(self): + self.trackVerticalProfileTab.model().insertRow(0) + self.trackVerticalProfileTab.selectRow(0) + self.trackVerticalProfileTab.setFocus() + + @pyqtSlot() + def on_rowDeleteButton_clicked(self): + indexes = self.trackVerticalProfileTab.selectionModel().selectedIndexes() + for i in indexes: + if not i.isValid(): + continue + print(i.row()) + self.trackVerticalProfileTab.model().removeRow(i.row()) @pyqtSlot() def on_makeStepButton_clicked(self): @@ -27,11 +46,12 @@ def on_makeStepButton_clicked(self): QtWidgets.QMessageBox.critical(self, "Error", sys.exc_info()[0]) self.populateFields() + print(self.__car.track.getTrackProfile()) @pyqtSlot() def on_actionAbout_triggered(self): self.AboutDialog = QtWidgets.QDialog() - self.AboutDialog.ui=gui.Ui_AboutDialog() + self.AboutDialog.ui = gui.Ui_AboutDialog() self.AboutDialog.ui.setupUi(self.AboutDialog) self.AboutDialog.setAttribute(Qt.WA_DeleteOnClose) self.AboutDialog.exec_() @@ -42,18 +62,6 @@ def populateFields(self): self.speedField.setText(f"{self.__car.getSimSpeed():.2f}") self.fuelField.setText(f"{self.__car.getSimFuel():.2f}") - def populateTrackProfile(self): - trackProfile=self.__car.track.getTrackProfile() - self.trackVerticalProfileTab.clear() - - nrows=len(trackProfile) - self.trackVerticalProfileTab.setRowCount(nrows) - for point in range(0,nrows): - pass - - - - if __name__ == "__main__": diff --git a/mainWindow.py b/mainWindow.py new file mode 100644 index 0000000..bb6ebf1 --- /dev/null +++ b/mainWindow.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file '.\mainWindow.ui' +# +# Created by: PyQt5 UI code generator 5.13.0 +# +# WARNING! All changes made in this file will be lost! + +