Merge lp:mapclient/bugfixes into lp:mapclient/testing

Proposed by Hugh Sorby
Status: Merged
Approved by: Hugh Sorby
Approved revision: 32
Merged at revision: 48
Proposed branch: lp:mapclient/bugfixes
Merge into: lp:mapclient/testing
Diff against target: 549 lines (+169/-67)
12 files modified
plugins/skeletonstep/__init__.py (+3/-3)
plugins/skeletonstep/skeletonstep/step.py (+8/-8)
src/core/threadcommandmanager.py (+36/-37)
src/widgets/aboutdialog.py (+7/-2)
src/widgets/mainwindow.py (+15/-1)
src/widgets/qt/aboutdialog.ui (+12/-3)
src/widgets/ui_aboutdialog.py (+7/-7)
src/widgets/workflowgraphicsitems.py (+6/-2)
src/widgets/workflowgraphicsscene.py (+1/-1)
src/widgets/workflowwidget.py (+22/-2)
tests/widgets_tests/utils.py (+46/-0)
tests/widgets_tests/widgetstests.py (+6/-1)
To merge this branch: bzr merge lp:mapclient/bugfixes
Reviewer Review Type Date Requested Status
Hugh Sorby Approve
Review via email: mp+194279@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Hugh Sorby (h-sorby) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/skeletonstep/__init__.py'
2--- plugins/skeletonstep/__init__.py 2013-07-02 02:33:08 +0000
3+++ plugins/skeletonstep/__init__.py 2013-11-07 04:12:40 +0000
4@@ -29,7 +29,7 @@
5 sys.path.insert(0, current_dir)
6
7 # import class that derives itself from the step mountpoint.
8-#from skeletonstep import step
9+# from skeletonstep import step
10
11-( _, tail ) = os.path.split(current_dir)
12-#print("Plugin '{0}' version {1} by {2} loaded".format(tail, __version__, __author__))
13+(_, tail) = os.path.split(current_dir)
14+# print("Plugin '{0}' version {1} by {2} loaded".format(tail, __version__, __author__))
15
16=== modified file 'plugins/skeletonstep/skeletonstep/step.py'
17--- plugins/skeletonstep/skeletonstep/step.py 2013-07-02 02:33:08 +0000
18+++ plugins/skeletonstep/skeletonstep/step.py 2013-11-07 04:12:40 +0000
19@@ -25,22 +25,22 @@
20 Skeleton step which is intended to be used as a starting point
21 for new steps.
22 '''
23-
24+
25 def __init__(self, location):
26 super(SkeletonStep, self).__init__('Skeleton', location)
27-
28+
29 def configure(self):
30 pass
31-
32+
33 def getIdentifier(self):
34- pass
35-
36+ return 'skeleton'
37+
38 def setIdentifier(self, identifier):
39 pass
40-
41+
42 def serialize(self, location):
43 pass
44-
45+
46 def deserialize(self, location):
47 pass
48-
49+
50
51=== modified file 'src/core/threadcommandmanager.py'
52--- src/core/threadcommandmanager.py 2013-06-27 04:11:01 +0000
53+++ src/core/threadcommandmanager.py 2013-11-07 04:12:40 +0000
54@@ -39,35 +39,35 @@
55 It has no functional purpose.
56 '''
57 Thread.__init__(self, name=name)
58-
59+
60 def setCaller(self, caller):
61 self._caller = caller
62-
63+
64 def runFinished(self):
65 self._caller and self._caller._commandFinished(self.name)
66-
67-
68+
69+
70 class CommandCopyDirectory(ThreadCommand):
71 ''' Threadable command to copy the contents of one directory to another.
72 This copy is not recursive.
73 '''
74-
75+
76 def __init__(self, from_dir, to_dir):
77 ThreadCommand.__init__(self, 'CommandCopyDirectory')
78 self._from_dir = from_dir
79 self._to_dir = to_dir
80-
81+
82 def run(self):
83 if not os.path.exists(self._to_dir):
84 os.mkdir(self._to_dir)
85-
86+
87 onlyfiles = [ join(self._from_dir, f) for f in listdir(self._from_dir) if isfile(join(self._from_dir, f)) ]
88 for f in onlyfiles:
89 copy(f, self._to_dir)
90-
91+
92 self.runFinished()
93-
94-
95+
96+
97 class CommandCreateWorkspace(ThreadCommand):
98 '''Threadable command to create a workspace on PMR.
99 '''
100@@ -75,12 +75,12 @@
101 ThreadCommand.__init__(self, 'CommandCreateWorkspace')
102 self._title = title
103 self._description = description
104-
105+
106 def run(self):
107 print('Warning: Not fully implemented')
108 self.runFinished()
109-
110-
111+
112+
113 class CommandIgnoreDirectoriesHg(ThreadCommand):
114 ''' Threadable command to add ignore directives to
115 all directories in given location. Requires a Mercurial
116@@ -92,8 +92,8 @@
117 self._hg = None
118 hg = which('hg')
119 if len(hg) > 0:
120- self._hg = hg[0]
121-
122+ self._hg = hg[0]
123+
124 def run(self):
125 if self._hg and os.path.exists(join(self._location, '.hg')):
126 onlydirs = [x for x in listdir(self._location) if isdir(join(self._location, x)) ]
127@@ -101,11 +101,11 @@
128 f = open(join(self._location, '.hgignore'), 'w')
129 f.writelines(ignoredirs)
130 f.close()
131-
132+
133 class CommandCloneWorkspace(ThreadCommand):
134 ''' Threadable command to clone a PMR workspace.
135 '''
136-
137+
138 def __init__(self, repourl, location, username, password):
139 ThreadCommand.__init__(self, 'CommandCloneWorkspace')
140 self._repourl = repourl
141@@ -115,8 +115,8 @@
142 self._hg = None
143 hg = which('hg')
144 if len(hg) > 0:
145- self._hg = hg[0]
146-
147+ self._hg = hg[0]
148+
149 def run(self):
150 '''Mercurial will not clone into a directory that is not empty. To work
151 around this we clone into a temporary directory and then move the '.hg'
152@@ -124,20 +124,20 @@
153 '''
154 if self._hg and not os.path.exists(join(self._location, '.hg')):
155 d = tempfile.mkdtemp(dir=self._location)
156-
157+
158 repourl = self._repourl[:7] + self._username + ':' + self._password + '@' + self._repourl[7:]
159 call([self._hg, 'clone', repourl, d])
160 mvdir(d, self._location)
161 # move(join(d, '.hg'), self._location)
162 rmtree(d)
163-
164+
165 self.runFinished()
166-
167+
168
169 class CommandCommit(ThreadCommand):
170 '''Threadable command to commit all changes at location to PMR
171 '''
172-
173+
174 def __init__(self, location, username, password, comment):
175 ThreadCommand.__init__(self, 'CommandCommit')
176 self._location = location
177@@ -147,8 +147,8 @@
178 self._hg = None
179 hg = which('hg')
180 if len(hg) > 0:
181- self._hg = hg[0]
182-
183+ self._hg = hg[0]
184+
185 def run(self):
186 if self._hg and os.path.exists(join(self._location, '.hg')):
187 # This is for the commit command
188@@ -163,25 +163,25 @@
189 repourl = repourl[:insert] + ':' + self._password + repourl[insert:]
190 process = Popen([self._hg, 'push', repourl], cwd=self._location)
191 process.communicate()
192-
193+
194 self.runFinished()
195-
196+
197
198 class ThreadCommandManager(object):
199 '''This class managers thread commands in a queue. The queue will
200 be executed in order serially.
201 '''
202-
203+
204 def __init__(self):
205 self._queue = []
206- self._finished = None # Callback for informing when the queue is empty
207-
208+ self._finished = None # Callback for informing when the queue is empty
209+
210 def registerFinishedCallback(self, callback):
211 self._finished = callback
212-
213+
214 def addCommand(self, c):
215 self._queue.append(c)
216-
217+
218 def execute(self):
219 if len(self._queue) > 0:
220 c = self._queue.pop(0)
221@@ -189,10 +189,10 @@
222 c.start()
223 elif self._finished:
224 self._finished()
225-
226+
227 def _commandFinished(self, thread_name):
228 self.execute()
229-
230+
231
232 def which(name, flags=os.X_OK):
233 result = []
234@@ -222,6 +222,5 @@
235 if os.path.exists(dst_file):
236 os.remove(dst_file)
237 move(src_file, dst_dir)
238-
239-
240-
241\ No newline at end of file
242+
243+
244
245=== modified file 'src/widgets/aboutdialog.py'
246--- src/widgets/aboutdialog.py 2013-06-14 01:51:27 +0000
247+++ src/widgets/aboutdialog.py 2013-11-07 04:12:40 +0000
248@@ -18,7 +18,10 @@
249 along with MAP Client. If not, see <http://www.gnu.org/licenses/>..
250 '''
251 from PySide.QtGui import QDialog
252+
253+from settings import info
254 from widgets.ui_aboutdialog import Ui_AboutDialog
255+
256 class AboutDialog(QDialog):
257 '''
258 About dialog to display program about information.
259@@ -32,12 +35,14 @@
260 QDialog.__init__(self, parent)
261 self._ui = Ui_AboutDialog()
262 self._ui.setupUi(self)
263+ text = self._ui.aboutTextLabel.text()
264+ self._ui.aboutTextLabel.setText(text.replace('##version##', info.VERSION_STRING))
265 self._makeConnections()
266-
267+
268 def _makeConnections(self):
269 self._ui.btn_Credits.clicked.connect(self.showCreditsDialog)
270 self._ui.btn_License.clicked.connect(self.showLicenseDialog)
271-
272+
273 def showCreditsDialog(self):
274 from widgets.creditsdialog import CreditsDialog
275 dlg = CreditsDialog(self)
276
277=== modified file 'src/widgets/mainwindow.py'
278--- src/widgets/mainwindow.py 2013-10-26 09:31:00 +0000
279+++ src/widgets/mainwindow.py 2013-11-07 04:12:40 +0000
280@@ -55,6 +55,8 @@
281 self._ui.stackedWidget.addWidget(self._workflowWidget)
282 self.setCurrentUndoRedoStack(self._workflowWidget.undoRedoStack())
283
284+ self._pluginManagerDlg = None
285+
286 def _createUndoAction(self, parent):
287 self.undoAction = QtGui.QAction('Undo', parent)
288 self.undoAction.setShortcut(QtGui.QKeySequence('Ctrl+Z'))
289@@ -147,9 +149,10 @@
290 def pluginManager(self):
291 from tools.pluginmanagerdialog import PluginManagerDialog
292 dlg = PluginManagerDialog(self)
293+ self._pluginManagerDlg = dlg
294 dlg.setDirectories(self._model.pluginManager().directories())
295 dlg.setLoadDefaultPlugins(self._model.pluginManager().loadDefaultPlugins())
296- dlg.reloadPlugins = self._model.pluginManager().load
297+ dlg.reloadPlugins = self._pluginManagerReloadPlugins
298
299 dlg.setModal(True)
300 if dlg.exec_():
301@@ -159,6 +162,17 @@
302 self._model.pluginManager().load()
303 self._workflowWidget.updateStepTree()
304
305+ self._pluginManagerDlg = None
306+
307+ def _pluginManagerReloadPlugins(self):
308+ '''
309+ Callback from the plugin manager to reload the current plugins.
310+ '''
311+ self._model.pluginManager().setDirectories(self._pluginManagerDlg.directories())
312+ self._model.pluginManager().setLoadDefaultPlugins(self._pluginManagerDlg.loadDefaultPlugins())
313+ self._model.pluginManager().load()
314+ self._workflowWidget.updateStepTree()
315+
316 def pluginWizard(self):
317 from tools.pluginwizard.wizarddialog import WizardDialog
318 from tools.pluginwizard.skeleton import Skeleton
319
320=== modified file 'src/widgets/qt/aboutdialog.ui'
321--- src/widgets/qt/aboutdialog.ui 2013-02-20 00:50:38 +0000
322+++ src/widgets/qt/aboutdialog.ui 2013-11-07 04:12:40 +0000
323@@ -23,7 +23,16 @@
324 <string>About MAP Client</string>
325 </property>
326 <layout class="QGridLayout" name="gridLayout">
327- <property name="margin">
328+ <property name="leftMargin">
329+ <number>0</number>
330+ </property>
331+ <property name="topMargin">
332+ <number>0</number>
333+ </property>
334+ <property name="rightMargin">
335+ <number>0</number>
336+ </property>
337+ <property name="bottomMargin">
338 <number>0</number>
339 </property>
340 <item row="0" column="0">
341@@ -49,12 +58,12 @@
342 </widget>
343 </item>
344 <item>
345- <widget class="QLabel" name="label">
346+ <widget class="QLabel" name="aboutTextLabel">
347 <property name="styleSheet">
348 <string notr="true">QLabel { background-color : white }</string>
349 </property>
350 <property name="text">
351- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; font-weight:600;&quot;&gt;MAP Client&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;MAP Client, a program to generate detailed musculoskeletal models for OpenSim.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Copyright (C) 2012 University of Auckland&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;MAP Client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;MAP Client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;You should have received a copy of the GNU General Public License along with MAP Client. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
352+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:24pt; font-weight:600;&quot;&gt;MAP Client ##version##&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;MAP Client, a program to generate detailed musculoskeletal models for OpenSim.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Copyright (C) 2012 University of Auckland&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;MAP Client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;MAP Client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;You should have received a copy of the GNU General Public License along with MAP Client. If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
353 </property>
354 <property name="wordWrap">
355 <bool>true</bool>
356
357=== modified file 'src/widgets/ui_aboutdialog.py'
358--- src/widgets/ui_aboutdialog.py 2013-06-14 01:51:27 +0000
359+++ src/widgets/ui_aboutdialog.py 2013-11-07 04:12:40 +0000
360@@ -2,7 +2,7 @@
361
362 # Form implementation generated from reading ui file 'qt/aboutdialog.ui'
363 #
364-# Created: Fri Jun 14 11:25:36 2013
365+# Created: Tue Nov 5 15:34:40 2013
366 # by: pyside-uic 0.2.14 running on PySide 1.1.2
367 #
368 # WARNING! All changes made in this file will be lost!
369@@ -34,11 +34,11 @@
370 self.label_2.setAlignment(QtCore.Qt.AlignCenter)
371 self.label_2.setObjectName("label_2")
372 self.verticalLayout.addWidget(self.label_2)
373- self.label = QtGui.QLabel(self.frame)
374- self.label.setStyleSheet("QLabel { background-color : white }")
375- self.label.setWordWrap(True)
376- self.label.setObjectName("label")
377- self.verticalLayout.addWidget(self.label)
378+ self.aboutTextLabel = QtGui.QLabel(self.frame)
379+ self.aboutTextLabel.setStyleSheet("QLabel { background-color : white }")
380+ self.aboutTextLabel.setWordWrap(True)
381+ self.aboutTextLabel.setObjectName("aboutTextLabel")
382+ self.verticalLayout.addWidget(self.aboutTextLabel)
383 self.gridLayout.addWidget(self.frame, 0, 0, 1, 1)
384 self.frame_3 = QtGui.QFrame(AboutDialog)
385 self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel)
386@@ -70,7 +70,7 @@
387
388 def retranslateUi(self, AboutDialog):
389 AboutDialog.setWindowTitle(QtGui.QApplication.translate("AboutDialog", "About MAP Client", None, QtGui.QApplication.UnicodeUTF8))
390- self.label.setText(QtGui.QApplication.translate("AboutDialog", "<html><head/><body><p align=\"center\"><span style=\" font-size:24pt; font-weight:600;\">MAP Client</span></p><p align=\"center\">MAP Client, a program to generate detailed musculoskeletal models for OpenSim.</p><p align=\"center\">Copyright (C) 2012 University of Auckland</p><p align=\"justify\">MAP Client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</p><p align=\"justify\">MAP Client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.</p><p align=\"justify\">You should have received a copy of the GNU General Public License along with MAP Client. If not, see &lt;http://www.gnu.org/licenses/&gt;.</p><p><br/></p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
391+ self.aboutTextLabel.setText(QtGui.QApplication.translate("AboutDialog", "<html><head/><body><p align=\"center\"><span style=\" font-size:24pt; font-weight:600;\">MAP Client ##version##</span></p><p align=\"center\">MAP Client, a program to generate detailed musculoskeletal models for OpenSim.</p><p align=\"center\">Copyright (C) 2012 University of Auckland</p><p align=\"justify\">MAP Client is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.</p><p align=\"justify\">MAP Client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.</p><p align=\"justify\">You should have received a copy of the GNU General Public License along with MAP Client. If not, see &lt;http://www.gnu.org/licenses/&gt;.</p><p><br/></p></body></html>", None, QtGui.QApplication.UnicodeUTF8))
392 self.btn_Credits.setText(QtGui.QApplication.translate("AboutDialog", "C&redits", None, QtGui.QApplication.UnicodeUTF8))
393 self.btn_License.setText(QtGui.QApplication.translate("AboutDialog", "&License", None, QtGui.QApplication.UnicodeUTF8))
394 self.btn_Close.setText(QtGui.QApplication.translate("AboutDialog", "&Close", None, QtGui.QApplication.UnicodeUTF8))
395
396=== modified file 'src/widgets/workflowgraphicsitems.py'
397--- src/widgets/workflowgraphicsitems.py 2013-10-25 07:33:34 +0000
398+++ src/widgets/workflowgraphicsitems.py 2013-11-07 04:12:40 +0000
399@@ -269,17 +269,21 @@
400 x_pos = -3 * w / 4
401 uses_count += 1
402 pred = 'http://physiomeproject.org/workflow/1.0/rdf-schema#uses'
403+ tooltip_stub = 'uses: '
404 else: # port in provides_ports:
405 port_total = provides_total
406 index = provides_count
407 x_pos = self.Size - w / 4
408 provides_count += 1
409 pred = 'http://physiomeproject.org/workflow/1.0/rdf-schema#provides'
410+ tooltip_stub = 'provides: '
411
412 triples = port.getTriplesForPred(pred)
413 triple_objects = [triple[2] for triple in triples]
414- port_item.moveBy(x_pos, self.Size / 2 + h / 3 * (4 * index - 2 * (port_total - 1) - 1))
415- port_item.setToolTip('uses: ' + ', '.join(triple_objects))
416+ alpha = h / 4.0 # Controls the spacing between the ports
417+ y_pos = self.Size / 2.0 - (port_total * h + (port_total - 1) * alpha) / 2.0 + (h + alpha) * index
418+ port_item.moveBy(x_pos, y_pos)
419+ port_item.setToolTip(tooltip_stub + ', '.join(triple_objects))
420 self._step_port_items.append(port_item)
421
422 self._configure_item = ConfigureIcon(self)
423
424=== modified file 'src/widgets/workflowgraphicsscene.py'
425--- src/widgets/workflowgraphicsscene.py 2013-10-25 07:33:34 +0000
426+++ src/widgets/workflowgraphicsscene.py 2013-11-07 04:12:40 +0000
427@@ -161,7 +161,7 @@
428 self.parent().setWidgetUndoRedoStack(stack)
429
430 def doneExecution(self):
431- self.parent().executeWorkflow()
432+ self.parent().executeNext()
433
434 def identifierOccursCount(self, identifier):
435 return self.parent().identifierOccursCount(identifier)
436
437=== modified file 'src/widgets/workflowwidget.py'
438--- src/widgets/workflowwidget.py 2013-10-25 07:33:34 +0000
439+++ src/widgets/workflowwidget.py 2013-11-07 04:12:40 +0000
440@@ -73,7 +73,6 @@
441 self.action_Close.setEnabled(workflowOpen)
442 self.setEnabled(workflowOpen)
443 self.action_Save.setEnabled(wfm.isModified())
444- self._ui.executeButton.setEnabled(wfm.scene().canExecute() and not wfm.isModified())
445 self._action_annotation.setEnabled(workflowOpen)
446
447 def updateStepTree(self):
448@@ -92,8 +91,29 @@
449 print('setting active - workflow widget')
450 self._mainWindow.setCurrentUndoRedoStack(self._undoStack)
451
452+ def executeNext(self):
453+ self._mainWindow.execute()
454+
455 def executeWorkflow(self):
456- self._mainWindow.execute() # .model().workflowManager().execute()
457+ wfm = self._mainWindow.model().workflowManager()
458+ error_count = 0
459+ error_msg = ''
460+ if wfm.isModified():
461+ error_count += 1
462+ error_msg += ' ' + str(error_count) + '. The workflow has not been saved.\n'
463+
464+ if not wfm.scene().canExecute():
465+ error_count += 1
466+ error_msg += ' ' + str(error_count) + '. Not all steps in the workflow have been successfully configured.\n'
467+
468+ if error_count == 0:
469+ self._mainWindow.execute() # .model().workflowManager().execute()
470+ else:
471+ error_prefix = 'The workflow could not be executed for the following reason'
472+ if error_count > 1:
473+ error_prefix += 's'
474+ error_prefix += ':\n\n'
475+ QtGui.QMessageBox.critical(self, 'Workflow Execution', error_prefix + error_msg, QtGui.QMessageBox.Ok)
476
477 def identifierOccursCount(self, identifier):
478 return self._mainWindow.model().workflowManager().identifierOccursCount(identifier)
479
480=== added file 'tests/widgets_tests/utils.py'
481--- tests/widgets_tests/utils.py 1970-01-01 00:00:00 +0000
482+++ tests/widgets_tests/utils.py 2013-11-07 04:12:40 +0000
483@@ -0,0 +1,46 @@
484+'''
485+MAP Client, a program to generate detailed musculoskeletal models for OpenSim.
486+ Copyright (C) 2012 University of Auckland
487+
488+This file is part of MAP Client. (http://launchpad.net/mapclient)
489+
490+ MAP Client is free software: you can redistribute it and/or modify
491+ it under the terms of the GNU General Public License as published by
492+ the Free Software Foundation, either version 3 of the License, or
493+ (at your option) any later version.
494+
495+ MAP Client is distributed in the hope that it will be useful,
496+ but WITHOUT ANY WARRANTY; without even the implied warranty of
497+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
498+ GNU General Public License for more details.
499+
500+ You should have received a copy of the GNU General Public License
501+ along with MAP Client. If not, see <http://www.gnu.org/licenses/>..
502+'''
503+import unittest
504+
505+class UtilsTestCase(unittest.TestCase):
506+
507+ size = 60
508+ h = 10
509+ alpha = 5
510+
511+
512+ def portPosition(self, n, i):
513+# print(self.size / 2.0 - self.h / 2.0, -(n - 1) * self.h - (n - 1) / 2 * self.alpha / 2.0, (self.h + self.alpha / 2.0) * i)
514+ return self.size / 2.0 - (n * self.h + (n - 1) * self.alpha) / 2.0 + (self.h + self.alpha) * i
515+# return self.size / 2.0 - self.h / 2.0 - (n - 1) * self.h - (n - 1) / 2 * self.alpha / 2.0 + (self.h + self.alpha / 2.0) * i
516+
517+ def testPortLocation_neq1(self):
518+ loc = self.portPosition(1, 0)
519+ self.assertEqual(25, loc)
520+
521+ def testPortLocation_neq2(self):
522+ loc = self.portPosition(2, 0)
523+ self.assertEqual(17.5, loc)
524+ loc = self.portPosition(2, 1)
525+ self.assertEqual(32.5, loc)
526+
527+if __name__ == "__main__":
528+ # import sys;sys.argv = ['', 'Test.testName']
529+ unittest.main()
530
531=== modified file 'tests/widgets_tests/widgetstests.py'
532--- tests/widgets_tests/widgetstests.py 2013-02-18 22:44:26 +0000
533+++ tests/widgets_tests/widgetstests.py 2013-11-07 04:12:40 +0000
534@@ -21,9 +21,14 @@
535 import unittest
536
537 def suite():
538+ tests = unittest.TestSuite()
539+
540 from widgets_tests.mainwindow import MainWindowTestCase
541- tests = unittest.TestSuite()
542 tests.addTests(unittest.TestLoader().loadTestsFromTestCase(MainWindowTestCase))
543+
544+ from widgets_tests.utils import UtilsTestCase
545+ tests.addTests(unittest.TestLoader().loadTestsFromTestCase(UtilsTestCase))
546+
547 return tests
548
549 def load_tests(loader, tests, pattern):

Subscribers

People subscribed via source and target branches

to all changes: