Skip to content

Commit f4bc886

Browse files
A few minor polishes
Mostly to ensure previous fixes are better implemented
1 parent 9f09e21 commit f4bc886

6 files changed

Lines changed: 53 additions & 40 deletions

File tree

controllers/csv_controller.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,10 @@ def export_plater(self, csv_lines: List[str], rows: str, cols: str) -> List[str]
135135
for i, plater_csv_content in enumerate(plater_data_list):
136136
# Format the CSV content (ensure proper line endings)
137137
if isinstance(plater_csv_content, str):
138-
csv_lines = [line + '\n' if not line.endswith('\n') else line
139-
for line in plater_csv_content.splitlines()]
138+
formatted_lines = [line + '\n' if not line.endswith('\n') else line
139+
for line in plater_csv_content.splitlines()]
140140
else:
141-
csv_lines = plater_csv_content
141+
formatted_lines = plater_csv_content
142142

143143
# Generate suggested filename
144144
if len(plater_data_list) == 1:
@@ -147,7 +147,7 @@ def export_plater(self, csv_lines: List[str], rows: str, cols: str) -> List[str]
147147
suggested_name = f"plate_{i+1}_plater.csv"
148148

149149
# Save with dialog
150-
path = write_csv_file(csv_lines, suggested_filename=suggested_name)
150+
path = write_csv_file(formatted_lines, suggested_filename=suggested_name)
151151

152152
if path == -1: # User cancelled
153153
logger.info(f"User cancelled PLATER save on plate {i+1}/{len(plater_data_list)}")

core/io_utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def write_figure(figure: Figure, filetypes: str, suggested_filename: str = '', m
7878
figure.savefig(path, dpi=FigureProperties.DPI, bbox_inches='tight')
7979
return os.path.basename(path)
8080
except (IOError, OSError) as e:
81-
logger.error(f"Failed to write {path[:-3]} file: {e}")
81+
logger.error(f"Failed to write {path[:-4]} file: {e}")
8282
return -2 # Write error
8383

8484
def write_figures_in_pdf(figures: List[Figure], suggested_filename: str = '', material_scales: Optional[List[Figure]] = None) -> Union[int,str]:
@@ -173,7 +173,7 @@ def read_csv_file(file_path: str) -> List[str]:
173173

174174
layout_text_array = convert_to_pharmbio_format(layout_text_array)
175175

176-
line_count = len(layout_text_array) - 1 # Exclude header
176+
line_count = len(layout_text_array)
177177
logger.info(f"CSV file loaded: {file_path}, {line_count} data lines")
178178
return layout_text_array # Remove header
179179
except (ValueError) as e:
@@ -223,6 +223,7 @@ def convert_to_pharmbio_format(layout_text_array: List[str]) -> List[str]:
223223
concentrations_matrix[i][j],
224224
',',
225225
drugs_matrix[i][j] + '_' + concentrations_matrix[i][j],
226+
','
226227
]))
227228

