Skip to content

Commit 87fcd30

Browse files
committed
Fixed the old pnlDataTable and split it into MVC
1 parent c45ae68 commit 87fcd30

File tree

5 files changed

+231
-96
lines changed

5 files changed

+231
-96
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from wx.lib.pubsub import pub as Publisher
2+
from view.clsDataTable import DataTable
3+
import pandas as pd
4+
import numpy as np
5+
6+
import wx
7+
__author__ = 'jmeline'
8+
9+
10+
class FrmDataTable(DataTable):
11+
def __init__(self, parent, **kwargs):
12+
self.parent = parent
13+
self.memDB = None
14+
DataTable.__init__(self, parent, **kwargs)
15+
16+
def init_publishers(self):
17+
Publisher.subscribe(self.onChangeSelection, "changeTableSelection")
18+
Publisher.subscribe(self.onRefresh, "refreshTable")
19+
Publisher.subscribe(self.olvDataTable.onDeselectAll, "deselectAllDataTable")
20+
21+
def init(self, memDB):
22+
self.olvDataTable.init(memDB)
23+
24+
def onItemSelected(self, event):
25+
pass
26+
27+
def onRefresh(self, e):
28+
self.olvDataTable.dataframe = self.memDB.getDataValuesDF()
29+
self.dataObjects = self.olvDataTable.dataframe.values.tolist()
30+
# self.myOlv.RefreshItems()
31+
32+
def onChangeSelection(self, datetime_list=None):
33+
"""
34+
Select values within
35+
"""
36+
self.olvDataTable.onDeselectAll()
37+
38+
if isinstance(datetime_list, pd.DataFrame):
39+
try:
40+
self.enableSelectDataTable = True
41+
olv = self.olvDataTable.dataframe.set_index("LocalDateTime")
42+
filtered_dataframe = self.olvDataTable.dataframe[olv.index.isin(datetime_list.index)]
43+
results = np.where(self.olvDataTable.dataframe.index.isin(filtered_dataframe.index))
44+
45+
for i in results[0]:
46+
self.olvDataTable.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)
47+
self.olvDataTable.Focus(results[0][0])
48+
self.enableSelectDataTable = False
49+
except:
50+
pass
51+
52+
if __name__ == "__main__":
53+
app = wx.App()
54+
frame = wx.Frame(None)
55+
panel = FrmDataTable(frame)
56+
frame.Show()
57+
app.MainLoop()
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import wx
2+
import logging
3+
from odmtools.common.logger import LoggerTool
4+
from lib.ObjectListView import VirtualObjectListView, ObjectListView, ColumnDefn
5+
import pandas as pd
6+
7+
tool = LoggerTool()
8+
logger = tool.setupLogger(__name__, __name__ + '.log', 'w', logging.DEBUG)
9+
10+
__author__ = 'jmeline'
11+
12+
13+
class OLVDataTable(VirtualObjectListView):
14+
def __init__(self, parent, **kwargs):
15+
VirtualObjectListView.__init__(self, parent, **kwargs)
16+
self.SetEmptyListMsg("No Series Selected for Editing")
17+
self.EnableSorting()
18+
self.sortedColumnIndex = -1
19+
self.currentItem = None
20+
self.dataframe = None
21+
22+
def init(self, memDB):
23+
self.memDB = memDB
24+
columns = [ColumnDefn(x.strip(), align="left", valueGetter=i, minimumWidth=125, width=125,
25+
stringConverter='%Y-%m-%d %H:%M:%S' if "date" in x.lower() else '%s')
26+
for x, i in self.memDB.getEditColumns()]
27+
self.useAlternateBackColors = True
28+
self.oddRowsBackColor = wx.Colour(191, 217, 217)
29+
self.SetColumns(columns)
30+
self.dataframe = self.memDB.getDataValuesDF()
31+
sort_by_index = list(self.dataframe.columns).index("LocalDateTime")
32+
self.dataframe.sort(self.dataframe.columns[sort_by_index], inplace=True)
33+
self.dataObjects = self.dataframe.values.tolist()
34+
35+
self.SetObjectGetter(self.ObjectGetter)
36+
self.SetItemCount(len(self.dataframe))
37+
38+
def EnableSorting(self):
39+
self.Bind(wx.EVT_LIST_COL_CLICK, self.onColSelected)
40+
if not self.smallImageList:
41+
self.SetImageLists()
42+
if (not self.smallImageList.HasName(ObjectListView.NAME_DOWN_IMAGE) and
43+
self.smallImageList.GetSize(0) == (16, 16)):
44+
self.RegisterSortIndicators()
45+
46+
def ObjectGetter(self, index):
47+
"""
48+
A Virtual list has to have a callable installed that says which model object is shown
49+
at a given index
50+
"""
51+
return self.dataObjects[index % len(self.dataObjects)]
52+
53+
def onColSelected(self, evt):
54+
"""
55+
Allows users to sort by clicking on columns
56+
"""
57+
if isinstance(self.dataframe, pd.DataFrame):
58+
if self.dataframe.empty:
59+
return
60+
else:
61+
if not self.dataframe:
62+
return
63+
64+
logger.debug("Column: %s" % evt.m_col)
65+
self.sortColumn(evt.m_col)
66+
67+
def sortColumn(self, selected_column):
68+
oldSortColumnIndex = self.sortedColumnIndex
69+
self.sortedColumnIndex = selected_column
70+
ascending = self.sortAscending
71+
if ascending:
72+
self.dataframe.sort(self.dataframe.columns[selected_column], inplace=True)
73+
self.sortAscending = False
74+
elif not ascending:
75+
self.dataframe.sort(self.dataframe.columns[selected_column], ascending=False, inplace=True)
76+
self.sortAscending = True
77+
78+
self._UpdateColumnSortIndicators(selected_column, oldSortColumnIndex)
79+
80+
self.dataObjects = self.dataframe.values.tolist()
81+
if self.GetItemCount:
82+
itemFrom = self.GetTopItem()
83+
itemTo = self.GetTopItem() + 1 + self.GetCountPerPage()
84+
itemTo = min(itemTo, self.GetItemCount() - 1)
85+
self.RefreshItems(itemFrom, itemTo)
86+
87+
def onItemSelected(self, event):
88+
"""
89+
90+
Disable selecting of an item in the DataTable, only sorting is available
91+
"""
92+
if not self.enableSelectDataTable:
93+
self.SetItemState(event.m_itemIndex, 0, wx.LIST_STATE_SELECTED)
94+
95+
def onDeselectAll(self):
96+
selected_item = self.GetFirstSelected()
97+
while selected_item != -1:
98+
self.SetItemState(selected_item, 0, wx.LIST_STATE_SELECTED)
99+
selected_item = self.GetNextSelected(selected_item)
100+
101+
def _rowFormatter(self, listItem, object):
102+
"""Handles the formatting of rows for object list view
103+
:param: wx.ListCtrl listitem
104+
:param: ModelObject object
105+
106+
:rtype: None
107+
"""
108+
objects = self.GetSelectedObjects()
109+
110+
# if self.currentItem and object in self.currentItem:
111+
if objects and object in objects:
112+
113+
# font type: wx.DEFAULT, wx.DECORATIVE, wx.ROMAN, wx.SCRIPT, wx.SWISS, wx.MODERN
114+
# slant: wx.NORMAL, wx.SLANT or wx.ITALIC
115+
# weight: wx.NORMAL, wx.LIGHT or wx.BOLD
116+
#font1 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.NORMAL)
117+
# use additional fonts this way ...
118+
#font1 = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Comic Sans MS')
119+
listItem.SetFont(
120+
wx.Font(9, wx.DECORATIVE, wx.ITALIC, wx.BOLD))
121+
else:
122+
listItem.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))

