1311 lines
62 KiB
Python
1311 lines
62 KiB
Python
from javax.swing import (JTable, JScrollPane, JFrame, JPanel, JComboBox, BorderFactory, DefaultCellEditor, JLabel,
|
|
UIManager, SwingConstants, JFileChooser, JTextField)
|
|
from javax.swing.table import TableCellRenderer, DefaultTableCellRenderer
|
|
from java.awt.event import MouseAdapter,MouseEvent, WindowListener, WindowEvent
|
|
from java.awt import GridLayout, Dimension, BorderLayout, Color
|
|
from javax.swing.table import AbstractTableModel, DefaultTableModel
|
|
from java.lang.Object import getClass
|
|
import jarray
|
|
from javax.swing.event import TableModelListener, TableModelEvent
|
|
from javax.swing.filechooser import FileNameExtensionFilter
|
|
from org.apache.commons.io import FilenameUtils
|
|
from java.io import File
|
|
from java.awt import Toolkit
|
|
from java.awt.event import ActionListener
|
|
import time
|
|
|
|
programmatic_update = False
|
|
|
|
class CreateAndShowGUI5(TableModelListener):
|
|
|
|
def __init__(self, class_ResetButtonMaster, route_name, param_scheduled_start, \
|
|
journey_time_row_displayed = False, add_row_columns_displayed = False, hidden = False):
|
|
|
|
global scheduled_start
|
|
global add_row_columns_displayed_gbl
|
|
|
|
self.journey_time_row_displayed = journey_time_row_displayed
|
|
self.add_row_columns_displayed = add_row_columns_displayed
|
|
add_row_columns_displayed_gbl = add_row_columns_displayed
|
|
|
|
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
|
|
self.route = RouteManager.getRouteByName(route_name)
|
|
|
|
scheduled_start = param_scheduled_start
|
|
self.logLevel = 0
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
#Create and set up the window.
|
|
|
|
self.frame = JFrame("Train Route: " + route_name + " Actions listed after station take place after arrive at that station, before train moves from that station")
|
|
self.frame.setSize(1000, 600)
|
|
|
|
# setup self.table
|
|
self.model = MyTableModel5()
|
|
self.model.route = self.route
|
|
self.model.addTableModelListener(MyModelListener5(self, class_ResetButtonMaster))
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
|
|
self.table = JTable(self.model)
|
|
self.table.setPreferredScrollableViewportSize(Dimension(600, 300));
|
|
|
|
self.table.setFillsViewportHeight(True);
|
|
self.table.setRowHeight(30);
|
|
|
|
# setup self.button_pane
|
|
self.set_button_pane()
|
|
|
|
self.scrollPane = JScrollPane(self.table)
|
|
self.scrollPane.setSize(Dimension(600, 500))
|
|
|
|
self.topPanel= JPanel();
|
|
self.topPanel.setLayout(BoxLayout(self.topPanel, BoxLayout.X_AXIS))
|
|
|
|
self.topPanel.add(self.scrollPane)
|
|
|
|
config = self.frame.getGraphicsConfiguration()
|
|
bounds = config.getBounds()
|
|
insets = Toolkit.getDefaultToolkit().getScreenInsets(config)
|
|
|
|
x = bounds.x + bounds.width - insets.right - self.frame.getWidth() -400
|
|
y = bounds.y + insets.top + 100
|
|
self.frame.setLocation(x, y)
|
|
|
|
contentPane = self.frame.getContentPane()
|
|
# contentPane.removeAll()
|
|
contentPane.add(self.topPanel, BorderLayout.CENTER)
|
|
contentPane.add(self.buttonPane, BorderLayout.PAGE_END)
|
|
self.populate_action(None)
|
|
self.cancel = False
|
|
self.completeTablePanel()
|
|
|
|
if hidden == False:
|
|
self.show_frame()
|
|
|
|
def show_frame(self):
|
|
self.frame.setVisible(True)
|
|
|
|
def hide_frame(self):
|
|
self.frame.setVisible(False)
|
|
|
|
def completeTablePanel(self):
|
|
global fast_clock_rate
|
|
|
|
# set the widths of the columns of self.table
|
|
self.columnModel = self.setup_column_widths_and_comboboxes()
|
|
|
|
# Get the size of the JFrame
|
|
size = self.scrollPane.getSize();
|
|
original_height = size.height
|
|
# print "original_height", original_height
|
|
# set height of scrollPane
|
|
size_of_one_row = 30
|
|
height = 50
|
|
for row in reversed(range(len(self.model.data))):
|
|
height += size_of_one_row
|
|
height = min(height, original_height)
|
|
self.scrollPane.setPreferredSize(Dimension(600, height))
|
|
|
|
# set whether stop sensor column is displayed
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if self.route is None : print "************ self.route is None C **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
|
|
stop_sensor_present_list = []
|
|
|
|
stop_sensor_present_list = [row1 for row1 in routelocations_rows_list
|
|
if row1 > self.model.find_row_first_location()
|
|
if self.model.stop_sensor_present(row1,
|
|
self.model.getValueAt(self.model.find_row_prev_location(row1), locations_col),
|
|
self.model.getValueAt(row1, locations_col)) == True]
|
|
|
|
columnModel = self.table.getColumnModel()
|
|
|
|
if not stop_sensor_present_list: # An empty list evaluates to False
|
|
columnModel.getColumn(stop_sensor_col).setMaxWidth(0)
|
|
columnModel.getColumn(stop_sensor_col).setMinWidth(0)
|
|
|
|
self.topPanel.add(self.scrollPane)
|
|
self.frame.pack();
|
|
self.frame.setVisible(True)
|
|
return
|
|
|
|
def set_button_pane(self):
|
|
global fast_clock_rate
|
|
|
|
self.buttonPane = JPanel();
|
|
self.buttonPane.setLayout(BoxLayout(self.buttonPane, BoxLayout.LINE_AXIS))
|
|
self.buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10))
|
|
|
|
button_close = JButton("Close", actionPerformed = self.close_action)
|
|
self.buttonPane.add(button_close)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
button_add_row = JButton("Toggle Add Row", actionPerformed = self.add_row_action)
|
|
self.buttonPane.add(button_add_row)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
button_show_wait = JButton("Toggle Journey/Wait Times", actionPerformed = self.show_wait_action)
|
|
self.buttonPane.add(button_show_wait)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
# if self.journey_time_row_displayed == False:
|
|
|
|
if self.journey_time_row_displayed == True:
|
|
button_wait_time = JButton("Set Wait Times", actionPerformed = self.change_wait_time_action)
|
|
self.buttonPane.add(button_wait_time)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
|
|
if "fast_clock_rate" not in globals():
|
|
fast_clock_rate = 10
|
|
if fast_clock_rate is not None:
|
|
secs_in_fast_minute = int(1.0 / float(str(fast_clock_rate)) * 60.0)
|
|
label_info = JLabel("Calculates to the precision of 1 fast minute. " + str(secs_in_fast_minute) + " seconds = 1 fast minute")
|
|
else:
|
|
label_info = JLabel("Displays to the precision of 1 fast minute. Several seconds = 1 fast minute")
|
|
self.buttonPane.add(label_info)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
|
|
class CustomRenderer(TableCellRenderer):
|
|
global add_row_columns_displayed_gbl
|
|
def __init__(self, all_locations, all_actions):
|
|
self.all_locations = all_locations
|
|
self.all_actions = all_actions
|
|
|
|
def getTableCellRendererComponent(self, table, value, isSelected, hasFocus, row, column):
|
|
# Create JComboBox dynamically based on row
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if ".py" in value:
|
|
combo_box = JComboBox(self.all_actions)
|
|
else:
|
|
combo_box = JComboBox(self.all_locations)
|
|
combo_box.setSelectedItem(value) # Set the current value
|
|
if add_row_columns_displayed_gbl == True:
|
|
combo_box.setEditable(True) # Make it editable for consistency
|
|
else:
|
|
combo_box.setEditable(False)
|
|
return combo_box
|
|
|
|
def get_locations_list(self):
|
|
LocationsManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
locations_list = LocationsManager.getLocationsByNameList()
|
|
my_list = [loc.getName() for loc in locations_list]
|
|
return my_list
|
|
|
|
|
|
|
|
class CustomEditor(DefaultCellEditor):
|
|
global add_row_columns_displayed_gbl
|
|
global programmatic_update
|
|
|
|
def __init__(self, all_locations, all_actions, model, class_CreateAndShowGUI5):
|
|
super(DefaultCellEditor, self).__init__(JComboBox())
|
|
self.all_locations = all_locations
|
|
self.all_actions = all_actions
|
|
# print "self.all_actions", self.all_actions
|
|
self.model = model
|
|
self.class_CreateAndShowGUI5 = class_CreateAndShowGUI5
|
|
|
|
def getTableCellEditorComponent(self, table, value, isSelected, row, column):
|
|
# Create JComboBox dynamically based on row
|
|
if ".py" in value:
|
|
combo_box = JComboBox(self.all_actions)
|
|
else:
|
|
combo_box = JComboBox(self.all_locations)
|
|
if add_row_columns_displayed_gbl == True:
|
|
combo_box.setEditable(True) # Make it editable
|
|
else:
|
|
combo_box.setEditable(False)
|
|
# Define an action listener to capture changes
|
|
combo_box.addActionListener(self.ComboBoxListener(combo_box, self.model, row, column, self.class_CreateAndShowGUI5))
|
|
|
|
combo_box.setSelectedItem(value) # Set the current value in the jTable
|
|
self.model.setValueAt(value, row, column) # Set the value in the model
|
|
|
|
self.editorComponent = combo_box
|
|
return combo_box
|
|
|
|
def getCellEditorValue(self):
|
|
# Return the value of the editor (selected or entered value)
|
|
return self.editorComponent.getSelectedItem()
|
|
|
|
class ComboBoxListener(ActionListener):
|
|
def __init__(self, combo_box, model, row, column, class_CreateAndShowGUI5):
|
|
self.combo_box = combo_box
|
|
self.model = model
|
|
self.row = row
|
|
self.column = column
|
|
self.class_CreateAndShowGUI5 = class_CreateAndShowGUI5
|
|
|
|
def actionPerformed(self, event):
|
|
|
|
# get location to add
|
|
location_name = str(self.combo_box.getSelectedItem())
|
|
LocationManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
location = LocationManager.newLocation(location_name)
|
|
# get location to remove
|
|
if self.class_CreateAndShowGUI5.route is None:
|
|
OptionDialog().displayMessage("route has not been set up")
|
|
else:
|
|
routeLocation = self.class_CreateAndShowGUI5.route.getRouteLocationBySequenceNumber(self.row+1)
|
|
self.class_CreateAndShowGUI5.route.deleteLocation(routeLocation)
|
|
self.class_CreateAndShowGUI5.route.addLocation(location, self.row+1)
|
|
|
|
|
|
def setup_column_widths_and_comboboxes(self):
|
|
|
|
# setup widths of columns
|
|
|
|
columnModel = self.table.getColumnModel();
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
columnModel.getColumn(locations_col).setPreferredWidth(300)
|
|
columnModel.getColumn(stop_sensor_col).setPreferredWidth(120)
|
|
|
|
if self.journey_time_row_displayed == False:
|
|
columnModel.getColumn(journey_time_col).setMaxWidth(0)
|
|
columnModel.getColumn(journey_time_col).setMinWidth(0)
|
|
columnModel.getColumn(wait_time_col).setMaxWidth(0)
|
|
columnModel.getColumn(wait_time_col).setMinWidth(0)
|
|
|
|
if self.add_row_columns_displayed == False:
|
|
columnModel.getColumn(add_loc_col).setMaxWidth(0)
|
|
columnModel.getColumn(add_loc_col).setMinWidth(0)
|
|
columnModel.getColumn(add_action_col).setMaxWidth(0)
|
|
columnModel.getColumn(add_action_col).setMinWidth(0)
|
|
|
|
# setup dropdowns for stations and actions
|
|
|
|
self.stopSensorColumn = self.table.getColumnModel().getColumn(stop_sensor_col)
|
|
# self.stopSensorColumn.setPreferredWidth(100)
|
|
self.combobox0 = JComboBox()
|
|
self.required_items_to_put_in_dropdown = ["Use Default", "Use Stop Sensor", "Use Speed Profile"]
|
|
for mode in self.required_items_to_put_in_dropdown:
|
|
self.combobox0.addItem(mode)
|
|
self.stopSensorColumn.setCellEditor(DefaultCellEditor(self.combobox0));
|
|
|
|
# setup Editor and Renderer for comboboxes
|
|
|
|
self.locations_col = self.table.getColumnModel().getColumn(locations_col)
|
|
|
|
all_locations = [str(loc) for loc in self.get_locations_list() if not ".py" in loc]
|
|
all_actions = [loc for loc in self.get_locations_list() if ".py" in loc]
|
|
|
|
my_all_actions = self.all_actions()
|
|
|
|
self.renderer_locations = ComboBoxCellRenderer()
|
|
self.renderer_actions = ComboBoxCellRenderer()
|
|
|
|
if self.add_row_columns_displayed:
|
|
self.locations_col.setCellEditor(self.CustomEditor(all_locations, my_all_actions, self.model, self))
|
|
else:
|
|
self.locations_col.setCellEditor(DefaultCellEditor(JTextField()))
|
|
if self.add_row_columns_displayed:
|
|
self.locations_col.setCellRenderer(self.CustomRenderer(all_locations, my_all_actions))
|
|
else:
|
|
self.locations_col.setCellRenderer(DefaultTableCellRenderer())
|
|
|
|
return columnModel
|
|
|
|
def get_locations_list(self):
|
|
LocationsManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
locations_list = LocationsManager.getLocationsByNameList()
|
|
my_list = [loc.getName() for loc in locations_list]
|
|
|
|
return my_list
|
|
|
|
def all_actions(self):
|
|
directory1 = DispatchMaster().action_directory_in_DispatcherSystem()
|
|
files = os.listdir(directory1)
|
|
|
|
python_files = [f for f in files if f.endswith(".py")]
|
|
# print "python_files", python_files
|
|
directory = DispatchMaster().action_directory()
|
|
files = os.listdir(directory)
|
|
python_files2 = [f for f in files if f.endswith(".py")]
|
|
# print "python_files2", python_files2
|
|
python_files.extend(python_files2)
|
|
return python_files
|
|
|
|
def update_duration_action(self, e):
|
|
# model = e.getSource()
|
|
# we need to update the journey times (with existing values) so that the update can take place
|
|
# in the TableListener routines
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
for row in range(len(self.model.data)):
|
|
value = self.model.getValueAt(row, duration_col)
|
|
if value is not None:
|
|
self.model.setValueAt(str(value), row, duration_col)
|
|
self.completeTablePanel()
|
|
|
|
def update_journey_time_action(self, e):
|
|
global programmatic_update
|
|
# we need to update the journey times (with existing values) so that the update can take place
|
|
# in the TableListener routines
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
for row in range(len(self.model.data)):
|
|
value = self.model.getValueAt(row, journey_time_col)
|
|
if value is not None:
|
|
programmatic_update = False # so it updates!
|
|
self.model.setValueAt(value, row, journey_time_col)
|
|
|
|
def add_row_action(self, e):
|
|
columnModel = self.table.getColumnModel();
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
columnModel.getColumn(locations_col).setPreferredWidth(300)
|
|
|
|
# hide the action and station columns when required
|
|
|
|
if self.add_row_columns_displayed:
|
|
self.add_row_columns_displayed = False
|
|
columnModel.getColumn(add_loc_col).setMaxWidth(0)
|
|
columnModel.getColumn(add_loc_col).setMinWidth(0)
|
|
columnModel.getColumn(add_action_col).setMaxWidth(0)
|
|
columnModel.getColumn(add_action_col).setMinWidth(0)
|
|
else:
|
|
self.add_row_columns_displayed = True
|
|
columnModel.getColumn(add_loc_col).setMaxWidth(400)
|
|
columnModel.getColumn(add_loc_col).setMinWidth(100)
|
|
columnModel.getColumn(add_action_col).setMaxWidth(400)
|
|
columnModel.getColumn(add_action_col).setMinWidth(100)
|
|
self.completeTablePanel()
|
|
|
|
def get_station_list(self):
|
|
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
|
|
if self.route is None :
|
|
OptionDialog().displayMessage("route has not been filled in")
|
|
return []
|
|
else:
|
|
locations_list = self.route.getLocationsBySequenceList()
|
|
my_list = [[location.getName(), location.getComment()] for location in locations_list]
|
|
return my_list
|
|
|
|
def populate_action(self, event):
|
|
|
|
items_to_put_in_dropdown = self.get_station_list()
|
|
self.model.populate(items_to_put_in_dropdown)
|
|
self.completeTablePanel()
|
|
|
|
def close_action(self, event):
|
|
self.frame.dispatchEvent(WindowEvent(self.frame, WindowEvent.WINDOW_CLOSING));
|
|
|
|
def show_wait_action(self, event):
|
|
columnModel = self.table.getColumnModel();
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
columnModel.getColumn(locations_col).setPreferredWidth(300)
|
|
|
|
if self.journey_time_row_displayed:
|
|
self.journey_time_row_displayed = False
|
|
columnModel.getColumn(journey_time_col).setMaxWidth(0)
|
|
columnModel.getColumn(journey_time_col).setMinWidth(0)
|
|
columnModel.getColumn(wait_time_col).setMaxWidth(0)
|
|
columnModel.getColumn(wait_time_col).setMinWidth(0)
|
|
else:
|
|
self.journey_time_row_displayed = True
|
|
columnModel.getColumn(journey_time_col).setMaxWidth(400)
|
|
columnModel.getColumn(journey_time_col).setMinWidth(100)
|
|
columnModel.getColumn(wait_time_col).setMaxWidth(400)
|
|
columnModel.getColumn(wait_time_col).setMinWidth(100)
|
|
|
|
self.set_button_pane()
|
|
contentPane = self.frame.getContentPane()
|
|
contentPane.removeAll()
|
|
contentPane.add(self.topPanel, BorderLayout.CENTER)
|
|
contentPane.add(self.buttonPane, BorderLayout.PAGE_END)
|
|
self.completeTablePanel()
|
|
|
|
def new_delay(self, old_val):
|
|
if old_val < 3:
|
|
new_val = 3
|
|
elif old_val < 5:
|
|
new_val = 5
|
|
elif old_val < 10:
|
|
new_val = 10
|
|
elif old_val < 15:
|
|
new_val = 15
|
|
else:
|
|
new_val = 0
|
|
return new_val
|
|
|
|
def delete_all_action(self, event):
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
for row in reversed(range(len(self.model.data))):
|
|
self.model.data.pop(row)
|
|
self.completeTablePanel()
|
|
|
|
def new_val(self, old_val):
|
|
old_val = int(old_val)
|
|
if old_val == 0:
|
|
new_val = 2
|
|
elif old_val < 2:
|
|
new_val = 2
|
|
elif old_val < 3:
|
|
new_val = 3
|
|
elif old_val < 5:
|
|
new_val = 5
|
|
elif old_val < 10:
|
|
new_val = 10
|
|
else:
|
|
new_val = 0
|
|
return str(new_val)
|
|
|
|
def change_wait_time_action(self, event):
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if self.route is None : print "************ self.route is None A **********************"
|
|
routeLocationList = self.route.getLocationsBySequenceList()
|
|
|
|
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
index = 0
|
|
for row in reversed(range(len(self.model.data))):
|
|
if self.model.isCellEditable(row, wait_time_col): # only get the rows we want to change
|
|
if index == 0:
|
|
old_val = str(self.model.data[row][wait_time_col])
|
|
if old_val == "": old_val = "0"
|
|
new_val = self.new_val(old_val)
|
|
self.model.setValueAt(new_val,row,wait_time_col)
|
|
# save value in operations
|
|
routeLocation = routeLocationList[row]
|
|
self.set_value_in_comment(routeLocation, new_val, "wait_time")
|
|
else:
|
|
self.model.setValueAt(new_val,row,wait_time_col) # set all the .,mn\ wait times to the same value
|
|
|
|
self.completeTablePanel()
|
|
|
|
def new_task(self, old_val):
|
|
|
|
if old_val == "Once":
|
|
new_val = "duration every 20 mins"
|
|
elif old_val == "duration every 20 mins":
|
|
new_val = "duration every 30 mins"
|
|
elif old_val == "duration every 30 mins":
|
|
new_val = "duration every Hour"
|
|
elif old_val == "duration every Hour":
|
|
new_val = "duration every 2 Hours"
|
|
elif old_val == "duration every 2 Hours":
|
|
new_val = "Once"
|
|
else:
|
|
return "Once"
|
|
return new_val
|
|
|
|
|
|
def save_action(self, event):
|
|
self.save()
|
|
|
|
def save(self):
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
for row in reversed(range(len(self.model.data))):
|
|
locations_name = str(self.model.data[row][locations_col])
|
|
journey_time_name = str(self.model.data[row][journey_time_col])
|
|
wait_time_name = str(self.model.data[row][wait_time_col])
|
|
duration_sec_name = str(self.model.data[row][duration_sec_col])
|
|
duration_name = str(self.model.data[row][duration_col])
|
|
departure_time_name = str(self.model.data[row][departure_time_col])
|
|
add_loc_name = str(self.model.data[row][add_loc_col])
|
|
add_action_name = str(self.model.data[row][add_action_col])
|
|
delete_name = str(self.model.data[row][delete_col])
|
|
stop_sensor_name = str(self.model.data[row][stop_sensor_col])
|
|
if locations_name != "" :
|
|
self.save_location_row(row, locations_name, journey_time_name, wait_time_name, duration_sec_name, \
|
|
departure_time_name, add_loc_name, add_action_name, delete_name, stop_sensor_name)
|
|
else:
|
|
msg = "Cannot save row: " + str(row) + " train name, route or delay is not set"
|
|
OptionDialog().displayMessage(msg,"")
|
|
self.completeTablePanel()
|
|
if self.model.getRowCount() == 0:
|
|
self.frame.dispatchEvent(WindowEvent(self.frame, WindowEvent.WINDOW_CLOSING))
|
|
|
|
def save_location_row(self, row, locations_name, journey_time_name, wait_time_name, duration_sec_name, \
|
|
departure_time_name, add_loc_name, add_action_name, delete_name, stop_sensor_name):
|
|
if self.route is None : print "************ self.route is None K **********************"
|
|
routeLocationList = self.route.getLocationsBySequenceList()
|
|
routeLocation = routeLocationList[row]
|
|
|
|
self.set_value_in_comment(routeLocation, wait_time_name, "wait_time")
|
|
|
|
if journey_time_name != None and journey_time_name != "":
|
|
self.set_value_in_comment(routeLocation, journey_time_name, "journey_time")
|
|
else:
|
|
self.set_value_in_comment(routeLocation, duration_sec_name, "duration_sec")
|
|
|
|
def set_value_in_comment(self, routeLocation, value, duration_string):
|
|
|
|
comment = routeLocation.getComment() #Null
|
|
|
|
if comment == None:
|
|
comment = ""
|
|
|
|
delim_start = "[" + duration_string + "-"
|
|
delim_end = "-" + duration_string + "]"
|
|
|
|
comment = self.insert_between(comment, delim_start, delim_end, value)
|
|
|
|
routeLocation.setComment(comment)
|
|
|
|
def delete_between(self, string, delim1, delim):
|
|
first, _, rest = string.partition(delim1)
|
|
_, _, rest = rest.partition(delim2)
|
|
cleaned_text = ' '.join([first.strip(), rest.strip()])
|
|
return cleaned_text
|
|
|
|
def insert_between(self, string, delim1, delim2, value):
|
|
first, _, rest = string.partition(delim1)
|
|
_, _, rest = rest.partition(delim2)
|
|
|
|
new_val = delim1 + str(value) + delim2
|
|
modified_text = new_val.join([first.strip(), rest.strip()])
|
|
return modified_text
|
|
|
|
def directory(self):
|
|
path = jmri.util.FileUtil.getUserFilesPath() + "dispatcher" + java.io.File.separator + "schedules"
|
|
if not os.path.exists(path):
|
|
os.makedirs(path)
|
|
return path + java.io.File.separator
|
|
|
|
def write_list(self, a_list, file):
|
|
# store list in binary file so 'wb' mode
|
|
if self.logLevel > 0: print "block_info" , a_list
|
|
if self.logLevel > 0: print "file" , file
|
|
file = str(file)
|
|
with open(file, 'wb') as fp:
|
|
pass
|
|
if self.logLevel > 0: print "V"
|
|
with open(file, 'wb') as fp:
|
|
if self.logLevel > 0: print "B"
|
|
for items in a_list:
|
|
if self.logLevel > 0: print "C", items
|
|
i = 0
|
|
for item in items:
|
|
if self.logLevel > 0: print "item", item
|
|
fp.write('"%s"' %item)
|
|
if i != 4: fp.write(",")
|
|
i+=1
|
|
fp.write('\n')
|
|
#fp.write('\n'.join(item))
|
|
#fp.write(items)
|
|
|
|
# Read list to memory
|
|
def read_list(self, file):
|
|
file = str(file)
|
|
if self.logLevel > 0: print "read list", file
|
|
# for reading also binary mode is important
|
|
#file = self.directory() + "blockDirections.txt"
|
|
n_list = []
|
|
# try:
|
|
with open(file, 'rb') as fp:
|
|
for line in fp:
|
|
if self.logLevel > 0: print "line" , line
|
|
x = line[:-1]
|
|
if self.logLevel > 0: print x
|
|
y = x.split(",")
|
|
#y = [item.replace('"','') for item in y]
|
|
if self.logLevel > 0: print "y" , y
|
|
n_list.append(y)
|
|
|
|
return n_list
|
|
|
|
class MyModelListener5(TableModelListener):
|
|
|
|
def __init__(self, class_CreateAndShowGUI5, class_ResetButtonMaster):
|
|
global programmatic_update
|
|
self.class_CreateAndShowGUI5 = class_CreateAndShowGUI5
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
self.cancel = False
|
|
self.logLevel = 0
|
|
self.i = 0
|
|
programmatic_update = False
|
|
self.mode = "none"
|
|
|
|
def tableChanged(self, e):
|
|
self.i +=1
|
|
global programmatic_update
|
|
global trains_allocated
|
|
row = e.getFirstRow()
|
|
column = e.getColumn()
|
|
self.model = e.getSource()
|
|
columnName = self.model.getColumnName(column)
|
|
|
|
class_CreateAndShowGUI5 = self.class_CreateAndShowGUI5
|
|
class_ResetButtonMaster = self.class_ResetButtonMaster
|
|
tablemodel = class_CreateAndShowGUI5.model
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if self.model.route is None : print "************ self.model.route is None J **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.model.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
if row in routelocations_rows_list:
|
|
if column == duration_sec_col:
|
|
# print "updating duration_sec_col", self.mode
|
|
|
|
# print "PROGRAMMATIC UPDATE", programmatic_update
|
|
# print "self.mode", self.mode
|
|
|
|
self.save_value_to_operations(row, duration_sec_col)
|
|
|
|
mode_on_entry = programmatic_update
|
|
if self.mode == "forwards" or programmatic_update == False:
|
|
programmatic_update == True
|
|
self.mode = "forwards"
|
|
# print "calculate_duration_from_duration_sec forwards"
|
|
# update duration
|
|
if row != self.model.find_row_first_location():
|
|
duration = str(self.calc_duration_from_duration_sec(row))
|
|
self.model.setValueAt(duration, row, duration_col)
|
|
# update departure time
|
|
if row != self.model.find_row_first_location():
|
|
departure = self.calc_departure_time(row)
|
|
self.setValueAt_programmatically(departure, row, departure_time_col)
|
|
programmatic_update == False
|
|
|
|
elif self.mode == "backwards" or programmatic_update == False:
|
|
# calculate journey time from wait time and duration_sec
|
|
programmatic_update == True
|
|
self.mode = "backwards"
|
|
if row != self.model.find_row_first_location():
|
|
# print "backwards calculate_journey_time_from_duration_sec_and_wait_time"
|
|
journey_time = self.calculate_journey_time_from_duration_sec_and_wait_time(row)
|
|
# print "journey time", journey_time
|
|
self.setValueAt_programmatically(journey_time, row, journey_time_col)
|
|
self.save_value_to_operations(row, journey_time_col)
|
|
programmatic_update == False
|
|
|
|
# update subsequent rows if user updates
|
|
if mode_on_entry == False:
|
|
self.update_subsequent_rows(row)
|
|
|
|
elif column == duration_col: #trains
|
|
# print
|
|
# print "we have updated duration_col mode =", self.mode
|
|
# 1) Calculate the duration in secs (from fast minutes
|
|
if self.mode == "backwards":
|
|
duration_sec = self.calc_duration_sec_from_duration(row)
|
|
# print "updating duration_sec", duration_sec
|
|
existing_val = self.model.getValueAt(row, duration_sec_col)
|
|
if existing_val != duration_sec:
|
|
self.setValueAt_programmatically(duration_sec, row, duration_sec_col)
|
|
self.save_value_to_operations(row, duration_sec_col)
|
|
|
|
elif column == departure_time_col: # sections
|
|
# print "departure_time_col set mode backwards", "programmatic_update", programmatic_update
|
|
|
|
# update subsequent rows only if first row
|
|
if row == self.model.find_row_first_location():
|
|
self.update_subsequent_rows(row)
|
|
return
|
|
|
|
# if we are calculating from duration_sec we have set programmatic_update to true
|
|
if programmatic_update == True:
|
|
# update subsequent rows
|
|
self.update_subsequent_rows(row)
|
|
return
|
|
|
|
# only done if user updates
|
|
self.mode = "backwards"
|
|
# when departure is clicked
|
|
# a) calculate the relevant duration
|
|
if row != self.model.find_row_first_location():
|
|
duration = self.calculate_duration_from_current_and_prev_departure_times(row)
|
|
# print "duration", duration
|
|
current_duration = self.model.getValueAt(row, duration_col)
|
|
# print "current_duration", current_duration, "duration", duration
|
|
if duration != current_duration:
|
|
self.model.setValueAt(duration, row, duration_col)
|
|
|
|
# update subsequent rows
|
|
self.update_subsequent_rows(row)
|
|
|
|
# elif column == delete_col:
|
|
# done below so can delete actions
|
|
elif column == journey_time_col or column == wait_time_col:
|
|
|
|
if programmatic_update == True: return
|
|
|
|
# only done if user updates
|
|
# print "journey_time_col set mode forwards"
|
|
self.mode = "forwards"
|
|
if row != self.model.find_row_first_location():
|
|
my_duration = self.calc_duration_sec_from_journey_time_and_wait_time(row)
|
|
self.model.setValueAt(my_duration, row, duration_sec_col)
|
|
# print "set value"
|
|
|
|
self.save_value_to_operations(row, journey_time_col)
|
|
self.save_value_to_operations(row, wait_time_col)
|
|
self.save_value_to_operations(row, duration_sec_col)
|
|
|
|
# update subsequent rows
|
|
self.update_subsequent_rows(row)
|
|
|
|
elif column == stop_sensor_col:
|
|
self.save_value_to_operations(row, stop_sensor_col)
|
|
|
|
# done here so can deal with action rows
|
|
if column == delete_col:
|
|
listener = self
|
|
self.model.removeTableModelListener(listener)
|
|
routelocation = class_CreateAndShowGUI5.route.getRouteLocationBySequenceNumber(row+1)
|
|
class_CreateAndShowGUI5.route.deleteLocation(routelocation)
|
|
self.delete_row(row)
|
|
class_CreateAndShowGUI5.completeTablePanel()
|
|
time.sleep(0.2)
|
|
self.model.addTableModelListener(listener)
|
|
|
|
elif column == add_loc_col:
|
|
#reset check box
|
|
listener = self
|
|
self.model.removeTableModelListener(listener)
|
|
self.model.setValueAt(False, row, column)
|
|
|
|
|
|
# add the station after the selected row
|
|
location_string = self.model.add_loc_at(row)
|
|
LocationManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
location = LocationManager.newLocation(location_string)
|
|
routeLocation = class_CreateAndShowGUI5.route.addLocation(location, row+2)
|
|
|
|
# self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, "0", "duration_sec")
|
|
# self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, "-", "stopMode")
|
|
class_CreateAndShowGUI5.completeTablePanel()
|
|
time.sleep(0.2)
|
|
self.model.addTableModelListener(listener)
|
|
return
|
|
|
|
elif column == add_action_col:
|
|
#reset check box
|
|
listener = self
|
|
self.model.removeTableModelListener(listener)
|
|
self.model.setValueAt(False, row, column)
|
|
|
|
# add the action after the selected row
|
|
location_string = self.model.add_action_at(row)
|
|
LocationManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
location = LocationManager.newLocation(location_string)
|
|
class_CreateAndShowGUI5.route.addLocation(location, row+2)
|
|
class_CreateAndShowGUI5.completeTablePanel()
|
|
time.sleep(0.2)
|
|
self.model.addTableModelListener(listener)
|
|
return
|
|
|
|
# elif column == locations_col:
|
|
# # the change is done in a combo box, so we do the work in the combo box listener
|
|
|
|
class_CreateAndShowGUI5.save() # save everything when the table is changed
|
|
|
|
def update_subsequent_rows(self, current_row):
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
global programmatic_update
|
|
|
|
# calculates forwards and backwards if programmatic_update False (see tableChanged duration_sec_col)
|
|
programmatic_update = False
|
|
if self.model.route is None : print "************ self.model.route is None H **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.model.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
|
|
for row in routelocations_rows_list:
|
|
if row > current_row:
|
|
# trigger the update command by touching the element
|
|
value = self.model.getValueAt(row, duration_sec_col)
|
|
self.model.setValueAt(value, row, duration_sec_col)
|
|
break
|
|
|
|
def save_value_to_operations(self, row, col):
|
|
value = self.model.getValueAt(row, col)
|
|
if self.model.route is None :
|
|
print "************ self.model.route is None I **********************"
|
|
return
|
|
# get routeLocation
|
|
routeLocationList = self.model.route.getLocationsBySequenceList()
|
|
routeLocation = routeLocationList[row]
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
|
|
if col == journey_time_col:
|
|
self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, value, "journey_time")
|
|
|
|
if col == wait_time_col:
|
|
self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, value, "wait_time")
|
|
|
|
if col == duration_sec_col:
|
|
self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, value, "duration_sec")
|
|
|
|
if col == stop_sensor_col:
|
|
self.class_CreateAndShowGUI5.set_value_in_comment(routeLocation, value, "stopMode")
|
|
|
|
|
|
def setValueAt_programmatically(self, value, row, col) :
|
|
global programmatic_update
|
|
programmatic_update = True # inhibit triggering further updates
|
|
self.model.setValueAt(value, row, col)
|
|
programmatic_update = False
|
|
|
|
|
|
|
|
def update_departure_time_col(self, current_row):
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if self.model.route is None : print "************ self.model.route is None H **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.model.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
|
|
for row in routelocations_rows_list:
|
|
if row > current_row:
|
|
# trigger the update command by touching the element
|
|
value = self.model.getValueAt(row, departure_time_col)
|
|
self.model.setValueAt(value, row, departure_time_col)
|
|
break
|
|
|
|
def update_duration_sec_col(self, current_row):
|
|
# print "update_duration_sec_col"
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if self.model.route is None : print "************ self.model.route is None H **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.model.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
|
|
for row in routelocations_rows_list:
|
|
if row > current_row:
|
|
# trigger the update command by touching the element
|
|
value = self.model.getValueAt(row, duration_sec_col)
|
|
self.model.setValueAt(value, row, duration_sec_col)
|
|
break
|
|
|
|
def calculate_duration_from_current_and_prev_departure_times(self, row):
|
|
# calculate duration from current and previous departure times
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_departure_time = self.model.getValueAt(row, departure_time_col)
|
|
prev_row = self.model.find_row_prev_location(row)
|
|
if prev_row == None:
|
|
return
|
|
previous_departure_time = self.model.getValueAt(prev_row, departure_time_col)
|
|
# time and prev_time are in HH:MM
|
|
hh, _, mm = current_departure_time.partition(":")
|
|
hhprev, _, mmprev = previous_departure_time.partition(":")
|
|
# print "mmprev", mmprev, "mm", mm
|
|
duration = int(hh) * 60 - int(hhprev) * 60 + int(mm) - int(mmprev)
|
|
return str(duration)
|
|
|
|
def calc_departure_time(self, row):
|
|
# calculate departure time from duration and prev departure time
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_duration = self.model.getValueAt(row, duration_col)
|
|
prev_row = self.model.find_row_prev_location(row)
|
|
if prev_row == None:
|
|
return
|
|
previous_departure_time = self.model.getValueAt(prev_row, departure_time_col)
|
|
hhprev, _, mmprev = previous_departure_time.partition(":")
|
|
departure_time_mins = str((int(mmprev) + int(float(current_duration))) % 60).zfill(2)
|
|
departure_time_hours = str(int(hhprev) + (int(mmprev) + int(float(current_duration))) // 60).zfill(2)
|
|
departure_time = departure_time_hours + ":" + departure_time_mins
|
|
return departure_time
|
|
|
|
def calc_duration_sec_from_duration(self, row):
|
|
global fast_clock_rate
|
|
global scheduler_master
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
|
|
try:
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_duration = str(int(self.model.getValueAt(row, duration_col))) # secs
|
|
# set fast clock rate
|
|
if "fast_clock_rate" not in globals():
|
|
[start_hour_gbl, end_hour_gbl, fast_clock_rate, speed_not_operational_gbl, \
|
|
scheduling_margin_gbl, scheduling_in_operation_gbl] = scheduler_master.read_list()
|
|
# convert to fast_minutes
|
|
current_duration_sec = (float(current_duration) / float(str(fast_clock_rate))) * 60.0 # fast minutes
|
|
# print "calc_duration_sec_from_duration", "current_duration_sec", current_duration_sec, "current_duration", current_duration
|
|
except:
|
|
# use the existing value
|
|
current_duration_sec = self.model.getValueAt(row, duration_sec_col)
|
|
return str(int(float(current_duration_sec)))
|
|
|
|
|
|
def calc_duration_sec_from_journey_time_and_wait_time(self, row):
|
|
global fast_clock_rate
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
|
|
try:
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_journey_time = int(self.model.getValueAt(row, journey_time_col)) # secs
|
|
current_wait_time = int(self.model.getValueAt(row, wait_time_col)) # secs
|
|
|
|
current_duration_sec = current_journey_time + current_wait_time
|
|
# round up to the next multiple of current_duration_sec
|
|
secs_in_fast_minute = int(1.0 / float(str(fast_clock_rate)) * 60.0)
|
|
current_duration_sec1 = (current_duration_sec // secs_in_fast_minute) * secs_in_fast_minute
|
|
# print ("current_journey_time", current_journey_time, "current_wait_time", current_wait_time, \
|
|
# "secs_in_fast_minute", secs_in_fast_minute, "current_duration_sec1", current_duration_sec1, "current_duration_sec", current_duration_sec)
|
|
if current_duration_sec1 != current_duration_sec:
|
|
current_duration_sec = current_duration_sec1 + secs_in_fast_minute
|
|
except:
|
|
# use the existing value
|
|
current_duration_sec = self.model.getValueAt(row, duration_sec_col)
|
|
return str(int(current_duration_sec))
|
|
|
|
def calculate_journey_time_from_duration_sec_and_wait_time(self, row):
|
|
global fast_clock_rate
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
|
|
try:
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_duration_sec = int(self.model.getValueAt(row, duration_sec_col)) # secs
|
|
current_wait_time = int(self.model.getValueAt(row, wait_time_col)) # secs
|
|
|
|
current_journey_time = current_duration_sec - current_wait_time
|
|
|
|
except:
|
|
# use the existing value
|
|
current_duration_sec = self.model.getValueAt(row, duration_sec_col)
|
|
return str(int(current_journey_time))
|
|
|
|
def calc_duration_from_duration_sec(self,row):
|
|
global fast_clock_rate
|
|
|
|
try:
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_duration_sec = self.model.getValueAt(row, duration_sec_col) # secs
|
|
|
|
# convert to fast_minutes
|
|
current_duration = (float(current_duration_sec) * int(str(fast_clock_rate))) / 60.0 # fast minutes
|
|
except:
|
|
# use the existing value
|
|
current_duration = self.model.getValueAt(row, duration_col)
|
|
return str(int(current_duration))
|
|
|
|
|
|
def calc_duration_from_journey_time_and_wait_time(self, row):
|
|
|
|
global fast_clock_rate
|
|
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
|
|
try:
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
current_journey_time = int(self.model.getValueAt(row, journey_time_col)) # secs
|
|
current_wait_time = int(self.model.getValueAt(row, wait_time_col)) # secs
|
|
|
|
# convert to fast_minutes
|
|
current_journey_time = (current_journey_time * int(str(fast_clock_rate))) / 60.0 # fast minutes
|
|
current_wait_time = (current_wait_time * int(str(fast_clock_rate)))/ 60.0 # fast minutes
|
|
|
|
current_duration = current_journey_time + current_wait_time
|
|
except:
|
|
# use the existing value
|
|
current_duration = self.model.getValueAt(row, duration_col)
|
|
return str(int(current_duration))
|
|
|
|
|
|
def delete_row(self, row):
|
|
self.model.data.pop(row)
|
|
|
|
class ComboBoxCellRenderer (TableCellRenderer):
|
|
|
|
def getTableCellRendererComponent(self, jtable, value, isSelected, hasFocus, row, column) :
|
|
panel = self.createPanel(value)
|
|
return panel
|
|
|
|
def createPanel(self, s) :
|
|
p = JPanel(BorderLayout())
|
|
p.add(JLabel(str(s), JLabel.LEFT), BorderLayout.WEST)
|
|
icon = UIManager.getIcon("Table.descendingSortIcon");
|
|
p.add(JLabel(icon, JLabel.RIGHT), BorderLayout.EAST);
|
|
p.setBorder(BorderFactory.createLineBorder(Color.blue));
|
|
return p;
|
|
|
|
class MyTableModel5 (DefaultTableModel):
|
|
|
|
columnNames = ["Station / Action", "Journey Time", "Wait Time", "Duration (secs)", "Duration (f mins)", "Departure Time", "Add Station", "Add Action","Delete Row", "Use of Stop Sensor"]
|
|
|
|
def __init__(self):
|
|
l1 = ["", "", False, "stop at end of route", "0.0", "0.0", False, False, False, "-"]
|
|
self.data = [l1]
|
|
self.route = None # updated from outside class
|
|
|
|
def remove_not_set_row(self):
|
|
b = False
|
|
for row in reversed(range(len(self.data))):
|
|
if self.data[row][1] == "":
|
|
self.data.pop(row)
|
|
|
|
def add_loc_at(self, row_index):
|
|
location = [str(loc) for loc in self.get_locations_list() if ".py" not in loc][0]
|
|
row_data = [location, "0", "0", "0","0", "00:00", False, False, False, "-"]
|
|
self.data.insert(row_index+1, row_data)
|
|
return location
|
|
|
|
def add_action_at(self, row_index):
|
|
action = self.all_actions()[0]
|
|
row_data = [action, "", "", "","", "", False, False, False, "-"]
|
|
self.data.insert(row_index+1, row_data)
|
|
return action
|
|
|
|
def get_locations_list(self):
|
|
LocationsManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.locations.LocationManager)
|
|
locations_list = LocationsManager.getLocationsByNameList()
|
|
my_list = [loc.getName() for loc in locations_list]
|
|
|
|
return my_list
|
|
|
|
def all_actions(self):
|
|
directory1 = DispatchMaster().action_directory_in_DispatcherSystem()
|
|
files = os.listdir(directory1)
|
|
# print "files in dispatcher system action directory", files
|
|
|
|
python_files = [f for f in files if f.endswith(".py")]
|
|
# print "directory1", directory1, "python_files", python_files
|
|
|
|
directory = DispatchMaster().action_directory()
|
|
files = os.listdir(directory)
|
|
python_files2 = [f for f in files if f.endswith(".py")]
|
|
# print "directory", directory, "python_files2", python_files2
|
|
python_files.extend(python_files2)
|
|
return python_files
|
|
|
|
|
|
def populate(self, items_to_put_in_dropdown):
|
|
# print "populate"
|
|
global scheduled_start
|
|
global programmatic_update
|
|
for row in reversed(range(len(self.data))):
|
|
self.data.pop(row)
|
|
# append all trains to put in dropdown
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
duration_sec_array = []
|
|
i = 0
|
|
for [location, comment] in items_to_put_in_dropdown:
|
|
if ".py" not in location: # omit actions
|
|
journey_time = self.find_between(comment, "[journey_time-", "-journey_time]")
|
|
if i == 0:
|
|
if journey_time == "": journey_time = ""
|
|
else:
|
|
if journey_time == "": journey_time = "0"
|
|
|
|
# get default wait time
|
|
memory = memories.getMemory("IM:" + "DS_wait_time")
|
|
# print "memory value" , memory.getValue()
|
|
if memory is None or memory.getValue() == "" or memory.getValue() is None:
|
|
memory = memories.provideMemory("IM:" + "DS_wait_time")
|
|
memory.setValue(3)
|
|
default = memory.getValue()
|
|
|
|
wait_time = self.find_between(comment, "[wait_time-", "-wait_time]")
|
|
# print "wait_time", wait_time
|
|
if i == 0:
|
|
if wait_time == "" or wait_time is "None" : wait_time = ""
|
|
else:
|
|
if wait_time == "" or "None" in wait_time : wait_time = str(default)
|
|
# print "set to default"
|
|
|
|
duration_sec = str(self.find_between(comment, "[duration_sec-", "-duration_sec]"))
|
|
|
|
if i == 0:
|
|
if duration_sec == "0": duration_sec = ""
|
|
else:
|
|
if duration_sec == "": duration_sec = "0"
|
|
|
|
duration_sec_array.append(duration_sec)
|
|
|
|
departure_time = "00:00"
|
|
duration = "0"
|
|
|
|
stop_at_stop_sensor = self.get_route_location_stop_mode(location)
|
|
else:
|
|
journey_time = None
|
|
departure_time = None
|
|
duration_sec = None
|
|
duration = None
|
|
wait_time = None
|
|
duration_sec_array.append(duration_sec)
|
|
stop_at_stop_sensor = None
|
|
i += 1
|
|
programmatic_update = True
|
|
self.data.append([location, journey_time, wait_time, duration_sec, duration, departure_time, False, False, False, stop_at_stop_sensor])
|
|
programmatic_update = False
|
|
|
|
# update the first location which is a station with the time of the schedule start
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
row = self.find_row_first_location()
|
|
if scheduled_start is not None:
|
|
self.setValueAt(scheduled_start, row, departure_time_col)
|
|
|
|
# # do the following after updating the first location so the departure times are calculated correctly
|
|
# i = 0
|
|
# for [location, comment] in items_to_put_in_dropdown:
|
|
# if ".py" not in location: # omit actions
|
|
# self.setValueAt(duration_sec_array[i], i, duration_sec_col)
|
|
# i += 1
|
|
|
|
def get_route_location_stop_mode(self, station_to_name):
|
|
route_location = self.route.getLastLocationByName(station_to_name)
|
|
comment = route_location.getComment()
|
|
stop_mode = self.find_between(comment, "[stopMode-", "-stopMode]")
|
|
return stop_mode
|
|
|
|
def find_row_first_location(self):
|
|
if self.route is None : print "************ self.route is None G **********************"
|
|
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
first_loc_sequence_no = routelocationsSequenceNumber_list[0][1]
|
|
route_location = routelocationsSequenceNumber_list[0][0]
|
|
|
|
row = first_loc_sequence_no - 1
|
|
return row # row number starts from 0
|
|
|
|
def find_row_next_location(self, row):
|
|
# given the row (rows start at 0, sequencenos start at 1) of a location that is not an action (a python file xx.py)
|
|
# find the next row of a location that is not an action
|
|
if self.route is None : print "************ self.route is None F **********************"
|
|
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
|
|
current_val = [[routelocation, sequenceNo] \
|
|
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
|
|
if row == sequenceNo - 1][0]
|
|
|
|
current_index = routelocationsSequenceNumber_list.index(current_val) # starts at 0
|
|
# try:
|
|
if len(routelocationsSequenceNumber_list) > current_index + 1: # len starts at 1
|
|
[routelocation, sequenceNo] = routelocationsSequenceNumber_list[current_index + 1]
|
|
else:
|
|
[routelocation, sequenceNo] = routelocationsSequenceNumber_list[current_index]
|
|
row1 = sequenceNo - 1
|
|
if row == row1:
|
|
return None
|
|
return row1 # row number starts from 0
|
|
|
|
def find_row_prev_location(self, row):
|
|
# get the row (sequenceNo) of the first location that is not an action (a python file xx.py)
|
|
if self.route is None : print "************ self.route is None E **********************"
|
|
routelocationsSequenceNumber_list = [ [routelocation, routelocation.getSequenceNumber()] \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
current_val = [[routelocation, sequenceNo] \
|
|
for [routelocation, sequenceNo] in routelocationsSequenceNumber_list \
|
|
if row == sequenceNo - 1][0]
|
|
current_index = routelocationsSequenceNumber_list.index(current_val) # starts at 0
|
|
if current_index > 0: #index starts at 0
|
|
[routelocation, sequenceNo] = routelocationsSequenceNumber_list[current_index - 1]
|
|
else:
|
|
[routelocation, sequenceNo] = routelocationsSequenceNumber_list[current_index]
|
|
row1 = sequenceNo - 1
|
|
if row == row1:
|
|
return None
|
|
return row1 # row number starts from 0
|
|
|
|
def find_between(self, s, first, last):
|
|
try:
|
|
start = s.index(first) + len(first)
|
|
end = s.index(last, start)
|
|
return s[start:end]
|
|
except Exception as e:
|
|
return ""
|
|
|
|
def getColumnCount(self) :
|
|
return len(self.columnNames)
|
|
|
|
|
|
def getRowCount(self) :
|
|
return len(self.data)
|
|
|
|
def getColumnName(self, col) :
|
|
return self.columnNames[col]
|
|
|
|
def getValueAt(self, row, col) :
|
|
return self.data[row][col]
|
|
|
|
def getColumnClass(self, col) :
|
|
return java.lang.Boolean.getClass(self.getValueAt(0,col))
|
|
|
|
#only include if table editable
|
|
def isCellEditable(self, row, col) :
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
# do not allow editing of duration in action cols
|
|
if self.route is None : print "************ self.route is None D **********************"
|
|
routelocations_rows_list = [routelocation.getSequenceNumber()-1 \
|
|
for routelocation in self.route.getLocationsBySequenceList() \
|
|
if ".py" not in routelocation.getName()]
|
|
if row not in routelocations_rows_list:
|
|
if col == duration_sec_col or col == duration_col or col == departure_time_col or col == wait_time_col or col == journey_time_col:
|
|
return False
|
|
if row == self.find_row_first_location():
|
|
if col == duration_sec_col or col == duration_col or col == departure_time_col or col == wait_time_col or col == journey_time_col:
|
|
return False
|
|
stop_sensor_present_list = [row1 for row1 in routelocations_rows_list
|
|
if row1 > self.find_row_first_location()
|
|
if self.stop_sensor_present(row1,
|
|
self.getValueAt(self.find_row_prev_location(row1), locations_col),
|
|
self.getValueAt(row1, locations_col)) == True]
|
|
if col == stop_sensor_col:
|
|
if row not in stop_sensor_present_list:
|
|
return False
|
|
|
|
if col == duration_col:
|
|
return False
|
|
return True
|
|
|
|
def stop_sensor_present(self, row, prev_station, last_station):
|
|
global g
|
|
# it is too difficult to determine whether a stop sensor is present
|
|
# (maybe later: would have to determine the last section of the last transit joining the previous and current locations)
|
|
# (and we wanted to determine this to see whether we could modify the stop sensor column cell)
|
|
# so we are going to determine whether we have set the use of a stop sensor in the past
|
|
# the
|
|
if row <= 0:
|
|
return False
|
|
if prev_station is None:
|
|
# print "prev_station is None"
|
|
return False
|
|
if last_station is None:
|
|
# print "last_station is None"
|
|
return False
|
|
if prev_station == last_station:
|
|
# print "prev_station == last_station"
|
|
return False
|
|
DM = DispatchMaster()
|
|
if g.g_express.containsVertex(prev_station) and g.g_express.containsVertex(last_station):
|
|
transit_name = DM.get_transit_name(prev_station, last_station)
|
|
else:
|
|
OptionDialog().displayMessage("You have an old route with a station that does not exist. \n Delete the old station!!\n\n" +\
|
|
"Either " + prev_station + " or " + last_station + "\n\n" + \
|
|
"You may have to close this panel repeatedly if there are several instances of old stations \n" + \
|
|
"in the route")
|
|
return False
|
|
if DM.forward_stopping_sensor_exists(transit_name):
|
|
return True
|
|
|
|
|
|
return False
|
|
|
|
# only include if data can change.
|
|
def setValueAt(self, value, row, col) :
|
|
[locations_col, journey_time_col, wait_time_col, duration_sec_col, duration_col, departure_time_col, add_loc_col, add_action_col, delete_col, stop_sensor_col] = [0, 1, 2, 3, 4, 5, 6, 7,8,9]
|
|
if col == departure_time_col:
|
|
if not self.isValidTimeFormat(value):
|
|
return
|
|
if col == duration_col or col == journey_time_col or col == wait_time_col:
|
|
if value == None:
|
|
return
|
|
try:
|
|
float(value)
|
|
except:
|
|
return
|
|
|
|
self.data[row][col] = value
|
|
self.fireTableCellUpdated(row, col)
|
|
|
|
def isValidTimeFormat(self, input_string):
|
|
import re
|
|
pattern = r"^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$" # Matches HH.MM format
|
|
my_match = re.match(pattern, input_string) is not None
|
|
return my_match
|