228229
return plater_layout_text_array
@@ -260,7 +261,7 @@ def scan_csv_plater_matrices(layout_text_array: List[str]) -> Tuple[int, int, Li
260261
for line in layout_text_array:
261262
if line.strip() == '':
262263
continue
263-
elif line == '\n': # happens on Windows machines (to be tested)
264+
elif line == '\n': # happens on Windows machines
264265
continue
265266

266267
elements = line.strip().split(',')
@@ -337,7 +338,6 @@ def path_truncate(path: str) -> str:
337338
338339
Args:
339340
path: File path to display
340-
label_object: Tkinter label widget to update
341341
342342
Returns:
343343
truncated path

models/constants.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
# Description: Constants for the MPLACE application
1717
#
1818
# Authors: Ramiz GINDULLIN (ramiz.gindullin@it.uu.se)
19-
# Version: 1.2.2
20-
# Last Revision: January 2026
19+
# Version: 1.2.5
20+
# Last Revision: March 2026
2121
#
2222

2323

@@ -118,6 +118,18 @@ class Performance:
118118
COLORMAP_COLOR_LIMIT = 20
119119

120120

121+
class MainMenu:
122+
"""List of main menu fields' titles."""
123+
LOAD_DZN = "Load DZN"
124+
LOAD_CSV = "Load CSV"
125+
GEN_DZN = "Generate DZN"
126+
RUN_MZN = "Run MiniZinc"
127+
VISUALIZE = "Visualize"
128+
RESET = "Reset"
129+
RCNT_DZN = "Recent DZN files"
130+
RCNT_CSV = "Recent CSV files"
131+
132+
121133
class PathsIni:
122134
"""Configuration file parsing constants."""
123135
# Configuration keys and prefixes

mplace.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ def _open_viz_window(self) -> None:
197197
if not state.csv_file_path:
198198
self.logger.warning("Attempted to open visualization without CSV loaded")
199199
tk.messagebox.showerror("Error", "Please load a CSV file first")
200+
self.views['main'].unlock()
200201
return
201202

202203
# Generate figure name template

views/main_view.py

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from controllers.main_controller import MainController
3232
from controllers.minizinc_controller import MiniZincController
3333
from controllers.csv_controller import CsvController
34-
from models.constants import PlateDefaults, UI, Messages, WindowConfig, FileTypes, PathsIni, Validation
34+
from models.constants import PlateDefaults, MainMenu, UI, Messages, WindowConfig, FileTypes, PathsIni, Validation
3535
from core.io_utils import path_show
3636
from ui.ui_validators import numeric_entry_callback
3737

@@ -72,15 +72,15 @@ def __init__(
7272
self._build_ui()
7373

7474
self._shortcuts = [
75-
# (menu, label, key_event, accelerator, handler, guard)
76-
("file", "Load DZN…", "<Control-d>", "Ctrl+D", self._on_load_dzn, None),
77-
("file", "Load CSV…", "<Control-f>", "Ctrl+f", self._on_load_csv, None),
78-
("tools", "Generate DZN…","<Control-g>", "Ctrl+G", self._on_generate_dzn, None),
79-
("tools", "Run MiniZinc…","<Control-r>", "Ctrl+R", self._on_run_minizinc, self.button_run_minizinc),
80-
("tools", "Visualize", "<Control-l>", "Ctrl+L", self._on_visualize, self.button_visualize),
81-
("tools", "Reset", "<Control-e>", "Ctrl+E", self._set_program_state_to_default_call, None),
75+
# (menu, label, key_event, accelerator, handler, guard)
76+
("file", MainMenu.LOAD_DZN, "<Control-d>", "Ctrl+D", self._on_load_dzn, None),
77+
("file", MainMenu.LOAD_CSV, "<Control-f>", "Ctrl+F", self._on_load_csv, None),
78+
("tools", MainMenu.GEN_DZN, "<Control-g>", "Ctrl+G", self._on_generate_dzn, None),
79+
("tools", MainMenu.RUN_MZN, "<Control-r>", "Ctrl+R", self._on_run_minizinc, self.button_run_minizinc),
80+
("tools", MainMenu.VISUALIZE, "<Control-l>", "Ctrl+L", self._on_visualize, self.button_visualize),
81+
("tools", MainMenu.RESET, "<Control-e>", "Ctrl+E", self._set_program_state_to_default_call, None),
8282
]
83-
83+
8484
self._setup_window()
8585
self._setup_shortcuts()
8686
self._setup_menu()
@@ -282,11 +282,11 @@ def _setup_menu(self) -> None:
282282
label=label, accelerator=accelerator, command=handler
283283
)
284284
# Insert the Recent submenus after the Load CSV entry
285-
if label == "Load CSV…":
285+
if label == MainMenu.LOAD_CSV:
286286
self.menu_file.add_separator()
287-
self.menu_file.add_cascade(label="Recent DZN files", menu=self.menu_recent_dzn)
288-
self.menu_file.add_cascade(label="Recent CSV files", menu=self.menu_recent_csv)
289-
elif label == "Run MiniZinc…":
287+
self.menu_file.add_cascade(label=MainMenu.RCNT_DZN, menu=self.menu_recent_dzn)
288+
self.menu_file.add_cascade(label=MainMenu.RCNT_CSV, menu=self.menu_recent_csv)
289+
elif label == MainMenu.RUN_MZN:
290290
self.menu_tools.add_separator() # separator before Visualize
291291

292292
self.menu_bar.add_cascade(label="File", menu=self.menu_file)
@@ -339,7 +339,7 @@ def _update_run_minizinc_button_state(self) -> None:
339339

340340
new_state = tk.NORMAL if button_should_be_enabled else tk.DISABLED
341341
self.button_run_minizinc.config(state=new_state)
342-
self.menu_tools.entryconfig("Run MiniZinc…", state=new_state)
342+
self.menu_tools.entryconfig(MainMenu.RUN_MZN, state=new_state)
343343

344344
if button_should_be_enabled:
345345
logger.debug("Run Model button enabled - config valid")
@@ -636,14 +636,14 @@ def lock(self) -> None:
636636
self.button__set_program_state_to_default.config(state=tk.DISABLED)
637637

638638
# Disable menu entries
639-
self.menu_file.entryconfig("Load DZN…", state=tk.DISABLED)
640-
self.menu_file.entryconfig("Load CSV…", state=tk.DISABLED)
641-
self.menu_file.entryconfig("Recent DZN files", state=tk.DISABLED)
642-
self.menu_file.entryconfig("Recent CSV files", state=tk.DISABLED)
643-
self.menu_tools.entryconfig("Generate DZN…", state=tk.DISABLED)
644-
self.menu_tools.entryconfig("Run MiniZinc…", state=tk.DISABLED)
645-
self.menu_tools.entryconfig("Visualize", state=tk.DISABLED)
646-
self.menu_tools.entryconfig("Reset", state=tk.DISABLED)
639+
self.menu_file.entryconfig( MainMenu.LOAD_DZN, state=tk.DISABLED)
640+
self.menu_file.entryconfig( MainMenu.LOAD_CSV, state=tk.DISABLED)
641+
self.menu_file.entryconfig( MainMenu.RCNT_DZN, state=tk.DISABLED)
642+
self.menu_file.entryconfig( MainMenu.RCNT_CSV, state=tk.DISABLED)
643+
self.menu_tools.entryconfig(MainMenu.GEN_DZN, state=tk.DISABLED)
644+
self.menu_tools.entryconfig(MainMenu.RUN_MZN, state=tk.DISABLED)
645+
self.menu_tools.entryconfig(MainMenu.VISUALIZE, state=tk.DISABLED)
646+
self.menu_tools.entryconfig(MainMenu.RESET, state=tk.DISABLED)
647647
logger.debug("Main window locked")
648648

649649
def unlock(self) -> None:
@@ -661,18 +661,18 @@ def unlock(self) -> None:
661661
self.button_load_dzn.config(state=tk.NORMAL)
662662
self.button_load_csv.config(state=tk.NORMAL)
663663
self.button__set_program_state_to_default.config(state=tk.NORMAL)
664-
self.menu_file.entryconfig("Load DZN…", state=tk.NORMAL)
665-
self.menu_file.entryconfig("Load CSV…", state=tk.NORMAL)
666-
self.menu_file.entryconfig("Recent DZN files", state=tk.NORMAL)
667-
self.menu_file.entryconfig("Recent CSV files", state=tk.NORMAL)
668-
self.menu_tools.entryconfig("Generate DZN…", state=tk.NORMAL)
669-
self.menu_tools.entryconfig("Reset", state=tk.NORMAL)
664+
self.menu_file.entryconfig( MainMenu.LOAD_DZN, state=tk.NORMAL)
665+
self.menu_file.entryconfig( MainMenu.LOAD_CSV, state=tk.NORMAL)
666+
self.menu_file.entryconfig( MainMenu.RCNT_DZN, state=tk.NORMAL)
667+
self.menu_file.entryconfig( MainMenu.RCNT_CSV, state=tk.NORMAL)
668+
self.menu_tools.entryconfig(MainMenu.GEN_DZN, state=tk.NORMAL)
669+
self.menu_tools.entryconfig(MainMenu.RESET, state=tk.NORMAL)
670670

671671
# Restore state-dependent controls without resetting data
672672
self._update_run_minizinc_button_state()
673673
if self.csv_file_path.get():
674674
self.button_visualize.config(state=tk.NORMAL)
675-
self.menu_tools.entryconfig("Visualize", state=tk.NORMAL)
675+
self.menu_tools.entryconfig(MainMenu.VISUALIZE, state=tk.NORMAL)
676676
logger.debug("Main window unlocked")
677677

678678
def show(self) -> None:

views/viz_view.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# Pure view layer - handles only UI display and matplotlib visualization.
1818
#
1919
# Authors: Ramiz GINDULLIN (ramiz.gindullin@it.uu.se)
20-
# Version: 1.2.4
20+
# Version: 1.2.5
2121
# Last Revision: March 2026
2222
#
2323

0 commit comments

Comments
 (0)