odmtools/gui/frmODMTools.py

Lines changed: 5 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import wx
1010
import sys
1111
import os
12+
from controller.frmDataTable import FrmDataTable
1213
import mnuRibbon
1314
import pnlPlot
1415
import pnlDataTable
@@ -231,8 +232,9 @@ def _init_ctrls(self, series_service):
231232

232233
####################grid Table View##################
233234
logger.debug("Loading DataTable ...")
234-
self.dataTable = pnlDataTable.pnlDataTable(self.pnlDocking)
235-
self.dataTable.toggleBindings()
235+
self.dataTable = FrmDataTable(self.pnlDocking)
236+
# self.dataTable = pnlDataTable.pnlDataTable(self.pnlDocking)
237+
# self.dataTable.toggleBindings()
236238
############# Script & Console ###############
237239
logger.debug("Loading Python Console ...")
238240
self.txtPythonConsole = ODMToolsConsole(parent=self.pnlDocking, size=wx.Size(200, 200))
@@ -300,52 +302,6 @@ def _init_aui_manager(self):
300302
self.refreshConnectionInfo()
301303
self._mgr.Update()
302304

303-
def _init_sizers(self):
304-
# generated method, don't edit
305-
self.s = wx.BoxSizer(wx.VERTICAL)
306-
self._init_s_Items(self.s)
307-
self.SetSizer(self.s)
308-
309-
def _init_s_Items(self, parent):
310-
# generated method, don't edit
311-
parent.AddWindow(self._ribbon, 0, wx.EXPAND)
312-
parent.AddWindow(self.pnlDocking, 85, flag=wx.ALL | wx.EXPAND)
313-
314-
def servicesValid(self, service, displayMsg=True):
315-
"""
316-
317-
:param displayMsg:
318-
Option to display a message box if there is an issue with a service. Default: True
319-
:return:
320-
"""
321-
valid = True
322-
323-
## Test if Series Catalog is empty
324-
if not service.get_used_sites():
325-
if displayMsg:
326-
msg = wx.MessageDialog(None,
327-
'Series Catalog cannot be empty. Please enter in a new database connection',
328-
'Series Catalog is empty', wx.OK | wx.ICON_ERROR)
329-
msg.ShowModal()
330-
valid = False
331-
332-
# @TODO If Jeff runs into other issues with services not being available, we can simply test different services here
333-
# if not service.get_all_variables():
334-
# valid = False
335-
336-
return valid
337-
338-
def on_about_request(self, event):
339-
frmAbout(self)
340-
341-
def MacReopenApp(self):
342-
"""Called when the doc icon is clicked, and ???"""
343-
344-
try: # it's possible for this event to come when the frame is closed
345-
self.GetTopWindow().Raise()
346-
except:
347-
pass
348-
349305
def refreshConnectionInfo(self):
350306
"""Updates the Series Selector Connection Information for the user"""
351307

