Skip to content

Commit e75db0d

Browse files
committed
Changing FU amounts
1 parent fbef123 commit e75db0d

6 files changed

Lines changed: 152 additions & 58 deletions

File tree

activity_browser/actions/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from .calculation_setup.cs_duplicate import CSDuplicate
2121
from .calculation_setup.cs_rename import CSRename
2222
from .calculation_setup.cs_add_functional_unit import CSAddFunctionalUnit
23+
from .calculation_setup.cs_change_functional_unit import CSChangeFunctionalUnit
2324
from .calculation_setup.cs_add_impact_category import CSAddImpactCategory
2425
from .calculation_setup.cs_delete_impact_category import CSDeleteImpactCategory
2526
from .calculation_setup.cs_delete_functional_unit import CSDeleteFunctionalUnit
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from logging import getLogger
2+
3+
from activity_browser import bwutils
4+
from activity_browser.actions.base import ABAction, exception_dialogs
5+
from activity_browser.mod import bw2data as bd
6+
7+
log = getLogger(__name__)
8+
9+
10+
class CSChangeFunctionalUnit(ABAction):
11+
"""
12+
Updates the functional unit amount for a specific inventory item in a calculation setup.
13+
14+
This method modifies the amount of a functional unit in the inventory of a given calculation setup
15+
and saves the updated setup.
16+
17+
Args:
18+
cs_name (str): The name of the calculation setup to modify.
19+
index (int): The index of the inventory item within the calculation setup.
20+
amount (float): The new amount to set for the functional unit.
21+
22+
Steps:
23+
- Retrieve the calculation setup by its name.
24+
- Extract the key of the inventory item at the specified index.
25+
- Update the amount for the specified inventory item.
26+
- Serialize and save the updated calculation setup.
27+
28+
Raises:
29+
Exception: If an error occurs during the process, it is handled by the `exception_dialogs` decorator.
30+
"""
31+
text = "Add Functional Unit to Calculation Setup"
32+
33+
@staticmethod
34+
@exception_dialogs
35+
def run(cs_name: str, index: int, amount: float):
36+
calculation_setup = bd.calculation_setups[cs_name]
37+
38+
key = list(calculation_setup['inv'][index].keys())[0]
39+
calculation_setup['inv'][index][key] = amount
40+
41+
bd.calculation_setups.serialize()

activity_browser/layouts/pages/activity_details/exchanges_tab.py

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -261,61 +261,6 @@ def paintEvent(self, event):
261261
painter.drawText(self.rect(), Qt.AlignCenter, "Drop here to create new exchanges")
262262

263263

