#!/usr/bin/env python #**************************************************************************** # flymainwin.py, the main window class # # FlyWay, a VFR/IFR Route Planner for Pilots # Copyright (C) 2002, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, Version 2. This program is # distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. #***************************************************************************** try: from __main__ import __version__, __author__, helpFilePath except ImportError: __version__ = __author__ = '??' helpFilePath = None from route import Route, RouteLeg, wpDistance from plandata import PlanData from mapdata import MapData from option import Option from optiondlg import OptionDlg, OptionDlgBool, OptionDlgInt, OptionDlgDbl from routeview import RouteView from wpview import WpView from planview import PlanView from mapview import MapView from weatherview import WeatherView from flydialogs import TimeDlg from printpreview import PrintPrevDlg from helpview import HelpView from recentfiles import RecentFiles from qt import * from xpm import * import sys, os.path class FlyMainWin(QMainWindow): """Main window, menus, toolbar, and status""" option = Option('flyway', 20) route = Route(option) routePopup = None docModified = 0 toolBar = None minPrintMargin = 0.25 maxPrintMargin = 3.0 printFontHt = 14 printGap = 44 defaultList = [\ "# Options for FlyWay, a flight planning program", "#", "# All options can be set from within the program,", "# editing here is not recommended", "#", "Airspeed 100", "12hrClock yes", "LocalClock yes", "#", "PrintPrev yes", "HorizMargin 0.5", "VertMargin 0.7", "PrintRoute yes", "PrintFltPlan yes", "PrintWaypoints yes", "PrintWeather yes", "#", "AddOnEnter yes", "DelKey yes", "PlanShowOnOpen yes", "#", "BackgroundR 255", "BackgroundG 255", "BackgroundB 255", "ForegroundR 0", "ForegroundG 0", "ForegroundB 0", "#", "RecentFile1 ", "RecentFile2 ", "RecentFile3 ", "RecentFile4 ", "#", "PlanType1 ", "PlanType2 X", "PlanType3 ", "PlanCraftID ", "PlanEquip ", "PlanAltitude 3500", "PlanRemark1 ", "PlanRemark2 ", "PlanRemark3 ", "PlanFuelHr 5", "PlanFuelMin 0", "PlanPilot1 ", "PlanPilot2 ", "PlanPilot3 ", "PlanNumAboard 1", "PlanColor W", "#", "WeatherPlain no", "WeatherDistance 20", "WeatherFdFactor 4", "WeatherKeepPass no", "WeatherUser ", "WeatherPassword "] def __init__(self, parent=None, name=None): QMainWindow.__init__(self, parent, name) FlyMainWin.option.loadAll(FlyMainWin.defaultList) FlyMainWin.option.addData('WindSpeed', '0') FlyMainWin.option.addData('WindDir', '360') FlyMainWin.option.addData('DepartHour', '8') FlyMainWin.option.addData('DepartMinute', '0') self.planView = None self.mapView = None self.weatherView = None self.helpView = None self.printer = QPrinter() self.printer.setPageSize(QPrinter.Letter) self.rtPageList = [] self.planPageList = [] self.wpPageList = [] self.wthrPageList = [] self.resize(540, 530) split = QSplitter(QSplitter.Vertical, self) self.setCentralWidget(split) self.rtView = RouteView(split) self.rtView.setFocus() self.wpView = WpView(split) split.setSizes([350, 180]) self.connect(self.rtView, PYSIGNAL('selChange'), self.wpView.setSelWp) self.connect(self.rtView, PYSIGNAL('selChange'), self.setMenuAvail) self.connect(self.rtView, PYSIGNAL('recalcDone'), self.updatePlan) self.connect(self.rtView, PYSIGNAL('statusBarMsg'), self.setStatusMsg) if sys.platform == 'win32': self.setCaption('FlyWay (PyQt)') else: self.setCaption('FlyWay') self.setIcon(QPixmap(fly_xpm)) self.updateColors() self.fileName = '' self.statusBar().message('Hit return to add a waypoint...', 100000) self.setupMenus() self.setMenuAvail() self.fltPlnGrp.setEnabled(0) def setStatusMsg(self, text, time): """Wrapper to set statusBar - fix qt2 bug if called from signal""" self.statusBar().message(text, time) def updatePlan(self): """Update flight plan, map & menus""" if self.planView and self.planView.isVisible(): self.planView.updatePlan() if self.mapView and self.mapView.isVisible(): self.mapView.updateMap() if self.weatherView: self.weatherView.updateCmdAvail() self.setMenuAvail() def setMenuAvail(self): """Update menu availability""" self.fileSaveAct.setEnabled(FlyMainWin.docModified) self.editWpGrp.setEnabled(len(FlyMainWin.route.wpList)) self.editUpAct.setEnabled(self.rtView.numSelect) self.editDownAct.setEnabled(self.rtView.numSelect < \ len(FlyMainWin.route.wpList) - 1) self.editMultWpGrp.setEnabled(len(FlyMainWin.route.wpList) > 1) def updateColors(self): """Adjust the colors to the current option settings""" pal = QApplication.palette() background = QColor(self.option.intData('BackgroundR', 0, 255), \ self.option.intData('BackgroundG', 0, 255), \ self.option.intData('BackgroundB', 0, 255)) foreground = QColor(self.option.intData('ForegroundR', 0, 255), \ self.option.intData('ForegroundG', 0, 255), \ self.option.intData('ForegroundB', 0, 255)) pal.setColor(QColorGroup.Base, background) pal.setColor(QPalette.Active, QColorGroup.Text, foreground) pal.setColor(QPalette.Inactive, QColorGroup.Text, foreground) QApplication.setPalette(pal, 1) pal.setColor(QColorGroup.Text, QColor(0, 0, 0)) self.statusBar().setPalette(pal) def openFile(self, fileName): """Open given file""" if FlyMainWin.route.readFile(fileName): if FlyMainWin.route.wpErrorList: QMessageBox.warning(self, 'FlyWay', \ 'Error - could not find the '\ 'following waypoints:\n%s' % '\n'.\ join(FlyMainWin.route.wpErrorList)) if sys.platform == 'win32': self.setCaption(fileName + ' - FlyWay (PyQt)') else: self.setCaption(fileName + ' - FlyWay') self.fileName = fileName self.recentFiles.addEntry(fileName) FlyMainWin.docModified = 0 self.rtView.numSelect = 0 self.rtView.recalc() if FlyMainWin.route.fltPlan \ and FlyMainWin.option.boolData('PlanShowOnOpen'): self.fltPlnShow(1) self.statusBar().message('Ready...', 4000) return 1 return 0 def recentOpen(self, filePath): """Open from recentFiles signal""" if filePath and self.savePrompt(): if not self.openFile(filePath): self.recentFiles.removeEntry(filePath) def fileNew(self): """New file command""" if self.savePrompt(): if self.planView: self.planView.close() self.planView = None if self.mapView: self.mapView.close() self.mapView = None FlyMainWin.route = Route(FlyMainWin.option) if sys.platform == 'win32': self.setCaption('FlyWay (PyQt)') else: self.setCaption('FlyWay') self.fileName = '' FlyMainWin.docModified = 0 self.rtView.numSelect = 0 self.rtView.recalc() self.statusBar().message('Hit return to add a waypoint...', 100000) def fileOpen(self): """Open a file""" self.statusBar().message('', 1) if self.savePrompt(): fileName = str(QFileDialog.getOpenFileName('', \ 'FlyWay Files (*.fly);;All Files (*)', self)) if fileName: if self.planView: self.planView.close() self.planView = None if self.mapView: self.mapView.close() self.mapView = None self.openFile(fileName) def fileSave(self): """Save current file""" if self.fileName: FlyMainWin.route.writeFile(self.fileName) FlyMainWin.docModified = 0 self.setMenuAvail() else: self.fileSaveAs() def fileSaveAs(self): """Save file with a new name""" dir, name = os.path.split(self.fileName) dlg = QFileDialog(dir, 'FlyWay Files (*.fly);;All Files (*)', \ self, '', 1) dlg.setMode(QFileDialog.AnyFile) dlg.setSelection(name) if sys.platform == 'win32': dlg.setCaption('Save As (PyQt)') else: dlg.setCaption('Save As') dlg.setIcon(QPixmap(fly_xpm)) result = dlg.exec_loop() fileName = str(dlg.selectedFile()) if result == QDialog.Accepted and fileName: if '.' not in fileName and \ str(dlg.selectedFilter()) == 'FlyWay Files (*.fly)': fileName += '.fly' if os.access(fileName, os.F_OK): text = 'File ' + fileName + ' exists\nReplace existing file?' ans = QMessageBox.information(self, 'FlyWay', text, \ 'Yes', 'No', 'Cancel', 0, 2) if ans != 0: if ans == 1: self.fileSaveAs() return if FlyMainWin.route.writeFile(fileName): if sys.platform == 'win32': self.setCaption(fileName + ' - FlyWay (PyQt)') else: self.setCaption(fileName + ' - FlyWay') self.fileName = fileName self.recentFiles.addEntry(fileName) FlyMainWin.docModified = 0 self.setMenuAvail() def printPage(self, pageNum, painter): """Send pageNum to painter""" painter.setPen(QColor(0, 0, 0)) if FlyMainWin.option.boolData('PrintRoute') \ and len(self.rtPageList) > pageNum - 1: endLine = None if len(self.rtPageList) > pageNum: endLine = self.rtPageList[pageNum][0] painter.save() painter.translate(-RouteView.margin, \ self.rtPageList[pageNum - 1][1]) self.rtView.paintTable(painter, self.rtPageList[pageNum - 1][0], \ endLine) painter.restore() if self.planView and FlyMainWin.option.boolData('PrintFltPlan') \ and len(self.planPageList) > pageNum - 1 \ and self.planPageList[pageNum - 1]: painter.save() painter.translate(0, self.planPageList[pageNum - 1]) self.planView.paintPlan(painter) painter.restore() if FlyMainWin.option.boolData('PrintWaypoints') \ and len(self.wpPageList) > pageNum - 1 \ and self.wpPageList[pageNum - 1]: for wpGroup in self.wpPageList[pageNum - 1]: painter.save() painter.translate(-WpView.idStart[0], wpGroup[1] \ - WpView.idStart[1]) self.wpView.paintWp(painter, wpGroup[0]) painter.restore() if FlyMainWin.option.boolData('PrintWeather') and self.weatherView \ and self.wthrPageList[pageNum - 1]: pos, text = self.wthrPageList[pageNum - 1] painter.setFont(self.weatherView.textView.font()) painter.drawText(0, pos, 5000, 5000, \ Qt.AlignLeft | Qt.WordBreak, text) def filePrint(self): """Print file""" useFile = self.printer.outputToFile() self.printer.setOutputFileName(os.path.splitext(self.fileName)[0] + \ '.ps') self.printer.setOutputToFile(useFile) self.printer.setFullPage(1) self.printer.setMinMax(1, 99) self.printer.setFromTo(1, 99) if not self.printer.setup(self): return paintMetrics = QPaintDeviceMetrics(self.printer) dpi = min(paintMetrics.logicalDpiX(), paintMetrics.logicalDpiY()) scale = dpi / 72.0 xMargin = int(max(self.printer.margins().width() / scale, \ 72 * self.option.numData('HorizMargin', \ FlyMainWin.minPrintMargin, \ FlyMainWin.maxPrintMargin))) yMargin = int(max(self.printer.margins().height() / scale, \ 72 * self.option.numData('VertMargin', \ FlyMainWin.minPrintMargin, \ FlyMainWin.maxPrintMargin))) pageSize = (int(paintMetrics.width() / scale), \ int(paintMetrics.height() / scale)) pageWidth = pageSize[0] - 2 * xMargin pageHeight = pageSize[1] - 2 * yMargin pageUsed = 0 self.rtPageList = [] if FlyMainWin.option.boolData('PrintRoute'): self.rtPageList = [(-1, 0)] # line num, y-pos offset pageUsed += RouteView.wpStart[1] for lineNum in range(len(FlyMainWin.route.wpList) * 2 - 1): pageUsed += RouteView.rowSize if pageUsed > pageHeight: # new page self.rtPageList.append((lineNum, FlyMainWin.printFontHt \ - lineNum * RouteView.rowSize \ - RouteView.wpStart[1])) pageUsed = FlyMainWin.printFontHt self.planPageList = [] if self.planView and FlyMainWin.option.boolData('PrintFltPlan'): self.planPageList = [None] * (len(self.rtPageList) - 1) pos = pageUsed + FlyMainWin.printGap pageUsed = pos + PlanView.rowPos[-1] if pageUsed > pageHeight: # new page self.planPageList.append(None) pos = FlyMainWin.printFontHt pageUsed = pos + PlanView.rowPos[-1] self.planPageList.append(pos) self.wpPageList = [] if FlyMainWin.option.boolData('PrintWaypoints'): self.wpPageList = [[]] * (max(len(self.rtPageList), \ len(self.planPageList)) - 1) thisPage = [] for wp in FlyMainWin.route.wpList: pos = pageUsed + FlyMainWin.printGap pageUsed = pos + (wp.detailNumLines() - 1) * WpView.rowSize if pageUsed > pageHeight: # new page self.wpPageList.append(thisPage) thisPage = [] pos = FlyMainWin.printFontHt pageUsed = pos + (wp.detailNumLines() - 1) * WpView.rowSize thisPage.append((wp, pos)) self.wpPageList.append(thisPage) self.wthrPageList = [] if FlyMainWin.option.boolData('PrintWeather') and self.weatherView: self.wthrPageList = [None] * (max(len(self.rtPageList), \ len(self.planPageList), \ len(self.wpPageList)) - 1) pos = pageUsed = pageUsed + FlyMainWin.printGap lineSpacing = QFontMetrics(self.weatherView.textView.font()).\ lineSpacing() weatherLines = [] weatherItem = [] for line in self.weatherView.printText(): weatherItem.append(line) pageUsed += lineSpacing if line == '': weatherLines.extend(weatherItem) weatherItem = [] elif pageUsed > pageHeight: # new page self.wthrPageList.append((pos, '\n'.join(weatherLines))) weatherLines = [] pos = FlyMainWin.printFontHt pageUsed = pos + len(weatherItem) * lineSpacing weatherLines.extend(weatherItem) if weatherLines: self.wthrPageList.append((pos, '\n'.join(weatherLines))) minPg = max(self.printer.fromPage(), 1) maxPg = max(len(self.rtPageList), len(self.planPageList), \ len(self.wpPageList), len(self.wthrPageList)) if 1 <= self.printer.toPage() < maxPg: maxPg = self.printer.toPage() if self.option.boolData('PrintPrev'): dlg = PrintPrevDlg(minPg, maxPg, pageSize, \ (pageWidth, pageHeight), (xMargin, yMargin), self.printPage, None, None, 1) dlg.setIcon(QPixmap(fly_xpm)) if dlg.exec_loop() != QDialog.Accepted: return self.printer.setFullPage(0) # try to fix MS margin problem painter = QPainter() if painter.begin(self.printer): if self.printer.pageOrder() == QPrinter.FirstPageFirst: seq = range(minPg, maxPg + 1) else: seq = range(maxPg, minPg - 1, -1) printMargin = ((pageSize[0] * scale - paintMetrics.width()) / 2, \ (pageSize[1] * scale - paintMetrics.height()) / 2) pageAvail = (pageSize[0] - 2 * xMargin, pageHeight) painter.setWindow(0, 0, pageAvail[0], pageAvail[1]) painter.setViewport(xMargin * scale -printMargin[0], \ yMargin * scale -printMargin[1], \ pageAvail[0] * scale, pageAvail[1] * scale) self.printPage(seq.pop(0), painter) for num in seq: self.printer.newPage() self.printPage(num, painter) painter.end() def filePrintOpt(self): """Set margins and page size for printing""" dlg = OptionDlg(self.option, self, None, 1) if sys.platform == 'win32': dlg.setCaption('Print Options (PyQt)') else: dlg.setCaption('Print Options') dlg.setIcon(QPixmap(fly_xpm)) dlg.startGroupBox('Print Preview') OptionDlgBool(dlg, 'PrintPrev', 'Preview before printing') dlg.startGroupBox('Margins') OptionDlgDbl(dlg, 'HorizMargin', 'Horizontal page margins (inch)', \ FlyMainWin.minPrintMargin, FlyMainWin.maxPrintMargin) OptionDlgDbl(dlg, 'VertMargin', 'Vertical page margins (inch)', \ FlyMainWin.minPrintMargin, FlyMainWin.maxPrintMargin) dlg.startGroupBox('Include in Printout') OptionDlgBool(dlg, 'PrintRoute', 'Route Table') OptionDlgBool(dlg, 'PrintFltPlan', 'Flight Plan') OptionDlgBool(dlg, 'PrintWaypoints', 'Waypoint Info') OptionDlgBool(dlg, 'PrintWeather', 'Weather Data') if dlg.exec_loop() == QDialog.Accepted and self.option.chgList: self.option.writeChanges() def editParam(self): """Change airspeed and wind condition""" dlg = OptionDlg(self.option, self, None, 1) if sys.platform == 'win32': dlg.setCaption('Parameters (PyQt)') else: dlg.setCaption('Parameters') dlg.setIcon(QPixmap(fly_xpm)) OptionDlgInt(dlg, 'Airspeed', 'Airspeed', 1, RouteLeg.maxAirspeed, \ 1, 5, 0, 0, ' kts') OptionDlgInt(dlg, 'WindSpeed', 'Wind Speed', 0, RouteLeg.maxWindSpeed,\ 0, 1, 0, 0, ' kts') OptionDlgInt(dlg, 'WindDir', 'Wind Direction', 0, 360, \ 0, 5, 1, 3, chr(176)) if dlg.exec_loop() == QDialog.Accepted: FlyMainWin.option.writeChanges() self.rtView.recalc() def editDepart(self): """Change departure time""" dlg = TimeDlg(self, None, 1) if dlg.exec_loop() == QDialog.Accepted: self.rtView.recalc() def fltPlnShow(self, show): """Toggle the flight plan window""" if show: if not self.planView: if not FlyMainWin.route.fltPlan: FlyMainWin.route.fltPlan = PlanData(self.option) FlyMainWin.route.fltPlan.setToDefaults() FlyMainWin.route.fltPlan.setDefaultRoute(FlyMainWin.route) self.planView = PlanView() self.connect(self.planView, PYSIGNAL('menuChg'), \ self.setMenuAvail) self.connect(self.planView, PYSIGNAL('viewClosed'), \ self.planMenuChg) self.connect(self.planView, PYSIGNAL('paramChg'), \ self.rtView.recalc) self.planView.show() self.planView.updatePlan() self.fltPlnGrp.setEnabled(1) else: self.planView.hide() self.fltPlnGrp.setEnabled(0) def planMenuChg(self): """Reset flight plan menu on plan view close""" self.fltPlnShowAct.setOn(0) self.fltPlnGrp.setEnabled(0) def fltPlnUpdate(self): """Update defaults with current settings""" FlyMainWin.route.fltPlan.updateDefaults() self.statusBar().message('Default settings have been updated', 4000) def fltPlnReset(self): """Reset flight plan to default settings""" FlyMainWin.route.fltPlan.setToDefaults() FlyMainWin.route.fltPlan.setDefaultRoute(FlyMainWin.route) self.planView.updatePlan() def toolsDist(self): """Compare route to direct distance""" if len(FlyMainWin.route.wpList) > 1: text = 'Current route distance: %3.0f\n\n'\ 'Direct route distance: %3.0f' text = text % (FlyMainWin.route.legList[-1].totalDist, \ wpDistance(FlyMainWin.route.wpList[0], \ FlyMainWin.route.wpList[-1])[0]) dlg = QMessageBox('Distance Comparison', text, \ QMessageBox.NoIcon, QMessageBox.Ok \ | QMessageBox.Default, 0, 0, self) dlg.setIcon(QPixmap(fly_xpm)) dlg.exec_loop() def toolsMap(self, show): """Activate the map view""" if show: if not self.mapView: if not FlyMainWin.route.mapData: FlyMainWin.route.mapData = MapData(FlyMainWin.route) self.mapView = MapView() self.connect(self.mapView, PYSIGNAL('viewClosed'), \ self.mapMenuChg) else: self.mapView.updateMap() self.mapView.show() else: self.mapView.hide() def mapMenuChg(self): """Reset map menu item on map view close""" self.toolsMapAct.setOn(0) def toolsWeather(self, show): """Activate the weather view""" if show: if not self.weatherView: self.weatherView = WeatherView() self.connect(self.weatherView, PYSIGNAL('viewClosed'), \ self.weatherMenuChg) self.weatherView.show() else: self.weatherView.hide() def weatherMenuChg(self): """Reset weather menu item on view close""" self.toolsWeatherAct.setOn(0) def toolsPref(self): """Set user preferences""" dlg = OptionDlg(FlyMainWin.option, self, None, 1) dlg.setIcon(QPixmap(fly_xpm)) OptionDlgBool(dlg, 'AddOnEnter', 'Enter key inserts waypoint') OptionDlgBool(dlg, 'DelKey', 'Delete key removes waypoint') OptionDlgBool(dlg, 'PlanShowOnOpen', 'Show flight plan when opening') OptionDlgBool(dlg, 'WeatherPlain', 'Default to plain language weather') OptionDlgBool(dlg, 'WeatherKeepPass', 'Remember DUATS password') OptionDlgInt(dlg, 'WeatherDistance', 'Default distance for weather', \ 1, WeatherView.maxDistance) OptionDlgInt(dlg, 'WeatherFdFactor', 'Winds aloft distance factor', \ 1, WeatherView.maxFdFactor) if dlg.exec_loop() == QDialog.Accepted and self.option.chgList: if not FlyMainWin.option.boolData('WeatherKeepPass'): FlyMainWin.option.changeData('WeatherPassword', '', 1) if self.weatherView: self.weatherView.password = '' FlyMainWin.option.writeChanges() def toolsBkColor(self): """Set view background color""" background = QColor(FlyMainWin.option.intData('BackgroundR', 0, 255), \ FlyMainWin.option.intData('BackgroundG', 0, 255), \ FlyMainWin.option.intData('BackgroundB', 0, 255)) newColor = QColorDialog.getColor(background, self) if newColor.isValid() and newColor != background: FlyMainWin.option.changeData('BackgroundR', `newColor.red()`, 1) FlyMainWin.option.changeData('BackgroundG', `newColor.green()`, 1) FlyMainWin.option.changeData('BackgroundB', `newColor.blue()`, 1) FlyMainWin.option.writeChanges() self.updateColors() def toolsTxtColor(self): """Set view text color""" foreground = QColor(FlyMainWin.option.intData('ForegroundR', 0, 255), \ FlyMainWin.option.intData('ForegroundG', 0, 255), \ FlyMainWin.option.intData('ForegroundB', 0, 255)) newColor = QColorDialog.getColor(foreground, self) if newColor.isValid() and newColor != foreground: FlyMainWin.option.changeData('ForegroundR', `newColor.red()`, 1) FlyMainWin.option.changeData('ForegroundG', `newColor.green()`, 1) FlyMainWin.option.changeData('ForegroundB', `newColor.blue()`, 1) FlyMainWin.option.writeChanges() self.updateColors() def findReadMeFile(self, pathList, fileName): """Search paths for file, return line list or None""" for path in pathList: try: f = open(os.path.join(path, fileName), 'r') lineList = f.readlines() f.close() return lineList except IOError: pass return None def helpReadMe(self): """View the ReadMe file""" if not self.helpView: modPath = os.path.abspath(sys.path[0]) pathList = [helpFilePath, os.path.join(modPath, '../doc/'), \ modPath] lineList = self.findReadMeFile(filter(None, pathList), \ 'README.html') if not lineList: self.statusBar().message('Read Me file not found', 4000) return self.helpView = HelpView('\n'.join(lineList), \ 'FlyWay README File') self.helpView.setIcon(QPixmap(fly_xpm)) self.helpView.show() def helpAbout(self): """About this program""" QMessageBox.about(self, 'FlyWay', 'FlyWay, Version %s by %s' % \ (__version__, __author__)) def savePrompt(self): """Ask for save if doc modified, return false on cancel""" if FlyMainWin.docModified: ans = QMessageBox.information(self, 'FlyWay', 'Save changes?', \ 'Yes', 'No', 'Cancel', 0, 2) if ans == 0: self.fileSave() elif ans == 2: return 0 return 1 def closeEvent(self, event): """Check if doc modified""" if self.savePrompt(): event.accept() else: event.ignore() def setupMenus(self): """Add menu and toolbar entries""" fileMenu = QPopupMenu(self) self.menuBar().insertItem('&File', fileMenu) FlyMainWin.toolBar = QToolBar(self) FlyMainWin.routePopup = QPopupMenu(self.rtView) fileNewAct = QAction('New File', QIconSet(QPixmap(filenew_xpm)), \ '&New', Qt.CTRL+Qt.Key_N, self) fileNewAct.setStatusTip('Start a new file') fileNewAct.addTo(fileMenu) fileNewAct.addTo(FlyMainWin.toolBar) self.connect(fileNewAct, SIGNAL('activated()'), self.fileNew) fileOpenAct = QAction('Open File', QIconSet(QPixmap(fileopen_xpm)), \ '&Open...', Qt.CTRL+Qt.Key_O, self) fileOpenAct.setStatusTip('Open a file from disk') fileOpenAct.addTo(fileMenu) fileOpenAct.addTo(FlyMainWin.toolBar) self.connect(fileOpenAct, SIGNAL('activated()'), self.fileOpen) fileMenu.insertSeparator() self.fileSaveAct = QAction('Save File', \ QIconSet(QPixmap(filesave_xpm)), \ '&Save', Qt.CTRL+Qt.Key_S, self) self.fileSaveAct.setStatusTip('Save changes to the current file') self.fileSaveAct.addTo(fileMenu) self.fileSaveAct.addTo(FlyMainWin.toolBar) self.connect(self.fileSaveAct, SIGNAL('activated()'), self.fileSave) fileSaveAsAct = QAction('Save As', 'Save &As...', 0, self) fileSaveAsAct.setStatusTip('Save the file with a new name') fileSaveAsAct.addTo(fileMenu) self.connect(fileSaveAsAct, SIGNAL('activated()'), self.fileSaveAs) fileMenu.insertSeparator() FlyMainWin.toolBar.addSeparator() filePrintAct = QAction('Print File', \ QIconSet(QPixmap(fileprint_xpm)), \ '&Print...', Qt.CTRL+Qt.Key_P, self) filePrintAct.setStatusTip('Print the route info') filePrintAct.addTo(fileMenu) filePrintAct.addTo(FlyMainWin.toolBar) self.connect(filePrintAct, SIGNAL('activated()'), self.filePrint) filePrintOptAct = QAction('Print Options', 'P&rint Options...', \ 0, self) filePrintOptAct.setStatusTip('Set margins and page size for printing') filePrintOptAct.addTo(fileMenu) self.connect(filePrintOptAct, SIGNAL('activated()'), self.filePrintOpt) fileMenu.insertSeparator() self.recentFiles = RecentFiles(self.option, 4, 30, self) self.connect(self.recentFiles, PYSIGNAL('askOpen'), self.recentOpen) self.recentFiles.initMenu(fileMenu, 100) fileMenu.insertSeparator() FlyMainWin.toolBar.addSeparator() fileQuitAct = QAction('Quit', '&Quit', Qt.CTRL+Qt.Key_Q, self) fileQuitAct.setStatusTip('Exit the application') fileQuitAct.addTo(fileMenu) self.connect(fileQuitAct, SIGNAL('activated()'), self.close) editMenu = QPopupMenu(self) self.menuBar().insertItem('&Edit', editMenu) self.editWpGrp = QActionGroup(self) self.editMultWpGrp = QActionGroup(self) editInBeforeAct = QAction('Insert Waypoint Before', \ 'Insert Waypoint &Before', 0, self.editWpGrp) editInBeforeAct.setStatusTip('Add a new waypoint before the selection') editInBeforeAct.addTo(editMenu) editInBeforeAct.addTo(FlyMainWin.routePopup) rt = FlyMainWin.route self.connect(editInBeforeAct, SIGNAL('activated()'), \ self.rtView.editInBefore) editInAfterAct = QAction('Insert Waypoint After', \ 'Insert Waypoint &After\tRTN', 0, self) editInAfterAct.setStatusTip('Add a new waypoint after the selection') editInAfterAct.addTo(editMenu) editInAfterAct.addTo(FlyMainWin.routePopup) self.connect(editInAfterAct, SIGNAL('activated()'), \ self.rtView.editInAfter) editDeleteAct = QAction('Delete Waypoint', '&Delete Waypoint\tDEL', \ 0, self.editWpGrp) editDeleteAct.setStatusTip('Delete the selected waypoint') editDeleteAct.addTo(editMenu) editDeleteAct.addTo(FlyMainWin.routePopup) self.connect(editDeleteAct, SIGNAL('activated()'), \ self.rtView.editDelete) editMenu.insertSeparator() FlyMainWin.routePopup.insertSeparator() self.editUpAct = QAction('Move Waypoint Up', 'Move Waypoint &Up', \ 0, self) self.editUpAct.setStatusTip('Move the selected waypoint upward') self.editUpAct.addTo(editMenu) self.editUpAct.addTo(FlyMainWin.routePopup) self.connect(self.editUpAct, SIGNAL('activated()'), \ self.rtView.editUp) self.editDownAct = QAction('Move Waypoint Down', \ '&Move Waypoint Down', 0, self) self.editDownAct.setStatusTip('Move the selected waypoint downward') self.editDownAct.addTo(editMenu) self.editDownAct.addTo(FlyMainWin.routePopup) self.connect(self.editDownAct, SIGNAL('activated()'), \ self.rtView.editDown) self.editReverseAct = QAction('Reverse Route', '&Reverse Route', \ 0, self.editMultWpGrp) self.editReverseAct.setStatusTip('Reverse the order of all waypoints') self.editReverseAct.addTo(editMenu) self.connect(self.editReverseAct, SIGNAL('activated()'), \ self.rtView.editReverse) editMenu.insertSeparator() editParamAct = QAction('Change Parameters', \ QIconSet(QPixmap(editparam_xpm)), \ '&Change Parameters...', 0, self) editParamAct.setStatusTip('Change airspeed and wind condition') editParamAct.addTo(editMenu) editParamAct.addTo(FlyMainWin.toolBar) self.connect(editParamAct, SIGNAL('activated()'), self.editParam) editDepartAct = QAction('Change Departure Time', \ QIconSet(QPixmap(editdepart_xpm)), \ 'Change Departure &Time...', 0, self) editDepartAct.setStatusTip('Change departure time') editDepartAct.addTo(editMenu) editDepartAct.addTo(FlyMainWin.toolBar) self.connect(editDepartAct, SIGNAL('activated()'), self.editDepart) fltPlnMenu = QPopupMenu(self) self.menuBar().insertItem('Flight &Plan', fltPlnMenu) FlyMainWin.toolBar.addSeparator() self.fltPlnShowAct = QAction('Show Flight Plan', \ QIconSet(QPixmap(fltplanshow_xpm)), \ '&Show Flight Plan', 0, self) self.fltPlnShowAct.setStatusTip('Toggle the flight plan window') self.fltPlnShowAct.setToggleAction(1) self.fltPlnShowAct.addTo(fltPlnMenu) self.fltPlnShowAct.addTo(FlyMainWin.toolBar) self.connect(self.fltPlnShowAct, SIGNAL('toggled(bool)'), \ self.fltPlnShow) fltPlnMenu.insertSeparator() self.fltPlnGrp = QActionGroup(self) fltPlnUpdateAct = QAction('Update Defaults', '&Update Defaults', \ 0, self.fltPlnGrp) fltPlnUpdateAct.setStatusTip('Update defaults with current settings') fltPlnUpdateAct.addTo(fltPlnMenu) self.connect(fltPlnUpdateAct, SIGNAL('activated()'), self.fltPlnUpdate) fltPlnResetAct = QAction('Reset to Defaults', '&Reset to Defaults', \ 0, self.fltPlnGrp) fltPlnResetAct.setStatusTip('Reset flight plan to default settings') fltPlnResetAct.addTo(fltPlnMenu) self.connect(fltPlnResetAct, SIGNAL('activated()'), self.fltPlnReset) toolsMenu = QPopupMenu(self) self.menuBar().insertItem('&Tools', toolsMenu) toolsDistAct = QAction('Distance Comparison', '&Distance Comparison', \ 0, self.editMultWpGrp) toolsDistAct.setStatusTip('Compare route to direct distance') toolsDistAct.addTo(toolsMenu) self.connect(toolsDistAct, SIGNAL('activated()'), self.toolsDist) self.toolsMapAct = QAction('View Map', \ QIconSet(QPixmap(mapshow_xpm)), \ 'View &Map', 0, self) self.toolsMapAct.setStatusTip('View a rough map of the route') self.toolsMapAct.setToggleAction(1) self.toolsMapAct.addTo(toolsMenu) self.toolsMapAct.addTo(FlyMainWin.toolBar) self.connect(self.toolsMapAct, SIGNAL('toggled(bool)'), self.toolsMap) self.toolsWeatherAct = QAction('View Weather', \ QIconSet(QPixmap(weathershow_xpm)), \ 'View &Weather', 0, self) self.toolsWeatherAct.setStatusTip('View weather info for the route') self.toolsWeatherAct.setToggleAction(1) self.toolsWeatherAct.addTo(toolsMenu) self.toolsWeatherAct.addTo(FlyMainWin.toolBar) self.connect(self.toolsWeatherAct, SIGNAL('toggled(bool)'), \ self.toolsWeather) toolsMenu.insertSeparator() toolsPrefAct = QAction('Preferences', '&Preferences...', 0, self) toolsPrefAct.setStatusTip('Set user preferences') toolsPrefAct.addTo(toolsMenu) self.connect(toolsPrefAct, SIGNAL('activated()'), self.toolsPref) toolsMenu.insertSeparator() toolsBkColorAct = QAction('Background Color', '&Background Color...', \ 0, self) toolsBkColorAct.setStatusTip('Set view background color') toolsBkColorAct.addTo(toolsMenu) self.connect(toolsBkColorAct, SIGNAL('activated()'), self.toolsBkColor) toolsTxtColorAct = QAction('Text Color', '&Text Color...', \ 0, self) toolsTxtColorAct.setStatusTip('Set view text color') toolsTxtColorAct.addTo(toolsMenu) self.connect(toolsTxtColorAct, SIGNAL('activated()'),\ self.toolsTxtColor) FlyMainWin.toolBar.addSeparator() helpMenu = QPopupMenu(self) self.menuBar().insertItem('&Help', helpMenu) helpReadMeAct = QAction('View ReadMe', QIconSet(QPixmap(help_xpm)), \ '&View ReadMe', 0, self) helpReadMeAct.setStatusTip('View the ReadMe file') helpReadMeAct.addTo(helpMenu) helpReadMeAct.addTo(FlyMainWin.toolBar) self.connect(helpReadMeAct, SIGNAL('activated()'), self.helpReadMe) helpAboutAct = QAction('About FlyWay', '&About FlyWay', 0, self) helpAboutAct.setStatusTip('About this program') helpAboutAct.addTo(helpMenu) self.connect(helpAboutAct, SIGNAL('activated()'), self.helpAbout)