def sendCpdlcMsg(self, callsign, msg): link = env.cpdlc.currentDataLink(callsign) if link == None: return if msg.type() == CpdlcMessage.ACK and link.msgCount() > 0: last_msg = link.lastMsg() if not last_msg.isFromMe() and last_msg.type() == CpdlcMessage.INSTR \ and yesNo_question(self.gui, 'ACK after received INSTR', last_msg.contents(), 'Execute instruction?'): try: instr = Instruction.fromEncodedStr(last_msg.contents()) self.instructAircraftByCallsign(callsign, instr) except ValueError: # raised by Instruction.fromEncodedStr if not yesNo_question(self.gui, 'CPDLC comm error', \ 'Unable to decode instruction.', 'Send ACK and perform manually?'): return # cancel sending any message except Instruction.Error as err: # raised by TeacherSessionManager.instructAircraftByCallsign if not yesNo_question(self.gui, 'CPDLC instruction error', \ 'Unable to perform instruction: %s' % err, 'Send ACK anyway?'): return # cancel sending any message else: # no problem executing instruction selection.writeStripAssignment(instr) if self.studentConnected() and link != None: link.appendMessage(msg) self.student.sendMessage( TeachingMsg( TeachingMsg.CPDLC, data=('%s\n%s%s' % (callsign, CPDLC_message_cmd_prefix, msg.text()))))
def changeFplOnlineStatus(self, new_status): t = now() if new_status == FPL.OPEN: text = 'Do you want also to update departure time with the current date & time below?\n%s, %s' % ( datestr(t), timestr(t)) text += '\n\nWARNING: Answering "yes" or "no" will open the flight plan online.' button = QMessageBox.question( self, 'Open FPL', text, buttons=(QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes)) if button == QMessageBox.Yes: self.depTime_edit.setDateTime( QDateTime(t.year, t.month, t.day, t.hour, t.minute)) ok = button != QMessageBox.Cancel elif new_status == FPL.CLOSED: ok = yesNo_question(self, 'Close FPL', 'Time is %s.' % timestr(t), 'This will close the flight plan online. OK?') if ok: try: settings.session_manager.changeFplStatus(self.fpl, new_status) except FplError as err: QMessageBox.critical(self, 'FPL open/close error', str(err)) self.updateOnlineStatusBox()
def savePreset(self): icao_pair = self.data_DEP.code, self.data_ARR.code route_txt = ' '.join(self.getRouteText().split()) got_routes = settings.route_presets.get(icao_pair, []) if route_txt == '' or route_txt in got_routes: QMessageBox.critical(self, 'Route preset rejected', 'This route entry is already saved!') return msg = 'Saving a route preset between %s and %s.' % icao_pair if got_routes != []: msg += '\n(%d route%s already saved for these end airports)' % ( len(got_routes), ('s' if len(got_routes) != 1 else '')) if yesNo_question(self, 'Saving route preset', msg, 'Confirm?'): try: settings.route_presets[icao_pair].append(route_txt) except KeyError: settings.route_presets[icao_pair] = [route_txt] self.recall_button.setEnabled(True) try: with open(route_presets_file, mode='a', encoding='utf8') as f: f.write('\n# Saved on %s at %s UTC:\n' % (datestr(), timestr())) f.write( '%s %s\t%s\n\n' % (self.data_DEP.code, self.data_ARR.code, route_txt)) QMessageBox.information( self, 'Route preset saved', 'Check file %s to remove or edit.' % route_presets_file) except OSError: QMessageBox.critical( self, 'Error', 'There was an error writing to "%s".\nYour preset will be lost at the end of the session.' )
def dropMimeData(self, mime, drop_action, row, column, parent): if drop_action == Qt.MoveAction and mime.hasFormat(strip_mime_type): strip = env.strips.fromMimeDez(mime) atc_callsign = self.ATCs[parent.row()].callsign if not settings.confirm_handovers or settings.session_manager.session_type == SessionType.TEACHER or \ yesNo_question(self.gui, 'Confirm handover', 'You are about to send your strip to %s.' % atc_callsign, 'Confirm?'): if settings.strip_autofill_before_handovers: strip.fillFromXPDR(ovr=False) strip.fillFromFPL(ovr=False) try: settings.session_manager.stripDroppedOnATC( strip, atc_callsign) except HandoverBlocked as err: if not err.silent: QMessageBox.critical(self.gui, 'Handover aborted', str(err)) else: selection.deselect() strip.writeDetail(sent_to_detail, atc_callsign) if settings.session_manager.session_type != SessionType.TEACHER: strip.linkAircraft(None) strip.linkFPL(None) env.strips.removeStrip(strip) env.discarded_strips.addStrip(strip) return True return False
def send_instruction(callsign, instr, consider_cpdlc): ''' Teacher sessions: direct control of selected aircraft with given instr (callsign match bypass). Other sessions: - perform manager-dependant instruction to callsign - give a cpdlcSuggGui to suggest sending through data link instead, if callsign is connected CAUTION: Instruction.encodeToStr raises NotImplementedError with non-encoded instruction types. ''' if settings.session_manager.session_type == SessionType.TEACHER: if selection.acft == None: QMessageBox.critical(settings.session_manager.gui, 'Traffic command error', 'No aircraft selected.') elif settings.teacher_ACFT_requesting_CPDLC_vectors == selection.acft.identifier: instr_str = instr.encodeToStr() settings.session_manager.sendCpdlcMsg( selection.acft.identifier, CpdlcMessage(True, CpdlcMessage.REQUEST, contents=instr_str)) QMessageBox.information( settings.session_manager.gui, 'CPDLC request sent', 'Requested through data link: ' + instr_str) else: settings.session_manager.instructAircraftByCallsign( selection.acft.identifier, instr) elif consider_cpdlc and env.cpdlc.isConnected(callsign) and yesNo_question(settings.session_manager.gui, \ 'Send CPDLC instruction', instr.encodeToStr(), 'Send this instruction through data link to %s?' % callsign): settings.session_manager.sendCpdlcMsg( callsign, CpdlcMessage(True, CpdlcMessage.INSTR, contents=instr.encodeToStr())) else: settings.session_manager.instructAircraftByCallsign(callsign, instr)
def discard_strip(parent_widget, strip, shelve): ''' Returns the discarded strip if operation not aborted. Argument "shelve" is True to shelve; False to delete. ''' if strip == None: return acft = strip.linkedAircraft() fpl = strip.linkedFPL() if shelve: # shelving strip if fpl == None or strip.FPLconflictList() != []: if settings.confirm_lossy_strip_releases and not yesNo_question(parent_widget, 'Lossy shelving', \ 'Strip has conflicts or no linked flight plan.', 'Release contact losing strip details?'): signals.stripEditRequest.emit(strip) return # abort shelving elif not fpl.existsOnline() or fpl.needsUpload(): if settings.confirm_lossy_strip_releases and not yesNo_question(parent_widget, 'Lossy shelving', \ 'Linked FPL is not online or has local changes.', 'Release contact without pushing details online?'): signals.FPLeditRequest.emit(fpl) return # abort shelving if fpl != None and fpl.status( ) == FPL.OPEN: # no aborting here, but offer to close FPL if releasing at destination if env.airport_data != None and fpl[ FPL.ICAO_ARR] == env.airport_data.navpoint.code: if yesNo_question(parent_widget, 'Shelving with open FPL', \ 'Linked FPL is open and arrival filed at location.', 'Would you like to close the flight plan?'): try: settings.session_manager.changeFplStatus( fpl, FPL.CLOSED) except FplError as err: QMessageBox.critical(parent_widget, 'FPL open/close error', str(err)) else: # deleting strip (not shelving) if acft != None or fpl != None: if settings.confirm_linked_strip_deletions and not yesNo_question( parent_widget, 'Delete strip', 'Strip is linked.', 'Delete?'): return # abort deletion strip.linkAircraft(None) strip.linkFPL(None) env.strips.removeStrip(strip) strip.writeDetail(shelved_detail, shelve) env.discarded_strips.addStrip(strip) if strip is selection.strip: selection.deselect() return strip
def matchingFPLsButtonClicked(self): if len(self.FPL_matches) == 1: if yesNo_question(self, 'Single matching FPL', self.FPL_matches[0].shortDescr(), \ 'Do you want to link this flight plan when saving the strip?'): self.linkFPL_tickBox.setChecked(True) self.FPL_link_on_save = self.FPL_matches[0] self.updateFplToLinkInfo() else: msg = '%d flight plans today matching callsign filter:\n' % len( self.FPL_matches) msg += '\n'.join(' %s' % fpl.shortDescr() for fpl in self.FPL_matches) QMessageBox.information(self, 'Matching FPLs', msg)
def drawAdditionalAirport(self): init = '' if self.last_airfield_clicked == None else self.last_airfield_clicked.code dialog = AirportListSearchDialog(self, env.navpoints, initCodeFilter=init) dialog.exec() if dialog.result() > 0 and yesNo_question(self, 'Draw additional airport', \ 'CAUTION: This may freeze the program for a few seconds.', 'OK?'): ad = dialog.selectedAirport() try: ad_data = get_airport_data(ad.code) self.scene.drawAdditionalAirportData(ad_data) signals.indicatePoint.emit(ad_data.navpoint.coordinates) self.last_airfield_clicked = None except NavpointError: print( 'ERROR: No airport "%s" to draw in map range. Please report with details.' % ad)
def closeEvent(self, event): if not self.force_on_close: strips = self.stripsInBay() if len(strips) > 0: if yesNo_question(self, 'Strip bay not empty', \ 'This strip bay is currently holding %d strip(s).' % len(strips), 'Rack strips and close?'): for strip in strips: strip.writeDetail(recycled_detail, True) env.strips.repositionStrip(strip, default_rack_name) else: event.ignore() return self.scene.disconnectAllSignals() signals.backgroundImagesReloaded.disconnect(self.rebuildBgMenu) signals.selectionChanged.disconnect(self.updateButtons) signals.sessionEnded.disconnect(self.scene.deleteAllStripItems) signals.mainWindowClosing.disconnect(self.forceClose) event.accept() self.windowClosing.emit() QWidget.closeEvent(self, event)
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 terminateLink(self): cs = self.data_link_model.acftCallsign() if yesNo_question(self, 'Terminate data link', 'Disconnect current data link with %s.' % cs, 'OK?'): settings.session_manager.disconnectCpdlc(cs)
def changeLocation(self): if yesNo_question(self, 'Change location', 'This will close the current session.', 'Are you sure?'): self.launcher.show() self.close()
def blacklistDest(self): cs = self.dest_combo.currentText() if cs != '' and yesNo_question(self, 'Blacklisting from chat', \ 'This will hide past and future messages from %s.' % cs, 'OK?'): self.chatHistory_filteredModel.blacklistSender(cs) self.clearBlacklist_action.setEnabled(True)
def pull_FPL_details(parent_widget): if yesNo_question(parent_widget, 'Pull FPL details', 'This will overwrite strip details.', 'Are you sure?'): selection.strip.fillFromFPL(ovr=True) signals.stripInfoChanged.emit()