877 lines
35 KiB
Python
877 lines
35 KiB
Python
from json.decoder import WHITESPACE
|
|
|
|
from javax.swing import JTable, JScrollPane, JFrame, JPanel, JComboBox, BorderFactory, DefaultCellEditor, JLabel, UIManager, SwingConstants, JFileChooser
|
|
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
|
|
import jmri
|
|
|
|
class CreateAndShowGUI4(TableModelListener):
|
|
|
|
def __init__(self, class_ResetButtonMaster):
|
|
global CreateAndShowGUI4_frame
|
|
self.logLevel = 0
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
#Create and set up the window.
|
|
|
|
self.initialise_model(class_ResetButtonMaster)
|
|
CreateAndShowGUI4_frame = JFrame("Scheduled Trains")
|
|
self.frame = CreateAndShowGUI4_frame
|
|
self.frame.setSize(600, 600);
|
|
|
|
|
|
|
|
self.completeTablePanel1()
|
|
# print "about to populate"
|
|
self.populate_action(None)
|
|
self.cancel = False
|
|
|
|
def completeTablePanel1(self):
|
|
|
|
self.topPanel= JPanel();
|
|
self.topPanel.setLayout(BoxLayout(self.topPanel, BoxLayout.X_AXIS))
|
|
self.self_table()
|
|
|
|
self.scrollPane = JScrollPane(self.table);
|
|
self.scrollPane.setPreferredSize(Dimension(600,600))
|
|
|
|
self.topPanel.add(self.scrollPane);
|
|
|
|
self.buttonPane = JPanel();
|
|
self.buttonPane.setLayout(BoxLayout(self.buttonPane, BoxLayout.LINE_AXIS))
|
|
self.buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10))
|
|
|
|
button_add = JButton("Add", actionPerformed = self.add_row_action)
|
|
self.buttonPane.add(button_add);
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
|
|
# button_populate = JButton("Populate", actionPerformed = self.populate_action)
|
|
# self.buttonPane.add(button_populate);
|
|
# self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
|
|
# button_tidy = JButton("Tidy", actionPerformed = self.tidy_action)
|
|
# self.buttonPane.add(button_tidy);
|
|
# self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
#
|
|
# button_apply = JButton("Save", actionPerformed = self.save_action)
|
|
# self.buttonPane.add(button_apply)
|
|
# self.buttonPane.add(Box.createHorizontalGlue());
|
|
|
|
button_close = JButton("Save & Close", actionPerformed = self.close_action)
|
|
self.buttonPane.add(button_close)
|
|
self.buttonPane.add(Box.createHorizontalGlue());
|
|
|
|
button_task = JButton("Repeat", actionPerformed = self.task_action)
|
|
self.buttonPane.add(button_task)
|
|
self.buttonPane.add(Box.createHorizontalGlue());
|
|
|
|
# button_task = JButton("Delay", actionPerformed = self.delay_action)
|
|
# self.buttonPane.add(button_task)
|
|
# self.buttonPane.add(Box.createHorizontalGlue());
|
|
|
|
button_delete = JButton("Delete All Rows", actionPerformed = self.delete_all_action)
|
|
self.buttonPane.add(button_delete)
|
|
self.buttonPane.add(Box.createHorizontalGlue());
|
|
|
|
button_savetofile = JButton("Save To File", actionPerformed = self.savetofile_action)
|
|
self.buttonPane.add(button_savetofile)
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
|
|
button_loadfromfile = JButton("Load From File", actionPerformed = self.loadfromfile_action)
|
|
self.buttonPane.add(button_loadfromfile)
|
|
self.buttonPane.add(Box.createRigidArea(Dimension(10, 0)))
|
|
|
|
button_deletesavedfile = JButton("Delete Saved Files", actionPerformed = self.deletesavedfile_action)
|
|
self.buttonPane.add(button_deletesavedfile)
|
|
self.buttonPane.add(Box.createHorizontalGlue())
|
|
|
|
contentPane = self.frame.getContentPane()
|
|
|
|
contentPane.removeAll()
|
|
contentPane.add(self.topPanel, BorderLayout.CENTER)
|
|
contentPane.add(self.buttonPane, BorderLayout.PAGE_END)
|
|
|
|
self.frame.pack();
|
|
self.frame.setVisible(True)
|
|
return
|
|
|
|
def completeTablePanel(self):
|
|
# self.self_table()
|
|
|
|
contentPane = self.frame.getContentPane()
|
|
|
|
contentPane.removeAll()
|
|
contentPane.add(self.topPanel, BorderLayout.CENTER)
|
|
contentPane.add(self.buttonPane, BorderLayout.PAGE_END)
|
|
size_of_one_row = 30
|
|
height = 50
|
|
for row in reversed(range(len(self.model.data))):
|
|
height += size_of_one_row
|
|
height = min(height, 800)
|
|
self.scrollPane.setPreferredSize(Dimension(1000,height))
|
|
|
|
self.frame.pack();
|
|
self.frame.setVisible(True)
|
|
return
|
|
|
|
def buttonPanel(self):
|
|
row1_1_button = JButton("Add Row", actionPerformed = self.add_row_action)
|
|
# row1_2_button = JButton("Save", actionPerformed = self.save_action)
|
|
|
|
row1 = JPanel()
|
|
row1.setLayout(BoxLayout(row1, BoxLayout.X_AXIS))
|
|
|
|
row1.add(Box.createVerticalGlue())
|
|
row1.add(Box.createRigidArea(Dimension(20, 0)))
|
|
row1.add(row1_1_button)
|
|
row1.add(Box.createRigidArea(Dimension(20, 0)))
|
|
row1.add(row1_2_button)
|
|
|
|
layout = BorderLayout()
|
|
# layout.setHgap(10);
|
|
# layout.setVgap(10);
|
|
|
|
jPanel = JPanel()
|
|
jPanel.setLayout(layout);
|
|
jPanel.add(self.table,BorderLayout.NORTH)
|
|
jPanel.add(row1,BorderLayout.SOUTH)
|
|
|
|
#return jPanel
|
|
return topPanel
|
|
|
|
def initialise_model(self, class_ResetButtonMaster):
|
|
|
|
self.model = None
|
|
self.model = MyTableModel4()
|
|
self.table = JTable(self.model)
|
|
self.model.addTableModelListener(MyModelListener4(self, class_ResetButtonMaster));
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
|
|
|
|
pass
|
|
def self_table(self):
|
|
|
|
self.table.setPreferredScrollableViewportSize(Dimension(1000, 300));
|
|
#table.setFillsViewportHeight(True)
|
|
#self.table.getModel().addtableModelListener(self)
|
|
self.table.setFillsViewportHeight(True);
|
|
self.table.setRowHeight(30);
|
|
#table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
|
|
# self.resizeColumnWidth(table)
|
|
columnModel = self.table.getColumnModel();
|
|
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
columnModel.getColumn(route_col).setPreferredWidth(300);
|
|
columnModel.getColumn(repeat_col).setPreferredWidth(210);
|
|
columnModel.getColumn(dont_schedule_col).setPreferredWidth(150);
|
|
columnModel.getColumn(train_name_col).setMinWidth(0); # train_name is unique identifier which can be hidden from user
|
|
columnModel.getColumn(train_name_col).setMaxWidth(0); # train_name is unique identifier which can be hidden from user
|
|
columnModel.getColumn(train_description_col).setPreferredWidth(300);
|
|
columnModel.getColumn(edit_col).setPreferredWidth(100);
|
|
columnModel.getColumn(delete_col).setPreferredWidth(100);
|
|
|
|
# routes column
|
|
|
|
self.routesColumn = self.table.getColumnModel().getColumn(route_col);
|
|
self.combobox1 = JComboBox()
|
|
|
|
RouteManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
|
|
routes = RouteManager.getRoutesByNameList()
|
|
for route in routes:
|
|
self.combobox1.addItem(route)
|
|
self.routesColumn.setCellEditor(DefaultCellEditor(self.combobox1))
|
|
renderer1 = ComboBoxCellRenderer4()
|
|
self.routesColumn.setCellRenderer(renderer1)
|
|
|
|
# repeat column
|
|
self.taskColumn = self.table.getColumnModel().getColumn(repeat_col)
|
|
self.combobox3 = JComboBox()
|
|
|
|
tasks = ["Once", "Repeat every 20 mins", "Repeat every 30 mins", "Repeat every Hour", "Repeat every 2 Hours"]
|
|
for task in tasks:
|
|
self.combobox3.addItem(task)
|
|
|
|
self.taskColumn.setCellEditor(DefaultCellEditor(self.combobox3))
|
|
renderer3 = ComboBoxCellRenderer4()
|
|
self.taskColumn.setCellRenderer(renderer3)
|
|
|
|
# train column
|
|
self.trainColumn = self.table.getColumnModel().getColumn(train_description_col)
|
|
self.combobox4 = JComboBox()
|
|
|
|
all_trains = self.get_all_roster_entries_with_speed_profile()
|
|
for train in all_trains:
|
|
self.combobox4.addItem(train)
|
|
|
|
self.trainColumn.setCellEditor(DefaultCellEditor(self.combobox4))
|
|
renderer4 = ComboBoxCellRenderer4()
|
|
self.trainColumn.setCellRenderer(renderer4)
|
|
|
|
|
|
|
|
jpane = JScrollPane(self.table)
|
|
panel = JPanel()
|
|
panel.add(jpane)
|
|
result = JScrollPane(panel)
|
|
return self.table
|
|
|
|
def get_all_roster_entries_with_speed_profile(self):
|
|
roster_entries_with_speed_profile = []
|
|
r = jmri.jmrit.roster.Roster.getDefault()
|
|
for roster_entry in jmri.jmrit.roster.Roster.getAllEntries(r):
|
|
if self.logLevel > 0: print "roster_entry.getSpeedProfile()",roster_entry,roster_entry.getSpeedProfile()
|
|
if roster_entry.getSpeedProfile() != None:
|
|
roster_entries_with_speed_profile.append(roster_entry.getId())
|
|
if self.logLevel > 0: print "roster_entry.getId()",roster_entry.getId()
|
|
return roster_entries_with_speed_profile
|
|
|
|
def add_row_action(self, e):
|
|
model = e.getSource()
|
|
# data = self.model.getValueAt(0, 0)
|
|
count = self.model.getRowCount()
|
|
colcount = self.model.getColumnCount()
|
|
self.model.add_row()
|
|
# self.save()
|
|
self.completeTablePanel()
|
|
|
|
def get_route_list(self):
|
|
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
|
|
train_list = TrainManager.getTrainsByTimeList()
|
|
my_list = [[train.getName(), train.getDescription(), train.getDepartureTime().partition(":")[2], train.getComment(), train.getRoute()] for train in train_list]
|
|
# print "my_list", my_list
|
|
return my_list
|
|
|
|
def populate_action(self, event):
|
|
# print "populating"
|
|
items_to_put_in_dropdown = self.get_route_list()
|
|
# print "items_to_put_in_dropdown", items_to_put_in_dropdown
|
|
self.model.populate(items_to_put_in_dropdown)
|
|
# print "populated"
|
|
self.completeTablePanel()
|
|
|
|
def tidy_action(self,e):
|
|
self.model.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
def savetofile_action(self, event):
|
|
|
|
#Tidy
|
|
self.model.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
if self.model.getRowCount() == 0:
|
|
msg = "There are no valid rows"
|
|
result = OptionDialog().displayMessage(msg)
|
|
return
|
|
|
|
msg = "Saving Valid rows"
|
|
result = OptionDialog().displayMessage(msg)
|
|
|
|
dir = self.directory()
|
|
j = JFileChooser(dir);
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.addChoosableFileFilter(filter);
|
|
j.setDialogTitle("Select a .txt file");
|
|
|
|
# Automatically select the first file in the directory
|
|
files = j.getCurrentDirectory().listFiles()
|
|
j.setSelectedFile(files[0])
|
|
|
|
ret = j.showSaveDialog(None)
|
|
if (ret == JFileChooser.APPROVE_OPTION) :
|
|
file = j.getSelectedFile()
|
|
if file == "" or file == None:
|
|
msg = "No file selected"
|
|
result = OptionDialog().displayMessage(msg)
|
|
return
|
|
if FilenameUtils.getExtension(file.getName()).lower() == "txt" :
|
|
#filename is OK as-is
|
|
pass
|
|
else:
|
|
#file = File(file.toString() + ".txt"); # append .txt if "foo.jpg.txt" is OK
|
|
file = File(file.getParentFile(), FilenameUtils.getBaseName(file.getName())+".txt") # ALTERNATIVELY: remove the extension (if any) and replace it with ".xml"
|
|
|
|
else:
|
|
return
|
|
if self.logLevel > 0: print "savetofile action", file
|
|
my_list = []
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
for row in range(len(self.model.data)):
|
|
time_name = str(self.model.data[row][time_col])
|
|
route_name = str(self.model.data[row][route_col])
|
|
task_name = str(self.model.data[row][repeat_col])
|
|
dont_schedule_name = str(self.model.data[row][dont_schedule_col])
|
|
train_name = str(self.model.data[row][train_name_col])
|
|
train_description = str(self.model.data[row][train_description_col])
|
|
edit_name = str(self.model.data[row][edit_col])
|
|
delete_name = str(self.model.data[row][delete_col])
|
|
row_list = [time_name, route_name, task_name, dont_schedule_name, train_name, train_description, edit_name, delete_name]
|
|
my_list.append(row_list)
|
|
self.write_list(my_list,file)
|
|
|
|
|
|
def loadfromfile_action(self, event):
|
|
# load the file
|
|
dir = self.directory()
|
|
j = JFileChooser(dir);
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.setDialogTitle("Select a .txt file")
|
|
j.addChoosableFileFilter(filter)
|
|
|
|
# Automatically select the first file in the directory
|
|
files = j.getCurrentDirectory().listFiles()
|
|
j.setSelectedFile(files[0])
|
|
|
|
ret = j.showOpenDialog(None)
|
|
if (ret == JFileChooser.APPROVE_OPTION) :
|
|
file = j.getSelectedFile()
|
|
if self.logLevel > 0: print "about to read list", file
|
|
my_list = self.read_list(file)
|
|
if self.logLevel > 0: print "my_list", my_list
|
|
for row in reversed(range(len(self.model.data))):
|
|
self.model.data.pop(row)
|
|
i = 0
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
for row in my_list:
|
|
[time_val, route_val, repeat_val, dont_schedule_val, train_name_val, train_description_val, edit_val, delete_val] = row
|
|
# print "reading row", row
|
|
self.model.add_row()
|
|
self.model.data[i][time_col] = time_val.replace('"','')
|
|
self.model.data[i][route_col] = route_val.replace('"','')
|
|
self.model.data[i][repeat_col] = repeat_val.replace('"','')
|
|
# print "dont_schedule_val", dont_schedule_val, "(dont_schedule_val == 'True'') ", (dont_schedule_val == "True")
|
|
self.model.data[i][dont_schedule_col] = (dont_schedule_val.replace('"','') == "True") #convert string to boolean
|
|
self.model.data[i][train_name_col] = train_name_val.replace('"','')
|
|
self.model.data[i][train_description_col] = train_description_val.replace('"','')
|
|
# self.model.data[i][edit_col] = edit_val.replace('"','')
|
|
# self.model.data[i][delete_col] = bool(delete_val.replace('"',''))
|
|
i += 1
|
|
# print "read row", row
|
|
|
|
self.save()
|
|
self.completeTablePanel()
|
|
|
|
msg = "Deleting invalid rows"
|
|
result = OptionDialog().displayMessage(msg)
|
|
if result == JOptionPane.NO_OPTION:
|
|
return
|
|
|
|
self.completeTablePanel()
|
|
self.save()
|
|
|
|
def deletesavedfile_action(self, event):
|
|
|
|
while(True):
|
|
|
|
self.model.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
if self.model.getRowCount() == 0:
|
|
return self.model.remove_not_set_row()
|
|
self.completeTablePanel()
|
|
|
|
if self.model.getRowCount() == 0:
|
|
return
|
|
|
|
dir = self.directory()
|
|
j = JFileChooser(dir);
|
|
j.setAcceptAllFileFilterUsed(False)
|
|
filter = FileNameExtensionFilter("text files txt", ["txt"])
|
|
j.addChoosableFileFilter(filter);
|
|
j.setDialogTitle("Delete not wanted files");
|
|
|
|
ret = j.showDialog(None, "Delete");
|
|
if ret == JFileChooser.APPROVE_OPTION:
|
|
file = j.getSelectedFile()
|
|
if file == "" or file == None:
|
|
return
|
|
if file.exists():
|
|
os.remove(file.getAbsolutePath())
|
|
# print("File " + file.getName() + " has been deleted successfully.")
|
|
else:
|
|
print("The selected file does not exist.")
|
|
else:
|
|
print("File selection cancelled.")
|
|
return
|
|
|
|
def close_action(self, event):
|
|
self.completeTablePanel()
|
|
self.save()
|
|
# Open and close the Operations Panel to force save of any extra trains
|
|
if self.find_frame_by_title("Trains") is None:
|
|
# print "did not find frame Trains so creating it"
|
|
a = jmri.jmrit.operations.trains.gui.TrainsTableAction()
|
|
a.actionPerformed(None)
|
|
# now close
|
|
f = self.find_frame_by_title("Trains")
|
|
if f is not None:
|
|
# print f
|
|
f.dispose()
|
|
# f = None
|
|
# print "should be closed"
|
|
self.frame.dispatchEvent(WindowEvent(self.frame, WindowEvent.WINDOW_CLOSING));
|
|
|
|
# Function to find a frame by name
|
|
def find_frame_by_name(self, name):
|
|
frames = JFrame.getFrames()
|
|
for f in frames:
|
|
# print f.getName()
|
|
if f.getName() == name:
|
|
return f
|
|
return None
|
|
|
|
# Function to find a frame by title
|
|
def find_frame_by_title(self, title):
|
|
frames = JFrame.getFrames()
|
|
for f in frames:
|
|
if f.getTitle() == title:
|
|
return f
|
|
return None
|
|
|
|
def delay_action(self, event):
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
for row in reversed(range(len(self.model.data))):
|
|
old_delay = int(self.model.data[0][train_name_col])
|
|
if old_delay == None: old_delay = 0
|
|
new_delay = self.new_delay(old_delay)
|
|
self.model.data[row][train_name_col] = new_delay
|
|
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):
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
# self.model.getDataVector().removeAllElements();
|
|
for row in reversed(range(len(self.model.data))):
|
|
self.model.data.pop(row)
|
|
# return
|
|
# # for rowToRemove in reversed(range(len(self.model.data))):
|
|
# for rowToRemove in range(len(self.model.data)):
|
|
# rowtoremove = self.table.
|
|
# self.model.removeRow(rowToRemove);
|
|
# if(table.getSelectedRow() != -1) {
|
|
# // remove selected row from the model
|
|
# model.removeRow(table.getSelectedRow());
|
|
# JOptionPane.showMessageDialog(null, "Selected row deleted successfully");
|
|
# }
|
|
#
|
|
# break
|
|
self.save()
|
|
self.completeTablePanel()
|
|
|
|
def new_val(self, old_val):
|
|
if old_val < 3:
|
|
new_val = 3
|
|
elif old_val < 10:
|
|
new_val = 10
|
|
elif old_val < 30:
|
|
new_val = 30
|
|
elif old_val < 100:
|
|
new_val = 100
|
|
else:
|
|
new_val = 1
|
|
return new_val
|
|
|
|
def task_action(self, event):
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
for row in reversed(range(len(self.model.data))):
|
|
old_val = str(self.model.data[0][repeat_col])
|
|
if old_val == None: old_val = 0
|
|
new_val = self.new_task(old_val)
|
|
self.model.data[row][repeat_col] = new_val
|
|
self.save()
|
|
self.completeTablePanel()
|
|
|
|
def new_task(self, old_val):
|
|
|
|
|
|
if old_val == "Once":
|
|
new_val = "Repeat every 20 mins"
|
|
elif old_val == "Repeat every 20 mins":
|
|
new_val = "Repeat every 30 mins"
|
|
elif old_val == "Repeat every 30 mins":
|
|
new_val = "Repeat every Hour"
|
|
elif old_val == "Repeat every Hour":
|
|
new_val = "Repeat every 2 Hours"
|
|
elif old_val == "Repeat every 2 Hours":
|
|
new_val = "Once"
|
|
else:
|
|
return "Once"
|
|
return new_val
|
|
|
|
|
|
# def save_action(self, event):
|
|
# self.save()
|
|
#
|
|
def save(self):
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
# print "save_action"
|
|
# print "self.model.data", self.model.data
|
|
self.clear_everything()
|
|
# print "self.model.data after", self.model.data
|
|
# print "apply action"
|
|
for row in reversed(range(len(self.model.data))):
|
|
# print "save row", row
|
|
time_name = str(self.model.data[row][time_col])
|
|
route_name = str(self.model.data[row][route_col])
|
|
train_name = str(self.model.data[row][train_name_col])
|
|
train_description = str(self.model.data[row][train_description_col])
|
|
repeat_name = str(self.model.data[row][repeat_col])
|
|
# print "repeat_name", repeat_name
|
|
dont_schedule_name = str(self.model.data[row][dont_schedule_col])
|
|
# if time_name != "" and route_name != "" and train_name_val != "":
|
|
if train_name != "":
|
|
# print "save schedule"
|
|
self.save_schedule(row, time_name, route_name, repeat_name, dont_schedule_name, train_name, train_description)
|
|
pass
|
|
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_schedule(self, row, time_name, route_name, repeat_name, dont_schedule_name, train_name, train_description):
|
|
print "save_schedule: train", train_name, "route_name", route_name, "time_name", time_name
|
|
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
|
|
train = TrainManager.newTrain(train_name)
|
|
RouteManager = jmri.InstanceManager.getDefault(jmri.jmrit.operations.routes.RouteManager)
|
|
route = RouteManager.getRouteByName(route_name)
|
|
train.setRoute(route)
|
|
train.setDescription(train_description)
|
|
result = time_name.split(":")
|
|
if len(result) == 2:
|
|
day = "0"
|
|
hour = result[0]
|
|
minute = result[1]
|
|
else:
|
|
day = result[0]
|
|
hour = result[1]
|
|
minute = result[2]
|
|
train.setDepartureTime(day, hour, minute)
|
|
self.set_skip(train, dont_schedule_name) # do this first
|
|
self.set_repeat(train, repeat_name)
|
|
train.setName(train_name)
|
|
# print "finished save schedule train.getName()", train.getName()
|
|
|
|
def set_repeat(self, train, repeat):
|
|
# print "in set_repeat"
|
|
comment = train.getComment() #Null
|
|
# if comment == None: comment = ""
|
|
# repeat_current = MyTableModel4().find_between(comment, "[repeat-", "-repeat]") # empty string
|
|
# print "repeat_currenr", repeat_current, "repeat", repeat
|
|
# if repeat_current != repeat:
|
|
# # self.delete_between(comment, "[repeat-", "-repeat]")
|
|
# comment = ""
|
|
# print "comment3a", comment
|
|
comment = self.insert_between(comment, "[repeat-", "-repeat]", repeat)
|
|
# print "comment3", comment
|
|
train.setComment(comment)
|
|
|
|
def set_skip(self, train, dont_schedule_name):
|
|
comment = train.getComment()
|
|
if comment == None: comment = ""
|
|
if dont_schedule_name == "True":
|
|
comment = "skip *" + comment
|
|
train.setComment(comment)
|
|
|
|
def delete_between(self, string, delim1, delim2):
|
|
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)
|
|
# print "string", string, "first.strip()", first.strip(), "rest.strip()", rest.strip()
|
|
new_val = delim1 + str(value) + delim2
|
|
modified_text = new_val.join([first.strip(), rest.strip()])
|
|
# print "modified_text",modified_text
|
|
return modified_text
|
|
|
|
def clear_everything(self):
|
|
TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
|
|
train_list = TrainManager.getTrainsByTimeList()
|
|
for train in train_list:
|
|
TrainManager.deregister(train)
|
|
|
|
|
|
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
|
|
#file = self.directory() + "blockDirections.txt"
|
|
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 != 7: 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 MyModelListener4(TableModelListener):
|
|
|
|
def __init__(self, class_CreateAndShowGUI4, class_ResetButtonMaster):
|
|
self.class_CreateAndShowGUI4 = class_CreateAndShowGUI4
|
|
self.class_ResetButtonMaster = class_ResetButtonMaster
|
|
self.cancel = False
|
|
self.logLevel = 0
|
|
self.i = 0
|
|
def tableChanged(self, e) :
|
|
# print "tableChanged"
|
|
self.i +=1
|
|
# if self.i % 2 == 0: return
|
|
global trains_allocated
|
|
global CreateAndShowGUI5_glb
|
|
row = e.getFirstRow()
|
|
column = e.getColumn()
|
|
# print "column", column
|
|
self.model = e.getSource()
|
|
columnName = self.model.getColumnName(column)
|
|
|
|
class_CreateAndShowGUI4 = self.class_CreateAndShowGUI4
|
|
class_ResetButtonMaster = self.class_ResetButtonMaster
|
|
tablemodel = class_CreateAndShowGUI4.model
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
if column == time_col:
|
|
# print "time col changed"
|
|
pass
|
|
elif column == edit_col: # sections
|
|
if self.model.getValueAt(row, edit_col) == True:
|
|
# print "starting edit"
|
|
route_data = str(self.model.getValueAt(row, route_col))
|
|
scheduled_start = self.model.getValueAt(row, time_col)
|
|
|
|
if route_data == "" or route_data is None or route_data == "None":
|
|
OptionDialog().displayMessage("Cannot display route as route name has not been specified")
|
|
else:
|
|
if "CreateAndShowGUI5_glb" in globals():
|
|
if CreateAndShowGUI5_glb != None:
|
|
CreateAndShowGUI5_glb.frame.dispose()
|
|
CreateAndShowGUI5_glb = CreateAndShowGUI5(self, route_data, scheduled_start)
|
|
# print "e"
|
|
self.model.setValueAt(False, row, edit_col)
|
|
elif column == delete_col:
|
|
# print "delete col/row"
|
|
title = ""
|
|
msg = "delete row?"
|
|
opt1 = "don't delete row"
|
|
opt2 = "delete row"
|
|
result = OptionDialog().customQuestionMessage2str(msg, title, opt1, opt2)
|
|
if result == opt2:
|
|
self.delete_row(row, class_CreateAndShowGUI4)
|
|
class_CreateAndShowGUI4.save() # save everything when the table is changed
|
|
# class_CreateAndShowGUI4.completeTablePanel() # don't need to refresh hence commented out
|
|
|
|
def save_route(self, class_CreateAndShowGUI4):
|
|
class_CreateAndShowGUI4.save()
|
|
|
|
def delete_row(self, row, class_CreateAndShowGUI4):
|
|
self.model.data.pop(row)
|
|
class_CreateAndShowGUI4.save()
|
|
class_CreateAndShowGUI4.completeTablePanel()
|
|
|
|
def show_time_picker(self):
|
|
# Show a simple JOptionPane input dialog for time selection
|
|
selected_time = JOptionPane.showInputDialog(None, "Select a time (HH:mm):")
|
|
return selected_time
|
|
|
|
class ComboBoxCellRenderer4 (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 MyTableModel4 (DefaultTableModel):
|
|
|
|
columnNames = ["Time", "Route", "Repeat", " Don't Schedule", "Train Name", "Train Description", "Edit_Row", "Delete Row"]
|
|
|
|
def __init__(self):
|
|
# l1 = ["", "", False, "stop at end of route", 10, False, False]
|
|
self.data = []
|
|
|
|
def remove_not_set_row(self):
|
|
b = False
|
|
for row in reversed(range(len(self.data))):
|
|
# print "row", row
|
|
if self.data[row][1] == "":
|
|
self.data.pop(row)
|
|
|
|
def add_row(self):
|
|
# TrainManager=jmri.InstanceManager.getDefault(jmri.jmrit.operations.trains.TrainManager)
|
|
# train_list = TrainManager.getTrainsByTimeList()
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
indices = []
|
|
for row in reversed(range(len(self.data))):
|
|
# indices = [int(train.getName().split("Train",1)[1]) for train in train_list if train.getName().startswith("Train")]
|
|
indices = [int(self.data[row][train_name_col].split("Train",1)[1]) for row in reversed(range(len(self.data)))
|
|
if self.data[row][train_name_col].startswith("Train")]
|
|
# print "indices", indices
|
|
if indices == []:
|
|
index = 1
|
|
else:
|
|
index = max(indices) + 1
|
|
train_name = "Train" + str(index) # the train name in operations trains is unique
|
|
train_description = "Select Train" # we put the roster name of the train in the description
|
|
# print "adding row"
|
|
self.data.append(["00:00", "", "Once", False, train_name, train_description, False, False])
|
|
# print "added row"
|
|
# print self.data
|
|
# print "added"
|
|
|
|
def populate(self, items_to_put_in_dropdown):
|
|
# print "in populate"
|
|
for row in reversed(range(len(self.data))):
|
|
self.data.pop(row)
|
|
# print "cleared everything"
|
|
# self.data = []
|
|
# append all trains to put in dropdown
|
|
[time_col, route_col, repeat_col, dont_schedule_col, train_name_col, train_description_col, edit_col, delete_col] = [0, 1, 2, 3, 4, 5, 6, 7]
|
|
for [train, train_description, time, comment, route] in items_to_put_in_dropdown:
|
|
# print "train", train
|
|
if "skip" in comment:
|
|
skip = True
|
|
else:
|
|
skip = False
|
|
# print "skip", skip
|
|
train_present = False
|
|
repeat = self.find_between(comment, "[repeat-", "-repeat]")
|
|
if repeat == "": repeat = "Once"
|
|
# print "append"
|
|
self.data.append([time, route, repeat, skip, train, train_description, False, False])
|
|
# print "appended"
|
|
# print "populated"
|
|
# delete rows with no trains
|
|
# for row in reversed(range(len(self.data))):
|
|
# if self.data[row][time_col] == None or self.data[row][dont_schedule_col] == "":
|
|
# self.data.pop(row)
|
|
|
|
def find_between(self, s, first, last):
|
|
try:
|
|
start = s.index(first) + len(first)
|
|
end = s.index(last, start)
|
|
return s[start:end]
|
|
except ValueError:
|
|
return ""
|
|
except IndexError:
|
|
return "Index Error H"
|
|
|
|
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]
|
|
# return 'fred'
|
|
|
|
def getColumnClass(self, col) :
|
|
|
|
return java.lang.Boolean.getClass(self.getValueAt(0,col))
|
|
# return java.lang.Boolean.getClass("fred")
|
|
|
|
|
|
#only include if table editable
|
|
def isCellEditable(self, row, col) :
|
|
# Note that the data/cell address is constant,
|
|
# no matter where the cell appears onscreen.
|
|
# cell_value = self.getValueAt(row, col)
|
|
return True
|
|
|
|
# only include if data can change.
|
|
def setValueAt(self, value, row, col) :
|
|
# print "row1", row, "col", col, "value", value
|
|
if col == 0:
|
|
# print "row2", row, "col", col, "value", value
|
|
if not self.isValidTimeFormat(value):
|
|
return
|
|
# print "row", row, "col", col, "value", value
|
|
self.data[row][col] = value
|
|
self.fireTableCellUpdated(row, col)
|
|
|
|
# if (isValidValue(aValue)) {
|
|
# data[rowIndex][columnIndex] = aValue;
|
|
# fireTableCellUpdated(rowIndex, columnIndex); // Notify the table
|
|
# }
|
|
|
|
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
|
|
# print "m", re.match(pattern, input_string) is not None
|
|
# print "my_match", re.match(pattern, input_string)
|
|
|
|
return my_match
|