264-
class ExchangeAmountDelegate(QtWidgets.QStyledItemDelegate):
265-
def displayText(self, value, locale):
266-
import math
267-
try:
268-
value = float(value)
269-
except ValueError:
270-
value = math.nan
271-
272-
if math.isnan(value):
273-
return ""
274-
return str(abs(value))
275-
276-
def createEditor(self, parent, option, index):
277-
editor = QtWidgets.QLineEdit(parent)
278-
locale = QtCore.QLocale(QtCore.QLocale.English)
279-
locale.setNumberOptions(QtCore.QLocale.RejectGroupSeparator)
280-
validator = QtGui.QRegularExpressionValidator(
281-
QtCore.QRegularExpression(r"^[+-]?((\d+(\.\d*)?)|(\.\d+))([eE][+-]?\d+)?$"),
282-
editor)
283-
validator.setLocale(locale)
284-
editor.setValidator(validator)
285-
return editor
286-
287-
def setEditorData(self, editor: QtWidgets.QLineEdit, index: QtCore.QModelIndex):
288-
"""Populate the editor with data if editing an existing field."""
289-
import math
290-
291-
data = index.data(QtCore.Qt.DisplayRole)
292-
293-
try:
294-
value = abs(float(data))
295-
except ValueError:
296-
value = math.nan
297-
298-
editor.setText(format(value, '.10f').rstrip('0').rstrip('.'))
299-
300-
def setModelData(
301-
self,
302-
editor: QtWidgets.QLineEdit,
303-
model: QtCore.QAbstractItemModel,
304-
index: QtCore.QModelIndex,
305-
):
306-
"""Take the editor, read the given value and set it in the model"""
307-
try:
308-
value = float(editor.text())
309-
old = float(index.data(QtCore.Qt.DisplayRole))
310-
311-
if old < 0:
312-
value = value * -1
313-
314-
model.setData(index, value, QtCore.Qt.EditRole)
315-
except ValueError:
316-
pass
317-
318-
319264
class ExchangesView(widgets.ABTreeView):
320265
"""
321266
A view that displays the exchanges in a tree structure.
@@ -325,7 +270,7 @@ class ExchangesView(widgets.ABTreeView):
325270
hovered_item (ExchangesItem): The item currently being hovered over.
326271
"""
327272
defaultColumnDelegates = {
328-
"amount": ExchangeAmountDelegate,
273+
"amount": delegates.AmountDelegate,
329274
"allocation_factor": delegates.FloatDelegate,
330275
"substitution_factor": delegates.FloatDelegate,
331276
"unit": delegates.StringDelegate,

activity_browser/layouts/pages/calculation_setup/functional_unit_section.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from qtpy import QtWidgets
2+
from qtpy.QtCore import Qt
23

34
import bw2data as bd
45
import pandas as pd
56

67
from activity_browser import actions
7-
from activity_browser.ui import widgets, icons
8+
from activity_browser.ui import widgets, icons, delegates
89
from activity_browser.bwutils import AB_metadata
910

1011

@@ -46,6 +47,7 @@ def build_df(self):
4647
act_df = AB_metadata.get_metadata(keys, cols)
4748
act_df["amount"] = amounts
4849
act_df["_activity_key"] = keys
50+
act_df["_cs_name"] = self.calculation_setup_name
4951

5052
act_df["_processor_key"] = act_df["processor"]
5153
act_df["_processor_key"] = act_df["_processor_key"].fillna(act_df["_activity_key"])
@@ -73,12 +75,15 @@ def build_df(self):
7375
act_df.update(act_df["product"].rename("name"))
7476
act_df["product"] = act_df["name"]
7577

76-
cols = ["amount", "unit", "product", "process", "database", "location", "_processor_key", "_activity_key"]
78+
cols = ["amount", "unit", "product", "process", "database", "location", "_processor_key", "_activity_key", "_cs_name"]
7779

7880
return act_df[cols].reset_index(drop=True)
7981

8082

8183
class FunctionalUnitView(widgets.ABTreeView):
84+
defaultColumnDelegates = {
85+
"amount": delegates.AmountDelegate
86+
}
8287

8388
class ContextMenu(widgets.ABMenu):
8489
menuSetup = [
@@ -119,10 +124,16 @@ def mouseDoubleClickEvent(self, event) -> None:
119124
Args:
120125
event: The mouse double click event.
121126
"""
127+
index = self.indexAt(event.pos())
128+
if index.column() == 0:
129+
return super().mouseDoubleClickEvent(event)
130+
122131
if self.selectedIndexes():
123132
activities = [index.internalPointer()["_processor_key"] for index in self.selectedIndexes()]
124133
actions.ActivityOpen.run(list(set(activities)))
125134

135+
return None
136+
126137
def dragMoveEvent(self, event) -> None:
127138
pass
128139

@@ -158,6 +169,45 @@ def decorationData(self, col: int, key: str):
158169
return icons.qicons.product
159170
if key == "process":
160171
return icons.qicons.process
172+
return super().decorationData(col, key)
173+
174+
def flags(self, col: int, key: str):
175+
"""
176+
Returns the item flags for the given column and key.
177+
178+
Args:
179+
col (int): The column index.
180+
key (str): The key for which to return the flags.
181+
182+
Returns:
183+
QtCore.Qt.ItemFlags: The item flags.
184+
"""
185+
flags = super().flags(col, key)
186+
if key in ["amount"]:
187+
return flags | Qt.ItemFlag.ItemIsEditable
188+
return flags
189+
190+
def setData(self, col: int, key: str, value) -> bool:
191+
"""
192+
Sets the data for the given column and key.
193+
194+
Args:
195+
col (int): The column index.
196+
key (str): The key for which to set the data.
197+
value: The value to set.
198+
199+
Returns:
200+
bool: True if the data was set successfully, False otherwise.
201+
"""
202+
if key not in ["amount"]:
203+
return False
204+
205+
cs_name = self["_cs_name"]
206+
index = self.key()
207+
208+
actions.CSChangeFunctionalUnit.run(cs_name, index, value)
209+
210+
161211

162212

163213
class FunctionalUnitModel(widgets.ABItemModel):

activity_browser/ui/delegates/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
from .new_formula import NewFormulaDelegate
1515
from .date_time import DateTimeDelegate
1616
from .property import PropertyDelegate
17+
from .amount import AmountDelegate
1718

1819
__all__ = [
20+
"AmountDelegate",
1921
"CheckboxDelegate",
2022
"ComboBoxDelegate",
2123
"DatabaseDelegate",
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from qtpy import QtCore, QtGui, QtWidgets
2+
3+
class AmountDelegate(QtWidgets.QStyledItemDelegate):
4+
def displayText(self, value, locale):
5+
import math
6+
try:
7+
value = float(value)
8+
except ValueError:
9+
value = math.nan
10+
11+
if math.isnan(value):
12+
return ""
13+
return str(abs(value))
14+
15+
def createEditor(self, parent, option, index):
16+
editor = QtWidgets.QLineEdit(parent)
17+
locale = QtCore.QLocale(QtCore.QLocale.English)
18+
locale.setNumberOptions(QtCore.QLocale.RejectGroupSeparator)
19+
validator = QtGui.QRegularExpressionValidator(
20+
QtCore.QRegularExpression(r"^[+-]?((\d+(\.\d*)?)|(\.\d+))([eE][+-]?\d+)?$"),
21+
editor)
22+
validator.setLocale(locale)
23+
editor.setValidator(validator)
24+
return editor
25+
26+
def setEditorData(self, editor: QtWidgets.QLineEdit, index: QtCore.QModelIndex):
27+
"""Populate the editor with data if editing an existing field."""
28+
import math
29+
30+
data = index.data(QtCore.Qt.DisplayRole)
31+
32+
try:
33+
value = abs(float(data))
34+
except ValueError:
35+
value = math.nan
36+
37+
editor.setText(format(value, '.10f').rstrip('0').rstrip('.'))
38+
39+
def setModelData(
40+
self,
41+
editor: QtWidgets.QLineEdit,
42+
model: QtCore.QAbstractItemModel,
43+
index: QtCore.QModelIndex,
44+
):
45+
"""Take the editor, read the given value and set it in the model"""
46+
try:
47+
value = float(editor.text())
48+
old = float(index.data(QtCore.Qt.DisplayRole))
49+
50+
if old < 0:
51+
value = value * -1
52+
53+
model.setData(index, value, QtCore.Qt.EditRole)
54+
except ValueError:
55+
pass

0 commit comments

Comments
 (0)