from common import *
from mlx.pirep import PIREP
from mlx.const import *
import time
#------------------------------------------------------------------------------
## @package mlx.gui.pirep
#
# The detailed PIREP viewer.
#
# The \ref PIREPViewer class is a dialog displaying all information found in a
# PIREP. It consists of three tabs. The Data tab displays the simple,
# itemizable data. The Comments & defects tab contains the flight comments and
# defects, while the Log tab contains the flight log collected by the
# \ref mlx.logger.Logger "logger".
#------------------------------------------------------------------------------
class PIREPViewer(gtk.Dialog):
"""The dialog for PIREP viewing."""
@staticmethod
def createFrame(label):
"""Create a frame with the given label.
The frame will contain an alignment to properly distance the
insides. The alignment will contain a VBox to contain the real
contents.
The function returns a tuple with the following items:
- the frame,
- the inner VBox."""
frame = gtk.Frame(label = label)
alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
xscale = 1.0, yscale = 1.0)
frame.add(alignment)
alignment.set_padding(padding_top = 4, padding_bottom = 4,
padding_left = 4, padding_right = 4)
box = gtk.VBox()
alignment.add(box)
return (frame, box)
@staticmethod
def getLabel(text):
"""Get a bold label with the given text."""
label = gtk.Label("" + text + "")
label.set_use_markup(True)
label.set_alignment(0.0, 0.5)
return label
@staticmethod
def getDataLabel(width = None, xAlignment = 0.0):
"""Get a bold label with the given text."""
label = gtk.Label()
if width is not None:
label.set_width_chars(width)
label.set_alignment(xAlignment, 0.5)
return label
@staticmethod
def getTextWindow(heightRequest = 40):
"""Get a scrollable text window.
Returns a tuple of the following items:
- the window,
- the text view."""
scrolledWindow = gtk.ScrolledWindow()
scrolledWindow.set_shadow_type(SHADOW_IN)
scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
textView = gtk.TextView()
textView.set_wrap_mode(WRAP_WORD)
textView.set_editable(False)
textView.set_cursor_visible(False)
textView.set_size_request(-1, heightRequest)
scrolledWindow.add(textView)
return (scrolledWindow, textView)
@staticmethod
def tableAttach(table, column, row, labelText, width = None,
dataLabelXAlignment = 0.0):
"""Attach a labeled data to the given column and row of the
table.
If width is given, that will be the width of the data
label.
Returns the data label attached."""
dataBox = gtk.HBox()
table.attach(dataBox, column, column+1, row, row+1)
dataLabel = PIREPViewer.addLabeledData(dataBox, labelText,
width = width)
dataLabel.set_alignment(dataLabelXAlignment, 0.5)
return dataLabel
@staticmethod
def addLabeledData(hBox, labelText, width = None, dataPadding = 8):
"""Add a label and a data label to the given HBox.
Returnsd the data label."""
label = PIREPViewer.getLabel(labelText)
hBox.pack_start(label, False, False, 0)
dataLabel = PIREPViewer.getDataLabel(width = width)
hBox.pack_start(dataLabel, False, False, dataPadding)
return dataLabel
@staticmethod
def addVFiller(vBox, height = 4):
"""Add a filler to the given vertical box."""
filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
xscale = 1.0, yscale = 1.0)
filler.set_size_request(-1, height)
vBox.pack_start(filler, False, False, 0)
@staticmethod
def timestamp2text(label, timestamp):
"""Convert the given timestamp into a text containing the hour
and minute in UTC and put that text into the given label."""
tm = time.gmtime(timestamp)
label.set_text("%02d:%02d" % (tm.tm_hour, tm.tm_min))
def __init__(self, gui):
"""Construct the PIREP viewer."""
super(PIREPViewer, self).__init__(title = WINDOW_TITLE_BASE +
" - " +
xstr("pirepView_title"),
parent = gui.mainWindow)
self.set_resizable(False)
self._gui = gui
contentArea = self.get_content_area()
self._notebook = gtk.Notebook()
contentArea.pack_start(self._notebook, False, False, 4)
dataTab = self._buildDataTab()
label = gtk.Label(xstr("pirepView_tab_data"))
label.set_use_underline(True)
label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
self._notebook.append_page(dataTab, label)
commentsTab = self._buildCommentsTab()
label = gtk.Label(xstr("pirepView_tab_comments"))
label.set_use_underline(True)
label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
self._notebook.append_page(commentsTab, label)
logTab = self._buildLogTab()
label = gtk.Label(xstr("pirepView_tab_log"))
label.set_use_underline(True)
label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
self._notebook.append_page(logTab, label)
self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
self._okButton.set_can_default(True)
def setPIREP(self, pirep):
"""Setup the data in the dialog from the given PIREP."""
bookedFlight = pirep.bookedFlight
self._callsign.set_text(bookedFlight.callsign)
self._tailNumber.set_text(bookedFlight.tailNumber)
aircraftType = xstr("aircraft_" + icaoCodes[bookedFlight.aircraftType].lower())
self._aircraftType.set_text(aircraftType)
self._departureICAO.set_text(bookedFlight.departureICAO)
self._departureTime.set_text("%02d:%02d" % \
(bookedFlight.departureTime.hour,
bookedFlight.departureTime.minute))
self._arrivalICAO.set_text(bookedFlight.arrivalICAO)
self._arrivalTime.set_text("%02d:%02d" % \
(bookedFlight.arrivalTime.hour,
bookedFlight.arrivalTime.minute))
self._numPassengers.set_text(str(bookedFlight.numPassengers))
self._numCrew.set_text(str(bookedFlight.numCrew))
self._bagWeight.set_text(str(bookedFlight.bagWeight))
self._cargoWeight.set_text(str(bookedFlight.cargoWeight))
self._mailWeight.set_text(str(bookedFlight.mailWeight))
self._route.get_buffer().set_text(bookedFlight.route)
self._filedCruiseLevel.set_text("FL" + str(pirep.filedCruiseAltitude/100))
if pirep.cruiseAltitude != pirep.filedCruiseAltitude:
self._modifiedCruiseLevel.set_text("FL" + str(pirep.cruiseAltitude/100))
else:
self._modifiedCruiseLevel.set_text("-")
self._userRoute.get_buffer().set_text(pirep.route)
self._departureMETAR.get_buffer().set_text(pirep.departureMETAR)
self._arrivalMETAR.get_buffer().set_text(pirep.arrivalMETAR)
self._departureRunway.set_text(pirep.departureRunway)
self._sid.set_text(pirep.sid)
self._star.set_text("-" if pirep.star is None else pirep.star)
self._transition.set_text("-" if pirep.transition is None else pirep.transition)
self._approachType.set_text(pirep.approachType)
self._arrivalRunway.set_text(pirep.arrivalRunway)
PIREPViewer.timestamp2text(self._blockTimeStart, pirep.blockTimeStart)
PIREPViewer.timestamp2text(self._blockTimeEnd, pirep.blockTimeEnd)
PIREPViewer.timestamp2text(self._flightTimeStart, pirep.flightTimeStart)
PIREPViewer.timestamp2text(self._flightTimeEnd, pirep.flightTimeEnd)
self._flownDistance.set_text("%.1f" % (pirep.flownDistance,))
self._fuelUsed.set_text("%.0f" % (pirep.fuelUsed,))
rating = pirep.rating
if rating<0:
self._rating.set_markup('NO GO')
else:
self._rating.set_text("%.1f %%" % (rating,))
self._flownNumCrew.set_text("%d" % (pirep.numCrew,))
self._flownNumPassengers.set_text("%d" % (pirep.numPassengers,))
self._flownBagWeight.set_text("%.0f" % (pirep.bagWeight,))
self._flownCargoWeight.set_text("%.0f" % (pirep.cargoWeight,))
self._flownMailWeight.set_text("%.0f" % (pirep.mailWeight,))
self._flightType.set_text(xstr("flighttype_" +
flightType2string(pirep.flightType)))
self._online.set_text(xstr("pirepView_" +
("yes" if pirep.online else "no")))
delayCodes = ""
for code in pirep.delayCodes:
if delayCodes: delayCodes += ", "
delayCodes += code
self._delayCodes.get_buffer().set_text(delayCodes)
self._comments.get_buffer().set_text(pirep.comments)
self._flightDefects.get_buffer().set_text(pirep.flightDefects)
logBuffer = self._log.get_buffer()
logBuffer.set_text("")
lineIndex = 0
for (timeStr, line) in pirep.logLines:
isFault = lineIndex in pirep.faultLineIndexes
appendTextBuffer(logBuffer,
formatFlightLogLine(timeStr, line),
isFault = isFault)
lineIndex += 1
self._notebook.set_current_page(0)
self._okButton.grab_default()
def _buildDataTab(self):
"""Build the data tab of the viewer."""
table = gtk.Table(1, 2)
table.set_row_spacings(4)
table.set_col_spacings(16)
table.set_homogeneous(True)
box1 = gtk.VBox()
table.attach(box1, 0, 1, 0, 1)
box2 = gtk.VBox()
table.attach(box2, 1, 2, 0, 1)
flightFrame = self._buildFlightFrame()
box1.pack_start(flightFrame, False, False, 4)
routeFrame = self._buildRouteFrame()
box1.pack_start(routeFrame, False, False, 4)
departureFrame = self._buildDepartureFrame()
box2.pack_start(departureFrame, True, True, 4)
arrivalFrame = self._buildArrivalFrame()
box2.pack_start(arrivalFrame, True, True, 4)
statisticsFrame = self._buildStatisticsFrame()
box2.pack_start(statisticsFrame, False, False, 4)
miscellaneousFrame = self._buildMiscellaneousFrame()
box1.pack_start(miscellaneousFrame, False, False, 4)
return table
def _buildFlightFrame(self):
"""Build the frame for the flight data."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
dataBox = gtk.HBox()
mainBox.pack_start(dataBox, False, False, 0)
self._callsign = \
PIREPViewer.addLabeledData(dataBox,
xstr("pirepView_callsign"),
width = 8)
self._tailNumber = \
PIREPViewer.addLabeledData(dataBox,
xstr("pirepView_tailNumber"),
width = 7)
PIREPViewer.addVFiller(mainBox)
dataBox = gtk.HBox()
mainBox.pack_start(dataBox, False, False, 0)
self._aircraftType = \
PIREPViewer.addLabeledData(dataBox,
xstr("pirepView_aircraftType"),
width = 25)
PIREPViewer.addVFiller(mainBox)
table = gtk.Table(3, 2)
mainBox.pack_start(table, False, False, 0)
table.set_row_spacings(4)
table.set_col_spacings(8)
self._departureICAO = \
PIREPViewer.tableAttach(table, 0, 0,
xstr("pirepView_departure"),
width = 5)
self._departureTime = \
PIREPViewer.tableAttach(table, 1, 0,
xstr("pirepView_departure_time"),
width = 6)
self._arrivalICAO = \
PIREPViewer.tableAttach(table, 0, 1,
xstr("pirepView_arrival"),
width = 5)
self._arrivalTime = \
PIREPViewer.tableAttach(table, 1, 1,
xstr("pirepView_arrival_time"),
width = 6)
table = gtk.Table(3, 2)
mainBox.pack_start(table, False, False, 0)
table.set_row_spacings(4)
table.set_col_spacings(8)
self._numPassengers = \
PIREPViewer.tableAttach(table, 0, 0,
xstr("pirepView_numPassengers"),
width = 4)
self._numCrew = \
PIREPViewer.tableAttach(table, 1, 0,
xstr("pirepView_numCrew"),
width = 3)
self._bagWeight = \
PIREPViewer.tableAttach(table, 0, 1,
xstr("pirepView_bagWeight"),
width = 5)
self._cargoWeight = \
PIREPViewer.tableAttach(table, 1, 1,
xstr("pirepView_cargoWeight"),
width = 5)
self._mailWeight = \
PIREPViewer.tableAttach(table, 2, 1,
xstr("pirepView_mailWeight"),
width = 5)
PIREPViewer.addVFiller(mainBox)
mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_route")),
False, False, 0)
(routeWindow, self._route) = PIREPViewer.getTextWindow()
mainBox.pack_start(routeWindow, False, False, 0)
return frame
def _buildRouteFrame(self):
"""Build the frame for the user-specified route and flight
level."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
levelBox = gtk.HBox()
mainBox.pack_start(levelBox, False, False, 0)
self._filedCruiseLevel = \
PIREPViewer.addLabeledData(levelBox,
xstr("pirepView_filedCruiseLevel"),
width = 6)
self._modifiedCruiseLevel = \
PIREPViewer.addLabeledData(levelBox,
xstr("pirepView_modifiedCruiseLevel"),
width = 6)
PIREPViewer.addVFiller(mainBox)
(routeWindow, self._userRoute) = PIREPViewer.getTextWindow()
mainBox.pack_start(routeWindow, False, False, 0)
return frame
def _buildDepartureFrame(self):
"""Build the frame for the departure data."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_departure"))
mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
False, False, 0)
(metarWindow, self._departureMETAR) = \
PIREPViewer.getTextWindow(heightRequest = -1)
mainBox.pack_start(metarWindow, True, True, 0)
PIREPViewer.addVFiller(mainBox)
dataBox = gtk.HBox()
mainBox.pack_start(dataBox, False, False, 0)
self._departureRunway = \
PIREPViewer.addLabeledData(dataBox,
xstr("pirepView_runway"),
width = 5)
self._sid = \
PIREPViewer.addLabeledData(dataBox,
xstr("pirepView_sid"),
width = 12)
return frame
def _buildArrivalFrame(self):
"""Build the frame for the arrival data."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_arrival"))
mainBox.pack_start(PIREPViewer.getLabel("METAR:"),
False, False, 0)
(metarWindow, self._arrivalMETAR) = \
PIREPViewer.getTextWindow(heightRequest = -1)
mainBox.pack_start(metarWindow, True, True, 0)
PIREPViewer.addVFiller(mainBox)
table = gtk.Table(2, 2)
mainBox.pack_start(table, False, False, 0)
table.set_row_spacings(4)
table.set_col_spacings(8)
self._star = \
PIREPViewer.tableAttach(table, 0, 0,
xstr("pirepView_star"),
width = 12)
self._transition = \
PIREPViewer.tableAttach(table, 1, 0,
xstr("pirepView_transition"),
width = 12)
self._approachType = \
PIREPViewer.tableAttach(table, 0, 1,
xstr("pirepView_approachType"),
width = 7)
self._arrivalRunway = \
PIREPViewer.tableAttach(table, 1, 1,
xstr("pirepView_runway"),
width = 5)
return frame
def _buildStatisticsFrame(self):
"""Build the frame for the statistics data."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
table = gtk.Table(4, 2)
mainBox.pack_start(table, False, False, 0)
table.set_row_spacings(4)
table.set_col_spacings(8)
table.set_homogeneous(False)
self._blockTimeStart = \
PIREPViewer.tableAttach(table, 0, 0,
xstr("pirepView_blockTimeStart"),
width = 6)
self._blockTimeEnd = \
PIREPViewer.tableAttach(table, 1, 0,
xstr("pirepView_blockTimeEnd"),
width = 8)
self._flightTimeStart = \
PIREPViewer.tableAttach(table, 0, 1,
xstr("pirepView_flightTimeStart"),
width = 6)
self._flightTimeEnd = \
PIREPViewer.tableAttach(table, 1, 1,
xstr("pirepView_flightTimeEnd"),
width = 6)
self._flownDistance = \
PIREPViewer.tableAttach(table, 0, 2,
xstr("pirepView_flownDistance"),
width = 8)
self._fuelUsed = \
PIREPViewer.tableAttach(table, 1, 2,
xstr("pirepView_fuelUsed"),
width = 6)
self._rating = \
PIREPViewer.tableAttach(table, 0, 3,
xstr("pirepView_rating"),
width = 7)
return frame
def _buildMiscellaneousFrame(self):
"""Build the frame for the miscellaneous data."""
(frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
table = gtk.Table(3, 2)
mainBox.pack_start(table, False, False, 0)
table.set_row_spacings(4)
table.set_col_spacings(8)
self._flownNumPassengers = \
PIREPViewer.tableAttach(table, 0, 0,
xstr("pirepView_numPassengers"),
width = 4)
self._flownNumCrew = \
PIREPViewer.tableAttach(table, 1, 0,
xstr("pirepView_numCrew"),
width = 3)
self._flownBagWeight = \
PIREPViewer.tableAttach(table, 0, 1,
xstr("pirepView_bagWeight"),
width = 5)
self._flownCargoWeight = \
PIREPViewer.tableAttach(table, 1, 1,
xstr("pirepView_cargoWeight"),
width = 6)
self._flownMailWeight = \
PIREPViewer.tableAttach(table, 2, 1,
xstr("pirepView_mailWeight"),
width = 5)
self._flightType = \
PIREPViewer.tableAttach(table, 0, 2,
xstr("pirepView_flightType"),
width = 15)
self._online = \
PIREPViewer.tableAttach(table, 1, 2,
xstr("pirepView_online"),
width = 5)
PIREPViewer.addVFiller(mainBox)
mainBox.pack_start(PIREPViewer.getLabel(xstr("pirepView_delayCodes")),
False, False, 0)
(textWindow, self._delayCodes) = PIREPViewer.getTextWindow()
mainBox.pack_start(textWindow, False, False, 0)
return frame
def _buildCommentsTab(self):
"""Build the tab with the comments and flight defects."""
table = gtk.Table(2, 1)
table.set_col_spacings(16)
(frame, commentsBox) = \
PIREPViewer.createFrame(xstr("pirepView_comments"))
table.attach(frame, 0, 1, 0, 1)
(commentsWindow, self._comments) = \
PIREPViewer.getTextWindow(heightRequest = -1)
commentsBox.pack_start(commentsWindow, True, True, 0)
(frame, flightDefectsBox) = \
PIREPViewer.createFrame(xstr("pirepView_flightDefects"))
table.attach(frame, 1, 2, 0, 1)
(flightDefectsWindow, self._flightDefects) = \
PIREPViewer.getTextWindow(heightRequest = -1)
flightDefectsBox.pack_start(flightDefectsWindow, True, True, 0)
return table
def _buildLogTab(self):
"""Build the log tab."""
mainBox = gtk.VBox()
(logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
addFaultTag(self._log.get_buffer())
mainBox.pack_start(logWindow, True, True, 0)
return mainBox
#------------------------------------------------------------------------------