def upload_FPL_updates(fpl): ''' Uploads local updates made to the FPL since last pull, overriding online values. This method assumes the FPL exists online. ''' assert fpl.existsOnline() query = 'editFlightplan&email=%s&password=%s' % ( settings.lenny64_account_email, settings.lenny64_password_md5) query += '&flightplanId=%d' % fpl.online_id query += '&' + urlencode( lenny64_fpl_details(fpl, fpl.modified_details.keys())) lenny64_query(query, expect='flightplan') # server response ignored for d in list(fpl.modified_details): if d != FPL.COMMENTS and d != FPL.WTC: del fpl.modified_details[d] if FPL.COMMENTS in fpl.modified_details: try: push_FPL_custom_var(fpl.online_id, ATCpie_comment_element_tag, some(fpl[FPL.COMMENTS], '')) del fpl.modified_details[FPL.COMMENTS] except Lenny64Error: pass if FPL.WTC in fpl.modified_details: try: push_FPL_custom_var(fpl.online_id, ATCpie_wakeTurb_element_tag, some(fpl[FPL.WTC], '')) del fpl.modified_details[FPL.WTC] except Lenny64Error: pass
def shortDescr_AD(self): dep = self.details[FPL.ICAO_DEP] arr = self.details[FPL.ICAO_ARR] if dep != None and dep == arr: return '%s local' % dep else: return '%s to %s' % (some(dep, '?'), some(arr, '?'))
def _parseRoute(self): try: dep = self.lookup(FPL.ICAO_DEP, fpl=True) arr = self.lookup(FPL.ICAO_ARR, fpl=True) mid = self.lookup(FPL.ROUTE, fpl=True) self.details[parsed_route_detail] = Route(some(dep, ''), some(arr, ''), some(mid, '')) except NavpointError: # One of the end airports is missing or unrecognised self.details[parsed_route_detail] = None
def resetData(self): # FPL.CALLSIGN self.callsign_edit.setText(some(self.get_detail(FPL.CALLSIGN), '')) # FLIGHT_RULES self.flightRules_select.setCurrentText( some(self.get_detail(FPL.FLIGHT_RULES), '')) # FPL.ACFT_TYPE self.aircraftType_edit.setCurrentText( some(self.get_detail(FPL.ACFT_TYPE), '')) # FPL.WTC self.wakeTurbCat_select.setCurrentText( some(self.get_detail(FPL.WTC), '')) # FPL.ICAO_DEP self.depAirportPicker_widget.setEditText( some(self.get_detail(FPL.ICAO_DEP), '')) # FPL.ICAO_ARR self.arrAirportPicker_widget.setEditText( some(self.get_detail(FPL.ICAO_ARR), '')) # ROUTE self.route_edit.setRouteText(some(self.get_detail(FPL.ROUTE), '')) # CRUISE_ALT self.cruiseAlt_edit.setText(some(self.get_detail(FPL.CRUISE_ALT), '')) # TAS tas = self.get_detail(FPL.TAS) self.TAS_enable.setChecked(tas != None) if tas != None: self.TAS_edit.setValue(tas.kt) # COMMENTS self.comments_edit.setPlainText(some(self.get_detail(FPL.COMMENTS), '')) self.callsign_edit.setFocus()
def resetData(self): # FPL.TIME_OF_DEP dep = self.fpl[FPL.TIME_OF_DEP] self.depTime_enable.setChecked(dep != None) if dep == None: dep = now() self.depTime_edit.setDateTime( QDateTime(dep.year, dep.month, dep.day, dep.hour, dep.minute)) # FPL.EET eet = self.fpl[FPL.EET] self.EET_enable.setChecked(eet != None) if eet != None: minutes = int(eet.total_seconds() / 60 + .5) self.EETh_edit.setValue(minutes // 60) self.EETmin_edit.setValue(minutes % 60) # ICAO_ALT self.altAirportPicker_widget.setEditText( some(self.fpl[FPL.ICAO_ALT], '')) # SOULS souls = self.fpl[FPL.SOULS] self.soulsOnBoard_enable.setChecked(souls != None) if souls != None: self.soulsOnBoard_edit.setValue(souls) # ONLINE COMMENTS self.viewOnlineComments_button.setEnabled( self.fpl.onlineComments() != []) SharedDetailSheet.resetData(self)
def data(self, index, role): if role == Qt.DisplayRole: rwy = self.runways[index.row()] col = index.column() width, surface = env.airport_data.physicalRunwayData( rwy.physicalRwyIndex()) if col == 0: # 'RWY return rwy.name elif col == 1: # LOC freq. txt = some(rwy.LOC_freq, 'none') if rwy.ILS_cat != None: txt += ' (%s)' % rwy.ILS_cat return txt elif col == 2: # GS if rwy.hasILS(): return '%.1f%% / %.1f°' % ( rwy.param_FPA, degrees(atan(rwy.param_FPA / 100))) else: return 'none' elif col == 3: # Surface return surface_types.get(surface, 'Unknown') elif col == 4: # Orientation return '%s°' % rwy.orientation().read() elif col == 5: # Length return '%d m' % (rwy.length(dthr=False) / m2NM) elif col == 6: # Width return '%d m' % width elif col == 7: # DTHR return 'none' if rwy.dthr == 0 else '%d m' % rwy.dthr elif col == 8: # THR elev. return 'N/A' if env.elevation_map == None else '%.1f ft' % env.elevation( rwy.threshold())
def pickNewColour(self): colour = QColorDialog.getColor(parent=self, title='Pick radar contact colour', initial=some(self.colour_choice, Qt.white)) if colour.isValid(): self.setChoice(colour)
def __init__(self, parent, external, port): ''' external is a host (possibly localhost) for external FGCom instance, or None for internal (child process) ''' QWidget.__init__(self, parent) self.setupUi(self) client_address = some(external, 'localhost'), port self.settings = FgcomSettings(socket(AF_INET, SOCK_DGRAM), client_address) self.controller = Ticker(self.settings.send, parent=self) self.frequency_combo.addFrequencies([(frq, descr) for frq, descr, t in env.frequencies]) self.frequency_combo.addFrequencies(frequencies_always_proposed) if external == None: # child process self.onOff_button.setToolTip('Internal FGCom instance using local port %d' % port) ad = world_navpoint_db.findClosest(env.radarPos(), types=[Navpoint.AD]).code if env.airport_data == None else settings.location_code self.instance = InternalFgcomInstance(port, ['--airport=%s' % ad], self) self.instance.started.connect(self.processHasStarted) self.instance.finished.connect(self.processHasStopped) self.onOff_button.toggled.connect(self.switchFGCom) else: # creating box for external instance self.instance = None self.onOff_button.setToolTip('External FGCom instance on %s:%d' % client_address) self.onOff_button.setChecked(True) # keep checked (tested for RDF) self.onOff_button.setEnabled(False) self.PTT_button.setEnabled(True) self.controller.start(fgcom_controller_ticker_interval) self.PTT_button.pressed.connect(lambda: self.PTT(True)) self.PTT_button.released.connect(lambda: self.PTT(False)) self.softVolume_tickBox.clicked.connect(self.setVolume) self.frequency_combo.frequencyChanged.connect(self.setFrequency) self.updateRDF() self.RDF_tickBox.toggled.connect(self.updateRDF) self.onOff_button.toggled.connect(self.updateRDF) signals.localSettingsChanged.connect(self.updateRDF)
def data(self, index, role): strip = self.stripAt(index) if strip == None: return None if role == Qt.DisplayRole: return str(strip) elif role == Qt.ToolTipRole: return some(strip.lookup(FPL.COMMENTS), '')
def recallMessage(self, index): msg = self.chatHistory_filteredModel.messageOnRow(index.row()) if msg.isFromMe(): self.dest_combo.setEditText(some(msg.recipient(), '')) self.chatLine_input.setEditText(msg.txtOnly()) else: self.dest_combo.setEditText(msg.sender()) self.chatLine_input.setFocus()
def speedInstruction(self): zero_cursor = self.radar_contact.IAS() if zero_cursor == None: zero_cursor = some(self.radar_contact.groundSpeed(), speedInstruction_defaultZeroCursor) return Speed( bounded(min_speed_instruction, zero_cursor.kt + self.diff_speed_measured, max_speed_instruction)).rounded(step=10)
def flightIsInTimeWindow(self, half_width, ref=None, strict=False): dep = self.details[FPL.TIME_OF_DEP] if dep == None: return False if ref == None: ref = now() lo = ref - half_width hi = ref + half_width eta = some(self.ETA(), dep) if strict: return dep >= lo and eta <= hi else: return dep <= hi and eta >= lo
def post_session(session_datetime, end_time, frq=None, icao=None): params = { 'email': settings.lenny64_account_email, 'password': settings.lenny64_password_md5, 'date': lenny64_date_string(session_datetime.date()), 'beginTime': lenny64_time_string(session_datetime.time()), 'endTime': lenny64_time_string(end_time), 'airportICAO': some(icao, settings.location_code) } if frq != None: params['fgcom'] = str(frq) query = 'newAtcSession&' + urlencode(params) lenny64_query(query, expect='event') # server response ignored
def __init__(self, parent, nav_db, initCodeFilter=None, initNameFilter=None): assert initCodeFilter == None or initNameFilter == None QDialog.__init__(self, parent) self.resize(350, 300) self.setWindowTitle('Airport search') self.setWindowIcon(QIcon(IconFile.panel_airportList)) self.navigator = AirportNavigatorWidget(self, nav_db) self.button_box = QDialogButtonBox( QDialogButtonBox.Cancel | QDialogButtonBox.Ok, self) layout = QVBoxLayout(self) layout.addWidget(self.navigator) layout.addWidget(self.button_box) self.selected_airport = None self.navigator.setAndUpdateFilter( initCodeFilter != None, some(initCodeFilter, some(initNameFilter, ''))) self.navigator.airportDoubleClicked.connect(self.selectAirport) self.button_box.accepted.connect(self.selectAirportFromSelection) self.button_box.rejected.connect(self.reject)
def suggestRoute(self): p1 = p2 = None if len(world_routing_db.exitsFrom(self.data_DEP)) == 0: p1 = input_entry_exit_point(self, True, self.data_DEP) if p1 == None: # cancelled return if len(world_routing_db.entriesTo(self.data_ARR)) == 0: p2 = input_entry_exit_point(self, False, self.data_ARR) # may be None if p2 == None: # cancelled return try: sugg_route_str = world_routing_db.shortestRouteStr( some(p1, self.data_DEP), some(p2, self.data_ARR)) if p1 != None: sugg_route_str = p1.code + ' ' + sugg_route_str if p2 != None: sugg_route_str += ' ' + p2.code if self.getRouteText() == '' or yesNo_question( self, 'Route suggestion', sugg_route_str, 'Accept suggestion above?'): self.setRouteText(sugg_route_str) except ValueError: QMessageBox.critical(self, 'Route suggestion', 'No route found.')
def fillFromSettings(self): ## Tower view (self.towerView_external_radioButton if settings.external_tower_viewer_process else self.towerView_internal_radioButton).setChecked(True) self.towerView_fgmsPort_edit.setValue(settings.tower_viewer_UDP_port) self.towerView_telnetPort_edit.setValue( settings.tower_viewer_telnet_port) self.fgCommand_edit.setText(settings.FGFS_executable) self.fgRootDir_edit.setText(settings.FGFS_root_dir) self.fgAircraftDir_edit.setText(settings.FGFS_aircraft_dir) self.fgSceneryDir_edit.setText(settings.FGFS_scenery_dir) self.externalTowerViewerHost_edit.setText( settings.external_tower_viewer_host) ## FGCom self.fgcomExe_edit.setText(settings.fgcom_executable_path) self.fgcomServer_edit.setText(settings.fgcom_server) self.fgcomReservedPort_edit.setValue(settings.reserved_fgcom_port) self.fgcomRadioBoxPorts_edit.setText(','.join( str(n) for n in settings.radio_fgcom_ports)) ## FlightGear MP self.fgmsServerHost_edit.setText(settings.FGMS_server_name) self.fgmsServerPort_edit.setValue(settings.FGMS_server_port) self.fgmsLegacyProtocol_tickBox.setChecked( settings.FGMS_legacy_protocol) self.nickname_edit.setText(settings.MP_social_name) self.ircServerHost_edit.setText(settings.MP_IRC_server_name) self.ircServerPort_edit.setValue(settings.MP_IRC_server_port) self.ircChannel_edit.setText(settings.MP_IRC_channel) self.orsxServer_edit.setText(settings.ORSX_server_name) self.orsxHandoverRange_edit.setValue( some(settings.ORSX_handover_range, 0)) self.lennyAccountEmail_edit.setText(settings.lenny64_account_email) self.lennyPassword_edit.setText('') # unchanged if stays blank self.FPLupdateInterval_edit.setValue( int(settings.FPL_update_interval.total_seconds()) / 60) self.METARupdateInterval_edit.setValue( int(settings.METAR_update_interval.total_seconds()) / 60) ## Solo and teacher session types self.soloAircraftTypes_edit.setPlainText('\n'.join( settings.solo_aircraft_types)) self.restrictAirlineChoiceToLiveries_tickBox.setChecked( settings.solo_restrict_to_available_liveries) self.preferEntryExitAirports_tickBox.setChecked( settings.solo_prefer_entry_exit_ADs) self.sphinxAcousticModel_edit.setText( settings.sphinx_acoustic_model_dir) self.audioDeviceIndex_edit.setValue(settings.audio_input_device_index)
def strip_auto_print_check(): if settings.session_manager.isRunning(): for fpl in env.FPLs.findAll(): reason_to_print = auto_print_strip_reason(fpl) if reason_to_print != None: strip = Strip() strip.linkFPL(fpl) strip.writeDetail( rack_detail, some(settings.auto_print_collecting_rack, default_rack_name)) strip.writeDetail(auto_printed_detail, True) fpl.strip_auto_printed = True env.strips.addStrip(strip) signals.stripAutoPrinted.emit(strip, reason_to_print) signals.selectionChanged.emit()
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.installEventFilter(RadioKeyEventFilter(self)) self.magneticDeclination_infoLabel.setText( some(env.readDeclination(), 'N/A')) self.radarPosition_infoLabel.setText(str(env.radarPos())) if env.airport_data == None: self.airport_tab.setEnabled(False) else: self.airportName_infoLabel.setText(env.locationName()) self.airportElevation_infoLabel.setText( '%.1f ft' % env.airport_data.field_elevation) table_model = RwyInfoTableModel(self) self.runway_tableView.setModel(table_model) for i in range(table_model.columnCount()): self.runway_tableView.resizeColumnToContents(i)
def resetData(self): ## Rack self.rack_select.setCurrentText( some(self.strip.lookup(rack_detail), unracked_strip_str)) ## Assigned stuff # Squawk code assSQ = self.strip.lookup(assigned_SQ_detail) self.assignSquawkCode.setChecked(assSQ != None) if assSQ != None: self.xpdrCode_select.setSQ(assSQ) # Heading assHdg = self.strip.lookup(assigned_heading_detail) self.assignHeading.setChecked(assHdg != None) if assHdg != None: self.assignedHeading_edit.setValue(int(assHdg.read())) # Altitude/FL assAlt = self.strip.lookup(assigned_altitude_detail) self.assignAltitude.setChecked(assAlt != None) if assAlt != None: self.assignedAltitude_edit.setText(assAlt) # Speed assSpd = self.strip.lookup(assigned_speed_detail) self.assignSpeed.setChecked(assSpd != None) if assSpd != None: self.assignedSpeed_edit.setValue(assSpd.kt) ## Links and conflicts: acft = self.strip.linkedAircraft() if acft == None: self.xpdrConflicts_info.setText('no link') else: clst = self.strip.transponderConflictList() self.xpdrConflicts_info.setText('no conflicts' if clst == [] else 'conflicts ' + ', '.join(clst)) fpl = self.strip.linkedFPL() if fpl == None: self.fplConflicts_info.setText('no link') else: clst = self.strip.FPLconflictList() self.fplConflicts_info.setText('no conflicts' if clst == [] else 'conflicts ' + ', '.join(clst)) ## FPL stuff SharedDetailSheet.resetData(self)
def data(self, index, role): strip, timestamp = self.discarded_strips[index.row()] if role == Qt.DisplayRole: line1 = some(strip.callsign(), '?') toATC = strip.lookup(sent_to_detail) if toATC == None: line2 = 'Shelved ' if strip.lookup( shelved_detail) else 'Deleted ' else: line1 += ' >> ' + toATC line2 = 'Sent ' line2 += rel_datetime_str(timestamp) ## RETURN return '%s\n %s' % (line1, line2) elif role == Qt.DecorationRole: if strip.lookup(sent_to_detail) == None: # was deleted or shelved return self.shelved_icon if strip.lookup( shelved_detail) else self.deleted_icon else: # was handed over return self.handed_over_icon
def __init__(self, spawn_coords, spawn_hdg, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.createCallsign_edit.setClearButtonEnabled(True) self.installEventFilter(RadioKeyEventFilter(self)) self.createAircraftType_edit.setAircraftFilter(lambda t: cruise_speed(t) != None) self.airline_codes = known_airline_codes() self.createAircraftType_edit.setEditText(CreateTrafficDialog.last_known_acft_type_used) self.startFrozen_tickBox.setChecked(CreateTrafficDialog.last_start_frozen) self.createStripLink_tickBox.setChecked(CreateTrafficDialog.last_strip_link) self.suggestCallsign() if env.airport_data == None: self.allow_taxi = False self.closest_PKG = None self.nearby_THRs = [] else: self.allow_taxi = env.airport_data.ground_net.closestNode(spawn_coords, maxdist=max_spawn_GND_dist) != None self.closest_PKG = env.airport_data.ground_net.closestParkingPosition(spawn_coords, maxdist=max_spawn_PKG_dist) self.nearby_THRs = [r.name for r in env.airport_data.allRunways() if r.threshold().distanceTo(spawn_coords) <= max_spawn_THR_dist] self.closestParkingPosition_info.setText(some(self.closest_PKG, '')) self.depRWY_select.addItems(sorted(self.nearby_THRs)) self.spawn_coords = spawn_coords self.spawn_hdg = spawn_hdg self.updateButtons() if self.allow_taxi: self.ground_status_radioButton.toggled.connect(self.toggleGroundStatus) self.ground_status_radioButton.setChecked(True) if self.closest_PKG != None: self.parked_tickBox.setChecked(True) else: self.ground_status_radioButton.setEnabled(False) self.toggleGroundStatus(False) self.depRWY_select.setEnabled(False) if self.nearby_THRs == []: self.ready_status_radioButton.setEnabled(False) elif self.closest_PKG == None: self.ready_status_radioButton.setChecked(True) self.accepted.connect(self.rememberOptions) self.createAircraftType_edit.editTextChanged.connect(self.updateButtons) self.createAircraftType_edit.editTextChanged.connect(self.suggestCallsign) self.createCallsign_edit.textChanged.connect(self.updateButtons)
def transfer_selected_or_instruct(next_atc_callsign): ''' CAUTION: Should not be called as teacher ''' assert settings.session_manager.session_type != SessionType.TEACHER selected_callsign = selection.selectedCallsign() data_auth_transferred = False if settings.CPDLC_authority_transfers and selected_callsign != None and env.cpdlc.isConnected( selected_callsign): try: settings.session_manager.transferCpdlcAuthority( selected_callsign, next_atc_callsign) data_auth_transferred = True except CpdlcAuthorityTransferFailed: pass if data_auth_transferred: QMessageBox.information(settings.session_manager.gui, 'CPDLC transfer', \ 'Data authority transferred to %s' % next_atc_callsign) else: # Hand over through regular instruction, possibly through data link instr = env.ATCs.handoverInstructionTo(next_atc_callsign) send_instruction(some(selected_callsign, ''), instr, settings.CPDLC_suggest_handover_instructions)
def lenny64_fpl_details(fpl, details): dct = {} if FPL.CALLSIGN in details: dct['callsign'] = fpl[FPL.CALLSIGN] if FPL.ICAO_DEP in details: dct['departureAirport'] = fpl[FPL.ICAO_DEP] if FPL.ICAO_ARR in details: dct['arrivalAirport'] = fpl[FPL.ICAO_ARR] if FPL.ICAO_ALT in details: dct['alternateDestination'] = fpl[FPL.ICAO_ALT] if FPL.CRUISE_ALT in details: dct['cruiseAltitude'] = fpl[FPL.CRUISE_ALT] if FPL.TAS in details: dct['trueAirspeed'] = fpl[FPL.TAS].kt if fpl[FPL.TAS] != None else None if FPL.TIME_OF_DEP in details: dct['dateDeparture'] = lenny64_date_string( fpl[FPL.TIME_OF_DEP]) if fpl[FPL.TIME_OF_DEP] != None else None dct['departureTime'] = lenny64_time_string( fpl[FPL.TIME_OF_DEP]) if fpl[FPL.TIME_OF_DEP] != None else None if FPL.EET in details and fpl[ FPL.TIME_OF_DEP] != None: # makes no sense without a TIME_OF_DEP if fpl[FPL.EET] == None: dct['dateArrival'] = None dct['arrivalTime'] = None else: arr = fpl[FPL.TIME_OF_DEP] + fpl[FPL.EET] dct['dateArrival'] = lenny64_date_string(arr) dct['arrivalTime'] = lenny64_time_string(arr) if FPL.ACFT_TYPE in details: dct['aircraft'] = fpl[FPL.ACFT_TYPE] if FPL.SOULS in details: dct['soulsOnBoard'] = fpl[FPL.SOULS] if FPL.ROUTE in details: dct['waypoints'] = fpl[FPL.ROUTE] if FPL.FLIGHT_RULES in details: dct['category'] = fpl[FPL.FLIGHT_RULES] return {d: some(v, '') for d, v in dct.items()}
def make_WW_XML(fgms_id, strip, owner, handover): header = ElementTree.Element('header') data = ElementTree.Element('data') # Header header.append(make_simple_element('callsign', fgms_id)) header.append(make_simple_element('owner', owner)) header.append(make_simple_element('handover', handover)) sq = strip.lookup(assigned_SQ_detail) header.append( make_simple_element('squawk', (None if sq == None else int('%o' % sq, base=10)))) header.append( make_simple_element('assignedAlt', strip.lookup(assigned_altitude_detail))) # Ignored header header.append(make_simple_element('status', 'ACTIVE')) header.append(make_simple_element('fgcom', 'false')) header.append(make_simple_element( 'flight', None)) # WW says: element must not be empty header.append(make_simple_element('assignedRunway', None)) header.append(make_simple_element('assignedRoute', None)) # Data data.append( make_simple_element( 'type', some(strip.lookup(FPL.FLIGHT_RULES, fpl=True), 'VFR'))) data.append( make_simple_element('aircraft', strip.lookup(FPL.ACFT_TYPE, fpl=True))) spd = strip.lookup(FPL.TAS, fpl=True) data.append( make_simple_element('trueAirspeed', (spd.kt if spd != None else None))) data.append( make_simple_element('departure', strip.lookup(FPL.ICAO_DEP, fpl=True))) data.append( make_simple_element('cruisingAlt', strip.lookup(FPL.CRUISE_ALT, fpl=True))) data.append(make_simple_element('route', strip.lookup(FPL.ROUTE, fpl=True))) data.append( make_simple_element('destination', strip.lookup(FPL.ICAO_ARR, fpl=True))) data.append( make_simple_element('remarks', strip.lookup(FPL.COMMENTS, fpl=True))) # Non-strip data for ATC-pie, but possibly given in linked flight plan dep = strip.lookup(FPL.TIME_OF_DEP, fpl=True) data.append( make_simple_element('departureTime', (None if dep == None else '%02d%02d' % (dep.hour, dep.minute)))) eet = strip.lookup(FPL.EET, fpl=True) eet = None if eet == None else int(eet.total_seconds() + .5) // 60 data.append( make_simple_element('estFlightTime', (None if eet == None else '%d:%02d' % (eet // 60, eet % 60)))) data.append( make_simple_element('alternateDest', strip.lookup(FPL.ICAO_ALT, fpl=True))) data.append( make_simple_element('soulsOnBoard', strip.lookup(FPL.SOULS, fpl=True))) # Hidden data (ulterior motive: recognise data generated by ATC-pie) hidden_wake_turb = some(strip.lookup(FPL.WTC, fpl=True), '') hidden_callsign = some(strip.callsign(fpl=True), '') data.append( make_simple_element( 'pilot', '%s%s%s' % (hidden_wake_turb, ATCpie_hidden_string, hidden_callsign))) # Ignored data data.append(make_simple_element('fuelTime', None)) # Wrap up root = ElementTree.Element('flightplan') root.append(header) root.append(data) return root
def updateDestOnNewSelection(self): if settings.session_manager.session_type != SessionType.TEACHER: self.dest_edit.setText(some(selection.selectedCallsign(), ''))
def __str__(self): return '[%s:%s]' % (some(self.lookup(rack_detail), ''), some(self.callsign(), ''))
def data(self, index, role): fpl = self.FPL_list[index.row()] col = index.column() if role == Qt.DisplayRole: if col == 0: if fpl.existsOnline() and fpl.needsUpload(): # not in sync with online version return '!!' elif col == 1: return some(fpl[FPL.CALLSIGN], '?') elif col == 2: return fpl.shortDescr_AD() elif col == 3: return fpl.shortDescr_time() elif role == Qt.DecorationRole: if col == 0: if fpl.existsOnline(): status = fpl.status() if status == FPL.FILED: dep = fpl[FPL.TIME_OF_DEP] if dep != None and now() > dep + FPL_outdated_delay: # outdated colour = settings.colour('FPL_filed_outdated') else: colour = settings.colour('FPL_filed') elif status == FPL.OPEN: eta = fpl.ETA() if eta == None: # warning colour = settings.colour('FPL_open_noETA') elif now() > eta: # overdue colour = settings.colour('FPL_open_overdue') else: colour = settings.colour('FPL_open') elif status == FPL.CLOSED: colour = settings.colour('FPL_closed') return coloured_square_icon(colour) elif role == Qt.ToolTipRole: if col == 0: if fpl.existsOnline(): status = fpl.status() if status == FPL.FILED: dep = fpl[FPL.TIME_OF_DEP] txt = 'Outdated' if dep != None and now() > dep + FPL_outdated_delay else 'Filed' elif status == FPL.OPEN: eta = fpl.ETA() if eta == None: # warning txt = 'Open, ETA unknown' else: txt = 'Open' minutes_overtime = int(round((now() - eta).total_seconds())) // 60 if minutes_overtime >= 1: txt += ', arrival overdue by %d h %02d min' % (minutes_overtime // 60, minutes_overtime % 60) elif status == FPL.CLOSED: txt = 'Closed' else: txt = 'Status N/A' if fpl.needsUpload(): txt += '\n(local changes)' return txt else: return 'Not online'
def paint_strip_box(parent_widget, painter, strip, rect): acft = strip.linkedAircraft() ### LINE 1 scs = strip.callsign(fpl=True) acs = None if acft == None else acft.xpdrCallsign() cs = some(scs, acs) if settings.strip_CPDLC_integration and cs != None and (acs == None or acs == scs): sdl = env.cpdlc.currentDataLink(cs) else: sdl = None ## Decorated callsign section callsign_section = '' # handover from fromATC = strip.lookup(received_from_detail) if fromATC != None: callsign_section += fromATC + ' >> ' # callsign(s) if sdl != None: callsign_section += '⚡ ' if sdl.status( ) == ConnectionStatus.OK else '[⚡] ' callsign_section += '<strong>%s</strong>' % some(cs, '?') if scs != None and acs != None and scs != acs: # callsign conflict with XPDR callsign_section += ' <strong>(%s)</strong>' % acs if strip.lookup(FPL.COMMENTS) != None: callsign_section += '*' # handover to toATC = strip.lookup(sent_to_detail) if toATC != None: callsign_section += ' >> ' + toATC if strip.lookup(duplicate_callsign_detail): # duplicate callsign warning callsign_section += ' !!dup' line1_sections = [callsign_section] ## Wake turb. cat. / aircraft type atyp = None if acft == None else acft.xpdrAcftType() typesec = some(strip.lookup(FPL.ACFT_TYPE, fpl=True), some(atyp, '')) wtc = strip.lookup(FPL.WTC, fpl=True) if wtc != None: typesec += '/%s' % wtc line1_sections.append(typesec) ## Optional sections # transponder code assSQ = strip.lookup(assigned_SQ_detail) if assSQ != None: if acft == None: # no ACFT linked line1_sections.append('sq=%04o' % assSQ) else: sq = acft.xpdrCode() if sq != None and sq != assSQ: line1_sections.append('sq=%04o (%04o)' % (assSQ, sq)) # conflicts conflicts = [] alert_lvl_hi = alert_lvl_lo = False if strip.transponderConflictList() != []: conflicts.append('!!XPDR') alert_lvl_hi = True if sdl != None and sdl.status() != ConnectionStatus.OK: conflicts.append('!!CPDLC') if sdl.status() == ConnectionStatus.PROBLEM: alert_lvl_hi = True else: alert_lvl_lo = True if settings.strip_route_vect_warnings: if len(strip.vectoringConflicts(env.QNH())) != 0: conflicts.append('!!vect') alert_lvl_lo = True elif strip.routeConflict(): conflicts.append('!!route') alert_lvl_lo = True if len(conflicts) > 0: line1_sections.append(' '.join(conflicts)) ### LINE 2 line2_sections = [] if settings.APP_spacing_hints: prev = env.strips.previousInSequence(strip) if prev != None: hint = spacing_hint(strip, prev) if hint != None: line2_sections.append('%s ' % hint) parsed_route = strip.lookup(parsed_route_detail) if parsed_route == None: arr = strip.lookup(FPL.ICAO_ARR, fpl=True) if arr != None: line2_sections.append(arr) elif acft == None: line2_sections.append(str(parsed_route)) else: line2_sections.append(parsed_route.toGoStr(acft.coords())) ## MAKE DOCUMENT html_line1 = ' '.join(line1_sections) html_line2 = ' '.join(line2_sections) doc = QTextDocument(parent_widget) doc.setHtml('<html><body><p>%s<br> %s</p></body></html>' % (html_line1, html_line2)) ## PAINT painter.save() ## Background and borders if acft == None: if strip.lookup(soft_link_detail) == None: bgcol = 'strip_unlinked' else: bgcol = 'strip_unlinked_identified' else: # an aircraft is linked if alert_lvl_hi: bgcol = 'strip_linked_alert' elif alert_lvl_lo: bgcol = 'strip_linked_warning' else: bgcol = 'strip_linked_OK' if strip is selection.strip: painter.setPen(new_pen(Qt.black, width=2)) else: painter.setPen(new_pen(Qt.darkGray)) painter.setBrush(QBrush(settings.colour(bgcol))) painter.drawRect(rect) painter.translate(rect.topLeft()) rules = strip.lookup(FPL.FLIGHT_RULES, fpl=True) if rules != None: # add a border along bottom edge of strip painter.setPen(Qt.NoPen) painter.setBrush( QBrush(Qt.black, style={ 'IFR': Qt.SolidPattern, 'VFR': Qt.BDiagPattern }.get(rules, Qt.NoBrush))) painter.drawRect(0, rect.height() - strip_IFR_border_width, rect.width(), strip_IFR_border_width) ## Text contents doc.drawContents( painter, QRectF(0, 0, rect.width(), rect.height() - strip_IFR_border_width)) painter.restore()
def trueAngle(self): return self.deg_angle if self.is_true else self.deg_angle + some( Heading.declination, 0)
def magneticAngle(self): return self.deg_angle - some(Heading.declination, 0) if self.is_true else self.deg_angle