Skip to content

Commit 289d00d

Browse files
committed
Merge 'improve-parameter-fixed-checkboxes' into maint
* take empty parameter-fixed value as False * improve behavior of parameter-fixed checkboxes * add tests to cover changed methods * fix spurious call to needsSave * support execution of wx GUI on travis Closes #32.
2 parents fe47600 + d9d39c6 commit 289d00d

3 files changed

Lines changed: 174 additions & 34 deletions

File tree

.travis.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ addons:
3131
- python-dev
3232
- python-numpy
3333
- python-setuptools
34+
- python-wxtools
3435

3536
before_install:
3637
- MYNAME=diffpy.pdfgui
@@ -95,8 +96,17 @@ install:
9596
exit 1;
9697
fi
9798

99+
before_script:
100+
# provide shell functions to execute coverage with GUI support
101+
- case ${TRAVIS_OS_NAME} in
102+
linux)
103+
guicoverage() { xvfb-run coverage "$@"; } ;;
104+
osx)
105+
guicoverage() { pythonw -m coverage "$@"; } ;;
106+
esac
107+
98108
script:
99-
- coverage run --source ${MYNAME} -m ${MYNAME}.tests.rundeps
109+
- guicoverage run --source ${MYNAME} -m ${MYNAME}.tests.rundeps
100110

101111
after_success:
102112
- pip install $MYPIPFLAGS codecov

src/diffpy/pdfgui/gui/parameterspanel.py

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -141,29 +141,26 @@ def refresh(self):
141141
self.grid_parameters.AutoSizeColumns()
142142
self.grid_parameters.EndBatch()
143143

144-
# FIXME
145-
# When selecting a block, this should be bypassed.
146-
#
147-
# I've tried really hard. I can't get it to work right.
148-
#
149-
# The problem: A left-click also generates a range-select event. When an
150-
# actual range is selected, it generates two selection events, one at the
151-
# start and one at the end of the selection. However, the one at the start
152-
# of the selection does not highlight a cell, and therefore gives no
153-
# coordinates.
144+
154145
def onCellLeftClick(self, event): # wxGlade: ParametersPanel.<event_handler>
155-
"""Toggle a fix/free cell when it is selected."""
156-
# Toggle the check box if it is selected
146+
"""Toggle a fix/free cell when clicked."""
157147
r = event.GetRow()
158148
c = event.GetCol()
159-
if c == 1:
160-
self.grid_parameters.SelectBlock(r,c,r,c)
161-
self.onPopupFixFree(event)
162-
# Don't actually select the cell until we're sure its not part of a
163-
# block. This is handled by onGridRangeSelect.
164-
event.Skip()
149+
# Only proceed if there is no selection and
150+
# this click has no keyboard modifiers.
151+
ignorethis = (c != 1 or self.grid_parameters.IsSelection() or
152+
event.ShiftDown() or event.ControlDown())
153+
if ignorethis:
154+
# do standard click event handling
155+
event.Skip()
156+
return
157+
# We consume the event here. This prevents focusing the clicked
158+
# cell after a click, but that is not necessary for a checkbox.
159+
state = int(self.grid_parameters.GetCellValue(r, c) or 0)
160+
self.applyCellChange(r, c, not state)
165161
return
166162

163+
167164
def onGridRangeSelect(self, event): # wxGlade: ParametersPanel.<event_handler>
168165
"""Handle range selections.
169166
@@ -256,19 +253,16 @@ def applyCellChange(self, row, col, value):
256253
self.mainFrame.needsSave()
257254

258255
elif col == 1: # flag "fixed"
259-
try:
260-
temp = self.parameters[key].fixed
261-
value = bool(int(value))
262-
if temp != value:
263-
self.parameters[key].fixed = value
264-
self.grid_parameters.SetCellValue(row,1,str(int(value)))
265-
self.mainFrame.needsSave()
266-
except ValueError:
267-
pass
256+
temp = bool(self.parameters[key].fixed)
257+
value = bool(int(value))
258+
if temp is not value:
259+
self.parameters[key].fixed = value
260+
self.grid_parameters.SetCellValue(row,1,str(int(value)))
261+
self.mainFrame.needsSave()
268262

269-
self.mainFrame.needsSave()
270263
return
271264

265+
272266
def popupMenu(self, window, x, y):
273267
"""Opens a popup menu
274268
@@ -337,11 +331,8 @@ def onPopupFixFree(self, event):
337331
indices = self.getSelectedParameters()
338332
for row in indices:
339333
state = self.grid_parameters.GetCellValue(row,1)
340-
# This might be triggered when we enter into edit mode, but the
341-
# grid cell will have a '' value. Check for that and ignore it.
342-
if state:
343-
state = bool(int(state))
344-
seldict[row] = state
334+
state = bool(int(state.strip() or "0"))
335+
seldict[row] = state
345336