@@ -363,7 +319,7 @@ def onDocking(self, value):
363319

364320
if value == "Table":
365321
paneDetails = self._mgr.GetPane(self.dataTable)
366-
self.dataTable.toggleBindings()
322+
# self.dataTable.toggleBindings()
367323

368324
elif value == "Selector":
369325
paneDetails = self._mgr.GetPane(self.pnlSelector)

odmtools/gui/pnlDataTable.py

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
from odmtools.common.logger import LoggerTool
1414

15-
1615
tool = LoggerTool()
1716
logger = tool.setupLogger(__name__, __name__ + '.log', 'w', logging.DEBUG)
1817

@@ -34,7 +33,7 @@ def _init_ctrls(self):
3433
parent=self.parent, size=wx.Size(677, 449),
3534
style=wx.TAB_TRAVERSAL)
3635
# self.record_service = self.parent.Parent.getRecordService()
37-
self.myOlv = VirtualObjectListView(self, -1, style=wx.LC_REPORT)
36+
self.myOlv = VirtualObjectListView(self, style=wx.LC_REPORT)
3837

3938
self.myOlv.SetEmptyListMsg("No Series Selected for Editing")
4039
self.currentItem = None
@@ -59,29 +58,29 @@ def _init_ctrls(self):
5958

6059

6160

