#!/usr/bin/env python #**************************************************************************** # weatherview.py, provides a window for weather display # # 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. #***************************************************************************** from weatherdata import WeatherData from flydialogs import PasswordDlg import flymainwin from xpm import * from qt import * import sys class WeatherView(QWidget): """A window that shows a weather data""" maxDistance = 999 maxFdFactor = 99 def __init__(self, parent=None, name=None, flags=0): QWidget.__init__(self, parent, name, flags) self.user = str(flymainwin.FlyMainWin.option.strData('WeatherUser', 1)) self.password = str(flymainwin.FlyMainWin.option.\ strData('WeatherPassword', 1)) self.sourceNum = (self.user and self.password) and 1 or 0 self.setFocusPolicy(QWidget.StrongFocus) self.resize(400, 300) if sys.platform == 'win32': self.setCaption('Weather Data (PyQt)') else: self.setCaption('Weather Data') self.setIcon(QPixmap(fly_xpm)) topLayout = QVBoxLayout(self, 5) ctrlLayout = QHBoxLayout(topLayout) subLayout = QVBoxLayout(ctrlLayout) sourceButtons = QVButtonGroup('Source', self) subLayout.addWidget(sourceButtons) QRadioButton('NOAA (http)', sourceButtons) QRadioButton('DUATS (telnet)', sourceButtons) sourceButtons.setButton(self.sourceNum) self.connect(sourceButtons, SIGNAL('clicked(int)'), self.setSource) self.plainButton = QCheckBox('Plain language', self) subLayout.addWidget(self.plainButton) self.plainButton.setChecked(flymainwin.FlyMainWin.option.\ boolData('WeatherPlain')) includeButtons = QVButtonGroup('Include', self) ctrlLayout.addWidget(includeButtons) self.metarButton = QCheckBox('METAR\'s', includeButtons) self.metarButton.setChecked(1) self.tafButton = QCheckBox('TAF\'s', includeButtons) self.tafButton.setChecked(1) self.fdButton = QCheckBox('Winds Aloft', includeButtons) self.fdButton.setChecked(0) self.connect(includeButtons, SIGNAL('clicked(int)'), self.updateCmdAvail) subLayout = QVBoxLayout(ctrlLayout) distBox = QHGroupBox('Distance', self) subLayout.addWidget(distBox) self.distSpin = QSpinBox(1, WeatherView.maxDistance, 5, distBox) self.distSpin.setValue(flymainwin.FlyMainWin.option.\ intData('WeatherDistance', 1, \ WeatherView.maxDistance)) QLabel('nmi from\nroute', distBox) self.updateButton = QPushButton('Update', self) subLayout.addWidget(self.updateButton) self.connect(self.updateButton, SIGNAL('clicked()'), self.updateWeather) self.updateCmdAvail() if qVersion()[0] >= '3': self.textView = QTextEdit(self) self.textView.setTextFormat(Qt.PlainText) self.blankLine = '\n' else: self.textView = QMultiLineEdit(self) self.blankLine = '' self.textView.setReadOnly(1) font = QFont('Fixed', self.font().pointSize()) if not str(QFontInfo(font).family()).lower().startswith('fixed'): font = QFont('Courier', self.font().pointSize()) self.textView.setFont(font) topLayout.addWidget(self.textView, 1) self.infoLabel = QLabel(self) self.infoLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) topLayout.addWidget(self.infoLabel) def updateWeather(self): """Fetch latest weather based on control settings""" if self.sourceNum == 1 and (not self.user or not self.password): dlg = PasswordDlg(self, None, 1) if dlg.exec_loop() != QDialog.Accepted: return self.user = dlg.user self.password = dlg.password if not self.user or not self.password: return QApplication.setOverrideCursor(Qt.waitCursor) self.infoLabel.setText('Working...') self.infoLabel.repaint() self.textView.clear() self.textView.repaint() data = WeatherData(flymainwin.FlyMainWin.route) fdDist = self.fdButton.isOn() and self.distSpin.value() * \ flymainwin.FlyMainWin.option.intData('WeatherFdFactor', 1, \ WeatherView.maxFdFactor) or 0 data.findAirports(self.distSpin.value(), fdDist) numMetar = data.numOfType('METAR') numTaf = data.numOfType('TAF') numFd = data.numOfType('FD') labelText = [] if self.metarButton.isOn(): labelText.append('%d METAR\'s' % numMetar) if self.tafButton.isOn(): labelText.append('%d TAF\'s' % numTaf) if self.fdButton.isOn(): labelText.append('%d FD\'s' % numFd) self.infoLabel.setText('Found %s...' % ' and '.join(labelText)) self.infoLabel.repaint() if self.sourceNum == 0: # http if self.metarButton.isOn() and numMetar: self.appendText('\n********* Surface Observations *********') data.fetchHttpReports(self.appendText, 'METAR', \ self.plainButton.isChecked()) if self.tafButton.isOn() and numTaf: self.appendText('\n********** Terminal Forecasts **********') data.fetchHttpReports(self.appendText, 'TAF', 0) else: # telnet data.openTelnet(self.user, self.password, self.appendText) if self.metarButton.isOn() and numMetar: self.appendText('\n********* Surface Observations *********') data.fetchTelnetReports(self.appendText, 'METAR', \ self.plainButton.isChecked()) if self.tafButton.isOn() and numTaf: self.appendText('\n********* Terminal Forecasts *********') data.fetchTelnetReports(self.appendText, 'TAF', \ self.plainButton.isChecked()) if self.fdButton.isOn() and numFd: self.appendText('\n********* Winds & Temps Aloft *********') data.fetchTelnetReports(self.appendText, 'FD', \ self.plainButton.isChecked()) data.closeTelnet() if str(self.textView.text()).strip(): self.infoLabel.setText('Done') else: self.infoLabel.setText(str(self.infoLabel.text())[:-3]) QApplication.restoreOverrideCursor() def appendText(self, text): """Add text to view and update""" self.textView.append(text) self.textView.append(self.blankLine) self.textView.repaint() def printText(self): """Return text lines for printing""" return str(self.textView.text()).split('\n') def setSource(self, num): self.sourceNum = num self.updateCmdAvail() def updateCmdAvail(self): """Update availability of update button based on types and waypoints""" self.updateButton.setEnabled(len(flymainwin.FlyMainWin.route.wpList) \ and (self.metarButton.isOn() or \ self.tafButton.isOn() or \ self.fdButton.isOn())) self.fdButton.setEnabled(self.sourceNum) if not self.sourceNum: self.fdButton.setChecked(0) self.plainButton.setEnabled(self.sourceNum or self.metarButton.isOn()) def closeEvent(self, event): """Signal that view is closing""" self.emit(PYSIGNAL('viewClosed'), ()) event.accept()