346337
# Find the majority state
347338
nfixed = seldict.values().count(True)
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/usr/bin/env python
2+
##############################################################################
3+
#
4+
# diffpy.pdfgui Complex Modeling Initiative
5+
# (c) 2018 Brookhaven Science Associates,
6+
# Brookhaven National Laboratory.
7+
# All rights reserved.
8+
#
9+
# File coded by: Pavol Juhas
10+
#
11+
# See AUTHORS.txt for a list of people who contributed.
12+
# See LICENSE.txt for license information.
13+
#
14+
##############################################################################
15+
16+
"""
17+
Unit tests for ParametersPanel class
18+
"""
19+
20+
import unittest
21+
22+
import wx.grid
23+
24+
from diffpy.pdfgui.gui.parameterspanel import ParametersPanel
25+
from diffpy.pdfgui.control.parameter import Parameter
26+
from diffpy.pdfgui.gui.pdfguiglobals import dbopts
27+
28+
# ----------------------------------------------------------------------------
29+
30+
class TestParametersPanel(unittest.TestCase):
31+
32+
def setUp(self):
33+
self._save_noerrordialog = dbopts.noerrordialog
34+
dbopts.noerrordialog = True
35+
self.app = wx.App()
36+
self.frame = wx.Frame(None)
37+
self.panel = ParametersPanel(self.frame, -1)
38+
self.panel.parameters.update([
39+
(1, Parameter(1, 0.1)),
40+
(5, Parameter(5, 0.5)),
41+
])
42+
self.panel.refresh()
43+
self.panel.mainFrame = _TMainFrame()
44+
self.frame.window = self.panel
45+
return
46+
47+
def tearDown(self):
48+
self.frame.Close()
49+
dbopts.noerrordialog = self._save_noerrordialog
50+
return
51+
52+
53+
def _leftclickcell(self, row, col, **kw):
54+
gp = self.panel.grid_parameters
55+
eventtype = wx.grid.EVT_GRID_CELL_LEFT_CLICK.typeId
56+
e = wx.grid.GridEvent(gp.Id, eventtype, gp, row, col, **kw)
57+
gp.ProcessEvent(e)
58+
return
59+
60+
61+
def test_onPopupFixFree(self):
62+
"Check ParametersPanel.onPopupFixFree"
63+
# event is not used, we just generate and reuse dummy event.
64+
e = wx.PyCommandEvent(wx.EVT_MENU.typeId, wx.ID_ANY)
65+
panel = self.panel
66+
gp = self.panel.grid_parameters
67+
plist = list(self.panel.parameters.values())
68+
gp.SetCellValue(0, 1, "")
69+
self.assertTrue(all(not p.fixed for p in plist))
70+
gp.SelectAll()
71+
panel.onPopupFixFree(e)
72+
self.assertTrue(all(p.fixed for p in plist))
73+
self.assertEqual("1", gp.GetCellValue(0, 1))
74+
panel.onPopupFixFree(e)
75+
self.assertTrue(all(not p.fixed for p in plist))
76+
gp.DeselectRow(0)
77+
panel.onPopupFixFree(e)
78+
self.assertFalse(plist[0].fixed)
79+
self.assertTrue(plist[1].fixed)
80+
return
81+
82+
83+
def test_applyCellChange(self):
84+
"Check ParametersPanel.applyCellChange"
85+
gp = self.panel.grid_parameters
86+
mf = self.panel.mainFrame
87+
panel = self.panel
88+
self.assertFalse(mf.altered)
89+
panel.applyCellChange(0, 0, 0.1)
90+
self.assertFalse(mf.altered)
91+
panel.applyCellChange(0, 0, 1.5)
92+
self.assertTrue(mf.altered)
93+
self.assertEqual("1.5", gp.GetCellValue(0, 0))
94+
self.assertEqual(1.5, panel.parameters[1].initialValue())
95+
return
96+
97+
98+
def test_onCellLeftClick(self):
99+
"Check click handling on the Parameters grid."
100+
gp = self.panel.grid_parameters
101+
p = self.panel.parameters[1]
102+
self.assertFalse(self.panel.mainFrame.altered)
103+
self.assertEqual("0", gp.GetCellValue(0, 1))
104+
self.assertFalse(p.fixed)
105+
self._leftclickcell(0, 1)
106+
self.assertEqual("1", gp.GetCellValue(0, 1))
107+
self.assertTrue(p.fixed)
108+
self.assertTrue(self.panel.mainFrame.altered)
109+
self._leftclickcell(0, 1)
110+
self.assertEqual("0", gp.GetCellValue(0, 1))
111+
self._leftclickcell(0, 1, control=True)
112+
self.assertEqual("0", gp.GetCellValue(0, 1))
113+
self._leftclickcell(0, 1, shift=True)
114+
self.assertEqual("0", gp.GetCellValue(0, 1))
115+
gp.SelectAll()
116+
self._leftclickcell(0, 1)
117+
self.assertEqual("0", gp.GetCellValue(0, 1))
118+
gp.ClearSelection()
119+
self._leftclickcell(0, 1)
120+
self.assertEqual("1", gp.GetCellValue(0, 1))
121+
return
122+
123+
# End of class TestParametersPanel
124+
125+
# Local Helpers --------------------------------------------------------------
126+
127+
class _TMainFrame(object):
128+
"Think mockup of the used MainFrame methods."
129+
130+
altered = False
131+
132+
def needsSave(self):
133+
self.altered = True
134+
return
135+
136+
# ----------------------------------------------------------------------------
137+
138+
if __name__ == '__main__':
139+
unittest.main()

0 commit comments

Comments
 (0)