Skip to content

Commit

Permalink
Refactor history table (#264)
Browse files Browse the repository at this point in the history
* Implement history table from dataframe view

* Remove TableWidget code

* Allow PandasModel to color values by both brightway and AB names
  • Loading branch information
dgdekoning authored Aug 21, 2019
1 parent 70ec110 commit 22d92dd
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 55 deletions.
129 changes: 74 additions & 55 deletions activity_browser/app/ui/tables/history.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,89 @@
# -*- coding: utf-8 -*-
import brightway2 as bw
from PyQt5 import QtCore, QtGui, QtWidgets
import pandas as pd
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QCursor
from PyQt5.QtWidgets import QAbstractItemView, QMenu

from . table import ABTableWidget, ABTableItem
from ..icons import icons
from ...signals import signals
from activity_browser.app.bwutils.commontasks import bw_keys_to_AB_names
from activity_browser.app.signals import signals

from .views import ABDataFrameView, dataframe_sync
from ..icons import qicons

class ActivitiesHistoryTable(ABTableWidget):
MAX_LENGTH = 40
COLUMNS = {
0: "name",
1: "reference product",
2: "location",
3: "unit",
}
HEADERS = ["Activity", "Reference Product", "Location", "Unit"]

def __init__(self, *args):
super(ActivitiesHistoryTable, self).__init__(*args)
class ActivitiesHistoryTable(ABDataFrameView):
COLUMNS = [
"name",
"reference product",
"location",
"unit",
]
HEADERS = [bw_keys_to_AB_names[c] for c in COLUMNS] + ["key"]

def __init__(self, parent=None):
super().__init__(parent=parent)
self.setDragEnabled(True)
self.setRowCount(0)
self.setColumnCount(len(self.HEADERS))
self.setup_context_menu()
self.connect_signals()
self.setSelectionMode(QAbstractItemView.SingleSelection)
self.sync()
self._connect_signals()

def setup_context_menu(self):
self.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.open_left_tab_action = QtWidgets.QAction(
QtGui.QIcon(icons.left), "Open in new tab", None
)
self.addAction(self.open_left_tab_action)
self.open_left_tab_action.triggered.connect(
lambda x: signals.open_activity_tab.emit(
self.currentItem().key
)
)
def _connect_signals(self):
self.doubleClicked.connect(self.open_tab_event)
signals.add_activity_to_history.connect(self.add_activity)
signals.project_selected.connect(self.sync)

def connect_signals(self):
self.itemDoubleClicked.connect(
lambda x: signals.open_activity_tab.emit(self.currentItem().key)
)
self.itemDoubleClicked.connect(
lambda x: signals.add_activity_to_history.emit(x.key)
@dataframe_sync
def sync(self, df=None):
if df is None:
df = pd.DataFrame([], columns=self.HEADERS)
self.dataframe = df

def contextMenuEvent(self, a0):
menu = QMenu(self)
menu.addAction(
qicons.right, "Open in new tab", self.open_tab
)
signals.add_activity_to_history.connect(self.add_activity)
signals.project_selected.connect(self.clear_history)
menu.popup(QCursor.pos())
menu.exec()

@pyqtSlot()
def open_tab(self):
""" Only a single row can be selected for the history,
trigger the open_tab_event.
"""
proxy = next(i for i in self.selectedIndexes())
self.open_tab_event(proxy)

def open_tab_event(self, proxy):
index = self.get_source_index(proxy)
key = self.dataframe.iloc[index.row(), ]["key"]
signals.open_activity_tab.emit(key)
self.add_activity(key)

def add_activity(self, key):
for row in range(self.rowCount()):
if self.item(row, 0).key == key:
self.removeRow(row)
break # otherwise iterating over object that has changed
@pyqtSlot(tuple)
def add_activity(self, key: tuple) -> None:
row = self.dataframe.loc[self.dataframe["key"].isin([key])]

ds = bw.get_activity(key)
self.insertRow(0)
for col, value in self.COLUMNS.items():
if value == 'location':
self.setItem(0, col, ABTableItem(str(ds.get(value, '')), key=key, color=value))
else:
self.setItem(0, col, ABTableItem(ds.get(value, ''), key=key, color=value))
if not row.empty:
# As data now exists in row, drop it from the dataframe
self.dataframe.drop(row.index, inplace=True)
else:
# Data didn't exist, so build a new row with the key
ds = bw.get_activity(key)
data = {
self.HEADERS[i]: ds.get(self.COLUMNS[i], "")
for i in range(len(self.COLUMNS))
}
data["key"] = key
row = pd.DataFrame(
[data], index=[0], columns=self.HEADERS
)

# Rebuild model with dataframe, added activity is placed at start
self.sync(pd.concat([row, self.dataframe]).reset_index(drop=True))

def _resize(self):
self.setColumnHidden(4, True) # Hide the 'key' column
self.resizeColumnsToContents()
self.resizeRowsToContents()

def clear_history(self):
self.clear()
self.setHorizontalHeaderLabels(self.HEADERS)
self.setRowCount(0)
3 changes: 3 additions & 0 deletions activity_browser/app/ui/tables/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from PyQt5.QtGui import QBrush

from ..style import style_item
from ...bwutils.commontasks import AB_names_to_bw_keys


class PandasModel(QAbstractTableModel):
Expand Down Expand Up @@ -34,6 +35,8 @@ def data(self, index, role=Qt.DisplayRole):

if role == Qt.ForegroundRole:
col_name = self._dataframe.columns[index.column()]
if col_name not in style_item.brushes:
col_name = AB_names_to_bw_keys.get(col_name, "")
return QBrush(style_item.brushes.get(col_name, style_item.brushes.get("default")))

return None
Expand Down

0 comments on commit 22d92dd

Please sign in to comment.