diff --git a/apps/modes_gui b/apps/modes_gui index ac86e37..bbf9af6 100755 --- a/apps/modes_gui +++ b/apps/modes_gui @@ -60,20 +60,28 @@ class mainwindow(QtGui.QMainWindow): self.db = QtSql.QSqlDatabase.addDatabase("QSQLITE") self.db.setDatabaseName(self.dbname) self.db.open() - #self.db = sqlite3.connect(self.dbname) - self.datamodel = modes_datamodel(self.db) + self.datamodel = QtSql.QSqlQueryModel() + self.datamodel.setQuery("select * from aircraft order by icao") + self.ui.list_aircraft.setModel(self.datamodel) self.ui.list_aircraft.setModelColumn(0) + self.icaodelegate = ICAOViewDelegate() self.ui.list_aircraft.setItemDelegate(self.icaodelegate) self.dashboard_mapper = QtGui.QDataWidgetMapper() self.dashboard_mapper.setModel(self.datamodel) - self.dashboard_mapper.addMapping(self.ui.line_ident, 2) - self.dashboard_mapper.addMapping(self.ui.line_alt, 3) - self.dashboard_mapper.addMapping(self.ui.line_latitude, 4) - self.dashboard_mapper.addMapping(self.ui.line_longitude, 5) - self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.dashboard_mapper.setCurrentModelIndex) + self.dashboard_mapper.addMapping(self.ui.prog_rssi, 2) + self.dashboard_mapper.addMapping(self.ui.line_latitude, 3) + self.dashboard_mapper.addMapping(self.ui.line_longitude, 4) + self.dashboard_mapper.addMapping(self.ui.line_alt, 5) + self.dashboard_mapper.addMapping(self.ui.line_speed, 6) + #self.dashboard_mapper.addMapping(self.ui.line_heading, 7) + self.dashboard_mapper.addMapping(self.ui.line_climb, 8) + self.dashboard_mapper.addMapping(self.ui.line_ident, 9) + self.dashboard_mapper.addMapping(self.ui.line_type, 10) + #hook up the update signal + self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.dashboard_mapper.setCurrentModelIndex) #goes and gets valid antenna, sample rate options from the device and grays out appropriate things def populate_source_options(self): @@ -212,9 +220,9 @@ class mainwindow(QtGui.QMainWindow): #all this does is fade the ICAOs out as their last report gets older class ICAOViewDelegate(QtGui.QStyledItemDelegate): def paint(self, painter, option, index): - paintstr = "%s" % index.model().data(index.model().index(index.row(), 0)) - last_report = index.model().data(index.model().index(index.row(), 1)) - age = (datetime.datetime.now() - datetime.datetime.strptime(str(last_report), "%Y-%m-%d %H:%M:%S")).total_seconds() + paintstr = "%x" % index.model().data(index.model().index(index.row(), 0)).toInt()[0] + last_report = str(index.model().data(index.model().index(index.row(), 1)).toString()) + age = (datetime.datetime.now() - datetime.datetime.strptime(last_report, "%Y-%m-%d %H:%M:%S")).total_seconds() #minimum alpha is 0x40 (oldest), max is 0xFF (newest) alpha = 0xFF - (0xBF / 600.) * min(age, 600) painter.setPen(QtGui.QColor(0, 0, 0, alpha)) @@ -222,76 +230,6 @@ class ICAOViewDelegate(QtGui.QStyledItemDelegate): painter.drawText(option.rect.left()+3, option.rect.top(), option.rect.width(), option.rect.height(), option.displayAlignment, paintstr) #TODO: draw highlight for selection -#so, not to be a dick or anything, but this thing could be entirely -#replaced with a clever SQL join or just a separate SQL table flattened -#in modes_sql and designed specifically for this. you can keep the older -#ones, too. this would let you access indices by column name, too. bonus. -#you wouldn't get the nice hierarchical tree view, though. what does that lose you? -class modes_datamodel(QtCore.QAbstractItemModel): - def __init__(self, db): - QtCore.QAbstractItemModel.__init__(self) - self.db = db - - def rowCount(self, parent=QtCore.QModelIndex()): - icaoquery = "select count(distinct icao) from positions" - query = QtSql.QSqlQuery() - query.exec_(icaoquery) - query.next() - return query.value(0).toInt()[0] - - def columnCount(self, parent=QtCore.QModelIndex()): - return 2 - - #for future use - def flags(self, index): - return QtCore.QAbstractItemModel.flags(self, index) - - def data(self, index, role=QtCore.Qt.DisplayRole): - if not index.isValid(): - return QtCore.QVariant() - if index.row() >= self.rowCount(): - return QtCore.QVariant() - if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: - #get ICAO of current index - query = QtSql.QSqlQuery() - #TODO: limit this to aircraft seen in last 600 seconds? or make a spinbox for this limit. - icaoquery = "select distinct icao from positions order by icao limit %i,1" % index.row() - query.exec_(icaoquery) - query.next() - icao = query.value(0).toInt()[0] - #TODO figure out how to grab multiple records in one query and return them all? - if index.column() == 0: #ICAO - return "%06x" % icao - elif index.column() == 1: #last seen - seenquery = "select seen from positions where icao = %i order by seen desc limit 1" % icao - query.exec_(seenquery) - return "" if query.next() is False else query.value(0).toString() - elif index.column() == 2: #ident - identquery = "select ident from ident where icao = %i" % icao - query.exec_(identquery) - return "" if query.next() is False else query.value(0).toString() - elif index.column() == 3: #altitude - querystr = "select alt from positions where icao = %i order by seen desc limit 1" % icao - query.exec_(querystr) - return "" if query.next() is False else "%i" % query.value(0).toInt()[0] - elif index.column() == 4: #latitude - querystr = "select lat from positions where icao = %i order by seen desc limit 1" % icao - query.exec_(querystr) - return "" if query.next() is False else "%.6f" % query.value(0).toFloat()[0] - elif index.column() == 5: #longitude - querystr = "select lon from positions where icao = %i order by seen desc limit 1" % icao - query.exec_(querystr) - return "" if query.next() is False else "%.6f" % query.value(0).toFloat()[0] - - else: - return QtCore.QVariant() - - def index(self, row, column, parent=QtCore.QModelIndex()): - return self.createIndex(row, column) - - def parent(self, child): - return QtCore.QModelIndex() - class output_handler(threading.Thread): def __init__(self, outputs, updates, queue): threading.Thread.__init__(self) diff --git a/python/modes_datamodel.py b/python/modes_datamodel.py new file mode 100644 index 0000000..acfb4e7 --- /dev/null +++ b/python/modes_datamodel.py @@ -0,0 +1,71 @@ + +#so, not to be a dick or anything, but this thing could be entirely +#replaced with a clever SQL join or just a separate SQL table flattened +#in modes_sql and designed specifically for this. you can keep the older +#ones, too. this would let you access indices by column name, too. bonus. +#you wouldn't get the nice hierarchical tree view, though. what does that lose you? +#you'd need a different datamodel for the tree view, that's all. +class modes_datamodel(QtCore.QAbstractItemModel): + def __init__(self, db): + QtCore.QAbstractItemModel.__init__(self) + self.db = db + + def rowCount(self, parent=QtCore.QModelIndex()): + icaoquery = "select count(distinct icao) from positions" + query = QtSql.QSqlQuery() + query.exec_(icaoquery) + query.next() + return query.value(0).toInt()[0] + + def columnCount(self, parent=QtCore.QModelIndex()): + return 5 + + #for future use + def flags(self, index): + return QtCore.QAbstractItemModel.flags(self, index) + + def data(self, index, role=QtCore.Qt.DisplayRole): + if not index.isValid(): + return QtCore.QVariant() + if index.row() >= self.rowCount(): + return QtCore.QVariant() + if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: + #get ICAO of current index + query = QtSql.QSqlQuery() + #TODO: limit this to aircraft seen in last 600 seconds? or make a spinbox for this limit. + icaoquery = "select distinct icao from positions order by icao limit %i,1" % index.row() + query.exec_(icaoquery) + query.next() + icao = query.value(0).toInt()[0] + #TODO figure out how to grab multiple records in one query and return them all? + if index.column() == 0: #ICAO + return "%06x" % icao + elif index.column() == 1: #last seen + seenquery = "select seen from positions where icao = %i order by seen desc limit 1" % icao + query.exec_(seenquery) + return "" if query.next() is False else query.value(0).toString() + elif index.column() == 2: #ident + identquery = "select ident from ident where icao = %i" % icao + query.exec_(identquery) + return "" if query.next() is False else query.value(0).toString() + elif index.column() == 3: #altitude + querystr = "select alt from positions where icao = %i order by seen desc limit 1" % icao + query.exec_(querystr) + return "" if query.next() is False else "%i" % query.value(0).toInt()[0] + elif index.column() == 4: #latitude + querystr = "select lat from positions where icao = %i order by seen desc limit 1" % icao + query.exec_(querystr) + return "" if query.next() is False else "%.6f" % query.value(0).toFloat()[0] + elif index.column() == 5: #longitude + querystr = "select lon from positions where icao = %i order by seen desc limit 1" % icao + query.exec_(querystr) + return "" if query.next() is False else "%.6f" % query.value(0).toFloat()[0] + + else: + return QtCore.QVariant() + + def index(self, row, column, parent=QtCore.QModelIndex()): + return self.createIndex(row, column) + + def parent(self, child): + return QtCore.QModelIndex()