62-
def toggleBindings(self):
63-
""" Activates/Deactivates Datatable specific bindings
64-
65-
:param activate:
66-
:return:
67-
"""
68-
69-
if self.toggle():
70-
#logger.info("binding activated...")
71-
try:
72-
self.myOlv.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onItemSelected, id=self.myOlv.GetId())
73-
self.myOlv.Bind(wx.EVT_CHAR, self.onKeyPress, id=self.myOlv.GetId())
74-
self.myOlv.Bind(wx.EVT_LIST_KEY_DOWN, self.onKeyPress, id=self.myOlv.GetId())
75-
except:
76-
pass
77-
else:
78-
#logger.info("binding deactivated...")
79-
try:
80-
self.myOlv.Unbind(wx.EVT_LIST_ITEM_FOCUSED, self.onItemSelected, id=self.myOlv.GetId())
81-
self.myOlv.Unbind(wx.EVT_CHAR, self.onKeyPress, id=self.myOlv.GetId())
82-
self.myOlv.Unbind(wx.EVT_LIST_KEY_DOWN, self.onKeyPress, id=self.myOlv.GetId())
83-
except:
84-
pass
61+
# def toggleBindings(self):
62+
# """ Activates/Deactivates Datatable specific bindings
63+
#
64+
# :param activate:
65+
# :return:
66+
# """
67+
#
68+
# if self.toggle():
69+
# #logger.info("binding activated...")
70+
# try:
71+
# self.myOlv.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onItemSelected, id=self.myOlv.GetId())
72+
# self.myOlv.Bind(wx.EVT_CHAR, self.onKeyPress, id=self.myOlv.GetId())
73+
# self.myOlv.Bind(wx.EVT_LIST_KEY_DOWN, self.onKeyPress, id=self.myOlv.GetId())
74+
# except:
75+
# pass
76+
# else:
77+
# #logger.info("binding deactivated...")
78+
# try:
79+
# self.myOlv.Unbind(wx.EVT_LIST_ITEM_FOCUSED, self.onItemSelected, id=self.myOlv.GetId())
80+
# self.myOlv.Unbind(wx.EVT_CHAR, self.onKeyPress, id=self.myOlv.GetId())
81+
# self.myOlv.Unbind(wx.EVT_LIST_KEY_DOWN, self.onKeyPress, id=self.myOlv.GetId())
82+
# except:
83+
# pass
8584

8685
def init(self, memDB):
8786
self.memDB = memDB
@@ -206,28 +205,6 @@ def onKeyPress(self, evt):
206205
def stopEdit(self):
207206
self.clear()
208207

209-
def _rowFormatter(self, listItem, object):
210-
"""Handles the formatting of rows for object list view
211-
:param: wx.ListCtrl listitem
212-
:param: ModelObject object
213-
214-
:rtype: None
215-
"""
216-
objects = self.myOlv.GetSelectedObjects()
217-
218-
#if self.currentItem and object in self.currentItem:
219-
if objects and object in objects:
220-
221-
# font type: wx.DEFAULT, wx.DECORATIVE, wx.ROMAN, wx.SCRIPT, wx.SWISS, wx.MODERN
222-
# slant: wx.NORMAL, wx.SLANT or wx.ITALIC
223-
# weight: wx.NORMAL, wx.LIGHT or wx.BOLD
224-
#font1 = wx.Font(10, wx.SWISS, wx.ITALIC, wx.NORMAL)
225-
# use additional fonts this way ...
226-
#font1 = wx.Font(10, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Comic Sans MS')
227-
listItem.SetFont(
228-
wx.Font(9, wx.DECORATIVE, wx.ITALIC, wx.BOLD))
229-
else:
230-
listItem.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma'))
231208

232209

233210

odmtools/view/clsDataTable.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from controller.olvDataTable import OLVDataTable
2+
3+
__author__ = 'jmeline'
4+
5+
import wx
6+
class DataTable(wx.Panel):
7+
def __init__(self, parent, **kwargs):
8+
kwargs['name'] = u'pnlDataTable'
9+
kwargs['parent'] = parent
10+
kwargs['size'] = wx.Size(677, 449)
11+
kwargs['style'] = wx.TAB_TRAVERSAL
12+
wx.Panel.__init__(self, **kwargs)
13+
14+
self.olvDataTable = OLVDataTable(self)
15+
sizer_2 = wx.BoxSizer(wx.VERTICAL)
16+
sizer_2.Add(self.olvDataTable, 1, wx.ALL | wx.EXPAND, 4)
17+
self.SetSizer(sizer_2)
18+
self.Layout()
19+
20+
21+
# Overridden in base class
22+
def onItemSelected(self, event):
23+
event.Skip()

0 commit comments

Comments
 (0)