Skip to content

Commit 2fe7580

Browse files
Various Fixes (#83)
* Added application Icon (not visible in MacOS) * Fixed typesetting in copy/paste * Removed superfluous line
1 parent bed6f4a commit 2fe7580

File tree

7 files changed

+63
-24
lines changed

7 files changed

+63
-24
lines changed

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ petab_gui="petab_gui:main"
5050

5151
[project.scripts]
5252
petab_gui_cli="petab_gui:main"
53+
54+
[tool.setuptools]
55+
include-package-data = true
56+
57+
[tool.setuptools.package-data]
58+
"petab_gui.assets" = ["PEtab.png"]

src/petab_gui/C.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"conditionId": {"type": np.object_, "optional": False},
3939
"conditionName": {"type": np.object_, "optional": False},
4040
}
41-
}
41+
}
4242

4343
CONFIG = {
4444
'window_title': 'My Application',

src/petab_gui/app.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from PySide6.QtWidgets import QApplication
2-
from PySide6.QtGui import QFileOpenEvent
2+
from PySide6.QtGui import QFileOpenEvent, QIcon
33
from PySide6.QtCore import QEvent
4+
from importlib.resources import files
45
import sys
56
import os
67
import petab.v1 as petab
@@ -21,6 +22,15 @@ def find_example(path: Path) -> Path:
2122
raise FileNotFoundError("Could not find examples directory")
2223

2324

25+
def get_icon() -> QIcon:
26+
"""Get the Icon for the Window"""
27+
icon_path = files("petab_gui.assets").joinpath("PEtab.png")
28+
if not icon_path.is_file():
29+
raise FileNotFoundError(f"Icon file not found: {icon_path}")
30+
icon = QIcon(str(icon_path))
31+
return icon
32+
33+
2434
class PEtabGuiApp(QApplication):
2535
def __init__(self):
2636
super().__init__(sys.argv)
@@ -29,6 +39,7 @@ def __init__(self):
2939
# self.apply_stylesheet()
3040
self.model = PEtabModel()
3141
self.view = MainWindow()
42+
self.view.setWindowIcon(get_icon())
3243
self.controller = MainController(self.view, self.model)
3344

3445
# hack to be discussed

src/petab_gui/assets/PEtab.png

20 KB
Loading

src/petab_gui/models/pandas_table_model.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,17 @@ def _set_data_single(self, index, value):
180180
column_name = self._data_frame.columns[column - col_setoff]
181181
old_value = self._data_frame.iloc[row, column - col_setoff]
182182
# cast to numeric if necessary
183-
if not self._data_frame[column_name].dtype == "object":
184-
try:
185-
value = float(value)
186-
except ValueError:
183+
expected_type = self._allowed_columns.get(column_name, None)
184+
if is_invalid(value):
185+
if not expected_type["optional"]:
186+
return False
187+
self._data_frame.iloc[row, column - col_setoff] = None
188+
self.dataChanged.emit(index, index, [Qt.DisplayRole])
189+
return True
190+
if expected_type:
191+
expected_type = expected_type["type"]
192+
value, error_message = validate_value(value, expected_type)
193+
if error_message:
187194
self.new_log_message.emit(
188195
f"Column '{column_name}' expects a numeric value",
189196
"red"

src/petab_gui/utils.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,10 @@ def highlightBlock(self, text):
488488

489489
def validate_value(value, expected_type):
490490
try:
491-
if expected_type == "STRING":
491+
if expected_type == np.object_:
492492
value = str(value)
493-
elif expected_type == "NUMERIC":
493+
elif expected_type == np.float64:
494494
value = float(value)
495-
elif expected_type == "BOOLEAN":
496-
value = bool(value)
497495
except ValueError as e:
498496
return None, str(e)
499497
return value, None
@@ -599,6 +597,12 @@ def get_selected_rectangles(table_view: QTableView) -> np.array:
599597
selected = get_selected(table_view, mode=INDEX)
600598
if not selected:
601599
return None
600+
601+
model = table_view.model()
602+
if hasattr(model, "mapToSource"):
603+
# map all indices to source
604+
selected = [model.mapToSource(index) for index in selected]
605+
602606
rows = [index.row() for index in selected]
603607
cols = [index.column() for index in selected]
604608
min_row, max_row = min(rows), max(rows)
@@ -609,6 +613,7 @@ def get_selected_rectangles(table_view: QTableView) -> np.array:
609613
)
610614
for index in selected:
611615
selected_rect[index.row() - min_row, index.column() - min_col] = True
616+
612617
return selected_rect, rect_start
613618

614619

src/petab_gui/views/table_view.py

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,33 +41,43 @@ def paste_from_clipboard(self):
4141
text = clipboard.text()
4242
if not text:
4343
return
44+
45+
# Get the proxy and source models
46+
proxy_model = self.table_view.model()
47+
source_model = proxy_model.sourceModel()
48+
49+
# Get the start index from the current selection
4450
start_index = self.table_view.selectionModel().currentIndex()
4551
if not start_index.isValid():
4652
return
47-
model = self.table_view.model()
48-
row_start, col_start = start_index.row(), start_index.column()
49-
# identify which invalid cells are being pasted into
53+
54+
# Map the start index to the source model
55+
source_index = proxy_model.mapToSource(start_index)
56+
row_start, col_start = source_index.row(), source_index.column()
57+
58+
# Parse clipboard data
5059
pasted_data = [line.split("\t") for line in text.split("\n") if
5160
line.strip()]
5261
num_rows = len(pasted_data)
53-
num_cols = max([len(line) for line in pasted_data])
62+
num_cols = max(len(line) for line in pasted_data)
63+
64+
# Identify which cells are being overridden
5465
overridden_cells = {
5566
(row_start + r, col_start + c)
5667
for r in range(num_rows)
5768
for c in range(num_cols)
58-
if model.index(row_start + r, col_start + c).isValid()
69+
if source_model.index(row_start + r, col_start + c).isValid()
5970
}
60-
invalid_overridden_cells = overridden_cells.intersection(
61-
model._invalid_cells
62-
)
63-
if invalid_overridden_cells:
71+
72+
# Handle invalid cells
73+
if hasattr(source_model, "_invalid_cells"):
74+
invalid_overridden_cells = overridden_cells.intersection(
75+
source_model._invalid_cells)
6476
for row_invalid, col_invalid in invalid_overridden_cells:
65-
model.discard_invalid_cell(row_invalid, col_invalid)
77+
source_model.discard_invalid_cell(row_invalid, col_invalid)
6678

67-
model.setDataFromText(
68-
text, start_index.row(),
69-
start_index.column()
70-
)
79+
# Paste the data into the source model
80+
source_model.setDataFromText(text, row_start, col_start)
7181

7282

7383
class ComboBoxDelegate(QStyledItemDelegate):

0 commit comments

Comments
 (0)