Skip to content

Commit a357541

Browse files
Add traitsUI widgets to filter a folder view.
1 parent 23b317a commit a357541

1 file changed

Lines changed: 95 additions & 21 deletions

File tree

stage5.3_fuller_application/pycasa/ui/image_folder_view.py

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
# General imports
22

33
# ETS imports
4-
from traits.api import Button, Instance, observe
5-
from traitsui.api import HGroup, Item, Label, ModelView, Spring, View
4+
import numpy as np
5+
import pandas as pd
6+
from traits.api import Bool, Button, Enum, Instance, List, observe
7+
from traitsui.api import HGroup, Item, Label, ListStrEditor, ModelView, \
8+
Spring, VGroup, View
69
from traitsui.ui_editors.data_frame_editor import DataFrameEditor
10+
711
# Local imports
8-
from ..model.image_folder import ImageFolder
12+
from ..model.image_folder import FILENAME_COL, ImageFolder, NUM_FACE_COL
913

1014

11-
DISPLAYED_COLUMNS = [
15+
DISPLAYED_COLUMNS = [FILENAME_COL, NUM_FACE_COL] + [
1216
'ApertureValue', 'ExifVersion', 'Model', 'Make', 'LensModel', 'DateTime',
13-
'ShutterSpeedValue', 'XResolution', 'YResolution'
17+
'ShutterSpeedValue', 'ExposureTime', 'XResolution', 'YResolution',
18+
'Orientation', 'GPSInfo', 'DigitalZoomRatio', 'FocalLengthIn35mmFilm',
19+
'ISOSpeedRatings', 'SceneType'
1420
]
1521

1622

@@ -21,28 +27,96 @@ class ImageFolderView(ModelView):
2127

2228
scan = Button("Scan for faces...")
2329

24-
view = View(
25-
Item("model.path", style="readonly", show_label=False),
26-
Item("model.data", editor=DataFrameEditor(columns=DISPLAYED_COLUMNS,
27-
update="data_updated"),
28-
show_label=False, visible_when="len(model.data) > 0"),
29-
HGroup(
30-
Spring(),
31-
Label("No images found. No data to show"),
32-
Spring(),
33-
visible_when="len(model.data) == 0",
34-
),
35-
HGroup(
36-
Spring(),
37-
Item("scan", show_label=False, enabled_when="len(model.data) > 0"),
38-
Spring(),
30+
# Filters widgets
31+
view_filter_controls = Bool
32+
33+
filtered_data = Instance(pd.DataFrame)
34+
35+
year_mask = Instance(pd.Series)
36+
37+
selected_years = List
38+
39+
all_years = List
40+
41+
selected_make = Enum(["All", "Canon", "Nikon", "Sony", "Apple", "samsung"])
42+
43+
make_mask = Instance(pd.Series)
44+
45+
def traits_view(self):
46+
view = View(
47+
Item("model.path", style="readonly", show_label=False),
48+
HGroup(
49+
Spring(),
50+
Item("view_filter_controls"),
51+
),
52+
HGroup(
53+
Item("all_years", label="Years",
54+
editor=ListStrEditor(selected="selected_years",
55+
multi_select=True)
56+
),
57+
Item("selected_make", label="Camera make"),
58+
visible_when="view_filter_controls",
59+
),
60+
Item("filtered_data",
61+
editor=DataFrameEditor(columns=DISPLAYED_COLUMNS,
62+
update="data_updated"),
63+
show_label=False, visible_when="len(model.data) > 0"),
64+
HGroup(
65+
Spring(),
66+
Label("No images found. No data to show"),
67+
Spring(),
68+
visible_when="len(model.data) == 0",
69+
),
70+
HGroup(
71+
Spring(),
72+
Item("scan", show_label=False,
73+
enabled_when="len(model.data) > 0"),
74+
Spring(),
75+
),
76+
resizable=True, height=800
3977
)
40-
)
78+
return view
79+
80+
# Listener methods --------------------------------------------------------
4181

4282
@observe("scan")
4383
def scan_for_faces(self, event):
4484
self.model.compute_num_faces()
4585

86+
@observe("selected_years")
87+
def update_years(self, event):
88+
self.year_mask = self.model.data['Year'].isin(self.selected_years)
89+
90+
@observe("selected_make")
91+
def update_make(self, event):
92+
if self.selected_make == "All":
93+
self.make_mask = pd.Series(np.ones(len(self.model.data),
94+
dtype=bool))
95+
else:
96+
self.make_mask = self.model.data['Make'] == self.selected_make
97+
98+
@observe("year_mask, make_mask")
99+
def update_filtered_data(self, event):
100+
self.filtered_data = self.model.data[self.year_mask & self.make_mask]
101+
102+
# Initialization methods --------------------------------------------------
103+
104+
def _make_mask_default(self):
105+
return pd.Series(np.ones(len(self.model.data), dtype=bool))
106+
107+
def _year_mask_default(self):
108+
return pd.Series(np.ones(len(self.model.data), dtype=bool))
109+
110+
def _filtered_data_default(self):
111+
return self.model.data
112+
113+
def _all_years_default(self):
114+
def parse_year(x):
115+
return x.split(":")[0] if isinstance(x, str) else "unknown"
116+
117+
self.model.data['Year'] = self.model.data['DateTime'].apply(parse_year)
118+
return sorted(self.model.data['Year'].unique().tolist())
119+
46120

47121
if __name__ == '__main__':
48122
from os.path import dirname, join

0 commit comments

Comments
 (0)