~daniel.bueltmann/openwns-wrowser/openwns-wrowser-debian

« back to all changes in this revision

Viewing changes to patches/openwns-wrowser-0.9beta2-0ubuntu3.patch

  • Committer: Daniel Bültmann
  • Date: 2010-10-24 14:16:36 UTC
  • Revision ID: me@daniel-bueltmann.de-20101024141636-0sfgmpgevjxz3hgn
some cleanup

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/bin/wrowser openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/bin/wrowser
2
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/bin/wrowser       1970-01-01 01:00:00.000000000 +0100
3
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/bin/wrowser   2010-04-29 17:49:15.351332996 +0200
4
 
@@ -0,0 +1,69 @@
5
 
+#!/usr/bin/python
6
 
+###############################################################################
7
 
+# This file is part of openWNS (open Wireless Network Simulator)
8
 
+# _____________________________________________________________________________
9
 
+#
10
 
+# Copyright (C) 2004-2007
11
 
+# Chair of Communication Networks (ComNets)
12
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
13
 
+# phone: ++49-241-80-27910,
14
 
+# fax: ++49-241-80-22242
15
 
+# email: info@openwns.org
16
 
+# www: http://www.openwns.org
17
 
+# _____________________________________________________________________________
18
 
+#
19
 
+# openWNS is free software; you can redistribute it and/or modify it under the
20
 
+# terms of the GNU Lesser General Public License version 2 as published by the
21
 
+# Free Software Foundation;
22
 
+#
23
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
24
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
25
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
26
 
+# details.
27
 
+#
28
 
+# You should have received a copy of the GNU Lesser General Public License
29
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
 
+#
31
 
+###############################################################################
32
 
+
33
 
+import sys
34
 
+import os
35
 
+import traceback
36
 
+
37
 
+from PyQt4 import QtGui
38
 
+
39
 
+# Path to this script
40
 
+p = sys.path[0]
41
 
+searchPath = os.path.dirname(sys.path[0])
42
 
+
43
 
+if "openwns" in os.listdir(searchPath):
44
 
+    print "Local installation of wrowser found."
45
 
+    print "Prepending %s to sys.path" % searchPath
46
 
+    sys.path.insert(0, searchPath)
47
 
+
48
 
+os.chdir(searchPath)
49
 
+import openwns.wrowser.Windows
50
 
+
51
 
+def wrowserExceptHook(eType, eValue, eTraceback):
52
 
+    message = "".join(traceback.format_exception(eType, eValue, eTraceback))
53
 
+    print message
54
 
+    response = QtGui.QMessageBox.critical(QtGui.QApplication.activeWindow(), "Python Exception", message, "Exit", "Debug", "Continue")
55
 
+    if response == 0:
56
 
+        sys.exit(255)
57
 
+    elif response == 1:
58
 
+        import pdb
59
 
+        pdb.set_trace()
60
 
+    else:
61
 
+        pass
62
 
+
63
 
+if __name__ == "__main__":
64
 
+    application = QtGui.QApplication(sys.argv)
65
 
+    application.setQuitOnLastWindowClosed(True)
66
 
+    application.setApplicationName("Wrowser")
67
 
+    application.setWindowIcon(QtGui.QIcon(":/icons/icon.png"))
68
 
+    application.setOrganizationName("RWTH Aachen University - ComNets")
69
 
+    application.setOrganizationDomain("www.comnets.rwth-aachen.de")
70
 
+    widget = openwns.wrowser.Windows.Main()
71
 
+    widget.show()
72
 
+    sys.excepthook = wrowserExceptHook
73
 
+    sys.exit(application.exec_())
74
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/COPYING openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/COPYING
75
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/COPYING   1970-01-01 01:00:00.000000000 +0100
76
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/COPYING       2010-04-29 17:49:15.353968415 +0200
77
 
@@ -0,0 +1,339 @@
78
 
+                   GNU GENERAL PUBLIC LICENSE
79
 
+                      Version 2, June 1991
80
 
+
81
 
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
82
 
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
83
 
+ Everyone is permitted to copy and distribute verbatim copies
84
 
+ of this license document, but changing it is not allowed.
85
 
+
86
 
+                           Preamble
87
 
+
88
 
+  The licenses for most software are designed to take away your
89
 
+freedom to share and change it.  By contrast, the GNU General Public
90
 
+License is intended to guarantee your freedom to share and change free
91
 
+software--to make sure the software is free for all its users.  This
92
 
+General Public License applies to most of the Free Software
93
 
+Foundation's software and to any other program whose authors commit to
94
 
+using it.  (Some other Free Software Foundation software is covered by
95
 
+the GNU Lesser General Public License instead.)  You can apply it to
96
 
+your programs, too.
97
 
+
98
 
+  When we speak of free software, we are referring to freedom, not
99
 
+price.  Our General Public Licenses are designed to make sure that you
100
 
+have the freedom to distribute copies of free software (and charge for
101
 
+this service if you wish), that you receive source code or can get it
102
 
+if you want it, that you can change the software or use pieces of it
103
 
+in new free programs; and that you know you can do these things.
104
 
+
105
 
+  To protect your rights, we need to make restrictions that forbid
106
 
+anyone to deny you these rights or to ask you to surrender the rights.
107
 
+These restrictions translate to certain responsibilities for you if you
108
 
+distribute copies of the software, or if you modify it.
109
 
+
110
 
+  For example, if you distribute copies of such a program, whether
111
 
+gratis or for a fee, you must give the recipients all the rights that
112
 
+you have.  You must make sure that they, too, receive or can get the
113
 
+source code.  And you must show them these terms so they know their
114
 
+rights.
115
 
+
116
 
+  We protect your rights with two steps: (1) copyright the software, and
117
 
+(2) offer you this license which gives you legal permission to copy,
118
 
+distribute and/or modify the software.
119
 
+
120
 
+  Also, for each author's protection and ours, we want to make certain
121
 
+that everyone understands that there is no warranty for this free
122
 
+software.  If the software is modified by someone else and passed on, we
123
 
+want its recipients to know that what they have is not the original, so
124
 
+that any problems introduced by others will not reflect on the original
125
 
+authors' reputations.
126
 
+
127
 
+  Finally, any free program is threatened constantly by software
128
 
+patents.  We wish to avoid the danger that redistributors of a free
129
 
+program will individually obtain patent licenses, in effect making the
130
 
+program proprietary.  To prevent this, we have made it clear that any
131
 
+patent must be licensed for everyone's free use or not licensed at all.
132
 
+
133
 
+  The precise terms and conditions for copying, distribution and
134
 
+modification follow.
135
 
+
136
 
+                   GNU GENERAL PUBLIC LICENSE
137
 
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
138
 
+
139
 
+  0. This License applies to any program or other work which contains
140
 
+a notice placed by the copyright holder saying it may be distributed
141
 
+under the terms of this General Public License.  The "Program", below,
142
 
+refers to any such program or work, and a "work based on the Program"
143
 
+means either the Program or any derivative work under copyright law:
144
 
+that is to say, a work containing the Program or a portion of it,
145
 
+either verbatim or with modifications and/or translated into another
146
 
+language.  (Hereinafter, translation is included without limitation in
147
 
+the term "modification".)  Each licensee is addressed as "you".
148
 
+
149
 
+Activities other than copying, distribution and modification are not
150
 
+covered by this License; they are outside its scope.  The act of
151
 
+running the Program is not restricted, and the output from the Program
152
 
+is covered only if its contents constitute a work based on the
153
 
+Program (independent of having been made by running the Program).
154
 
+Whether that is true depends on what the Program does.
155
 
+
156
 
+  1. You may copy and distribute verbatim copies of the Program's
157
 
+source code as you receive it, in any medium, provided that you
158
 
+conspicuously and appropriately publish on each copy an appropriate
159
 
+copyright notice and disclaimer of warranty; keep intact all the
160
 
+notices that refer to this License and to the absence of any warranty;
161
 
+and give any other recipients of the Program a copy of this License
162
 
+along with the Program.
163
 
+
164
 
+You may charge a fee for the physical act of transferring a copy, and
165
 
+you may at your option offer warranty protection in exchange for a fee.
166
 
+
167
 
+  2. You may modify your copy or copies of the Program or any portion
168
 
+of it, thus forming a work based on the Program, and copy and
169
 
+distribute such modifications or work under the terms of Section 1
170
 
+above, provided that you also meet all of these conditions:
171
 
+
172
 
+    a) You must cause the modified files to carry prominent notices
173
 
+    stating that you changed the files and the date of any change.
174
 
+
175
 
+    b) You must cause any work that you distribute or publish, that in
176
 
+    whole or in part contains or is derived from the Program or any
177
 
+    part thereof, to be licensed as a whole at no charge to all third
178
 
+    parties under the terms of this License.
179
 
+
180
 
+    c) If the modified program normally reads commands interactively
181
 
+    when run, you must cause it, when started running for such
182
 
+    interactive use in the most ordinary way, to print or display an
183
 
+    announcement including an appropriate copyright notice and a
184
 
+    notice that there is no warranty (or else, saying that you provide
185
 
+    a warranty) and that users may redistribute the program under
186
 
+    these conditions, and telling the user how to view a copy of this
187
 
+    License.  (Exception: if the Program itself is interactive but
188
 
+    does not normally print such an announcement, your work based on
189
 
+    the Program is not required to print an announcement.)
190
 
+
191
 
+These requirements apply to the modified work as a whole.  If
192
 
+identifiable sections of that work are not derived from the Program,
193
 
+and can be reasonably considered independent and separate works in
194
 
+themselves, then this License, and its terms, do not apply to those
195
 
+sections when you distribute them as separate works.  But when you
196
 
+distribute the same sections as part of a whole which is a work based
197
 
+on the Program, the distribution of the whole must be on the terms of
198
 
+this License, whose permissions for other licensees extend to the
199
 
+entire whole, and thus to each and every part regardless of who wrote it.
200
 
+
201
 
+Thus, it is not the intent of this section to claim rights or contest
202
 
+your rights to work written entirely by you; rather, the intent is to
203
 
+exercise the right to control the distribution of derivative or
204
 
+collective works based on the Program.
205
 
+
206
 
+In addition, mere aggregation of another work not based on the Program
207
 
+with the Program (or with a work based on the Program) on a volume of
208
 
+a storage or distribution medium does not bring the other work under
209
 
+the scope of this License.
210
 
+
211
 
+  3. You may copy and distribute the Program (or a work based on it,
212
 
+under Section 2) in object code or executable form under the terms of
213
 
+Sections 1 and 2 above provided that you also do one of the following:
214
 
+
215
 
+    a) Accompany it with the complete corresponding machine-readable
216
 
+    source code, which must be distributed under the terms of Sections
217
 
+    1 and 2 above on a medium customarily used for software interchange; or,
218
 
+
219
 
+    b) Accompany it with a written offer, valid for at least three
220
 
+    years, to give any third party, for a charge no more than your
221
 
+    cost of physically performing source distribution, a complete
222
 
+    machine-readable copy of the corresponding source code, to be
223
 
+    distributed under the terms of Sections 1 and 2 above on a medium
224
 
+    customarily used for software interchange; or,
225
 
+
226
 
+    c) Accompany it with the information you received as to the offer
227
 
+    to distribute corresponding source code.  (This alternative is
228
 
+    allowed only for noncommercial distribution and only if you
229
 
+    received the program in object code or executable form with such
230
 
+    an offer, in accord with Subsection b above.)
231
 
+
232
 
+The source code for a work means the preferred form of the work for
233
 
+making modifications to it.  For an executable work, complete source
234
 
+code means all the source code for all modules it contains, plus any
235
 
+associated interface definition files, plus the scripts used to
236
 
+control compilation and installation of the executable.  However, as a
237
 
+special exception, the source code distributed need not include
238
 
+anything that is normally distributed (in either source or binary
239
 
+form) with the major components (compiler, kernel, and so on) of the
240
 
+operating system on which the executable runs, unless that component
241
 
+itself accompanies the executable.
242
 
+
243
 
+If distribution of executable or object code is made by offering
244
 
+access to copy from a designated place, then offering equivalent
245
 
+access to copy the source code from the same place counts as
246
 
+distribution of the source code, even though third parties are not
247
 
+compelled to copy the source along with the object code.
248
 
+
249
 
+  4. You may not copy, modify, sublicense, or distribute the Program
250
 
+except as expressly provided under this License.  Any attempt
251
 
+otherwise to copy, modify, sublicense or distribute the Program is
252
 
+void, and will automatically terminate your rights under this License.
253
 
+However, parties who have received copies, or rights, from you under
254
 
+this License will not have their licenses terminated so long as such
255
 
+parties remain in full compliance.
256
 
+
257
 
+  5. You are not required to accept this License, since you have not
258
 
+signed it.  However, nothing else grants you permission to modify or
259
 
+distribute the Program or its derivative works.  These actions are
260
 
+prohibited by law if you do not accept this License.  Therefore, by
261
 
+modifying or distributing the Program (or any work based on the
262
 
+Program), you indicate your acceptance of this License to do so, and
263
 
+all its terms and conditions for copying, distributing or modifying
264
 
+the Program or works based on it.
265
 
+
266
 
+  6. Each time you redistribute the Program (or any work based on the
267
 
+Program), the recipient automatically receives a license from the
268
 
+original licensor to copy, distribute or modify the Program subject to
269
 
+these terms and conditions.  You may not impose any further
270
 
+restrictions on the recipients' exercise of the rights granted herein.
271
 
+You are not responsible for enforcing compliance by third parties to
272
 
+this License.
273
 
+
274
 
+  7. If, as a consequence of a court judgment or allegation of patent
275
 
+infringement or for any other reason (not limited to patent issues),
276
 
+conditions are imposed on you (whether by court order, agreement or
277
 
+otherwise) that contradict the conditions of this License, they do not
278
 
+excuse you from the conditions of this License.  If you cannot
279
 
+distribute so as to satisfy simultaneously your obligations under this
280
 
+License and any other pertinent obligations, then as a consequence you
281
 
+may not distribute the Program at all.  For example, if a patent
282
 
+license would not permit royalty-free redistribution of the Program by
283
 
+all those who receive copies directly or indirectly through you, then
284
 
+the only way you could satisfy both it and this License would be to
285
 
+refrain entirely from distribution of the Program.
286
 
+
287
 
+If any portion of this section is held invalid or unenforceable under
288
 
+any particular circumstance, the balance of the section is intended to
289
 
+apply and the section as a whole is intended to apply in other
290
 
+circumstances.
291
 
+
292
 
+It is not the purpose of this section to induce you to infringe any
293
 
+patents or other property right claims or to contest validity of any
294
 
+such claims; this section has the sole purpose of protecting the
295
 
+integrity of the free software distribution system, which is
296
 
+implemented by public license practices.  Many people have made
297
 
+generous contributions to the wide range of software distributed
298
 
+through that system in reliance on consistent application of that
299
 
+system; it is up to the author/donor to decide if he or she is willing
300
 
+to distribute software through any other system and a licensee cannot
301
 
+impose that choice.
302
 
+
303
 
+This section is intended to make thoroughly clear what is believed to
304
 
+be a consequence of the rest of this License.
305
 
+
306
 
+  8. If the distribution and/or use of the Program is restricted in
307
 
+certain countries either by patents or by copyrighted interfaces, the
308
 
+original copyright holder who places the Program under this License
309
 
+may add an explicit geographical distribution limitation excluding
310
 
+those countries, so that distribution is permitted only in or among
311
 
+countries not thus excluded.  In such case, this License incorporates
312
 
+the limitation as if written in the body of this License.
313
 
+
314
 
+  9. The Free Software Foundation may publish revised and/or new versions
315
 
+of the General Public License from time to time.  Such new versions will
316
 
+be similar in spirit to the present version, but may differ in detail to
317
 
+address new problems or concerns.
318
 
+
319
 
+Each version is given a distinguishing version number.  If the Program
320
 
+specifies a version number of this License which applies to it and "any
321
 
+later version", you have the option of following the terms and conditions
322
 
+either of that version or of any later version published by the Free
323
 
+Software Foundation.  If the Program does not specify a version number of
324
 
+this License, you may choose any version ever published by the Free Software
325
 
+Foundation.
326
 
+
327
 
+  10. If you wish to incorporate parts of the Program into other free
328
 
+programs whose distribution conditions are different, write to the author
329
 
+to ask for permission.  For software which is copyrighted by the Free
330
 
+Software Foundation, write to the Free Software Foundation; we sometimes
331
 
+make exceptions for this.  Our decision will be guided by the two goals
332
 
+of preserving the free status of all derivatives of our free software and
333
 
+of promoting the sharing and reuse of software generally.
334
 
+
335
 
+                           NO WARRANTY
336
 
+
337
 
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
338
 
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
339
 
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
340
 
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
341
 
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
342
 
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
343
 
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
344
 
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
345
 
+REPAIR OR CORRECTION.
346
 
+
347
 
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
348
 
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
349
 
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
350
 
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
351
 
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
352
 
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
353
 
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
354
 
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
355
 
+POSSIBILITY OF SUCH DAMAGES.
356
 
+
357
 
+                    END OF TERMS AND CONDITIONS
358
 
+
359
 
+           How to Apply These Terms to Your New Programs
360
 
+
361
 
+  If you develop a new program, and you want it to be of the greatest
362
 
+possible use to the public, the best way to achieve this is to make it
363
 
+free software which everyone can redistribute and change under these terms.
364
 
+
365
 
+  To do so, attach the following notices to the program.  It is safest
366
 
+to attach them to the start of each source file to most effectively
367
 
+convey the exclusion of warranty; and each file should have at least
368
 
+the "copyright" line and a pointer to where the full notice is found.
369
 
+
370
 
+    <one line to give the program's name and a brief idea of what it does.>
371
 
+    Copyright (C) <year>  <name of author>
372
 
+
373
 
+    This program is free software; you can redistribute it and/or modify
374
 
+    it under the terms of the GNU General Public License as published by
375
 
+    the Free Software Foundation; either version 2 of the License, or
376
 
+    (at your option) any later version.
377
 
+
378
 
+    This program is distributed in the hope that it will be useful,
379
 
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
380
 
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
381
 
+    GNU General Public License for more details.
382
 
+
383
 
+    You should have received a copy of the GNU General Public License along
384
 
+    with this program; if not, write to the Free Software Foundation, Inc.,
385
 
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
386
 
+
387
 
+Also add information on how to contact you by electronic and paper mail.
388
 
+
389
 
+If the program is interactive, make it output a short notice like this
390
 
+when it starts in an interactive mode:
391
 
+
392
 
+    Gnomovision version 69, Copyright (C) year name of author
393
 
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
394
 
+    This is free software, and you are welcome to redistribute it
395
 
+    under certain conditions; type `show c' for details.
396
 
+
397
 
+The hypothetical commands `show w' and `show c' should show the appropriate
398
 
+parts of the General Public License.  Of course, the commands you use may
399
 
+be called something other than `show w' and `show c'; they could even be
400
 
+mouse-clicks or menu items--whatever suits your program.
401
 
+
402
 
+You should also get your employer (if you work as a programmer) or your
403
 
+school, if any, to sign a "copyright disclaimer" for the program, if
404
 
+necessary.  Here is a sample; alter the names:
405
 
+
406
 
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
407
 
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
408
 
+
409
 
+  <signature of Ty Coon>, 1 April 1989
410
 
+  Ty Coon, President of Vice
411
 
+
412
 
+This General Public License does not permit incorporating your program into
413
 
+proprietary programs.  If your program is a subroutine library, you may
414
 
+consider it more useful to permit linking proprietary applications with the
415
 
+library.  If this is what you want to do, use the GNU Lesser General
416
 
+Public License instead of this License.
417
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/COPYING.LESSER openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/COPYING.LESSER
418
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/COPYING.LESSER    1970-01-01 01:00:00.000000000 +0100
419
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/COPYING.LESSER        2010-04-29 17:49:15.351332996 +0200
420
 
@@ -0,0 +1,504 @@
421
 
+                 GNU LESSER GENERAL PUBLIC LICENSE
422
 
+                      Version 2.1, February 1999
423
 
+
424
 
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
425
 
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
426
 
+ Everyone is permitted to copy and distribute verbatim copies
427
 
+ of this license document, but changing it is not allowed.
428
 
+
429
 
+[This is the first released version of the Lesser GPL.  It also counts
430
 
+ as the successor of the GNU Library Public License, version 2, hence
431
 
+ the version number 2.1.]
432
 
+
433
 
+                           Preamble
434
 
+
435
 
+  The licenses for most software are designed to take away your
436
 
+freedom to share and change it.  By contrast, the GNU General Public
437
 
+Licenses are intended to guarantee your freedom to share and change
438
 
+free software--to make sure the software is free for all its users.
439
 
+
440
 
+  This license, the Lesser General Public License, applies to some
441
 
+specially designated software packages--typically libraries--of the
442
 
+Free Software Foundation and other authors who decide to use it.  You
443
 
+can use it too, but we suggest you first think carefully about whether
444
 
+this license or the ordinary General Public License is the better
445
 
+strategy to use in any particular case, based on the explanations below.
446
 
+
447
 
+  When we speak of free software, we are referring to freedom of use,
448
 
+not price.  Our General Public Licenses are designed to make sure that
449
 
+you have the freedom to distribute copies of free software (and charge
450
 
+for this service if you wish); that you receive source code or can get
451
 
+it if you want it; that you can change the software and use pieces of
452
 
+it in new free programs; and that you are informed that you can do
453
 
+these things.
454
 
+
455
 
+  To protect your rights, we need to make restrictions that forbid
456
 
+distributors to deny you these rights or to ask you to surrender these
457
 
+rights.  These restrictions translate to certain responsibilities for
458
 
+you if you distribute copies of the library or if you modify it.
459
 
+
460
 
+  For example, if you distribute copies of the library, whether gratis
461
 
+or for a fee, you must give the recipients all the rights that we gave
462
 
+you.  You must make sure that they, too, receive or can get the source
463
 
+code.  If you link other code with the library, you must provide
464
 
+complete object files to the recipients, so that they can relink them
465
 
+with the library after making changes to the library and recompiling
466
 
+it.  And you must show them these terms so they know their rights.
467
 
+
468
 
+  We protect your rights with a two-step method: (1) we copyright the
469
 
+library, and (2) we offer you this license, which gives you legal
470
 
+permission to copy, distribute and/or modify the library.
471
 
+
472
 
+  To protect each distributor, we want to make it very clear that
473
 
+there is no warranty for the free library.  Also, if the library is
474
 
+modified by someone else and passed on, the recipients should know
475
 
+that what they have is not the original version, so that the original
476
 
+author's reputation will not be affected by problems that might be
477
 
+introduced by others.
478
 
+
479
 
+  Finally, software patents pose a constant threat to the existence of
480
 
+any free program.  We wish to make sure that a company cannot
481
 
+effectively restrict the users of a free program by obtaining a
482
 
+restrictive license from a patent holder.  Therefore, we insist that
483
 
+any patent license obtained for a version of the library must be
484
 
+consistent with the full freedom of use specified in this license.
485
 
+
486
 
+  Most GNU software, including some libraries, is covered by the
487
 
+ordinary GNU General Public License.  This license, the GNU Lesser
488
 
+General Public License, applies to certain designated libraries, and
489
 
+is quite different from the ordinary General Public License.  We use
490
 
+this license for certain libraries in order to permit linking those
491
 
+libraries into non-free programs.
492
 
+
493
 
+  When a program is linked with a library, whether statically or using
494
 
+a shared library, the combination of the two is legally speaking a
495
 
+combined work, a derivative of the original library.  The ordinary
496
 
+General Public License therefore permits such linking only if the
497
 
+entire combination fits its criteria of freedom.  The Lesser General
498
 
+Public License permits more lax criteria for linking other code with
499
 
+the library.
500
 
+
501
 
+  We call this license the "Lesser" General Public License because it
502
 
+does Less to protect the user's freedom than the ordinary General
503
 
+Public License.  It also provides other free software developers Less
504
 
+of an advantage over competing non-free programs.  These disadvantages
505
 
+are the reason we use the ordinary General Public License for many
506
 
+libraries.  However, the Lesser license provides advantages in certain
507
 
+special circumstances.
508
 
+
509
 
+  For example, on rare occasions, there may be a special need to
510
 
+encourage the widest possible use of a certain library, so that it becomes
511
 
+a de-facto standard.  To achieve this, non-free programs must be
512
 
+allowed to use the library.  A more frequent case is that a free
513
 
+library does the same job as widely used non-free libraries.  In this
514
 
+case, there is little to gain by limiting the free library to free
515
 
+software only, so we use the Lesser General Public License.
516
 
+
517
 
+  In other cases, permission to use a particular library in non-free
518
 
+programs enables a greater number of people to use a large body of
519
 
+free software.  For example, permission to use the GNU C Library in
520
 
+non-free programs enables many more people to use the whole GNU
521
 
+operating system, as well as its variant, the GNU/Linux operating
522
 
+system.
523
 
+
524
 
+  Although the Lesser General Public License is Less protective of the
525
 
+users' freedom, it does ensure that the user of a program that is
526
 
+linked with the Library has the freedom and the wherewithal to run
527
 
+that program using a modified version of the Library.
528
 
+
529
 
+  The precise terms and conditions for copying, distribution and
530
 
+modification follow.  Pay close attention to the difference between a
531
 
+"work based on the library" and a "work that uses the library".  The
532
 
+former contains code derived from the library, whereas the latter must
533
 
+be combined with the library in order to run.
534
 
+
535
 
+                 GNU LESSER GENERAL PUBLIC LICENSE
536
 
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
537
 
+
538
 
+  0. This License Agreement applies to any software library or other
539
 
+program which contains a notice placed by the copyright holder or
540
 
+other authorized party saying it may be distributed under the terms of
541
 
+this Lesser General Public License (also called "this License").
542
 
+Each licensee is addressed as "you".
543
 
+
544
 
+  A "library" means a collection of software functions and/or data
545
 
+prepared so as to be conveniently linked with application programs
546
 
+(which use some of those functions and data) to form executables.
547
 
+
548
 
+  The "Library", below, refers to any such software library or work
549
 
+which has been distributed under these terms.  A "work based on the
550
 
+Library" means either the Library or any derivative work under
551
 
+copyright law: that is to say, a work containing the Library or a
552
 
+portion of it, either verbatim or with modifications and/or translated
553
 
+straightforwardly into another language.  (Hereinafter, translation is
554
 
+included without limitation in the term "modification".)
555
 
+
556
 
+  "Source code" for a work means the preferred form of the work for
557
 
+making modifications to it.  For a library, complete source code means
558
 
+all the source code for all modules it contains, plus any associated
559
 
+interface definition files, plus the scripts used to control compilation
560
 
+and installation of the library.
561
 
+
562
 
+  Activities other than copying, distribution and modification are not
563
 
+covered by this License; they are outside its scope.  The act of
564
 
+running a program using the Library is not restricted, and output from
565
 
+such a program is covered only if its contents constitute a work based
566
 
+on the Library (independent of the use of the Library in a tool for
567
 
+writing it).  Whether that is true depends on what the Library does
568
 
+and what the program that uses the Library does.
569
 
+  
570
 
+  1. You may copy and distribute verbatim copies of the Library's
571
 
+complete source code as you receive it, in any medium, provided that
572
 
+you conspicuously and appropriately publish on each copy an
573
 
+appropriate copyright notice and disclaimer of warranty; keep intact
574
 
+all the notices that refer to this License and to the absence of any
575
 
+warranty; and distribute a copy of this License along with the
576
 
+Library.
577
 
+
578
 
+  You may charge a fee for the physical act of transferring a copy,
579
 
+and you may at your option offer warranty protection in exchange for a
580
 
+fee.
581
 
+
582
 
+  2. You may modify your copy or copies of the Library or any portion
583
 
+of it, thus forming a work based on the Library, and copy and
584
 
+distribute such modifications or work under the terms of Section 1
585
 
+above, provided that you also meet all of these conditions:
586
 
+
587
 
+    a) The modified work must itself be a software library.
588
 
+
589
 
+    b) You must cause the files modified to carry prominent notices
590
 
+    stating that you changed the files and the date of any change.
591
 
+
592
 
+    c) You must cause the whole of the work to be licensed at no
593
 
+    charge to all third parties under the terms of this License.
594
 
+
595
 
+    d) If a facility in the modified Library refers to a function or a
596
 
+    table of data to be supplied by an application program that uses
597
 
+    the facility, other than as an argument passed when the facility
598
 
+    is invoked, then you must make a good faith effort to ensure that,
599
 
+    in the event an application does not supply such function or
600
 
+    table, the facility still operates, and performs whatever part of
601
 
+    its purpose remains meaningful.
602
 
+
603
 
+    (For example, a function in a library to compute square roots has
604
 
+    a purpose that is entirely well-defined independent of the
605
 
+    application.  Therefore, Subsection 2d requires that any
606
 
+    application-supplied function or table used by this function must
607
 
+    be optional: if the application does not supply it, the square
608
 
+    root function must still compute square roots.)
609
 
+
610
 
+These requirements apply to the modified work as a whole.  If
611
 
+identifiable sections of that work are not derived from the Library,
612
 
+and can be reasonably considered independent and separate works in
613
 
+themselves, then this License, and its terms, do not apply to those
614
 
+sections when you distribute them as separate works.  But when you
615
 
+distribute the same sections as part of a whole which is a work based
616
 
+on the Library, the distribution of the whole must be on the terms of
617
 
+this License, whose permissions for other licensees extend to the
618
 
+entire whole, and thus to each and every part regardless of who wrote
619
 
+it.
620
 
+
621
 
+Thus, it is not the intent of this section to claim rights or contest
622
 
+your rights to work written entirely by you; rather, the intent is to
623
 
+exercise the right to control the distribution of derivative or
624
 
+collective works based on the Library.
625
 
+
626
 
+In addition, mere aggregation of another work not based on the Library
627
 
+with the Library (or with a work based on the Library) on a volume of
628
 
+a storage or distribution medium does not bring the other work under
629
 
+the scope of this License.
630
 
+
631
 
+  3. You may opt to apply the terms of the ordinary GNU General Public
632
 
+License instead of this License to a given copy of the Library.  To do
633
 
+this, you must alter all the notices that refer to this License, so
634
 
+that they refer to the ordinary GNU General Public License, version 2,
635
 
+instead of to this License.  (If a newer version than version 2 of the
636
 
+ordinary GNU General Public License has appeared, then you can specify
637
 
+that version instead if you wish.)  Do not make any other change in
638
 
+these notices.
639
 
+
640
 
+  Once this change is made in a given copy, it is irreversible for
641
 
+that copy, so the ordinary GNU General Public License applies to all
642
 
+subsequent copies and derivative works made from that copy.
643
 
+
644
 
+  This option is useful when you wish to copy part of the code of
645
 
+the Library into a program that is not a library.
646
 
+
647
 
+  4. You may copy and distribute the Library (or a portion or
648
 
+derivative of it, under Section 2) in object code or executable form
649
 
+under the terms of Sections 1 and 2 above provided that you accompany
650
 
+it with the complete corresponding machine-readable source code, which
651
 
+must be distributed under the terms of Sections 1 and 2 above on a
652
 
+medium customarily used for software interchange.
653
 
+
654
 
+  If distribution of object code is made by offering access to copy
655
 
+from a designated place, then offering equivalent access to copy the
656
 
+source code from the same place satisfies the requirement to
657
 
+distribute the source code, even though third parties are not
658
 
+compelled to copy the source along with the object code.
659
 
+
660
 
+  5. A program that contains no derivative of any portion of the
661
 
+Library, but is designed to work with the Library by being compiled or
662
 
+linked with it, is called a "work that uses the Library".  Such a
663
 
+work, in isolation, is not a derivative work of the Library, and
664
 
+therefore falls outside the scope of this License.
665
 
+
666
 
+  However, linking a "work that uses the Library" with the Library
667
 
+creates an executable that is a derivative of the Library (because it
668
 
+contains portions of the Library), rather than a "work that uses the
669
 
+library".  The executable is therefore covered by this License.
670
 
+Section 6 states terms for distribution of such executables.
671
 
+
672
 
+  When a "work that uses the Library" uses material from a header file
673
 
+that is part of the Library, the object code for the work may be a
674
 
+derivative work of the Library even though the source code is not.
675
 
+Whether this is true is especially significant if the work can be
676
 
+linked without the Library, or if the work is itself a library.  The
677
 
+threshold for this to be true is not precisely defined by law.
678
 
+
679
 
+  If such an object file uses only numerical parameters, data
680
 
+structure layouts and accessors, and small macros and small inline
681
 
+functions (ten lines or less in length), then the use of the object
682
 
+file is unrestricted, regardless of whether it is legally a derivative
683
 
+work.  (Executables containing this object code plus portions of the
684
 
+Library will still fall under Section 6.)
685
 
+
686
 
+  Otherwise, if the work is a derivative of the Library, you may
687
 
+distribute the object code for the work under the terms of Section 6.
688
 
+Any executables containing that work also fall under Section 6,
689
 
+whether or not they are linked directly with the Library itself.
690
 
+
691
 
+  6. As an exception to the Sections above, you may also combine or
692
 
+link a "work that uses the Library" with the Library to produce a
693
 
+work containing portions of the Library, and distribute that work
694
 
+under terms of your choice, provided that the terms permit
695
 
+modification of the work for the customer's own use and reverse
696
 
+engineering for debugging such modifications.
697
 
+
698
 
+  You must give prominent notice with each copy of the work that the
699
 
+Library is used in it and that the Library and its use are covered by
700
 
+this License.  You must supply a copy of this License.  If the work
701
 
+during execution displays copyright notices, you must include the
702
 
+copyright notice for the Library among them, as well as a reference
703
 
+directing the user to the copy of this License.  Also, you must do one
704
 
+of these things:
705
 
+
706
 
+    a) Accompany the work with the complete corresponding
707
 
+    machine-readable source code for the Library including whatever
708
 
+    changes were used in the work (which must be distributed under
709
 
+    Sections 1 and 2 above); and, if the work is an executable linked
710
 
+    with the Library, with the complete machine-readable "work that
711
 
+    uses the Library", as object code and/or source code, so that the
712
 
+    user can modify the Library and then relink to produce a modified
713
 
+    executable containing the modified Library.  (It is understood
714
 
+    that the user who changes the contents of definitions files in the
715
 
+    Library will not necessarily be able to recompile the application
716
 
+    to use the modified definitions.)
717
 
+
718
 
+    b) Use a suitable shared library mechanism for linking with the
719
 
+    Library.  A suitable mechanism is one that (1) uses at run time a
720
 
+    copy of the library already present on the user's computer system,
721
 
+    rather than copying library functions into the executable, and (2)
722
 
+    will operate properly with a modified version of the library, if
723
 
+    the user installs one, as long as the modified version is
724
 
+    interface-compatible with the version that the work was made with.
725
 
+
726
 
+    c) Accompany the work with a written offer, valid for at
727
 
+    least three years, to give the same user the materials
728
 
+    specified in Subsection 6a, above, for a charge no more
729
 
+    than the cost of performing this distribution.
730
 
+
731
 
+    d) If distribution of the work is made by offering access to copy
732
 
+    from a designated place, offer equivalent access to copy the above
733
 
+    specified materials from the same place.
734
 
+
735
 
+    e) Verify that the user has already received a copy of these
736
 
+    materials or that you have already sent this user a copy.
737
 
+
738
 
+  For an executable, the required form of the "work that uses the
739
 
+Library" must include any data and utility programs needed for
740
 
+reproducing the executable from it.  However, as a special exception,
741
 
+the materials to be distributed need not include anything that is
742
 
+normally distributed (in either source or binary form) with the major
743
 
+components (compiler, kernel, and so on) of the operating system on
744
 
+which the executable runs, unless that component itself accompanies
745
 
+the executable.
746
 
+
747
 
+  It may happen that this requirement contradicts the license
748
 
+restrictions of other proprietary libraries that do not normally
749
 
+accompany the operating system.  Such a contradiction means you cannot
750
 
+use both them and the Library together in an executable that you
751
 
+distribute.
752
 
+
753
 
+  7. You may place library facilities that are a work based on the
754
 
+Library side-by-side in a single library together with other library
755
 
+facilities not covered by this License, and distribute such a combined
756
 
+library, provided that the separate distribution of the work based on
757
 
+the Library and of the other library facilities is otherwise
758
 
+permitted, and provided that you do these two things:
759
 
+
760
 
+    a) Accompany the combined library with a copy of the same work
761
 
+    based on the Library, uncombined with any other library
762
 
+    facilities.  This must be distributed under the terms of the
763
 
+    Sections above.
764
 
+
765
 
+    b) Give prominent notice with the combined library of the fact
766
 
+    that part of it is a work based on the Library, and explaining
767
 
+    where to find the accompanying uncombined form of the same work.
768
 
+
769
 
+  8. You may not copy, modify, sublicense, link with, or distribute
770
 
+the Library except as expressly provided under this License.  Any
771
 
+attempt otherwise to copy, modify, sublicense, link with, or
772
 
+distribute the Library is void, and will automatically terminate your
773
 
+rights under this License.  However, parties who have received copies,
774
 
+or rights, from you under this License will not have their licenses
775
 
+terminated so long as such parties remain in full compliance.
776
 
+
777
 
+  9. You are not required to accept this License, since you have not
778
 
+signed it.  However, nothing else grants you permission to modify or
779
 
+distribute the Library or its derivative works.  These actions are
780
 
+prohibited by law if you do not accept this License.  Therefore, by
781
 
+modifying or distributing the Library (or any work based on the
782
 
+Library), you indicate your acceptance of this License to do so, and
783
 
+all its terms and conditions for copying, distributing or modifying
784
 
+the Library or works based on it.
785
 
+
786
 
+  10. Each time you redistribute the Library (or any work based on the
787
 
+Library), the recipient automatically receives a license from the
788
 
+original licensor to copy, distribute, link with or modify the Library
789
 
+subject to these terms and conditions.  You may not impose any further
790
 
+restrictions on the recipients' exercise of the rights granted herein.
791
 
+You are not responsible for enforcing compliance by third parties with
792
 
+this License.
793
 
+
794
 
+  11. If, as a consequence of a court judgment or allegation of patent
795
 
+infringement or for any other reason (not limited to patent issues),
796
 
+conditions are imposed on you (whether by court order, agreement or
797
 
+otherwise) that contradict the conditions of this License, they do not
798
 
+excuse you from the conditions of this License.  If you cannot
799
 
+distribute so as to satisfy simultaneously your obligations under this
800
 
+License and any other pertinent obligations, then as a consequence you
801
 
+may not distribute the Library at all.  For example, if a patent
802
 
+license would not permit royalty-free redistribution of the Library by
803
 
+all those who receive copies directly or indirectly through you, then
804
 
+the only way you could satisfy both it and this License would be to
805
 
+refrain entirely from distribution of the Library.
806
 
+
807
 
+If any portion of this section is held invalid or unenforceable under any
808
 
+particular circumstance, the balance of the section is intended to apply,
809
 
+and the section as a whole is intended to apply in other circumstances.
810
 
+
811
 
+It is not the purpose of this section to induce you to infringe any
812
 
+patents or other property right claims or to contest validity of any
813
 
+such claims; this section has the sole purpose of protecting the
814
 
+integrity of the free software distribution system which is
815
 
+implemented by public license practices.  Many people have made
816
 
+generous contributions to the wide range of software distributed
817
 
+through that system in reliance on consistent application of that
818
 
+system; it is up to the author/donor to decide if he or she is willing
819
 
+to distribute software through any other system and a licensee cannot
820
 
+impose that choice.
821
 
+
822
 
+This section is intended to make thoroughly clear what is believed to
823
 
+be a consequence of the rest of this License.
824
 
+
825
 
+  12. If the distribution and/or use of the Library is restricted in
826
 
+certain countries either by patents or by copyrighted interfaces, the
827
 
+original copyright holder who places the Library under this License may add
828
 
+an explicit geographical distribution limitation excluding those countries,
829
 
+so that distribution is permitted only in or among countries not thus
830
 
+excluded.  In such case, this License incorporates the limitation as if
831
 
+written in the body of this License.
832
 
+
833
 
+  13. The Free Software Foundation may publish revised and/or new
834
 
+versions of the Lesser General Public License from time to time.
835
 
+Such new versions will be similar in spirit to the present version,
836
 
+but may differ in detail to address new problems or concerns.
837
 
+
838
 
+Each version is given a distinguishing version number.  If the Library
839
 
+specifies a version number of this License which applies to it and
840
 
+"any later version", you have the option of following the terms and
841
 
+conditions either of that version or of any later version published by
842
 
+the Free Software Foundation.  If the Library does not specify a
843
 
+license version number, you may choose any version ever published by
844
 
+the Free Software Foundation.
845
 
+
846
 
+  14. If you wish to incorporate parts of the Library into other free
847
 
+programs whose distribution conditions are incompatible with these,
848
 
+write to the author to ask for permission.  For software which is
849
 
+copyrighted by the Free Software Foundation, write to the Free
850
 
+Software Foundation; we sometimes make exceptions for this.  Our
851
 
+decision will be guided by the two goals of preserving the free status
852
 
+of all derivatives of our free software and of promoting the sharing
853
 
+and reuse of software generally.
854
 
+
855
 
+                           NO WARRANTY
856
 
+
857
 
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
858
 
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
859
 
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
860
 
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
861
 
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
862
 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
863
 
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
864
 
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
865
 
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
866
 
+
867
 
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
868
 
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
869
 
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
870
 
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
871
 
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
872
 
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
873
 
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
874
 
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
875
 
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
876
 
+DAMAGES.
877
 
+
878
 
+                    END OF TERMS AND CONDITIONS
879
 
+
880
 
+           How to Apply These Terms to Your New Libraries
881
 
+
882
 
+  If you develop a new library, and you want it to be of the greatest
883
 
+possible use to the public, we recommend making it free software that
884
 
+everyone can redistribute and change.  You can do so by permitting
885
 
+redistribution under these terms (or, alternatively, under the terms of the
886
 
+ordinary General Public License).
887
 
+
888
 
+  To apply these terms, attach the following notices to the library.  It is
889
 
+safest to attach them to the start of each source file to most effectively
890
 
+convey the exclusion of warranty; and each file should have at least the
891
 
+"copyright" line and a pointer to where the full notice is found.
892
 
+
893
 
+    <one line to give the library's name and a brief idea of what it does.>
894
 
+    Copyright (C) <year>  <name of author>
895
 
+
896
 
+    This library is free software; you can redistribute it and/or
897
 
+    modify it under the terms of the GNU Lesser General Public
898
 
+    License as published by the Free Software Foundation; either
899
 
+    version 2.1 of the License, or (at your option) any later version.
900
 
+
901
 
+    This library is distributed in the hope that it will be useful,
902
 
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
903
 
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
904
 
+    Lesser General Public License for more details.
905
 
+
906
 
+    You should have received a copy of the GNU Lesser General Public
907
 
+    License along with this library; if not, write to the Free Software
908
 
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
909
 
+
910
 
+Also add information on how to contact you by electronic and paper mail.
911
 
+
912
 
+You should also get your employer (if you work as a programmer) or your
913
 
+school, if any, to sign a "copyright disclaimer" for the library, if
914
 
+necessary.  Here is a sample; alter the names:
915
 
+
916
 
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
917
 
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
918
 
+
919
 
+  <signature of Ty Coon>, 1 April 1990
920
 
+  Ty Coon, President of Vice
921
 
+
922
 
+That's all there is to it!
923
 
+
924
 
+
925
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons.mk openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons.mk
926
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons.mk      1970-01-01 01:00:00.000000000 +0100
927
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons.mk  2010-04-29 17:49:15.353968415 +0200
928
 
@@ -0,0 +1,66 @@
929
 
+# -*- mode: makefile; coding: utf-8 -*-
930
 
+# Copyright © 2005 Matthew A. Nicholson <matt@matt-land.com>
931
 
+# Copyright © 2008,2010 Jonas Smedegaard <dr@jones.dk>
932
 
+# Description: Builds and cleans SCons (SConstruct file) packages
933
 
+#
934
 
+# This program is free software; you can redistribute it and/or
935
 
+# modify it under the terms of the GNU General Public License as
936
 
+# published by the Free Software Foundation; either version 2, or (at
937
 
+# your option) any later version.
938
 
+#
939
 
+# This program is distributed in the hope that it will be useful, but
940
 
+# WITHOUT ANY WARRANTY; without even the implied warranty of
941
 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
942
 
+# General Public License for more details.
943
 
+#
944
 
+# You should have received a copy of the GNU General Public License
945
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
946
 
+
947
 
+_cdbs_scripts_path ?= /usr/local/libexec
948
 
+_cdbs_rules_path ?= /usr/local/share/cdbs/1/rules
949
 
+_cdbs_class_path ?= /usr/local/share/cdbs/1/class
950
 
+
951
 
+ifndef _cdbs_class_scons
952
 
+_cdbs_class_scons = 1
953
 
+
954
 
+include $(_cdbs_rules_path)/buildcore.mk$(_cdbs_makefile_suffix)
955
 
+include $(CURDIR)/debian/cdbs/1/class/scons-vars.mk$(_cdbs_makefile_suffix)
956
 
+
957
 
+CDBS_BUILD_DEPENDS_class_scons ?= scons
958
 
+CDBS_BUILD_DEPENDS += , $(CDBS_BUILD_DEPENDS_class_scons)
959
 
+
960
 
+DEB_PHONY_RULES += scons-clean
961
 
+
962
 
+common-build-arch common-build-indep:: debian/stamp-scons-build
963
 
+debian/stamp-scons-build:
964
 
+       $(DEB_SCONS_INVOKE) $(DEB_SCONS_BUILD_TARGET) $(DEB_SCONS_OPTIONS) $(DEB_SCONS_BUILD_OPTIONS)
965
 
+       touch debian/stamp-scons-build
966
 
+
967
 
+clean:: scons-clean
968
 
+scons-clean::
969
 
+       $(DEB_SCONS_INVOKE) $(DEB_SCONS_CLEAN_TARGET) $(DEB_SCONS_OPTIONS) --keep-going --clean || true
970
 
+       rm -f debian/stamp-scons-build
971
 
+       rm -rf .sconf_temp/
972
 
+       rm -f .sconsign.dblite config.log
973
 
+
974
 
+common-install-arch common-install-indep:: common-install-impl
975
 
+common-install-impl::
976
 
+       @if test -n "$(DEB_SCONS_INSTALL_TARGET)"; then \
977
 
+         echo $(DEB_SCONS_INVOKE) $(DEB_SCONS_INSTALL_TARGET) $(DEB_SCONS_OPTIONS) $(DEB_SCONS_INSTALL_OPTIONS); \
978
 
+         $(DEB_SCONS_INVOKE) $(DEB_SCONS_INSTALL_TARGET) $(DEB_SCONS_OPTIONS) $(DEB_SCONS_INSTALL_OPTIONS); \
979
 
+       else \
980
 
+         echo "DEB_SCONS_INSTALL_TARGET unset, skipping default scons.mk common-install target"; \
981
 
+       fi
982
 
+
983
 
+ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS)))
984
 
+common-post-build-arch common-post-build-indep:: common-post-build-impl
985
 
+common-post-build-impl::
986
 
+       @if test -n "$(DEB_SCONS_CHECK_TARGET)"; then \
987
 
+         echo $(DEB_SCONS_INVOKE) $(DEB_SCONS_CHECK_TARGET); \
988
 
+         $(DEB_SCONS_INVOKE) $(DEB_SCONS_CHECK_TARGET) $(DEB_SCONS_OPTIONS); \
989
 
+       else \
990
 
+          echo "DEB_SCONS_CHECK_TARGET unset, not running checks"; \
991
 
+       fi
992
 
+endif
993
 
+
994
 
+endif
995
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons-vars.mk openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons-vars.mk
996
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons-vars.mk 1970-01-01 01:00:00.000000000 +0100
997
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/cdbs/1/class/scons-vars.mk     2010-04-29 17:49:15.353968415 +0200
998
 
@@ -0,0 +1,50 @@
999
 
+# -*- mode: makefile; coding: utf-8 -*-
1000
 
+# Copyright © 2005 Matthew A. Nicholson <matt@matt-land.com>
1001
 
+# Copyright © 2008,2010 Jonas Smedegaard <dr@jones.dk>
1002
 
+# Description: Defines useful variables for SCons (SConstruct file) packages
1003
 
+#
1004
 
+# This program is free software; you can redistribute it and/or
1005
 
+# modify it under the terms of the GNU General Public License as
1006
 
+# published by the Free Software Foundation; either version 2, or (at
1007
 
+# your option) any later version.
1008
 
+#
1009
 
+# This program is distributed in the hope that it will be useful, but
1010
 
+# WITHOUT ANY WARRANTY; without even the implied warranty of
1011
 
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1012
 
+# General Public License for more details.
1013
 
+#
1014
 
+# You should have received a copy of the GNU General Public License
1015
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1016
 
+
1017
 
+_cdbs_scripts_path ?= /usr/local/libexec
1018
 
+_cdbs_rules_path ?= /usr/local/share/cdbs/1/rules
1019
 
+_cdbs_class_path ?= /usr/local/share/cdbs/1/class
1020
 
+
1021
 
+ifndef _cdbs_class_scons_vars
1022
 
+_cdbs_class_scons_vars = 1
1023
 
+
1024
 
+include $(_cdbs_class_path)/langcore.mk$(_cdbs_makefile_suffix)
1025
 
+
1026
 
+DEB_SCONS_ENVVARS = 
1027
 
+DEB_SCONS_INVOKE = $(DEB_SCONS_ENVVARS) scons --directory="$(DEB_BUILDDIR)" CC="$(or $(CC_$(cdbs_curpkg)),$(CC))" CFLAGS="$(or $(CFLAGS_$(cdbs_curpkg)),$(CFLAGS))" CXX="$(or $(CXX_$(cdbs_curpkg)),$(CXX))" CXXFLAGS="$(or $(CXXFLAGS_$(cdbs_curpkg)),$(CXXFLAGS))"
1028
 
+
1029
 
+# general options (passed on all scons commands)
1030
 
+DEB_SCONS_OPTIONS =
1031
 
+
1032
 
+# build target and options (only passed on build)
1033
 
+DEB_SCONS_BUILD_TARGET =
1034
 
+DEB_SCONS_BUILD_OPTIONS =
1035
 
+
1036
 
+# install target and options (only passed on install)
1037
 
+DEB_SCONS_INSTALL_TARGET = install
1038
 
+DEB_SCONS_INSTALL_OPTIONS =
1039
 
+
1040
 
+# clean target
1041
 
+DEB_SCONS_CLEAN_TARGET = .
1042
 
+
1043
 
+DEB_SCONS_CHECK_TARGET =
1044
 
+
1045
 
+CDBS_BUILD_DEPENDS_class_scons-vars ?= cdbs
1046
 
+CDBS_BUILD_DEPENDS += , $(CDBS_BUILD_DEPENDS_class_scons-vars)
1047
 
+
1048
 
+endif
1049
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/changelog openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/changelog
1050
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/changelog  1970-01-01 01:00:00.000000000 +0100
1051
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/changelog      2010-04-29 17:49:15.353968415 +0200
1052
 
@@ -0,0 +1,5 @@
1053
 
+openwns-wrowser (0.9beta2-0ubuntu2) hardy; urgency=low
1054
 
+
1055
 
+  * Initial release
1056
 
+
1057
 
+ -- Christian Kukla <cka@comnets.rwth-aachen.de>  Tue, 23 Mar 2010 12:51:57 +0100
1058
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/compat openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/compat
1059
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/compat     1970-01-01 01:00:00.000000000 +0100
1060
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/compat 2010-04-29 17:49:15.353968415 +0200
1061
 
@@ -0,0 +1 @@
1062
 
+5
1063
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/control openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/control
1064
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/control    1970-01-01 01:00:00.000000000 +0100
1065
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/control        2010-04-29 17:49:15.353968415 +0200
1066
 
@@ -0,0 +1,15 @@
1067
 
+Source: openwns-wrowser
1068
 
+Section: science
1069
 
+Priority: extra
1070
 
+Maintainer: Christian Kukla <cka@comnets.rwth-aachen.de>
1071
 
+Build-Depends: cdbs, debhelper (>= 5), python, python-central (>= 0.6.0), pyqt4-dev-tools, scons
1072
 
+Standards-Version: 3.8.3
1073
 
+XS-Python-Version: >=2.5
1074
 
+Homepage: http://www.openwns.org/
1075
 
+
1076
 
+Package: openwns-wrowser
1077
 
+Architecture: any
1078
 
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-psycopg2, python-matplotlib, python-scipy, pyqt4-dev-tools, openwns-common
1079
 
+XB-Python-Version: ${python:Versions}
1080
 
+Description: The openWNS results browser
1081
 
+ Browse simulation results with ease.
1082
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/copyright openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/copyright
1083
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/copyright  1970-01-01 01:00:00.000000000 +0100
1084
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/copyright      2010-04-29 17:49:15.353968415 +0200
1085
 
@@ -0,0 +1,41 @@
1086
 
+This package was debianized by Christian Kukla <cka@comnets.rwth-aachen.de> on
1087
 
+Tue, 23 Mar 2010 12:51:57 +0100.
1088
 
+
1089
 
+It was downloaded from http://launchpad.net/openwns-wrowser
1090
 
+
1091
 
+Upstream Authors: 
1092
 
+
1093
 
+    Swen Kühnlein <swen@da-inda.net>
1094
 
+    Marc Schinnenburg <marc@schinnenburg.net>
1095
 
+    Daniel Bültmann <me@daniel-bueltmann.de>
1096
 
+    Klaus Sambale <ksw@comnets.rwth-aachen.de>
1097
 
+    Ramin Rezai Rad <rrr@comnets.rwth-aachen.de>
1098
 
+
1099
 
+Copyright: 
1100
 
+
1101
 
+    Copyright (C) 2004-2008
1102
 
+    ComNets Research Group
1103
 
+    RWTH Aachen University
1104
 
+    Kopernikusstr. 5, D-52074 Aachen, Germany
1105
 
+
1106
 
+License:
1107
 
+
1108
 
+    This package is free software; you can redistribute it and/or
1109
 
+    modify it under the terms of the GNU Lesser General Public
1110
 
+    License as published by the Free Software Foundation; either
1111
 
+    version 2 of the License, or (at your option) any later version.
1112
 
+
1113
 
+    This package is distributed in the hope that it will be useful,
1114
 
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
1115
 
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1116
 
+    Lesser General Public License for more details.
1117
 
+
1118
 
+    You should have received a copy of the GNU Lesser General Public
1119
 
+    License along with this package; if not, write to the Free Software
1120
 
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
1121
 
+
1122
 
+On Debian systems, the complete text of the GNU Lesser General
1123
 
+Public License can be found in `/usr/share/common-licenses/LGPL'.
1124
 
+
1125
 
+The Debian packaging is (C) 2010, Christian Kukla  <cka@comnets.rwth-aachen.de> and
1126
 
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
1127
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/dirs openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/dirs
1128
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/dirs       1970-01-01 01:00:00.000000000 +0100
1129
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/dirs   2010-04-29 17:49:15.353968415 +0200
1130
 
@@ -0,0 +1,6 @@
1131
 
+usr
1132
 
+usr/bin
1133
 
+usr/sbin
1134
 
+usr/share
1135
 
+usr/share/pixmaps
1136
 
+usr/share/applications
1137
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/icon/wrowser.desktop openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/icon/wrowser.desktop
1138
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/icon/wrowser.desktop       1970-01-01 01:00:00.000000000 +0100
1139
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/icon/wrowser.desktop   2010-04-29 17:49:15.353968415 +0200
1140
 
@@ -0,0 +1,9 @@
1141
 
+[Desktop Entry]
1142
 
+Name=openWNS wrowser
1143
 
+Comment=The openWNS Result Browser
1144
 
+Exec=/usr/bin/wrowser
1145
 
+Icon=wrowser
1146
 
+Terminal=false
1147
 
+Type=Application
1148
 
+Categories=Qt;Education;Science
1149
 
+
1150
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/icon/wrowser.xpm openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/icon/wrowser.xpm
1151
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/icon/wrowser.xpm   1970-01-01 01:00:00.000000000 +0100
1152
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/icon/wrowser.xpm       2010-04-29 17:49:15.353968415 +0200
1153
 
@@ -0,0 +1,320 @@
1154
 
+/* XPM */
1155
 
+static char * wrowser_xpm[] = {
1156
 
+"32 32 285 2",
1157
 
+"      c None",
1158
 
+".     c #C8C8C8",
1159
 
+"+     c #CDBEB3",
1160
 
+"@     c #C9C4C1",
1161
 
+"#     c #CBC1BB",
1162
 
+"$     c #C9C4C0",
1163
 
+"%     c #C9C6C4",
1164
 
+"&     c #CCBFB5",
1165
 
+"*     c #D3B39D",
1166
 
+"=     c #F87015",
1167
 
+"-     c #FF6600",
1168
 
+";     c #F87219",
1169
 
+">     c #CCC0B8",
1170
 
+",     c #D9A989",
1171
 
+"'     c #FB6B0A",
1172
 
+")     c #F47825",
1173
 
+"!     c #DEA077",
1174
 
+"~     c #E49662",
1175
 
+"{     c #DAA786",
1176
 
+"]     c #CAC3BE",
1177
 
+"^     c #F57620",
1178
 
+"/     c #FE6601",
1179
 
+"(     c #F57724",
1180
 
+"_     c #CAC3BD",
1181
 
+":     c #F47928",
1182
 
+"<     c #DEA076",
1183
 
+"[     c #FB6C0C",
1184
 
+"}     c #DF9E74",
1185
 
+"|     c #E29765",
1186
 
+"1     c #F96F13",
1187
 
+"2     c #CBC1B9",
1188
 
+"3     c #E09B6D",
1189
 
+"4     c #EF8137",
1190
 
+"5     c #D8AA8C",
1191
 
+"6     c #D2B4A0",
1192
 
+"7     c #E98C4F",
1193
 
+"8     c #F47824",
1194
 
+"9     c #CCC0B9",
1195
 
+"0     c #FD6805",
1196
 
+"a     c #D2B5A1",
1197
 
+"b     c #FC6A09",
1198
 
+"c     c #C9C5C3",
1199
 
+"d     c #CFBAAB",
1200
 
+"e     c #F97015",
1201
 
+"f     c #FA6E12",
1202
 
+"g     c #DCA37D",
1203
 
+"h     c #ED843D",
1204
 
+"i     c #E09C70",
1205
 
+"j     c #EA8A49",
1206
 
+"k     c #EE833C",
1207
 
+"l     c #E5925A",
1208
 
+"m     c #E98B4C",
1209
 
+"n     c #D9A98A",
1210
 
+"o     c #F37928",
1211
 
+"p     c #E5945E",
1212
 
+"q     c #D0B9AA",
1213
 
+"r     c #FE6702",
1214
 
+"s     c #D9A887",
1215
 
+"t     c #E49561",
1216
 
+"u     c #FA6E11",
1217
 
+"v     c #F47927",
1218
 
+"w     c #D4B199",
1219
 
+"x     c #F6741E",
1220
 
+"y     c #D9A888",
1221
 
+"z     c #ED853F",
1222
 
+"A     c #F6751F",
1223
 
+"B     c #D7AC90",
1224
 
+"C     c #CFBAAC",
1225
 
+"D     c #E98D50",
1226
 
+"E     c #EC8641",
1227
 
+"F     c #F67520",
1228
 
+"G     c #E69158",
1229
 
+"H     c #C9C5C2",
1230
 
+"I     c #F77219",
1231
 
+"J     c #EE833B",
1232
 
+"K     c #CFBAAD",
1233
 
+"L     c #D1B6A4",
1234
 
+"M     c #F7731B",
1235
 
+"N     c #E29867",
1236
 
+"O     c #C8C7C6",
1237
 
+"P     c #CCBBB0",
1238
 
+"Q     c #F37B2B",
1239
 
+"R     c #F57622",
1240
 
+"S     c #C8C7C7",
1241
 
+"T     c #E5925B",
1242
 
+"U     c #DAA684",
1243
 
+"V     c #C6C6C6",
1244
 
+"W     c #EC8744",
1245
 
+"X     c #D4B19A",
1246
 
+"Y     c #C2C2C2",
1247
 
+"Z     c #7E7E81",
1248
 
+"`     c #8B8B8D",
1249
 
+" .    c #78797C",
1250
 
+"..    c #757679",
1251
 
+"+.    c #8E8E90",
1252
 
+"@.    c #77777A",
1253
 
+"#.    c #C0C0C1",
1254
 
+"$.    c #5F5F63",
1255
 
+"%.    c #AAAAAB",
1256
 
+"&.    c #A1A1A2",
1257
 
+"*.    c #78787B",
1258
 
+"=.    c #C7C7C7",
1259
 
+"-.    c #939496",
1260
 
+";.    c #5C5D61",
1261
 
+">.    c #55565A",
1262
 
+",.    c #727276",
1263
 
+"'.    c #C1C1C1",
1264
 
+").    c #D7AB8E",
1265
 
+"!.    c #828385",
1266
 
+"~.    c #5F6064",
1267
 
+"{.    c #47484D",
1268
 
+"].    c #48494E",
1269
 
+"^.    c #636467",
1270
 
+"/.    c #BBBCBC",
1271
 
+"(.    c #3C3D42",
1272
 
+"_.    c #656569",
1273
 
+":.    c #909092",
1274
 
+"<.    c #58585C",
1275
 
+"[.    c #ADADAE",
1276
 
+"}.    c #434449",
1277
 
+"|.    c #919293",
1278
 
+"1.    c #B0B0B1",
1279
 
+"2.    c #505155",
1280
 
+"3.    c #7F8082",
1281
 
+"4.    c #AFAFB0",
1282
 
+"5.    c #515256",
1283
 
+"6.    c #9E9FA0",
1284
 
+"7.    c #5B5C60",
1285
 
+"8.    c #9C9C9D",
1286
 
+"9.    c #545559",
1287
 
+"0.    c #A8A8A9",
1288
 
+"a.    c #B9B9BA",
1289
 
+"b.    c #3F4045",
1290
 
+"c.    c #A2A2A3",
1291
 
+"d.    c #929294",
1292
 
+"e.    c #58595D",
1293
 
+"f.    c #424348",
1294
 
+"g.    c #898A8C",
1295
 
+"h.    c #BEBEBF",
1296
 
+"i.    c #B1B1B2",
1297
 
+"j.    c #B6B6B7",
1298
 
+"k.    c #717275",
1299
 
+"l.    c #7B7B7E",
1300
 
+"m.    c #6E6F72",
1301
 
+"n.    c #5A5A5E",
1302
 
+"o.    c #C0C0C0",
1303
 
+"p.    c #B8B8B8",
1304
 
+"q.    c #48484D",
1305
 
+"r.    c #858587",
1306
 
+"s.    c #4F5054",
1307
 
+"t.    c #8A8A8D",
1308
 
+"u.    c #57585C",
1309
 
+"v.    c #C4C4C4",
1310
 
+"w.    c #56575B",
1311
 
+"x.    c #9A9A9C",
1312
 
+"y.    c #757578",
1313
 
+"z.    c #99999B",
1314
 
+"A.    c #A3A3A4",
1315
 
+"B.    c #C3C3C3",
1316
 
+"C.    c #B8B8B9",
1317
 
+"D.    c #B3B3B4",
1318
 
+"E.    c #69696D",
1319
 
+"F.    c #494A4E",
1320
 
+"G.    c #5E5E62",
1321
 
+"H.    c #ACACAD",
1322
 
+"I.    c #BEBEBE",
1323
 
+"J.    c #747578",
1324
 
+"K.    c #939395",
1325
 
+"L.    c #B7B7B8",
1326
 
+"M.    c #8C8D8F",
1327
 
+"N.    c #414247",
1328
 
+"O.    c #B2B2B2",
1329
 
+"P.    c #6A6B6E",
1330
 
+"Q.    c #959597",
1331
 
+"R.    c #545459",
1332
 
+"S.    c #B4B4B5",
1333
 
+"T.    c #838386",
1334
 
+"U.    c #868688",
1335
 
+"V.    c #BFBFBF",
1336
 
+"W.    c #BABABA",
1337
 
+"X.    c #9E9EA0",
1338
 
+"Y.    c #66666A",
1339
 
+"Z.    c #949494",
1340
 
+"`.    c #919191",
1341
 
+" +    c #ABABAB",
1342
 
+".+    c #B7B7B7",
1343
 
+"++    c #9D9D9D",
1344
 
+"@+    c #9F9F9F",
1345
 
+"#+    c #A1A1A1",
1346
 
+"$+    c #999999",
1347
 
+"%+    c #939393",
1348
 
+"&+    c #7A7A7A",
1349
 
+"*+    c #B0B0B0",
1350
 
+"=+    c #8C8C8C",
1351
 
+"-+    c #C5C5C5",
1352
 
+";+    c #A3A3A3",
1353
 
+">+    c #A7A7A7",
1354
 
+",+    c #B4B4B4",
1355
 
+"'+    c #8D8D8D",
1356
 
+")+    c #878787",
1357
 
+"!+    c #808080",
1358
 
+"~+    c #787878",
1359
 
+"{+    c #AAAAAA",
1360
 
+"]+    c #BCBCBC",
1361
 
+"^+    c #373737",
1362
 
+"/+    c #161616",
1363
 
+"(+    c #6F6F6F",
1364
 
+"_+    c #686868",
1365
 
+":+    c #7C7C7C",
1366
 
+"<+    c #3E3E3E",
1367
 
+"[+    c #202020",
1368
 
+"}+    c #5C5C5C",
1369
 
+"|+    c #696969",
1370
 
+"1+    c #3A3A3A",
1371
 
+"2+    c #4A4A4A",
1372
 
+"3+    c #313131",
1373
 
+"4+    c #A5A5A5",
1374
 
+"5+    c #1A1A1A",
1375
 
+"6+    c #727272",
1376
 
+"7+    c #505050",
1377
 
+"8+    c #636363",
1378
 
+"9+    c #656565",
1379
 
+"0+    c #464646",
1380
 
+"a+    c #2C2C2C",
1381
 
+"b+    c #575757",
1382
 
+"c+    c #363636",
1383
 
+"d+    c #545454",
1384
 
+"e+    c #A8A8A8",
1385
 
+"f+    c #626262",
1386
 
+"g+    c #1D1D1D",
1387
 
+"h+    c #BDBDBD",
1388
 
+"i+    c #454545",
1389
 
+"j+    c #292929",
1390
 
+"k+    c #616161",
1391
 
+"l+    c #353535",
1392
 
+"m+    c #121212",
1393
 
+"n+    c #2B2B2B",
1394
 
+"o+    c #979797",
1395
 
+"p+    c #141414",
1396
 
+"q+    c #171717",
1397
 
+"r+    c #4C4C4C",
1398
 
+"s+    c #1F1F1F",
1399
 
+"t+    c #B9B9B9",
1400
 
+"u+    c #242424",
1401
 
+"v+    c #282828",
1402
 
+"w+    c #B6B6B6",
1403
 
+"x+    c #777777",
1404
 
+"y+    c #020202",
1405
 
+"z+    c #7B7B7B",
1406
 
+"A+    c #828282",
1407
 
+"B+    c #646464",
1408
 
+"C+    c #474747",
1409
 
+"D+    c #AFAFAF",
1410
 
+"E+    c #080808",
1411
 
+"F+    c #9B9B9B",
1412
 
+"G+    c #303030",
1413
 
+"H+    c #B5B5B5",
1414
 
+"I+    c #2E2E2E",
1415
 
+"J+    c #767676",
1416
 
+"K+    c #0A0A0A",
1417
 
+"L+    c #A6A6A6",
1418
 
+"M+    c #000000",
1419
 
+"N+    c #414141",
1420
 
+"O+    c #3D3D3D",
1421
 
+"P+    c #707070",
1422
 
+"Q+    c #6D6D6D",
1423
 
+"R+    c #797979",
1424
 
+"S+    c #0B0B0B",
1425
 
+"T+    c #A0A0A0",
1426
 
+"U+    c #8E8E8E",
1427
 
+"V+    c #262626",
1428
 
+"W+    c #6A6A6A",
1429
 
+"X+    c #323232",
1430
 
+"Y+    c #2A2A2A",
1431
 
+"Z+    c #2D2D2D",
1432
 
+"`+    c #AEAEAE",
1433
 
+" @    c #030303",
1434
 
+".@    c #222222",
1435
 
+"+@    c #606060",
1436
 
+"@@    c #535353",
1437
 
+"#@    c #858585",
1438
 
+"$@    c #989898",
1439
 
+"%@    c #757575",
1440
 
+"&@    c #5B5B5B",
1441
 
+"*@    c #929292",
1442
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1443
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1444
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1445
 
+". . . + . . . @ . # . . . $ @ . . % . & . . . . . . . . . . . . ",
1446
 
+". * = - ; > , ' ) - ! . ~ - - { ] ^ ; / ( . . . . . . . . . . . ",
1447
 
+"_ : < . [ } | 1 2 3 4 5 - 6 7 8 9 0 a ! b c . . . . . . . . . . ",
1448
 
+"d e + . f g h | . i j k ; l m ~ n o . p 8 . . . . . . . . . . . ",
1449
 
+"q r s t u d v k w x y z A B z C D E . F G . . . . . . . . . . . ",
1450
 
+"H l I J K L ^ j M N O P Q R } S T U V W X . . . . . . V Y . . . ",
1451
 
+". . . . . 5 o $ . . . Z ` .  .... +.@.#.$.%.. &.*.=.-.;.>.,.'.. ",
1452
 
+". . . . . ).| % . . . !.~.. {.].V ^. ./.(._.V :.<.[.}.|.1.2.3.. ",
1453
 
+". . . . . . . . . . . 4.5.6.7.^.8.9.0.a.(.b.c.d.e.0.f.g.h.i.j.. ",
1454
 
+". . . . . . . . . . . #.;.k.l.!.m.n.o.p.q.r.s.t.u.v.:.7.s.w.x.. ",
1455
 
+". . . . . . . . . . . v.y.f.z.A.b.k.B.C.}.D.E.F.G.H.:.. I.J.s.. ",
1456
 
+". . . . . . . . . . . . K.(.L./.(.M.. p.N.1.'.(.;.O.f.P.Q.R.E.. ",
1457
 
+". . . . . . . . . . . . S.T.B.B.U.O.. V.Z W.. X.g.V [.Y.w.*.B.. ",
1458
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1459
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1460
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1461
 
+"v.Z.Y `. +.+++@+#+$+v.%+&+*+v.=+-+;+>+,+'+. )+!+B.. *+~+#+. {+;+",
1462
 
+"]+^+`./+(+_+:+<+[+}+|+1+2+3+4+5+o.[+6+7+8+9+0+a+b+W.c+d+/+e+f+g+",
1463
 
+"h+1+i+j+k+l+;+m+)+{+n+>+V./+o+p+'+q+r+s+t+u+v+:+w+|+u+x+y+z+<+A+",
1464
 
+"I.^+u+B+v+C+D+E+. F+G+.+>+q+H+g+I+J+K+}+v.L+i+M+'+N+O+P+Q+;+3+;+",
1465
 
+"o.c+}+R+S+T+U+G+. e+V+W+X+W+. Y+Z+`+ @>+'+g+z+.@T++@O+}+@@H+G+H+",
1466
 
+"-+Z.*+`+#@. e+$@. . %+}+#@. . =+e+]+'+'.. %@&@*@. ]+|+Q+Y p.`.-+",
1467
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1468
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1469
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1470
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1471
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1472
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
1473
 
+". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "};
1474
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/openwns-wrowser.install openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/openwns-wrowser.install
1475
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/openwns-wrowser.install    1970-01-01 01:00:00.000000000 +0100
1476
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/openwns-wrowser.install        2010-04-29 17:49:15.353968415 +0200
1477
 
@@ -0,0 +1,2 @@
1478
 
+debian/icon/wrowser.desktop /usr/share/applications
1479
 
+debian/icon/wrowser.xpm /usr/share/pixmaps
1480
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/pycompat openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/pycompat
1481
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/pycompat   1970-01-01 01:00:00.000000000 +0100
1482
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/pycompat       2010-04-29 17:49:15.353968415 +0200
1483
 
@@ -0,0 +1 @@
1484
 
+2
1485
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/rules openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/rules
1486
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/debian/rules      1970-01-01 01:00:00.000000000 +0100
1487
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/debian/rules  2010-04-29 17:49:15.353968415 +0200
1488
 
@@ -0,0 +1,17 @@
1489
 
+#!/usr/bin/make -f
1490
 
+
1491
 
+# use python-central
1492
 
+DEB_PYTHON_SYSTEM := pycentral
1493
 
+
1494
 
+include /usr/share/cdbs/1/rules/debhelper.mk
1495
 
+include /usr/share/cdbs/1/class/python-distutils.mk
1496
 
+include $(CURDIR)/debian/cdbs/1/class/scons.mk
1497
 
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
1498
 
+
1499
 
+# Don't compress .py files
1500
 
+DEB_COMPRESS_EXCLUDE := .py
1501
 
+# Don't remove this line
1502
 
+DEB_SCONS_INSTALL_TARGET := 
1503
 
+
1504
 
+
1505
 
+
1506
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/exportTemplates/plotAll.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/exportTemplates/plotAll.py
1507
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/exportTemplates/plotAll.py        1970-01-01 01:00:00.000000000 +0100
1508
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/exportTemplates/plotAll.py    2010-04-29 17:49:15.351332996 +0200
1509
 
@@ -0,0 +1,14 @@
1510
 
+import imp
1511
 
+import wrowser.FigurePlotter
1512
 
+import os
1513
 
+
1514
 
+for fileName in os.listdir('.'):
1515
 
+    if fileName.endswith('.py') and fileName!='plotAll.py' :
1516
 
+        print "file:",fileName
1517
 
+        try:
1518
 
+            module = imp.load_module('PlotParameters', file(fileName), '.', ('.py', 'r', imp.PY_SOURCE))
1519
 
+            #module.PlotParameters.color = False #parameter is modified for all plots
1520
 
+            print "going to plot the figure"
1521
 
+            wrowser.FigurePlotter.loadCampaignAndPlotGraphs(module.PlotParameters)
1522
 
+        except ImportError :
1523
 
+            print "this file does not contain the class 'PlotParameters'"
1524
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/exportTemplates/readDBandPlot openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/exportTemplates/readDBandPlot
1525
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/exportTemplates/readDBandPlot     1970-01-01 01:00:00.000000000 +0100
1526
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/exportTemplates/readDBandPlot 2010-04-29 17:49:15.351332996 +0200
1527
 
@@ -0,0 +1,13 @@
1528
 
+  #plotOrder = [0,2,1,3] # plot first graph 0 , then graph 2 , ...
1529
 
+  color_styles = ['b-', 'g-', 'r-', 'c-', 'm-','b--', 'r--', 'g--', 'c--', 'm--']
1530
 
+  bw_markers = ['+','.','*','x','o','v','^','<','>','s','p','*','h','H','D','d',',','|']
1531
 
+  #additional plots are defined as done here
1532
 
+  additional_plots = [
1533
 
+    #{'x': [1,400], 'y':[200,200], 'label':'a horizontal line' , 'style':'b--'},
1534
 
+    #{'x': [1,400], 'y':[1*.98,400*0.98], 'label':'98 % line' , 'style':'g--'}
1535
 
+  ]
1536
 
+  outputFormats = [ 'png', 'pdf']
1537
 
+
1538
 
+import wrowser.FigurePlotter
1539
 
+if __name__ == '__main__': wrowser.FigurePlotter.loadCampaignAndPlotGraphs(PlotParameters)
1540
 
+
1541
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/MAINTAINER openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/MAINTAINER
1542
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/MAINTAINER        1970-01-01 01:00:00.000000000 +0100
1543
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/MAINTAINER    2010-04-29 17:49:15.351332996 +0200
1544
 
@@ -0,0 +1,3 @@
1545
 
+Karsten Klagges <kks@comnets.rwth-aachen.de>
1546
 
+Swen K�hnlein <swen@comnets.rwth-aachen.de>
1547
 
+Marc Schinnenburg <msg@comnets.rwth-aachen.de>
1548
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/__init__.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/__init__.py
1549
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/__init__.py       1970-01-01 01:00:00.000000000 +0100
1550
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/__init__.py   2010-04-29 17:49:15.353968415 +0200
1551
 
@@ -0,0 +1,25 @@
1552
 
+import os
1553
 
+import sys
1554
 
+
1555
 
+validPaths = []
1556
 
+
1557
 
+for path in sys.path:
1558
 
+    if os.path.exists(os.path.join(path, 'openwns')):
1559
 
+        newPath = os.path.join(path, 'openwns')
1560
 
+        if os.path.join('lib', 'PyConfig') in newPath:
1561
 
+            validPaths.insert(0, newPath)
1562
 
+        else:
1563
 
+            validPaths.append(newPath)
1564
 
+
1565
 
+if len(validPaths) == 0:
1566
 
+    raise ImportError('Cannot import module')
1567
 
+
1568
 
+__path__ = validPaths
1569
 
+
1570
 
+for path in validPaths:
1571
 
+    initPath = os.path.join(path, '__init__.py')
1572
 
+    if not os.path.exists(os.path.join(path, '__openwns__mainModule__')):
1573
 
+        try:
1574
 
+            execfile(initPath)
1575
 
+        except IOError:
1576
 
+            pass
1577
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Configuration.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Configuration.py
1578
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Configuration.py  1970-01-01 01:00:00.000000000 +0100
1579
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Configuration.py      2010-04-29 17:49:15.353968415 +0200
1580
 
@@ -0,0 +1,198 @@
1581
 
+###############################################################################
1582
 
+# This file is part of openWNS (open Wireless Network Simulator)
1583
 
+# _____________________________________________________________________________
1584
 
+#
1585
 
+# Copyright (C) 2004-2007
1586
 
+# Chair of Communication Networks (ComNets)
1587
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
1588
 
+# phone: ++49-241-80-27910,
1589
 
+# fax: ++49-241-80-22242
1590
 
+# email: info@openwns.org
1591
 
+# www: http://www.openwns.org
1592
 
+# _____________________________________________________________________________
1593
 
+#
1594
 
+# openWNS is free software; you can redistribute it and/or modify it under the
1595
 
+# terms of the GNU Lesser General Public License version 2 as published by the
1596
 
+# Free Software Foundation;
1597
 
+#
1598
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
1599
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1600
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
1601
 
+# details.
1602
 
+#
1603
 
+# You should have received a copy of the GNU Lesser General Public License
1604
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1605
 
+#
1606
 
+###############################################################################
1607
 
+
1608
 
+import os
1609
 
+import sys
1610
 
+import pwd
1611
 
+import ConfigParser
1612
 
+
1613
 
+class MissingConfigurationFile(Exception):
1614
 
+
1615
 
+    def __init__(self, filename):
1616
 
+        self.filename = filename
1617
 
+
1618
 
+    def __str__(self):
1619
 
+        return "Cannot open configuration file: " + self.filename
1620
 
+
1621
 
+
1622
 
+class WrongFilePermissions(Exception):
1623
 
+
1624
 
+    def __init__(self, filename):
1625
 
+        self.filename = filename
1626
 
+
1627
 
+    def __str__(self):
1628
 
+        msg = "Wrong file access permissions to \'%s\'. Due to security reasons only the owner of the file must have read/write access. Consider changing the database password if unauthorized people might have become aware of it." % self.filename
1629
 
+        return msg
1630
 
+
1631
 
+class MissingConfigurationEntry(Exception):
1632
 
+
1633
 
+    def __init__(self, filename, entry):
1634
 
+        self.entry = entry
1635
 
+        self.filename = filename
1636
 
+
1637
 
+    def __str__(self):
1638
 
+        return "Entry %s is missing in config" % (self.entry, )
1639
 
+
1640
 
+class MissingConfigurationSection(Exception):
1641
 
+
1642
 
+    def __init__(self, filename,section):
1643
 
+        self.section = section
1644
 
+        self.filename = filename
1645
 
+
1646
 
+    def __str__(self):
1647
 
+        return "Section %s is missing in config" % (self.section, )
1648
 
+
1649
 
+class BadConfigurationFile(Exception):
1650
 
+
1651
 
+    def __init__(self, filename):
1652
 
+        self.filename = filename
1653
 
+
1654
 
+    def __str__(self):
1655
 
+        return "The configuration file %s cannot be read." % (self.filename, )
1656
 
+
1657
 
+class SandboxConfiguration(object):
1658
 
+  
1659
 
+    def __init__(self):
1660
 
+        self.parser = ConfigParser.SafeConfigParser()
1661
 
+        self.confFile = os.path.join(os.environ['HOME'], '.wns', 'sandbox.conf')
1662
 
+        
1663
 
+    def read(self):
1664
 
+
1665
 
+        try:
1666
 
+            self.parser.read([self.confFile])
1667
 
+        except ConfigParser.MissingSectionHeaderError, e:
1668
 
+            raise BadConfigurationFile(self.confFile)        
1669
 
+        
1670
 
+        if 'Sandbox' in self.parser.sections():
1671
 
+            if 'path' in self.parser.options('Sandbox'):
1672
 
+                setattr(self, 'sandboxPath', str(self.parser.get('Sandbox', 'path')))
1673
 
+            else:
1674
 
+                raise MissingConfigurationEntry(self.confFile, "Sandbox.path")
1675
 
+            if 'flavour' in self.parser.options('Sandbox'):
1676
 
+                setattr(self, 'sandboxFlavour', str(self.parser.get('Sandbox', 'flavour')))
1677
 
+            else:
1678
 
+                raise MissingConfigurationEntry(self.confFile, "Sandbox.flavour")
1679
 
+        else:
1680
 
+            raise MissingConfigurationSection(self.confFile, "Sandbox")
1681
 
+
1682
 
+    def writeSandboxConf(self, owner):        
1683
 
+        if 'Sandbox' not in self.parser.sections():
1684
 
+            self.parser.add_section('Sandbox')
1685
 
+
1686
 
+        self.parser.set('Sandbox', 'path', getattr(self, 'sandboxPath'))
1687
 
+        self.parser.set('Sandbox', 'flavour', getattr(self, 'sandboxFlavour'))
1688
 
+
1689
 
+        config = file(self.confFile, 'w')
1690
 
+        self.parser.write(config)
1691
 
+        config.close()
1692
 
+        os.chown(self.confFile, pwd.getpwnam(owner)[2], pwd.getpwnam(owner)[3])
1693
 
+        os.chmod(self.confFile, 0644)
1694
 
+
1695
 
+
1696
 
+
1697
 
+class Configuration(object):
1698
 
+
1699
 
+    def __init__(self):
1700
 
+        self.parser = ConfigParser.SafeConfigParser()
1701
 
+        self.dbAccessConfFile = os.path.join(os.environ['HOME'], '.wns', 'dbAccess.conf')
1702
 
+
1703
 
+    def read(self, filename = ''):
1704
 
+
1705
 
+        try:
1706
 
+            self.parser.read([self.dbAccessConfFile, filename])
1707
 
+        except ConfigParser.MissingSectionHeaderError, e:
1708
 
+            raise BadConfigurationFile(filename)
1709
 
+
1710
 
+        if 'DB' in self.parser.sections():
1711
 
+            if 'host' in self.parser.options('DB'):
1712
 
+                setattr(self, 'dbHost', self.parser.get('DB', 'host'))
1713
 
+            else:
1714
 
+                raise MissingConfigurationEntry(filename, "DB.host")
1715
 
+
1716
 
+            if 'name' in self.parser.options('DB'):
1717
 
+                setattr(self, 'dbName', self.parser.get('DB', 'name'))
1718
 
+            else:
1719
 
+                raise MissingConfigurationEntry(filename, "DB.name")
1720
 
+        else:
1721
 
+            raise MissingConfigurationSection(filename, "DB")
1722
 
+
1723
 
+        if 'User' in self.parser.sections():
1724
 
+            if 'name' in self.parser.options('User'):
1725
 
+                setattr(self, 'userName', self.parser.get('User', 'name'))
1726
 
+            else:
1727
 
+                raise MissingConfigurationEntry(filename, "User.name")
1728
 
+
1729
 
+            if 'password' in self.parser.options('User'):
1730
 
+                setattr(self, 'userPassword', self.parser.get('User', 'password'))
1731
 
+            else:
1732
 
+                raise MissingConfigurationEntry(filename, "User.password")
1733
 
+        else:
1734
 
+            raise MissingConfigurationSection(filename, "User")
1735
 
+
1736
 
+        if 'Campaign' in self.parser.sections():
1737
 
+            if 'id' in self.parser.options('Campaign'):
1738
 
+                setattr(self, 'campaignId', int(self.parser.get('Campaign', 'id')))
1739
 
+            else:
1740
 
+                raise MissingConfigurationEntry(filename, "Campaign.id")
1741
 
+
1742
 
+    def writeDbAccessConf(self, filename, owner):
1743
 
+        dbAccessConfFile = filename
1744
 
+        if 'DB' not in self.parser.sections():
1745
 
+            self.parser.add_section('DB')
1746
 
+
1747
 
+        self.parser.set('DB', 'host', getattr(self, 'dbHost'))
1748
 
+        self.parser.set('DB', 'name', getattr(self, 'dbName'))
1749
 
+
1750
 
+        if 'User' not in self.parser.sections():
1751
 
+            self.parser.add_section('User')
1752
 
+
1753
 
+        self.parser.set('User', 'name', getattr(self, 'userName'))
1754
 
+        self.parser.set('User', 'password', getattr(self, 'userPassword'))
1755
 
+
1756
 
+        wnsDir = os.environ['HOME']+"/.wns"
1757
 
+        if not os.path.exists(wnsDir) :
1758
 
+            os.makedirs(wnsDir)
1759
 
+
1760
 
+        config = file(dbAccessConfFile, 'w')
1761
 
+        config.write('# Keep this file private. Do NOT change file access permissions. Security hazard!\n\n')
1762
 
+        self.parser.write(config)
1763
 
+        config.close()
1764
 
+        os.chown(dbAccessConfFile, pwd.getpwnam(owner)[2], pwd.getpwnam(owner)[3])
1765
 
+        os.chmod(dbAccessConfFile, 0600)
1766
 
+
1767
 
+
1768
 
+    def writeCampaignConf(self, filename):
1769
 
+        if 'Campaign' not in self.parser.sections():
1770
 
+            self.parser.add_section('Campaign')
1771
 
+
1772
 
+        self.parser.set('Campaign', 'id', str(getattr(self, 'campaignId')))
1773
 
+
1774
 
+        config = file(filename, 'w')
1775
 
+        config.write('# Do NOT edit this file manually!\n\n')
1776
 
+        self.parser.write(config)
1777
 
+        config.close()
1778
 
+        os.chmod(filename, 0644)
1779
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Data.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Data.py
1780
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Data.py   1970-01-01 01:00:00.000000000 +0100
1781
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Data.py       2010-04-29 17:49:15.353968415 +0200
1782
 
@@ -0,0 +1,42 @@
1783
 
+###############################################################################
1784
 
+# This file is part of openWNS (open Wireless Network Simulator)
1785
 
+# _____________________________________________________________________________
1786
 
+#
1787
 
+# Copyright (C) 2004-2007
1788
 
+# Chair of Communication Networks (ComNets)
1789
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
1790
 
+# phone: ++49-241-80-27910,
1791
 
+# fax: ++49-241-80-22242
1792
 
+# email: info@openwns.org
1793
 
+# www: http://www.openwns.org
1794
 
+# _____________________________________________________________________________
1795
 
+#
1796
 
+# openWNS is free software; you can redistribute it and/or modify it under the
1797
 
+# terms of the GNU Lesser General Public License version 2 as published by the
1798
 
+# Free Software Foundation;
1799
 
+#
1800
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
1801
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1802
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
1803
 
+# details.
1804
 
+#
1805
 
+# You should have received a copy of the GNU Lesser General Public License
1806
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1807
 
+#
1808
 
+###############################################################################
1809
 
+
1810
 
+from Tools import Observable
1811
 
+
1812
 
+class Figure(Observable):
1813
 
+    def __init__(self):
1814
 
+        Observable.__init__(self)
1815
 
+        self.graphs = []
1816
 
+        self.grid = (False, False, False, False)
1817
 
+        self.marker = "."
1818
 
+        self.scale = ("linear", None, "linear", None)
1819
 
+        self.legend = False
1820
 
+        self.title = ""
1821
 
+        self.colormap = "jet"
1822
 
+        self.colorbar = True
1823
 
+        self.xAxisTitle = ""
1824
 
+        self.yAxisTitle = ""
1825
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Debug.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Debug.py
1826
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Debug.py  1970-01-01 01:00:00.000000000 +0100
1827
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Debug.py      2010-04-29 17:49:15.353968415 +0200
1828
 
@@ -0,0 +1,66 @@
1829
 
+###############################################################################
1830
 
+# This file is part of openWNS (open Wireless Network Simulator)
1831
 
+# _____________________________________________________________________________
1832
 
+#
1833
 
+# Copyright (C) 2004-2007
1834
 
+# Chair of Communication Networks (ComNets)
1835
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
1836
 
+# phone: ++49-241-80-27910,
1837
 
+# fax: ++49-241-80-22242
1838
 
+# email: info@openwns.org
1839
 
+# www: http://www.openwns.org
1840
 
+# _____________________________________________________________________________
1841
 
+#
1842
 
+# openWNS is free software; you can redistribute it and/or modify it under the
1843
 
+# terms of the GNU Lesser General Public License version 2 as published by the
1844
 
+# Free Software Foundation;
1845
 
+#
1846
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
1847
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1848
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
1849
 
+# details.
1850
 
+#
1851
 
+# You should have received a copy of the GNU Lesser General Public License
1852
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1853
 
+#
1854
 
+###############################################################################
1855
 
+
1856
 
+import time
1857
 
+import inspect
1858
 
+
1859
 
+class Debug:
1860
 
+    output = True
1861
 
+
1862
 
+class printCallCounter:
1863
 
+    ctr = 0
1864
 
+
1865
 
+def printCall(instance = None, args = ""):
1866
 
+    if Debug.output:
1867
 
+        print printCallCounter.ctr, time.strftime("%c")
1868
 
+        printCallCounter.ctr += 1
1869
 
+        print "instance: ", instance
1870
 
+        function = inspect.stack()[1][3]
1871
 
+        print "function: ", function
1872
 
+        print "args: ", args
1873
 
+        print ""
1874
 
+
1875
 
+def debugCall(argFormatter = lambda x: x,
1876
 
+              kwargFormatter = lambda x: x,
1877
 
+              resultFormatter = lambda x: x):
1878
 
+
1879
 
+    def wrapCall(func):
1880
 
+
1881
 
+        def callFunc(*args, **kwargs):
1882
 
+            if Debug.output:
1883
 
+                print "Calling " + func.func_name
1884
 
+                print "with args", argFormatter(args)
1885
 
+                print " - kwargs", kwargFormatter(kwargs)
1886
 
+            result = func(*args, **kwargs)
1887
 
+            if Debug.output:
1888
 
+                print "yields", resultFormatter(result)
1889
 
+                print ""
1890
 
+            return result
1891
 
+
1892
 
+        return callFunc
1893
 
+
1894
 
+    return wrapCall
1895
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Dialogues.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Dialogues.py
1896
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Dialogues.py      1970-01-01 01:00:00.000000000 +0100
1897
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Dialogues.py  2010-04-29 17:49:15.353968415 +0200
1898
 
@@ -0,0 +1,411 @@
1899
 
+###############################################################################
1900
 
+# This file is part of openWNS (open Wireless Network Simulator)
1901
 
+# _____________________________________________________________________________
1902
 
+#
1903
 
+# Copyright (C) 2004-2007
1904
 
+# Chair of Communication Networks (ComNets)
1905
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
1906
 
+# phone: ++49-241-80-27910,
1907
 
+# fax: ++49-241-80-22242
1908
 
+# email: info@openwns.org
1909
 
+# www: http://www.openwns.org
1910
 
+# _____________________________________________________________________________
1911
 
+#
1912
 
+# openWNS is free software; you can redistribute it and/or modify it under the
1913
 
+# terms of the GNU Lesser General Public License version 2 as published by the
1914
 
+# Free Software Foundation;
1915
 
+#
1916
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
1917
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1918
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
1919
 
+# details.
1920
 
+#
1921
 
+# You should have received a copy of the GNU Lesser General Public License
1922
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
1923
 
+#
1924
 
+###############################################################################
1925
 
+
1926
 
+import os
1927
 
+import datetime
1928
 
+
1929
 
+from PyQt4 import QtCore, QtGui
1930
 
+
1931
 
+from Tools import URI, Observing
1932
 
+
1933
 
+import Models
1934
 
+import Debug
1935
 
+import time
1936
 
+
1937
 
+from ui.Dialogues_Preferences_ui import Ui_Dialogues_Preferences
1938
 
+class Preferences(QtGui.QDialog, Ui_Dialogues_Preferences):
1939
 
+
1940
 
+    def __init__(self, *args):
1941
 
+        QtGui.QDialog.__init__(self, *args)
1942
 
+        self.setupUi(self)
1943
 
+
1944
 
+    def readFromConfig(self, filename, owner):
1945
 
+        import Configuration
1946
 
+        try:
1947
 
+            c = Configuration.Configuration()
1948
 
+            c.read(filename)
1949
 
+        except Configuration.MissingConfigurationFile, e:
1950
 
+            setattr(c, 'dbHost', "")
1951
 
+            setattr(c, 'dbName', "")
1952
 
+            setattr(c, 'userName', "")
1953
 
+            setattr(c, 'userPassword', "")
1954
 
+            c.writeDbAccessConf(filename, owner)
1955
 
+        except (Configuration.BadConfigurationFile,
1956
 
+                Configuration.MissingConfigurationSection,
1957
 
+                Configuration.MissingConfigurationEntry), e:
1958
 
+            QtGui.QMessageBox.warning(self, "Parse Error", "Cannot read %s. Creating a new one.\n Error is : %s" % (unicode(e.filename), str(e)))
1959
 
+            setattr(c, 'dbHost', "")
1960
 
+            setattr(c, 'dbName', "")
1961
 
+            setattr(c, 'userName', "")
1962
 
+            setattr(c, 'userPassword', "")
1963
 
+            c.writeDbAccessConf(filename, owner)
1964
 
+
1965
 
+        self.hostname.setText(c.dbHost)
1966
 
+        self.databasename.setText(c.dbName)
1967
 
+        self.username.setText(c.userName)
1968
 
+        self.password.setText(c.userPassword)
1969
 
+        
1970
 
+        try:
1971
 
+            cSandbox = Configuration.SandboxConfiguration()
1972
 
+            cSandbox.read()
1973
 
+        except Configuration.MissingConfigurationFile, e:
1974
 
+            setattr(cSandbox, 'sandboxPath', "")
1975
 
+            setattr(cSandbox, 'sandboxFlavour', "dbg")
1976
 
+            c.writeDbAccessConf(filename, owner)
1977
 
+        except (Configuration.BadConfigurationFile,
1978
 
+                Configuration.MissingConfigurationSection,
1979
 
+                Configuration.MissingConfigurationEntry), e:
1980
 
+            setattr(cSandbox, 'sandboxPath', "")
1981
 
+            setattr(cSandbox, 'sandboxFlavour', "dbg")
1982
 
+            cSandbox.writeSandboxConf(owner)
1983
 
+
1984
 
+        self.sandboxpath.setText(cSandbox.sandboxPath)
1985
 
+        self.sandboxflavour.setCurrentIndex(self.sandboxflavour.findText(QtCore.QString(cSandbox.sandboxFlavour)))
1986
 
+
1987
 
+    def writeToConfig(self, filename, owner):
1988
 
+        import Configuration
1989
 
+        c = Configuration.Configuration()
1990
 
+        c.read(filename)
1991
 
+
1992
 
+        setattr(c, 'dbHost', str(self.hostname.text()))
1993
 
+        setattr(c, 'dbName', str(self.databasename.text()))
1994
 
+        setattr(c, 'userName', str(self.username.text()))
1995
 
+        setattr(c, 'userPassword', str(self.password.text()))
1996
 
+        c.writeDbAccessConf(filename, owner)
1997
 
+
1998
 
+        cSandbox = Configuration.SandboxConfiguration()
1999
 
+        cSandbox.read()
2000
 
+        setattr(cSandbox, 'sandboxPath', str(self.sandboxpath.text()))
2001
 
+        setattr(cSandbox, 'sandboxFlavour', str(self.sandboxflavour.currentText()))
2002
 
+        cSandbox.writeSandboxConf(owner)
2003
 
+
2004
 
+from ui.Dialogues_OpenCampaignDb_ui import Ui_Dialogues_OpenCampaignDb
2005
 
+class OpenCampaignDb(QtGui.QDialog, Ui_Dialogues_OpenCampaignDb):
2006
 
+    def __init__(self, *args):
2007
 
+        from openwns.wrowser.simdb import Campaigns
2008
 
+
2009
 
+        QtGui.QDialog.__init__(self, *args)
2010
 
+        self.setupUi(self)
2011
 
+
2012
 
+        self.campaignsModel = Models.CampaignDb(Campaigns.getCampaignsDict())
2013
 
+        self.campaigns.setModel(self.campaignsModel)
2014
 
+
2015
 
+        user = os.getenv("USER")
2016
 
+        userIndex = self.campaignsModel.getUserRow(user)
2017
 
+        if userIndex != -1 :
2018
 
+            self.campaigns.expand(userIndex)
2019
 
+            self.campaigns.scrollTo(userIndex)
2020
 
+
2021
 
+        for column in xrange(self.campaignsModel.columnCount()):
2022
 
+            self.campaigns.resizeColumnToContents(column)
2023
 
+
2024
 
+    def getCampaign(self):
2025
 
+        return self.campaignsModel.getCampaign(self.campaigns.selectedIndexes()[0])
2026
 
+
2027
 
+from ui.Dialogues_OpenDSV_ui import Ui_Dialogues_OpenDSV
2028
 
+class OpenDSV(QtGui.QDialog, Ui_Dialogues_OpenDSV):
2029
 
+    def __init__(self, *args):
2030
 
+        QtGui.QWidget.__init__(self, *args)
2031
 
+        self.setupUi(self)
2032
 
+
2033
 
+    @QtCore.pyqtSignature("bool")
2034
 
+    def on_openButton_clicked(self, checked):
2035
 
+        Debug.printCall(self, checked)
2036
 
+        fileDialogue = QtGui.QFileDialog(self, "Select a campaign", os.getcwd(), "DSV files (*.csv *.txt)")
2037
 
+        fileDialogue.setAcceptMode(QtGui.QFileDialog.AcceptOpen)
2038
 
+        fileDialogue.setFileMode(QtGui.QFileDialog.ExistingFile)
2039
 
+        fileDialogue.setViewMode(QtGui.QFileDialog.Detail)
2040
 
+        if fileDialogue.exec_() == QtGui.QDialog.Accepted:
2041
 
+            fileName = fileDialogue.selectedFiles()[0]
2042
 
+            self.fileNameEdit.setText(fileName)
2043
 
+
2044
 
+    @QtCore.pyqtSignature("")
2045
 
+    def on_fileNameEdit_editingFinished(self):
2046
 
+        Debug.printCall(self)
2047
 
+        text = str(self.fileNameEdit.text())
2048
 
+        if not text.startswith("/"):
2049
 
+            text = os.path.abspath(text)
2050
 
+            self.fileNameEdit.setText(text)
2051
 
+
2052
 
+    def getSettings(self):
2053
 
+        from Tools import Chameleon as Values
2054
 
+
2055
 
+        return Values(fileName = str(self.fileNameEdit.text()),
2056
 
+                      delimiter = str(self.delimiterEdit.text()),
2057
 
+                      directoryColumn = str(self.directoryColumnEdit.text()),
2058
 
+                      subDirectory = str(self.subDirectoryEdit.text()))
2059
 
+
2060
 
+class Progress(QtGui.QProgressDialog):
2061
 
+    def __init__(self, labelText, minShow, *args):
2062
 
+        QtGui.QProgressDialog.__init__(self, *args)
2063
 
+#        self.setCancelButton(None)
2064
 
+        self.setCancelButtonText("Cancel")
2065
 
+        self.labelText = labelText
2066
 
+        self.setLabelText(labelText)
2067
 
+        self.setMinimumDuration(minShow)
2068
 
+        self.setAutoClose(True)
2069
 
+        self.reset()
2070
 
+
2071
 
+    def reset(self):
2072
 
+        self.setMinimum(0)
2073
 
+        self.startTime = datetime.datetime.now()
2074
 
+        QtGui.QProgressDialog.reset(self)
2075
 
+
2076
 
+    def setCurrentAndMaximum(self, current, maximum, additionalText = ""):
2077
 
+        import Time
2078
 
+
2079
 
+        self.setMaximum(maximum)
2080
 
+        self.setValue(current)
2081
 
+        labelText = self.labelText
2082
 
+        if len(additionalText) > 0:
2083
 
+            labelText += "\n" + additionalText
2084
 
+        if maximum > 0 and float(current)/maximum >= 0.01:
2085
 
+            elapsed = datetime.datetime.now() - self.startTime
2086
 
+            total = elapsed * maximum / current
2087
 
+            remaining = total - elapsed
2088
 
+            labelText += "\napprox. " + Time.Delta(remaining).asString() + " left"
2089
 
+        self.setLabelText(labelText)
2090
 
+        if QtGui.QApplication.hasPendingEvents():
2091
 
+            QtGui.QApplication.instance().syncX()
2092
 
+            QtGui.QApplication.instance().processEvents()
2093
 
+        time.sleep(0.006)
2094
 
+
2095
 
+from ui.Dialogues_ColumnSelect_ui import Ui_Dialogues_ColumnSelect
2096
 
+class ColumnSelect(QtGui.QDialog, Ui_Dialogues_ColumnSelect):
2097
 
+    def __init__(self, cancelFlag, *args):
2098
 
+        QtGui.QDialog.__init__(self, *args)
2099
 
+        self.cancelFlag = cancelFlag
2100
 
+        self.setupUi(self)
2101
 
+
2102
 
+    def do(self, columns, deselectedColumns):
2103
 
+        self.columnList.addItems(columns)
2104
 
+        for row in range(0, self.columnList.count()):
2105
 
+            item = self.columnList.item(row)
2106
 
+            self.columnList.setItemSelected(item, not item.text() in deselectedColumns)
2107
 
+        if self.exec_() == QtGui.QDialog.Accepted:
2108
 
+            parameters = []
2109
 
+            for row in range(0, self.columnList.count()):
2110
 
+                item = self.columnList.item(row)
2111
 
+                if self.columnList.isItemSelected(item):
2112
 
+                    parameters.append(str(item.text()))
2113
 
+            return parameters
2114
 
+        else:
2115
 
+            self.cancelFlag.cancelled = True
2116
 
+            return []
2117
 
+
2118
 
+from ui.Dialogues_ConfigureGraph_ui import Ui_Dialogues_ConfigureGraph
2119
 
+class ConfigureGraph(QtGui.QDialog, Ui_Dialogues_ConfigureGraph):
2120
 
+
2121
 
+    def __init__(self, figure, *args):
2122
 
+        import matplotlib.numerix as numerix
2123
 
+
2124
 
+        self.figure = figure
2125
 
+        self.scales = {"linear": ("linear", None),
2126
 
+                       "ld": ("log", 2),
2127
 
+                       "ln": ("log", numerix.e),
2128
 
+                       "lg": ("log", 10)}
2129
 
+        self.scalesReverse = dict(zip(self.scales.values(),
2130
 
+                                      self.scales.keys()))
2131
 
+
2132
 
+        QtGui.QWidget.__init__(self, *args)
2133
 
+        self.setupUi(self)
2134
 
+
2135
 
+        if self.figure.grid[0]:
2136
 
+            self.xgridMajor.setCheckState(QtCore.Qt.Checked)
2137
 
+        if self.figure.grid[1]:
2138
 
+            self.xgridMinor.setCheckState(QtCore.Qt.Checked)
2139
 
+        if self.figure.grid[2]:
2140
 
+            self.ygridMajor.setCheckState(QtCore.Qt.Checked)
2141
 
+        if self.figure.grid[3]:
2142
 
+            self.ygridMinor.setCheckState(QtCore.Qt.Checked)
2143
 
+
2144
 
+        self.xscale.setCurrentIndex(self.xscale.findText(self.scalesReverse[self.figure.scale[0:2]]))
2145
 
+        self.yscale.setCurrentIndex(self.yscale.findText(self.scalesReverse[self.figure.scale[2:4]]))
2146
 
+
2147
 
+        self.marker.setCurrentIndex(self.marker.findText(self.figure.marker))
2148
 
+        if self.figure.legend:
2149
 
+            self.showLegend.setCheckState(QtCore.Qt.Checked)
2150
 
+        self.titleEdit.setText(self.figure.title)
2151
 
+        self.xAxisEdit.setText(self.figure.xAxisTitle)
2152
 
+        self.yAxisEdit.setText(self.figure.yAxisTitle)
2153
 
+        if self.figure.colorbar:
2154
 
+            self.colorbarCheckBox.setCheckState(QtCore.Qt.Checked)
2155
 
+        else:
2156
 
+            self.colorbarCheckBox.setCheckState(QtCore.Qt.Unchecked)
2157
 
+
2158
 
+        self.colormapComboBox.setCurrentIndex(self.colormapComboBox.findText(self.figure.colormap))
2159
 
+
2160
 
+
2161
 
+    @QtCore.pyqtSignature("")
2162
 
+    def on_buttonBox_accepted(self):
2163
 
+        self.applyData()
2164
 
+
2165
 
+    @QtCore.pyqtSignature("QAbstractButton*")
2166
 
+    def on_buttonBox_clicked(self, button):
2167
 
+        if self.buttonBox.buttonRole(button) == QtGui.QDialogButtonBox.ApplyRole:
2168
 
+            self.applyData()
2169
 
+
2170
 
+    def applyData(self):
2171
 
+        grid = (self.xgridMajor.checkState() == QtCore.Qt.Checked,
2172
 
+                self.xgridMinor.checkState() == QtCore.Qt.Checked,
2173
 
+                self.ygridMajor.checkState() == QtCore.Qt.Checked,
2174
 
+                self.ygridMinor.checkState() == QtCore.Qt.Checked)
2175
 
+        if grid != self.figure.grid:
2176
 
+            self.figure.grid = grid
2177
 
+        scale = self.scales[str(self.xscale.currentText())] + \
2178
 
+                            self.scales[str(self.yscale.currentText())]
2179
 
+        if scale != self.figure.scale:
2180
 
+            self.figure.scale = scale
2181
 
+
2182
 
+        marker = str(self.marker.currentText())
2183
 
+        if marker == "None":
2184
 
+            marker = ""
2185
 
+        if marker != self.figure.marker:
2186
 
+            self.figure.marker = marker
2187
 
+
2188
 
+        legend = self.showLegend.checkState() == QtCore.Qt.Checked
2189
 
+        if legend != self.figure.legend:
2190
 
+            self.figure.legend = legend
2191
 
+
2192
 
+        self.figure.colormap = self.colormapComboBox.currentText()
2193
 
+        self.figure.colorbar = self.colorbarCheckBox.checkState() == QtCore.Qt.Checked
2194
 
+
2195
 
+        title = str(self.titleEdit.text())
2196
 
+        if self.figure.title != title:
2197
 
+            self.figure.title = title
2198
 
+
2199
 
+        if self.figure.xAxisTitle != str(self.xAxisEdit.text()):
2200
 
+            self.figure.xAxisTitle = str(self.xAxisEdit.text())
2201
 
+
2202
 
+        if self.figure.yAxisTitle != str(self.yAxisEdit.text()):
2203
 
+            self.figure.yAxisTitle = str(self.yAxisEdit.text())
2204
 
+
2205
 
+class SelectItem(QtGui.QDialog):
2206
 
+
2207
 
+    class ComboBox(QtGui.QWidget):
2208
 
+
2209
 
+        def __init__(self, caption, items, *args):
2210
 
+            QtGui.QWidget.__init__(self, *args)
2211
 
+            self.mylayout = QtGui.QHBoxLayout(self)
2212
 
+            self.mylayout.setMargin(9)
2213
 
+            self.mylayout.setSpacing(6)
2214
 
+            self.mylayout.setObjectName("mylayout")
2215
 
+
2216
 
+            self.label = QtGui.QLabel(self)
2217
 
+            self.label.setText(caption)
2218
 
+            self.mylayout.addWidget(self.label)
2219
 
+
2220
 
+            self.comboBox = QtGui.QComboBox(self)
2221
 
+            self.comboBox.addItems(items)
2222
 
+            self.mylayout.addWidget(self.comboBox)
2223
 
+
2224
 
+        def selectedIndex(self):
2225
 
+            return self.comboBox.currentIndex()
2226
 
+
2227
 
+        def selectedText(self):
2228
 
+            return self.comboBox.currentText()
2229
 
+
2230
 
+    class RadioButtons(QtGui.QWidget):
2231
 
+
2232
 
+        def __init__(self, caption, items, *args):
2233
 
+            QtGui.QWidget.__init__(self, *args)
2234
 
+
2235
 
+            self.mylayout = QtGui.QVBoxLayout(self)
2236
 
+            self.mylayout.setMargin(9)
2237
 
+            self.mylayout.setSpacing(6)
2238
 
+            self.mylayout.setObjectName("mylayout")
2239
 
+
2240
 
+            self.groupbox = QtGui.QGroupBox(self)
2241
 
+            self.groupbox.setObjectName("groupbox")
2242
 
+            self.groupbox.setTitle(caption)
2243
 
+            self.mylayout.addWidget(self.groupbox)
2244
 
+
2245
 
+            self.groupboxlayout = QtGui.QVBoxLayout(self.groupbox)
2246
 
+            self.groupboxlayout.setMargin(9)
2247
 
+            self.groupboxlayout.setSpacing(6)
2248
 
+
2249
 
+            self.radiobuttons = []
2250
 
+            for index, item in enumerate(items):
2251
 
+                radiobutton = QtGui.QRadioButton(self.groupbox)
2252
 
+                radiobutton.setObjectName("radiobutton" + str(index))
2253
 
+                radiobutton.setText(item)
2254
 
+                self.groupboxlayout.addWidget(radiobutton)
2255
 
+                self.radiobuttons.append(radiobutton)
2256
 
+
2257
 
+            self.radiobuttons[0].setChecked(True)
2258
 
+
2259
 
+        def selectedIndex(self):
2260
 
+            for index in xrange(len(self.radiobuttons)):
2261
 
+                if self.radiobuttons[index].isChecked():
2262
 
+                    return index
2263
 
+            raise Exception("SelectItem.RadioButtons instance in invalid state")
2264
 
+
2265
 
+        def selectedText(self):
2266
 
+            return self.radiobuttons[self.selectedIndex()].text()
2267
 
+
2268
 
+    def __init__(self, title, caption, items, parent = None, selectWidget = ComboBox, *args):
2269
 
+        assert(len(items) > 0)
2270
 
+        self.items = items
2271
 
+        QtGui.QDialog.__init__(self, parent, *args)
2272
 
+        self.setObjectName("SelectItem")
2273
 
+        self.mylayout = QtGui.QVBoxLayout(self)
2274
 
+        self.mylayout.setMargin(9)
2275
 
+        self.mylayout.setSpacing(6)
2276
 
+        self.mylayout.setObjectName("mylayout")
2277
 
+
2278
 
+        self.setWindowTitle(title)
2279
 
+
2280
 
+        self.selectWidget = selectWidget(caption, items, self)
2281
 
+        self.selectWidget.setObjectName("selectWidget")
2282
 
+        self.mylayout.addWidget(self.selectWidget)
2283
 
+
2284
 
+        self.buttonBox = QtGui.QDialogButtonBox(self)
2285
 
+        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
2286
 
+        self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok)
2287
 
+        self.buttonBox.setObjectName("buttonBox")
2288
 
+        self.mylayout.addWidget(self.buttonBox)
2289
 
+
2290
 
+        self.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.accept)
2291
 
+        self.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
2292
 
+
2293
 
+    def selectedIndex(self):
2294
 
+        if len(self.items) == 1:
2295
 
+            return 0
2296
 
+        else:
2297
 
+            return self.selectWidget.selectedIndex()
2298
 
+
2299
 
+    def selectedText(self):
2300
 
+        if len(self.items) == 1:
2301
 
+            return self.items[0]
2302
 
+        else:
2303
 
+            return str(self.selectWidget.selectedText())
2304
 
+
2305
 
+    def exec_(self):
2306
 
+        if len(self.items) == 1:
2307
 
+            return QtGui.QDialog.Accepted
2308
 
+        else:
2309
 
+            return QtGui.QDialog.exec_(self)
2310
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/FigurePlotter.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/FigurePlotter.py
2311
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/FigurePlotter.py  1970-01-01 01:00:00.000000000 +0100
2312
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/FigurePlotter.py      2010-04-29 17:49:15.353968415 +0200
2313
 
@@ -0,0 +1,146 @@
2314
 
+import optparse
2315
 
+import sys
2316
 
+import os
2317
 
+import math
2318
 
+import openwns.wrowser.Configuration as simDbConf
2319
 
+import openwns.wrowser.simdb.Database as simDb
2320
 
+from openwns.wrowser.simdb.Campaigns import setCampaign as simDbSetCampaign
2321
 
+
2322
 
+from openwns.wrowser.probeselector import PostgresReader
2323
 
+from openwns.wrowser.probeselector import Interface
2324
 
+from openwns.wrowser.probeselector import Representations
2325
 
+from openwns.wrowser.probeselector import Errors
2326
 
+from openwns.wrowser.probeselector.Interface import Facade
2327
 
+
2328
 
+from matplotlib import rc
2329
 
+from matplotlib.figure import Figure
2330
 
+from matplotlib.backends.backend_pdf import FigureCanvasPdf as FigureCanvas
2331
 
+from matplotlib.font_manager import FontProperties
2332
 
+from pylab import *
2333
 
+
2334
 
+from scipy.special import erf
2335
 
+
2336
 
+def loadCampaignAndPlotGraphs(PlotParameters):
2337
 
+    def lineStyle():
2338
 
+
2339
 
+        for style in PlotParameters.color_styles :
2340
 
+            yield style
2341
 
+
2342
 
+    def lineStyleBW():
2343
 
+
2344
 
+        for style in PlotParameters.bw_styles :
2345
 
+            yield style
2346
 
+
2347
 
+    def markerBW():
2348
 
+
2349
 
+        for marker in PlotParameters.bw_markers :
2350
 
+            yield marker
2351
 
+
2352
 
+    def hatches():
2353
 
+
2354
 
+        for hatch in ['/','\\','|','-','+','x','.','//','\\' ]:
2355
 
+            yield hatch
2356
 
+
2357
 
+    ## Get the campaign
2358
 
+    dbConfig = simDbConf.Configuration()
2359
 
+    dbConfig.read()
2360
 
+    simDb.Database.connectConf(dbConfig)
2361
 
+    simDbSetCampaign([int(PlotParameters.campaignId)])
2362
 
+    campaignReader = PostgresReader.CampaignReader(int(PlotParameters.campaignId), Interface.DoNotSelectProbeSelectUI())
2363
 
+    print 'Accessing charts from database server with campaignId: ' + str(PlotParameters.campaignId)
2364
 
+
2365
 
+
2366
 
+    print "Reading Campaign"
2367
 
+    campaign = Representations.Campaign(*campaignReader.read())
2368
 
+    print "Creating Facade:",
2369
 
+    ch = Interface.Facade(campaign)
2370
 
+    print "done"
2371
 
+
2372
 
+    outputdir = 'figures'
2373
 
+    if not os.path.exists(outputdir) :
2374
 
+        os.makedirs(outputdir)
2375
 
+
2376
 
+    font = FontProperties()
2377
 
+    font.set_size('x-large')
2378
 
+
2379
 
+    filteredFacade = ch.filteredByExpression(PlotParameters.filterExpression)
2380
 
+    print "Found " + str(len(filteredFacade.getScenarios())) + " scenarios"
2381
 
+
2382
 
+    figure(figsize=(9, 8))
2383
 
+    xlabel(PlotParameters.xLabel,fontproperties = font)
2384
 
+    ylabel(PlotParameters.yLabel,fontproperties = font)
2385
 
+
2386
 
+    labels=[]
2387
 
+
2388
 
+    if PlotParameters.color:
2389
 
+        ls = lineStyle()
2390
 
+    else:
2391
 
+        markerBW = markerBW()
2392
 
+
2393
 
+    probeNr = 0
2394
 
+    try:
2395
 
+     if PlotParameters.type == 'Param':
2396
 
+        if PlotParameters.useXProbe:
2397
 
+            graphList = filteredFacade.getGraphs(PlotParameters.parameterName, PlotParameters.probeName, PlotParameters.probeEntry, PlotParameters.aggrParam, PlotParameters.confidence, PlotParameters.confidenceLevel, plotNotAggregatedGraphs=PlotParameters.originalPlots, useXProbe = PlotParameters.useXProbe, xProbeName = PlotParameters.xProbeName, xProbeEntry = PlotParameters.xProbeEntry)
2398
 
+        else:
2399
 
+            graphList = filteredFacade.getGraphs(PlotParameters.parameterName, PlotParameters.probeName, PlotParameters.probeEntry, PlotParameters.aggrParam, PlotParameters.confidence, PlotParameters.confidenceLevel, plotNotAggregatedGraphs=PlotParameters.originalPlots)
2400
 
+     else:
2401
 
+        graphList = filteredFacade.getHistograms( PlotParameters.probeName, PlotParameters.type, PlotParameters.aggrParam, plotNotAggregatedGraphs=PlotParameters.originalPlots) #, PlotParameters.aggrParam, PlotParameters.confidence)
2402
 
+    except Errors.MultipleErrors, e:
2403
 
+     graphList = e.graphs
2404
 
+
2405
 
+    i=0
2406
 
+    if len(graphList)==0:
2407
 
+        print "no graphs to plot"
2408
 
+    marker=PlotParameters.marker
2409
 
+    for graphNum in PlotParameters.plotOrder :
2410
 
+        graph = graphList[graphNum]
2411
 
+        labels.append(str(graph.sortkey))
2412
 
+
2413
 
+        try:
2414
 
+            if PlotParameters.color:
2415
 
+                style=ls.next()
2416
 
+            else:
2417
 
+                style='k'
2418
 
+                marker=markerBW.next()
2419
 
+        except StopIteration:
2420
 
+            print "You need to define more linestyles or reduce the number of plotted graphs"
2421
 
+            os._exit(1)
2422
 
+        X=[x  for x,y in graph.points]
2423
 
+        Y=[y*PlotParameters.scaleFactorY+PlotParameters.moveY  for x,y in graph.points]
2424
 
+        key = Facade.getGraphDescription(graph) #PlotParameters.legendLabelMapping.keys()[i]
2425
 
+        plot([x*PlotParameters.scaleFactorX+PlotParameters.moveX  for x in X ], Y , style , label=PlotParameters.legendLabelMapping[key],marker=marker)
2426
 
+        try:
2427
 
+          if PlotParameters.type == 'Param':
2428
 
+            if PlotParameters.confidence :
2429
 
+                for i in range(len(X)):
2430
 
+                    e = graph.confidenceIntervalDict[X[i]]
2431
 
+                    errorbar(X[i]*PlotParameters.scaleFactorX+PlotParameters.moveX, Y[i], yerr=e , fmt=style)
2432
 
+        except: None
2433
 
+        i+=1
2434
 
+    for additional in PlotParameters.additional_plots :
2435
 
+        plot(additional['x'], additional['y'] , additional['style'] , label=additional['label'])
2436
 
+
2437
 
+    if PlotParameters.doClip:
2438
 
+        axis([PlotParameters.minX,PlotParameters.maxX,PlotParameters.minY,PlotParameters.maxY])
2439
 
+    scalex = PlotParameters.scale[0]
2440
 
+    scaley = PlotParameters.scale[2]
2441
 
+    if scalex != 'linear' :
2442
 
+        xbase = PlotParameters.scale[1]
2443
 
+        xscale('log',basex=xbase)
2444
 
+    if scaley != 'linear' :
2445
 
+        ybase= PlotParameters.scale[3]
2446
 
+        yscale('log',basey=ybase)
2447
 
+    a = gca()
2448
 
+    a.get_xaxis().grid(PlotParameters.grid[0], which="major")
2449
 
+    a.get_xaxis().grid(PlotParameters.grid[1], which="minor")
2450
 
+    a.get_yaxis().grid(PlotParameters.grid[2], which="major")
2451
 
+    a.get_yaxis().grid(PlotParameters.grid[3], which="minor")
2452
 
+
2453
 
+    if PlotParameters.showTitle :
2454
 
+        title(PlotParameters.figureTitle)
2455
 
+    if PlotParameters.legend:
2456
 
+        legend(prop = font, loc=PlotParameters.legendPosition) # (0.9, 0.01))
2457
 
+    print 'Plotting: ',PlotParameters.fileName
2458
 
+    for format in PlotParameters.outputFormats :
2459
 
+        savefig(os.path.join(outputdir, PlotParameters.fileName+'.'+format))
2460
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/__init__.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/__init__.py
2461
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/__init__.py       1970-01-01 01:00:00.000000000 +0100
2462
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/__init__.py   2010-04-29 17:49:15.353968415 +0200
2463
 
@@ -0,0 +1,27 @@
2464
 
+###############################################################################
2465
 
+# This file is part of openWNS (open Wireless Network Simulator)
2466
 
+# _____________________________________________________________________________
2467
 
+#
2468
 
+# Copyright (C) 2004-2007
2469
 
+# Chair of Communication Networks (ComNets)
2470
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
2471
 
+# phone: ++49-241-80-27910,
2472
 
+# fax: ++49-241-80-22242
2473
 
+# email: info@openwns.org
2474
 
+# www: http://www.openwns.org
2475
 
+# _____________________________________________________________________________
2476
 
+#
2477
 
+# openWNS is free software; you can redistribute it and/or modify it under the
2478
 
+# terms of the GNU Lesser General Public License version 2 as published by the
2479
 
+# Free Software Foundation;
2480
 
+#
2481
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
2482
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2483
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
2484
 
+# details.
2485
 
+#
2486
 
+# You should have received a copy of the GNU Lesser General Public License
2487
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
2488
 
+#
2489
 
+###############################################################################
2490
 
+
2491
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Models.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Models.py
2492
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/Models.py 1970-01-01 01:00:00.000000000 +0100
2493
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/Models.py     2010-04-29 17:49:15.353968415 +0200
2494
 
@@ -0,0 +1,485 @@
2495
 
+###############################################################################
2496
 
+# This file is part of openWNS (open Wireless Network Simulator)
2497
 
+# _____________________________________________________________________________
2498
 
+#
2499
 
+# Copyright (C) 2004-2007
2500
 
+# Chair of Communication Networks (ComNets)
2501
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
2502
 
+# phone: ++49-241-80-27910,
2503
 
+# fax: ++49-241-80-22242
2504
 
+# email: info@openwns.org
2505
 
+# www: http://www.openwns.org
2506
 
+# _____________________________________________________________________________
2507
 
+#
2508
 
+# openWNS is free software; you can redistribute it and/or modify it under the
2509
 
+# terms of the GNU Lesser General Public License version 2 as published by the
2510
 
+# Free Software Foundation;
2511
 
+#
2512
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
2513
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2514
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
2515
 
+# details.
2516
 
+#
2517
 
+# You should have received a copy of the GNU Lesser General Public License
2518
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
2519
 
+#
2520
 
+###############################################################################
2521
 
+
2522
 
+import copy
2523
 
+import openwns.wrowser.Tools
2524
 
+
2525
 
+
2526
 
+from PyQt4 import QtCore, QtGui
2527
 
+
2528
 
+import Debug
2529
 
+
2530
 
+class CampaignDb(QtCore.QAbstractItemModel):
2531
 
+
2532
 
+    headerNames = ["User", "Campaign Title", "Campaign Description", "Campaign Size"]
2533
 
+
2534
 
+    def __init__(self, campaignIds, parent = None):
2535
 
+        QtCore.QAbstractItemModel.__init__(self, parent)
2536
 
+        self.campaignIds = campaignIds
2537
 
+        for username, campaigns in self.campaignIds.items():
2538
 
+            if None in campaigns.keys():
2539
 
+                del self.campaignIds[username]
2540
 
+        self.sortedCampaignIdsKeys = sorted(campaignIds.keys())
2541
 
+
2542
 
+    def getCampaign(self, index):
2543
 
+        userName = self.sortedCampaignIdsKeys[index.internalId()]
2544
 
+        return map(lambda x: x[0], sorted(self.campaignIds[userName].items(), key = lambda x: x[1][0].lower()))[index.row()]
2545
 
+
2546
 
+    def columnCount(self, parent = QtCore.QModelIndex()):
2547
 
+        return len(self.headerNames)
2548
 
+
2549
 
+    def rowCount(self, parent = QtCore.QModelIndex()):
2550
 
+        if parent.isValid() and parent.internalId() == 1000000001:
2551
 
+            userName = self.sortedCampaignIdsKeys[parent.row()]
2552
 
+            return len(self.campaignIds[userName])
2553
 
+        elif not parent.isValid():
2554
 
+            return len(self.sortedCampaignIdsKeys)
2555
 
+        else:
2556
 
+            return 0
2557
 
+
2558
 
+    def parent(self, index = QtCore.QModelIndex()):
2559
 
+        if not index.isValid():
2560
 
+            return QtCore.QModelIndex()
2561
 
+        elif index.internalId() == 1000000001:
2562
 
+            return QtCore.QModelIndex()
2563
 
+        elif index.internalId() < 1000000000:
2564
 
+            return self.index(index.internalId(), 0, QtCore.QModelIndex())
2565
 
+        print index.internalId()
2566
 
+        return QtCore.QModelIndex()
2567
 
+
2568
 
+    def index(self, row, column, parent = QtCore.QModelIndex()):
2569
 
+        if not parent.isValid():
2570
 
+            return self.createIndex(row, column, 1000000001)
2571
 
+        elif parent.internalId() == 1000000001:
2572
 
+            return self.createIndex(row, column, parent.row())
2573
 
+        else:
2574
 
+            return self.createIndex(row, column, 1000000000)
2575
 
+
2576
 
+    def flags(self, index):
2577
 
+        if not index.isValid():
2578
 
+            return QtCore.Qt.ItemIsEnabled
2579
 
+        if index.internalId() < 1000000000:
2580
 
+            userName = self.sortedCampaignIdsKeys[index.internalId()]
2581
 
+            if sorted(self.campaignIds[userName].values(), key = lambda x: x[0].lower())[index.row()][3]:
2582
 
+                return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
2583
 
+            else:
2584
 
+                return QtCore.Qt.ItemFlags()
2585
 
+        return QtCore.Qt.ItemIsEnabled
2586
 
+
2587
 
+    def headerData(self, section, orientation, role):
2588
 
+        if role != QtCore.Qt.DisplayRole or orientation != QtCore.Qt.Horizontal:
2589
 
+            return QtCore.QVariant()
2590
 
+        return QtCore.QVariant(self.headerNames[section])
2591
 
+
2592
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2593
 
+        if not index.isValid() or index.internalId() == 1000000000:
2594
 
+            return QtCore.QVariant()
2595
 
+
2596
 
+        if role == QtCore.Qt.DisplayRole:
2597
 
+            if index.internalId() == 1000000001 and index.column() == 0:
2598
 
+                return QtCore.QVariant(self.sortedCampaignIdsKeys[index.row()])
2599
 
+            elif index.internalId() < 1000000000 and index.column() == 1:
2600
 
+                userName = self.sortedCampaignIdsKeys[index.internalId()]
2601
 
+                return QtCore.QVariant(sorted(self.campaignIds[userName].values(), key = lambda x: x[0].lower())[index.row()][0])
2602
 
+            elif index.internalId() < 1000000000 and index.column() == 2:
2603
 
+                userName = self.sortedCampaignIdsKeys[index.internalId()]
2604
 
+                return QtCore.QVariant(sorted(self.campaignIds[userName].values(), key = lambda x: x[0].lower())[index.row()][1])
2605
 
+            elif index.internalId() < 1000000000 and index.column() == 3:
2606
 
+                userName = self.sortedCampaignIdsKeys[index.internalId()]
2607
 
+                return QtCore.QVariant(sorted(self.campaignIds[userName].values(), key = lambda x: x[0].lower())[index.row()][2])
2608
 
+
2609
 
+        return QtCore.QVariant()
2610
 
+
2611
 
+    def getUserRow(self, user):
2612
 
+        for i in range(self.rowCount()):
2613
 
+            desc = str(self.data(self.index(i,0)).toString()) 
2614
 
+            if desc.find(user) != -1 :
2615
 
+                return self.index(i,0)
2616
 
+        return -1
2617
 
2618
 
+class SimulationParameters(QtCore.QAbstractItemModel):
2619
 
+
2620
 
+    headerNames = ["Parameter", "Values"]
2621
 
+
2622
 
+    def __init__(self, campaign, onlyNumeric = False, parent = None):
2623
 
+        QtCore.QAbstractItemModel.__init__(self, parent)
2624
 
+        self.onlyNumeric = onlyNumeric
2625
 
+        self.setCampaign(campaign, onlyNumeric)
2626
 
+        self.parameterValueCheckStates = {}
2627
 
+        for parameterName in self.parameterNames:
2628
 
+            self.parameterValueCheckStates[parameterName] = {}
2629
 
+            for value in self.parameterValues[parameterName]:
2630
 
+                self.parameterValueCheckStates[parameterName][value] = True
2631
 
+
2632
 
+    def setCampaign(self, campaign, onlyNumeric = False):
2633
 
+        Debug.printCall(self, (campaign, onlyNumeric))
2634
 
+        self.emit(QtCore.SIGNAL("layoutAboutToBeChanged()"))
2635
 
+        self.campaign = campaign
2636
 
+        if onlyNumeric:
2637
 
+            self.parameterNames = sorted([name for name in campaign.getParameterNames() if self.campaign.isNumericParameter(name)])
2638
 
+        else:
2639
 
+            self.parameterNames = sorted(list(campaign.getParameterNames()))
2640
 
+        self.parameterValues = {}
2641
 
+        for parameterName in self.parameterNames:
2642
 
+            self.parameterValues[parameterName] = sorted(list(campaign.getValuesOfParameter(parameterName)))
2643
 
+        self.emit(QtCore.SIGNAL("layoutChanged()"))
2644
 
+
2645
 
+    def __getValueSelection(self, checkStates):
2646
 
+        selection = {}
2647
 
+        for parameterName in self.parameterNames:
2648
 
+            selection[parameterName] = [value for value in self.parameterValues[parameterName] if checkStates[parameterName][value]]
2649
 
+        return selection
2650
 
+
2651
 
+    def getValueSelection(self):
2652
 
+        return self.__getValueSelection(self.parameterValueCheckStates)
2653
 
+
2654
 
+    def getParameterValues(self):
2655
 
+        return self.parameterValues
2656
 
+
2657
 
+    def getCheckStates(self):
2658
 
+        return self.parameterValueCheckStates
2659
 
+
2660
 
+    def columnCount(self, parent = QtCore.QModelIndex()):
2661
 
+        return len(self.headerNames)
2662
 
+
2663
 
+    def rowCount(self, parent = QtCore.QModelIndex()):
2664
 
+        if parent.isValid() and parent.internalId() == 1000000001:
2665
 
+            parameterName = self.parameterNames[parent.row()]
2666
 
+            return len(self.parameterValues[parameterName])
2667
 
+        elif not parent.isValid():
2668
 
+            return len(self.parameterNames)
2669
 
+        else:
2670
 
+            return 0
2671
 
+
2672
 
+    def parent(self, index = QtCore.QModelIndex()):
2673
 
+        if not index.isValid():
2674
 
+            return QtCore.QModelIndex()
2675
 
+        elif index.internalId() == 1000000001:
2676
 
+            return QtCore.QModelIndex()
2677
 
+        elif index.internalId() < 1000000000:
2678
 
+            return self.index(index.internalId(), 0, QtCore.QModelIndex())
2679
 
+        return QtCore.QModelIndex()
2680
 
+
2681
 
+    def index(self, row, column, parent = QtCore.QModelIndex()):
2682
 
+        if not parent.isValid():
2683
 
+            return self.createIndex(row, column, 1000000001)
2684
 
+        elif parent.internalId() == 1000000001:
2685
 
+            return self.createIndex(row, column, parent.row())
2686
 
+        else:
2687
 
+            return self.createIndex(row, column, 1000000000)
2688
 
+
2689
 
+    def flags(self, index):
2690
 
+        if not index.isValid():
2691
 
+            return QtCore.Qt.ItemIsEnabled
2692
 
+        if index.internalId() < 1000000000:
2693
 
+            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable
2694
 
+        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
2695
 
+
2696
 
+    def headerData(self, section, orientation, role):
2697
 
+        if role != QtCore.Qt.DisplayRole or orientation != QtCore.Qt.Horizontal:
2698
 
+            return QtCore.QVariant()
2699
 
+        return QtCore.QVariant(self.headerNames[section])
2700
 
+
2701
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2702
 
+        if not index.isValid() or index.internalId() == 1000000000:
2703
 
+            return QtCore.QVariant()
2704
 
+
2705
 
+        if role == QtCore.Qt.DisplayRole:
2706
 
+            if index.internalId() == 1000000001 and index.column() == 0:
2707
 
+                return QtCore.QVariant(self.parameterNames[index.row()])
2708
 
+            elif index.internalId() < 1000000000 and index.column() == 1:
2709
 
+                parameterName = self.parameterNames[index.internalId()]
2710
 
+                values = self.parameterValues[parameterName]
2711
 
+                return QtCore.QVariant(values[index.row()])
2712
 
+        elif role == QtCore.Qt.CheckStateRole and index.internalId() < 1000000000 and index.column() == 1:
2713
 
+            parameterName = self.parameterNames[index.internalId()]
2714
 
+            value = self.parameterValues[parameterName][index.row()]
2715
 
+            if self.parameterValueCheckStates[parameterName][value]:
2716
 
+                return QtCore.QVariant(QtCore.Qt.Checked)
2717
 
+            else:
2718
 
+                return QtCore.QVariant(QtCore.Qt.Unchecked)
2719
 
+
2720
 
+        return QtCore.QVariant()
2721
 
+
2722
 
+    def setData(self, index, value, role):
2723
 
+        if not index.isValid():
2724
 
+            return False
2725
 
+
2726
 
+        if role == QtCore.Qt.CheckStateRole and index.internalId() < 1000000000 and index.column() == 1:
2727
 
+            state = value.toInt()[0]
2728
 
+            parameterName = self.parameterNames[index.internalId()]
2729
 
+            parameterValue = self.parameterValues[parameterName][index.row()]
2730
 
+            if state == QtCore.Qt.Unchecked:
2731
 
+                checkStates = copy.deepcopy(self.parameterValueCheckStates)
2732
 
+                checkStates[parameterName][parameterValue] = False
2733
 
+                if self.campaign.filteredBySelection(self.__getValueSelection(checkStates)).isEmpty():
2734
 
+                    return False
2735
 
+                self.parameterValueCheckStates = checkStates
2736
 
+            elif state == QtCore.Qt.Checked:
2737
 
+                checkStates = copy.deepcopy(self.parameterValueCheckStates)
2738
 
+                checkStates[parameterName][parameterValue] = True
2739
 
+                if self.campaign.filteredBySelection(self.__getValueSelection(checkStates)).isEmpty():
2740
 
+                    return False
2741
 
+                self.parameterValueCheckStates = checkStates
2742
 
+            else:
2743
 
+                return False
2744
 
+            self.emit(QtCore.SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), index, index)
2745
 
+            return True
2746
 
+        return False
2747
 
+
2748
 
+    def toggleCheckboxes(self,row=10):
2749
 
+        toggleParam=self.parameterNames[row]
2750
 
+        for value in self.parameterValues[toggleParam] :
2751
 
+            newValue = not self.parameterValueCheckStates[toggleParam][value] 
2752
 
+            self.parameterValueCheckStates[toggleParam][value] = newValue
2753
 
+        if self.campaign.filteredBySelection(self.__getValueSelection(self.parameterValueCheckStates)).isEmpty():
2754
 
+            for value in self.parameterValues[toggleParam] :
2755
 
+                if self.parameterValueCheckStates[toggleParam][value]==False :
2756
 
+                    self.parameterValueCheckStates[toggleParam][value]=True 
2757
 
+                    if not self.campaign.filteredBySelection(self.__getValueSelection(self.parameterValueCheckStates)).isEmpty():
2758
 
+                        break
2759
 
+                    self.parameterValueCheckStates[toggleParam][value]=False
2760
 
+
2761
 
+
2762
 
+class ProbeNames(QtCore.QAbstractListModel):
2763
 
+    def __init__(self, campaign, probeClasses = [None], parent = None):
2764
 
+        QtCore.QAbstractListModel.__init__(self, parent)
2765
 
+        self.campaign = campaign
2766
 
+        self.probeClasses = probeClasses
2767
 
+        self.filterText = ""
2768
 
+        self.__setupProbeNames()
2769
 
+
2770
 
+    def __setupProbeNames(self):
2771
 
+        self.probeNamesUnion = sorted(list(reduce(set.union, [set(self.campaign.getProbeNames(probeClass).union) for probeClass in self.probeClasses])))
2772
 
+        self.probeNamesUnionFiltered = self.getFilteredProbeNames()
2773
 
+        self.probeNamesIntersection = reduce(set.intersection, [set(self.campaign.getProbeNames(probeClass).intersection) for probeClass in self.probeClasses])
2774
 
+
2775
 
+    def rowCount(self, parent = QtCore.QModelIndex()):
2776
 
+        if parent.isValid():
2777
 
+            return 0
2778
 
+        else:
2779
 
+            return len(self.probeNamesUnionFiltered)
2780
 
+
2781
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2782
 
+        if not index.isValid():
2783
 
+            return QtCore.QVariant()
2784
 
+
2785
 
+        if role == QtCore.Qt.DisplayRole:
2786
 
+            return QtCore.QVariant(self.getProbeName(index))
2787
 
+        elif role == QtCore.Qt.TextColorRole:
2788
 
+            if self.getProbeName(index) in self.probeNamesIntersection:
2789
 
+                return QtCore.QVariant(QtGui.QColor("black"))
2790
 
+            else:
2791
 
+                return QtCore.QVariant(QtGui.QColor("grey"))
2792
 
+
2793
 
+        return QtCore.QVariant()
2794
 
+
2795
 
+    def getFilteredProbeNames(self):
2796
 
+        return self.getProbeNamesFilteredBy(self.filterText)
2797
 
+
2798
 
+    def getProbeNamesFilteredBy(self, filterText):
2799
 
+        return [probeName for probeName in self.probeNamesUnion if filterText.lower() in probeName.lower()]
2800
 
+
2801
 
+    def getProbeName(self, index):
2802
 
+        return self.probeNamesUnionFiltered[index.row()]
2803
 
+
2804
 
+    def setFilter(self, filterText):
2805
 
+        self.emit(QtCore.SIGNAL("modelAboutToBeReset()"))
2806
 
+        self.filterText = filterText
2807
 
+        self.probeNamesUnionFiltered = self.getFilteredProbeNames()
2808
 
+        self.emit(QtCore.SIGNAL("modelReset()"))
2809
 
+
2810
 
+    def setCampaign(self, campaign):
2811
 
+        self.emit(QtCore.SIGNAL("modelAboutToBeReset()"))
2812
 
+        self.campaign = campaign
2813
 
+        self.__setupProbeNames()
2814
 
+        self.emit(QtCore.SIGNAL("modelReset()"))
2815
 
+
2816
 
+    def getProbeIndexes(self, probeList):
2817
 
+        indexes = []
2818
 
+        for probe in probeList :
2819
 
+            if probe in self.probeNamesUnionFiltered: 
2820
 
+                indexes.append(self.createIndex(self.probeNamesUnionFiltered.index(probe),0))
2821
 
+        return indexes            
2822
 
+
2823
 
+class ProbeEntries(QtCore.QAbstractListModel):
2824
 
+    def __init__(self, campaign, parent = None):
2825
 
+        QtCore.QAbstractListModel.__init__(self, parent)
2826
 
+        self.campaign = campaign
2827
 
+        self.probeEntries = []
2828
 
+
2829
 
+    def rowCount(self, parent = QtCore.QModelIndex()):
2830
 
+        if parent.isValid():
2831
 
+            return 0
2832
 
+        else:
2833
 
+            return len(self.probeEntries)
2834
 
+
2835
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2836
 
+        if not index.isValid() or index.row() >= self.rowCount():
2837
 
+            return QtCore.QVariant()
2838
 
+        if role == QtCore.Qt.DisplayRole:
2839
 
+            return QtCore.QVariant(self.getProbeEntry(index))
2840
 
+        return QtCore.QVariant()
2841
 
+
2842
 
+    def getProbeEntry(self, index):
2843
 
+        return self.probeEntries[index.row()]
2844
 
+
2845
 
+    def findProbeEntry(self, text):
2846
 
+        for index, entry in enumerate(self.probeEntries):
2847
 
+            if entry == text:
2848
 
+                return index
2849
 
+        return 1000000001
2850
 
+
2851
 
+    def changeProbes(self, probeNames):
2852
 
+        self.probeNames = probeNames
2853
 
+        self.emit(QtCore.SIGNAL("modelAboutToBeReset()"))
2854
 
+        if len(probeNames):
2855
 
+            probeEntries = set(self.__getProbeClassEntries(probeNames[0]))
2856
 
+            for probeName in probeNames[1:]:
2857
 
+                probeEntries &= set(self.__getProbeClassEntries(probeName))
2858
 
+        else:
2859
 
+            probeEntries = set([])
2860
 
+        self.probeEntries = sorted(list(probeEntries))
2861
 
+        self.emit(QtCore.SIGNAL("modelReset()"))
2862
 
+
2863
 
+    def setCampaign(self, campaign):
2864
 
+        self.campaign = campaign
2865
 
+        self.changeProbes(self.probeNames)
2866
 
+
2867
 
+    def __getProbeClassEntries(self, probeName):
2868
 
+        probeClass = self.campaign.getProbeClass(probeName)
2869
 
+        if probeClass == None:
2870
 
+            return []
2871
 
+        probeEntries = probeClass.valueNames
2872
 
+        probeEntries.sort()
2873
 
+        return probeEntries
2874
 
+
2875
 
+class ProbeData(QtCore.QAbstractTableModel):
2876
 
+
2877
 
+    def __init__(self, campaign, probeName, parent = None):
2878
 
+        QtCore.QAbstractListModel.__init__(self, parent)
2879
 
+        self.campaign = campaign
2880
 
+        self.probeName = probeName
2881
 
+        self.probeData = campaign.getAllProbeDataExtended(probeName)
2882
 
+        self.parameterNames = list(campaign.getParameterNames())
2883
 
+        #self.valueNames = set()
2884
 
+        self.probeInfoNames = set()
2885
 
+        for data in self.probeData:
2886
 
+            self.probeInfoNames |= set(data[1].keys())
2887
 
+        self.headerNames = self.parameterNames + list(self.probeInfoNames)
2888
 
+
2889
 
+    def rowCount(self, parent = QtCore.QModelIndex()):
2890
 
+        if parent.isValid():
2891
 
+            return 0
2892
 
+        else:
2893
 
+            return len(self.probeData)
2894
 
+
2895
 
+    def columnCount(self, parent = QtCore.QModelIndex()):
2896
 
+        if parent.isValid():
2897
 
+            return 0
2898
 
+        else:
2899
 
+            return len(self.headerNames)
2900
 
+
2901
 
+    def headerData(self, section, orientation, role):
2902
 
+        if role != QtCore.Qt.DisplayRole or orientation != QtCore.Qt.Horizontal:
2903
 
+            return QtCore.QVariant()
2904
 
+        return QtCore.QVariant(self.headerNames[section])
2905
 
+
2906
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2907
 
+        if not index.isValid() or index.row() >= self.rowCount():
2908
 
+            return QtCore.QVariant()
2909
 
+        if role == QtCore.Qt.DisplayRole:
2910
 
+            key = self.headerNames[index.column()]
2911
 
+            if key in self.parameterNames:
2912
 
+                return QtCore.QVariant(self.probeData[index.row()][0][key])
2913
 
+            elif key in self.probeInfoNames:
2914
 
+                if self.probeData[index.row()][1].has_key(key):
2915
 
+                    return QtCore.QVariant(self.probeData[index.row()][1][key])
2916
 
+        if role == QtCore.Qt.ForegroundRole:
2917
 
+            key = self.headerNames[index.column()]
2918
 
+            if key in self.probeInfoNames:
2919
 
+                return QtCore.QVariant(QtGui.QColor("blue"))
2920
 
+        return QtCore.QVariant()
2921
 
+
2922
 
+    def getPath(self, index):
2923
 
+        print "get path to scenario"
2924
 
+        try:
2925
 
+            path = self.probeData[index.row()][1]['filename'] 
2926
 
+            if path.find('scratch') != -1 :
2927
 
+                #print "the scenario was queued with an old simcontrol.py, hence the database does not contain the path to your scenario folder"
2928
 
+                return None 
2929
 
+            return path
2930
 
+        except:
2931
 
+            #print "the scenario has no entry for the probe file, it seems that the scenario is crashed or not finished"
2932
 
+            return None
2933
 
+
2934
 
+    def printTable(self):
2935
 
+        for row in range(self.rowCount()):
2936
 
+            for col in range(self.columnCount()):
2937
 
+                desc = str(self.data(self.index(row,col)).toString()) 
2938
 
+                print "col:",col
2939
 
+                print "desc:",desc
2940
 
+
2941
 
+class Legend(QtCore.QAbstractListModel):
2942
 
+
2943
 
+    def __init__(self, lineWidth = 70, lines = [], labels = [], *args):
2944
 
+        QtCore.QAbstractListModel.__init__(self, *args)
2945
 
+        self.lineWidth = lineWidth
2946
 
+        self.updateLinesNLabels(lines, labels)
2947
 
+
2948
 
+    def updateLinesNLabels(self, lines, labels):
2949
 
+        from Tools import renderLineSampleImage
2950
 
+        if len(labels)>0 :
2951
 
+            labels = openwns.wrowser.Tools.uniqElements(labels)
2952
 
+        
2953
 
+        if len(lines) != len(labels):
2954
 
+            raise Exception("Models.Legend: " + str(len(lines)) + " graphs, but " + str(len(labels)) + " labels!?")
2955
 
+
2956
 
+        self.emit(QtCore.SIGNAL("modelAboutToBeReset()"))
2957
 
+        self.linesLabels = []
2958
 
+        for line, label in zip(lines, labels):
2959
 
+            image = renderLineSampleImage(line[0], self.lineWidth)
2960
 
+            self.linesLabels.append((image, label))
2961
 
+        self.emit(QtCore.SIGNAL("modelReset()"))
2962
 
+
2963
 
+    def rowCount(self, parent):
2964
 
+        if parent.isValid():
2965
 
+            return 0
2966
 
+        return len(self.linesLabels)
2967
 
+
2968
 
+    def headerData(self, section, orientation, role = QtCore.Qt.DisplayRole):
2969
 
+        return QtCore.QVariant()
2970
 
+
2971
 
+    def data(self, index, role = QtCore.Qt.DisplayRole):
2972
 
+        if not index.isValid() or index.column() != 0:
2973
 
+            return QtCore.QVariant()
2974
 
+        line, label = self.linesLabels[index.row()]
2975
 
+        if role == QtCore.Qt.DisplayRole:
2976
 
+            return QtCore.QVariant(label)
2977
 
+        elif role == QtCore.Qt.DecorationRole:
2978
 
+            return QtCore.QVariant(line)
2979
 
+        return QtCore.QVariant()
2980
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfigurationDatabase.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfigurationDatabase.py
2981
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfigurationDatabase.py     1970-01-01 01:00:00.000000000 +0100
2982
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfigurationDatabase.py 2010-04-29 17:49:15.353968415 +0200
2983
 
@@ -0,0 +1,139 @@
2984
 
+#! /usr/bin/python
2985
 
+###############################################################################
2986
 
+# This file is part of openWNS (open Wireless Network Simulator)
2987
 
+# _____________________________________________________________________________
2988
 
+#
2989
 
+# Copyright (C) 2004-2007
2990
 
+# Chair of Communication Networks (ComNets)
2991
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
2992
 
+# phone: ++49-241-80-27910,
2993
 
+# fax: ++49-241-80-22242
2994
 
+# email: info@openwns.org
2995
 
+# www: http://www.openwns.org
2996
 
+# _____________________________________________________________________________
2997
 
+#
2998
 
+# openWNS is free software; you can redistribute it and/or modify it under the
2999
 
+# terms of the GNU Lesser General Public License version 2 as published by the
3000
 
+# Free Software Foundation;
3001
 
+#
3002
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
3003
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
3004
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
3005
 
+# details.
3006
 
+#
3007
 
+# You should have received a copy of the GNU Lesser General Public License
3008
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3009
 
+#
3010
 
+###############################################################################
3011
 
+
3012
 
+from openwns.wrowser.simdb.Parameters import AutoSimulationParameters, Parameters, Bool, Int, Float, String
3013
 
+
3014
 
+#####################################
3015
 
+# Advanced parameter generation HowTo
3016
 
+
3017
 
+#
3018
 
+# Ok, now it gets tricky. First some example from practice:
3019
 
+# Assume you have a given scenario, and you want to evaluate the saturation throughput, depending on
3020
 
+# the number of mobile nodes and the number of subchannels. What would you do with the simple approach?
3021
 
+#
3022
 
+
3023
 
+class Set(Parameters):
3024
 
+    numMobileNodes = Int()
3025
 
+    numSubchannels = Int()
3026
 
+    offeredTraffic = Float()
3027
 
+
3028
 
+params = Set()
3029
 
+
3030
 
+for params.numMobileNodes in [50, 100, 150]:
3031
 
+    for params.numSubchannels in [3, 4, 5]:
3032
 
+        for ot in xrange(1,11):
3033
 
+            params.offeredTraffic = ot*1e6
3034
 
+            params.write()
3035
 
+
3036
 
+#
3037
 
+# This creates 3*3*10 = 90 simulations, thus 10 samples for each setting of parameters. And now you hope that
3038
 
+# you have found, for each parameter, some samples below and some above the saturation point. How realistic is that?
3039
 
+# Not very much. So you run all simulations, wait for the output, look at the offered vs. throughput, generate new
3040
 
+# simulations etc... it can be much simpler!
3041
 
+#
3042
 
+# First some definitions:
3043
 
+#  parameter: Something that descibes the type of the scenario, e.g.. numMobileNodes, numSubchannels
3044
 
+#  input: You feed this to your scenario, e.g. offeredTraffic
3045
 
+#  output: Your get this out of your scenario, e.g. throughput
3046
 
+#
3047
 
+# Thus, scenario is a (black-box) function f_{parameter}(input) = output and you search for
3048
 
+#      max_x f_{parameter}(x) = x
3049
 
+# i.e. the highest input so that the output==input. Aka fixed point.
3050
 
+#
3051
 
+# You can do that in the following way:
3052
 
+#
3053
 
+# First, define parameters (with range!) and input (with start value!)
3054
 
+class Set(AutoSimulationParameters):
3055
 
+    # parameters with range
3056
 
+    numMobileNodes = Int(parameterRange = [50, 100, 150])
3057
 
+    numSubchannels = Int(parameterRange = [3, 4, 5])
3058
 
+
3059
 
+    # input with start value
3060
 
+    offeredTraffic = Float(default = 1e6)
3061
 
+
3062
 
+#
3063
 
+# Then, there needs to be a method which searches through the database and returns a list with entries [scenario_id, value input, value output], given
3064
 
+# a sql-string describing the current parameters, the name of the input variable and a cursor to the db (easy to get, see below)
3065
 
+#
3066
 
+def getTotalThroughput(paramsString, inputName, cursor):
3067
 
+
3068
 
+    # query the aggregated ip-throughput of node 1
3069
 
+    myQuery = " \
3070
 
+    SELECT parameter.scenario_id, parameter." + inputName + ", values.mean \
3071
 
+    FROM pd_fs values, (SELECT scenario_id, " + inputName + " FROM parameter_sets WHERE " + paramsString + ") AS parameter \
3072
 
+    WHERE values.scenario_id = parameter.scenario_id AND \
3073
 
+          value.alt_name = 'ip.endToEnd.window.aggregated.bitThroughput_wns.node.Node.id1_SC1' \
3074
 
+    ORDER BY parameter." + inputName + ";"
3075
 
+    cursor.execute(myQuery)
3076
 
+    qResults = cursor.fetchall()
3077
 
+
3078
 
+    return qResults
3079
 
+
3080
 
+#
3081
 
+# Then, some pre-work to get the cursor
3082
 
+#
3083
 
+import openwns.wrowser.Configuration as config
3084
 
+conf = config.Configuration()
3085
 
+conf.read("./.campaign.conf")
3086
 
+db.Database.connectConf(conf)
3087
 
+cursor = db.Database.getCursor()
3088
 
+
3089
 
+#
3090
 
+# Let the fun start!
3091
 
+# For the initialization, params needs to have the name of the input variable (same as above), the cursor, the campaign id (easy) and a function pointer
3092
 
+# how to get the results
3093
 
+params = Set('offeredTraffic', cursor, conf.parser.getint("Campaign", "id"), getTotalThroughput)
3094
 
+
3095
 
+#
3096
 
+# Start a binary search to find the maximum fixed point of the input variable
3097
 
+# maxError is the maximum deviation of input and output to be still "similar" enough, i.e. if (output/input > 1-maxError) then output == input.
3098
 
+#      Required because simulation results fluctuate if not run for an infinite time.
3099
 
+# exactness is the allowed deviation of the fixed point in percent
3100
 
+#      Required because it needs too many samples to find the exact max_x: f(x)=x
3101
 
+# createSimulations = False is a dry run, without writing into the db
3102
 
+# debug is for helpful debug output
3103
 
+
3104
 
+[status, results] = params.binarySearch(maxError = 0.1, exactness = 0.05, createSimulations=True, debug=True)
3105
 
+print "%d new / %d waiting / %d finished simulations" %(status['new'], status['waiting'], status['finished'])
3106
 
+
3107
 
+#
3108
 
+# if new simulations have been generated -> create scenarios & queue them!
3109
 
+if(status['new'] > 0):
3110
 
+    subprocess.call(['./simcontrol.py --create-scenarios'], shell = True)
3111
 
+    subprocess.call(['./simcontrol.py --queue-scenarios-with-state=NotQueued'], shell = True)
3112
 
+#
3113
 
+# save results
3114
 
+if(status['finished'] > 0):
3115
 
+    outFile = open("currentResults.pkl", "wb")
3116
 
+    pickle.dump(results, outFile)
3117
 
+    outFile.close()
3118
 
+
3119
 
+# That's it
3120
 
+# Saves you approx. 70-90% of simulations (time, disk space) in comparison to the simple method
3121
 
+###############################################################################################
3122
 
+
3123
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfiguration.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfiguration.py
3124
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfiguration.py     1970-01-01 01:00:00.000000000 +0100
3125
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/campaignConfiguration.py 2010-04-29 17:49:15.353968415 +0200
3126
 
@@ -0,0 +1,65 @@
3127
 
+#! /usr/bin/python
3128
 
+###############################################################################
3129
 
+# This file is part of openWNS (open Wireless Network Simulator)
3130
 
+# _____________________________________________________________________________
3131
 
+#
3132
 
+# Copyright (C) 2004-2007
3133
 
+# Chair of Communication Networks (ComNets)
3134
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
3135
 
+# phone: ++49-241-80-27910,
3136
 
+# fax: ++49-241-80-22242
3137
 
+# email: info@openwns.org
3138
 
+# www: http://www.openwns.org
3139
 
+# _____________________________________________________________________________
3140
 
+#
3141
 
+# openWNS is free software; you can redistribute it and/or modify it under the
3142
 
+# terms of the GNU Lesser General Public License version 2 as published by the
3143
 
+# Free Software Foundation;
3144
 
+#
3145
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
3146
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
3147
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
3148
 
+# details.
3149
 
+#
3150
 
+# You should have received a copy of the GNU Lesser General Public License
3151
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3152
 
+#
3153
 
+###############################################################################
3154
 
+
3155
 
+from wrowser.simdb.Parameters import Parameters, Bool, Int, Float, String
3156
 
+
3157
 
+###################################
3158
 
+# Simple parameter generation HowTo
3159
 
+#
3160
 
+# First, you need to define your simulation parameters in a class derived from Parameters, e.g.
3161
 
+#
3162
 
+class Set(Parameters):
3163
 
+    example = Int()
3164
 
+#
3165
 
+# Then, an instance of Set needs to be created
3166
 
+#
3167
 
+
3168
 
+params = Set()
3169
 
+
3170
 
+#
3171
 
+# now the Parameters in params get populated with different values. Each time "write" is called the current values fixed.
3172
 
+#
3173
 
+
3174
 
+for i in xrange(5):
3175
 
+    params.example = 10**(i)
3176
 
+    params.write()
3177
 
+
3178
 
+#
3179
 
+# in your config.py, you need
3180
 
+#
3181
 
+
3182
 
+from openwns.wrowser.simdb.SimConfig import params
3183
 
+
3184
 
+#
3185
 
+# and then configure using the params instance
3186
 
+#
3187
 
+
3188
 
+MyExample.examples = params.example
3189
 
+
3190
 
+# That's it
3191
 
+####################################
3192
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/__init__.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/__init__.py
3193
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/__init__.py  1970-01-01 01:00:00.000000000 +0100
3194
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/__init__.py      2010-04-29 17:49:15.353968415 +0200
3195
 
@@ -0,0 +1,184 @@
3196
 
+import os
3197
 
+import shutil
3198
 
+import datetime
3199
 
+
3200
 
+import sys
3201
 
+
3202
 
+import PrepareCampaign
3203
 
+
3204
 
+from wnsbase.playground.builtins.Install.Install import InstallCommand
3205
 
+
3206
 
+import wnsbase.playground.Core
3207
 
+core = wnsbase.playground.Core.getCore()
3208
 
+
3209
 
+class PrepareCampaignCommand(wnsbase.playground.plugins.Command.Command):
3210
 
+
3211
 
+    def __getDirectoryProposal(self, directory):
3212
 
+        files = os.listdir(directory)
3213
 
+        filteredFiles = [f[11:] for f in files if f.startswith('simulations')]
3214
 
+        ids = []
3215
 
+        # print filteredFiles
3216
 
+        for f in filteredFiles:
3217
 
+            print f
3218
 
+            if f == '':
3219
 
+                f = 1
3220
 
+            try:
3221
 
+                print ids
3222
 
+                ids.append(int(f))
3223
 
+            except ValueError:
3224
 
+                pass
3225
 
+        #    print ids
3226
 
+        proposedDirectory = 'simulations'
3227
 
+        if len(ids) > 0:
3228
 
+            proposedDirectory += str(max(ids)+1)
3229
 
+        return proposedDirectory
3230
 
+
3231
 
+    def __init__(self):
3232
 
+        usage = "\n%prog preparecampaign PATH\n\n"
3233
 
+        rationale = "Prepare a simulation campaign."
3234
 
+
3235
 
+        usage += rationale
3236
 
+
3237
 
+        usage += """
3238
 
+
3239
 
+            A directory 'directory' and the sub-directories 'sandbox' as well
3240
 
+            as 'simulations' will be created. 'sandbox' will contain all
3241
 
+            necessary libraries and the openwns. After installation the
3242
 
+            directory will be changed to read-only mode in order to prevent
3243
 
+            accidently removing the directory or altering its content. The
3244
 
+            simulations directory is empty. Directories for different
3245
 
+            simulations should be placed here.
3246
 
+"""
3247
 
+        wnsbase.playground.plugins.Command.Command.__init__(self, "preparecampaign", rationale, usage)
3248
 
+
3249
 
+        self.optParser.add_option("-f", "--configFile",
3250
 
+                                  type="string", dest = "configFile", metavar = "FILE", default = "config/projects.py",
3251
 
+                                  help = "choose a configuration file (e.g., --configFile=config/projects.py)")
3252
 
+
3253
 
+        self.optParser.add_option("", "--addProfOpt",
3254
 
+                                  dest = "addProfOpt", default = False,
3255
 
+                                  action = "store_true",
3256
 
+                                  help = "additionally build and install (static) version for profiling")
3257
 
+
3258
 
+        self.optParser.add_option("", "--static",
3259
 
+                                  dest = "static", default = False,
3260
 
+                                  action = "store_true",
3261
 
+                                  help = "build static executable")
3262
 
+        self.numberOfArgs = 1
3263
 
+
3264
 
+
3265
 
+    def run(self):
3266
 
+        """ Prepare a directory with a dbg and an opt version.
3267
 
+
3268
 
+        A directory 'directory' and the sub-directories 'sandbox' as well
3269
 
+        as 'simulations' will be created. 'sandbox' will contain all
3270
 
+        necessary libraries and the openwns. After installation the
3271
 
+        directory will be changed to read-only mode in order to prevent
3272
 
+        accidently removing the directory or altering its content. The
3273
 
+        simulations directory is empty. Directories for different
3274
 
+        simulations should be placed here.
3275
 
+        """
3276
 
+
3277
 
+        print "Preparing simulation campaign. Please wait..."
3278
 
+
3279
 
+        # copy simcontrol.py and sim.py to $OPENWNSROOT/bin
3280
 
+        absPathToOpenWNS = os.path.abspath(core.getPathToSDK())
3281
 
+
3282
 
+        thisPluginPath = os.path.dirname(__file__)
3283
 
+        shutil.copy(os.path.join(thisPluginPath, 'simcontrol.py'), os.path.join(absPathToOpenWNS,'bin'))
3284
 
+        shutil.copy(os.path.join(thisPluginPath, 'sim.py'), os.path.join(absPathToOpenWNS, 'bin'))
3285
 
+        os.system("chmod u+x " + os.path.join(absPathToOpenWNS, 'bin', 'sim.py'))
3286
 
+
3287
 
+        directory = "".join(self.args)
3288
 
+        # Import playground stuff
3289
 
+        projects = core.getProjects()
3290
 
+
3291
 
+        absSandboxDir = os.path.abspath(os.path.join(directory, "sandbox"))
3292
 
+        campaignName = os.path.basename(os.path.abspath(directory))
3293
 
+        logFile = os.path.join(directory, campaignName + ".history")
3294
 
+
3295
 
+        updating = False
3296
 
+
3297
 
+        if os.path.exists(directory):
3298
 
+            if os.path.exists(logFile):
3299
 
+                print "Found simulation campaign in directory %s." % directory
3300
 
+                answer = raw_input("Shall I try to (U)pdate the sandbox or do you want to (C)reate a new sub campaign? Type \'e\' to exit (u/c/e) [e]: ")
3301
 
+                answer = answer.lower()
3302
 
+                if answer == "u":
3303
 
+                    if os.path.exists(absSandboxDir):
3304
 
+                        os.system("chmod -R u+w " + absSandboxDir)
3305
 
+                        os.system("rm -rf " + absSandboxDir)
3306
 
+                    if os.path.exists(logFile):
3307
 
+                        os.system("chmod u+w " + logFile)
3308
 
+                    logFileHandle = file(logFile, 'a')
3309
 
+                    updating = True
3310
 
+                elif answer == "c":
3311
 
+                    PrepareCampaign.createNewSubCampaign(directory)
3312
 
+                    sys.exit(0)
3313
 
+                else:
3314
 
+                    sys.exit(0)
3315
 
+            else:
3316
 
+                print "Directory %s already exists and does not seem to be a simulation campaign directory." % directory
3317
 
+                print "Please remove the directory or use a different name and try again."
3318
 
+                sys.exit(0)
3319
 
+        else:
3320
 
+            os.makedirs(directory)
3321
 
+            logFileHandle = file(logFile, 'w')
3322
 
+            logFileHandle.write("Do NOT remove this file!\n\n")
3323
 
+            shutil.copy('.thisIsTheRootOfWNS', directory)
3324
 
+
3325
 
+        logFileHandle.write("---START---" + datetime.datetime.today().strftime('%d.%m.%y %H:%M:%S') + "---\n\n")
3326
 
+        logFileHandle.write("Setting up simulation campaign directory...\n\n")
3327
 
+
3328
 
+        if not updating:
3329
 
+            PrepareCampaign.createNewSubCampaign(directory)
3330
 
+
3331
 
+        if not os.path.exists(absSandboxDir):
3332
 
+            os.makedirs(absSandboxDir)
3333
 
+
3334
 
+        self.installWNS(absSandboxDir)
3335
 
+
3336
 
+        PrepareCampaign.updateSubCampaigns(directory)
3337
 
+        shutil.copy(os.path.join(os.path.dirname(__file__),"sim.py"), directory)
3338
 
+        os.system("chmod u+x " + os.path.join(directory, "sim.py"))
3339
 
+
3340
 
+        logFileHandle.write("Simulation campaign directory successfully set up.\n\n")
3341
 
+        logFileHandle.write("---END---" + datetime.datetime.today().strftime('%d.%m.%y %H:%M:%S') + "---\n")
3342
 
+        logFileHandle.close()
3343
 
+
3344
 
+        # make read only
3345
 
+        os.system("chmod -R u-w,g-w,o-w " + absSandboxDir)
3346
 
+        os.system("chmod u-w,g-w,o-w " + logFile)
3347
 
+
3348
 
+
3349
 
+    def installWNS(self, absSandboxDir):
3350
 
+        commonArgs = ["--sandboxDir="+absSandboxDir, '--scons="preparingcampaign=1"']
3351
 
+        installCommand = InstallCommand()
3352
 
+        # install fresh version
3353
 
+        print "running ./playground.py install --flavour=dbg -f " + self.options.configFile
3354
 
+        installCommand.startup(commonArgs + ["--flavour=dbg"])
3355
 
+        installCommand.run()
3356
 
+
3357
 
+        staticString = " "
3358
 
+        if self.options.static:
3359
 
+            staticString = " --static "
3360
 
+
3361
 
+        print "running ./playground.py install --flavour=opt" + staticString + "-f " + self.options.configFile
3362
 
+        installCommand.startup(commonArgs + ["--flavour=opt"])
3363
 
+        installCommand.options.static = self.options.static
3364
 
+        installCommand.run()
3365
 
+
3366
 
+        if self.options.addProfOpt:
3367
 
+            print "running ./playground.py install --flavour=profOpt" + staticString + "-f " + self.options.configFile
3368
 
+            installCommand.startup(commonArgs + ["--flavour=profOpt"])
3369
 
+            installCommand.options.static = self.options.static
3370
 
+            installCommand.run()
3371
 
+
3372
 
+
3373
 
+if not core.hasPlugin("SimulationCampaign"):
3374
 
+    core.registerPlugin("SimulationCampaign")
3375
 
+
3376
 
+    prepareCommand = PrepareCampaignCommand()
3377
 
+
3378
 
+    core.registerCommand(prepareCommand)
3379
 
+
3380
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/PrepareCampaign.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/PrepareCampaign.py
3381
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/PrepareCampaign.py   1970-01-01 01:00:00.000000000 +0100
3382
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/PrepareCampaign.py       2010-04-29 17:49:15.353968415 +0200
3383
 
@@ -0,0 +1,108 @@
3384
 
+###############################################################################
3385
 
+# This file is part of openWNS (open Wireless Network Simulator)
3386
 
+# _____________________________________________________________________________
3387
 
+#
3388
 
+# Copyright (C) 2004-2007
3389
 
+# Chair of Communication Networks (ComNets)
3390
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
3391
 
+# phone: ++49-241-80-27910,
3392
 
+# fax: ++49-241-80-22242
3393
 
+# email: info@openwns.org
3394
 
+# www: http://www.openwns.org
3395
 
+# _____________________________________________________________________________
3396
 
+#
3397
 
+# openWNS is free software; you can redistribute it and/or modify it under the
3398
 
+# terms of the GNU Lesser General Public License version 2 as published by the
3399
 
+# Free Software Foundation;
3400
 
+#
3401
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
3402
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
3403
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
3404
 
+# details.
3405
 
+#
3406
 
+# You should have received a copy of the GNU Lesser General Public License
3407
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3408
 
+#
3409
 
+###############################################################################
3410
 
+
3411
 
+import os
3412
 
+import shutil
3413
 
+
3414
 
+try:
3415
 
+    import openwns.wrowser.simdb.Database as db
3416
 
+    import openwns.wrowser.Configuration as conf
3417
 
+except ImportError:
3418
 
+    # No global installation, lets try if we are part of Wrowser
3419
 
+    print "Cannot find wrowser in your PYTHONPATH. Trying if we are part of a local wrowser. Adding ../../../"
3420
 
+    import sys
3421
 
+    sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
3422
 
+    import openwns.wrowser.simdb.Database as db
3423
 
+    import openwns.wrowser.Configuration as conf
3424
 
+    print "Success. Please consider to add the wrowser to your PYTHONPATH!"
3425
 
+
3426
 
+__config = conf.Configuration()
3427
 
+__config.read()
3428
 
+db.Database.connectConf(__config)
3429
 
+
3430
 
+
3431
 
+def __getDirectoryProposal(directory):
3432
 
+    files = os.listdir(directory)
3433
 
+    filteredFiles = [f[11:] for f in files if f.startswith('simulations')]
3434
 
+    ids = []
3435
 
+#    print filteredFiles
3436
 
+    for f in filteredFiles:
3437
 
+        print f
3438
 
+        if f == '':
3439
 
+            f = 1
3440
 
+        try:
3441
 
+            print ids
3442
 
+            ids.append(int(f))
3443
 
+        except ValueError:
3444
 
+            pass
3445
 
+#    print ids
3446
 
+    proposedDirectory = 'simulations'
3447
 
+    if len(ids) > 0:
3448
 
+        proposedDirectory += str(max(ids)+1)
3449
 
+    return proposedDirectory
3450
 
+
3451
 
+
3452
 
+def createNewSubCampaign(directory):
3453
 
+    proposedDirectory = __getDirectoryProposal(directory)
3454
 
+    while True:
3455
 
+        subCampaign = raw_input('Please enter the name of the directory the simulations shall be stored in [%s]: ' % proposedDirectory)
3456
 
+        if subCampaign == '':
3457
 
+            subCampaign = proposedDirectory
3458
 
+
3459
 
+        subCampaignDir = os.path.join(directory, subCampaign)
3460
 
+#        print subCampaignDir
3461
 
+
3462
 
+        if os.path.exists(subCampaignDir):
3463
 
+            print 'Path already exists. Please use a different name'
3464
 
+        else:
3465
 
+            break
3466
 
+
3467
 
+    os.mkdir(subCampaignDir)
3468
 
+    shutil.copy(os.path.join(os.path.dirname(__file__), 'simcontrol.py'), subCampaignDir)
3469
 
+    os.system("chmod u+x " + os.path.join(subCampaignDir, 'simcontrol.py'))
3470
 
+    shutil.copy(os.path.join(os.path.dirname(__file__), 'campaignConfiguration.py'), subCampaignDir)
3471
 
+    os.system("chmod u+x " + os.path.join(subCampaignDir, 'campaignConfiguration.py'))
3472
 
+
3473
 
+    campaignTitle = raw_input('Please enter a name for the campaign: ')
3474
 
+    campaignDescription = raw_input('Please enter a short description of the campaign: ')
3475
 
+    cursor = db.Database.getCursor()
3476
 
+    cursor.execute('INSERT INTO campaigns (title, description) VALUES (\'%s\', \'%s\')' % (campaignTitle, campaignDescription))
3477
 
+    cursor.execute('SELECT currval(\'administration.campaigns_id_seq\')')
3478
 
+    campaignConfig = conf.Configuration()
3479
 
+    campaignConfig.campaignId = cursor.fetchone()[0]
3480
 
+    campaignConfig.writeCampaignConf(os.path.join(subCampaignDir, '.campaign.conf'))
3481
 
+    cursor.connection.commit()
3482
 
+
3483
 
+
3484
 
+def updateSubCampaigns(directory):
3485
 
+    dirs = [f for f in os.listdir(directory) if os.path.isdir(f)]
3486
 
+    for d in dirs:
3487
 
+        path = os.path.join(directory, d, 'simcontrol.py')
3488
 
+        if os.path.exists(path):
3489
 
+            shutil.copy(os.path.join('sandbox', 'default', 'lib', 'python2.4', 'site-packages', 'pywns', 'simdb', 'scripts', 'simcontrol.py'),
3490
 
+                        os.path.join(path))
3491
 
+            os.system("chmod u+x " + path)
3492
 
diff -Nur -x '*.orig' -x '*~' openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/simcontrol.py openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/simcontrol.py
3493
 
--- openwns-wrowser-0.9beta2/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/simcontrol.py        1970-01-01 01:00:00.000000000 +0100
3494
 
+++ openwns-wrowser-0.9beta2.new/openwns-wrowser-0.9beta2/openwns/wrowser/playgroundPlugins/SimulationCampaign/simcontrol.py    2010-04-29 17:49:15.353968415 +0200
3495
 
@@ -0,0 +1,563 @@
3496
 
+#! /usr/bin/python
3497
 
+###############################################################################
3498
 
+# This file is part of openWNS (open Wireless Network Simulator)
3499
 
+# _____________________________________________________________________________
3500
 
+#
3501
 
+# Copyright (C) 2004-2007
3502
 
+# Chair of Communication Networks (ComNets)
3503
 
+# Kopernikusstr. 16, D-52074 Aachen, Germany
3504
 
+# phone: ++49-241-80-27910,
3505
 
+# fax: ++49-241-80-22242
3506
 
+# email: info@openwns.org
3507
 
+# www: http://www.openwns.org
3508
 
+# _____________________________________________________________________________
3509
 
+#
3510
 
+# openWNS is free software; you can redistribute it and/or modify it under the
3511
 
+# terms of the GNU Lesser General Public License version 2 as published by the
3512
 
+# Free Software Foundation;
3513
 
+#
3514
 
+# openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
3515
 
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
3516
 
+# A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
3517
 
+# details.
3518
 
+#
3519
 
+# You should have received a copy of the GNU Lesser General Public License
3520
 
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3521
 
+#
3522
 
+###############################################################################
3523
 
+
3524
 
+import os
3525
 
+import pwd
3526
 
+import sys
3527
 
+import shutil
3528
 
+import subprocess
3529
 
+import optparse
3530
 
+import re
3531
 
+import datetime
3532
 
+import time
3533
 
+
3534
 
+import openwns.wrowser.Configuration as conf
3535
 
+import openwns.wrowser.simdb.Database as db
3536
 
+import openwns.wrowser.simdb.Parameters as params
3537
 
+import openwns.wrowser.simdb.ProbeDB
3538
 
+import openwns.wrowser.Tools
3539
 
+
3540
 
+
3541
 
+config = conf.Configuration()
3542
 
+config.read('.campaign.conf')
3543
 
+db.Database.connectConf(config)
3544
 
+
3545
 
+def getWrowserDir():
3546
 
+    for cand in sys.path:
3547
 
+        if os.path.isdir(os.path.join(cand, 'openwns', 'wrowser')):
3548
 
+            return cand
3549
 
+    return None
3550
 
+
3551
 
+def __getFilteredScenarioIds(cursor, stateSpecial = None):
3552
 
+
3553
 
+    query = 'SELECT id FROM scenarios WHERE campaign_id = %d' % config.campaignId
3554
 
+
3555
 
+    if(options.state is not None):
3556
 
+        if('state' in options.state):
3557
 
+            query += ('AND ( %s )' % options.state)
3558
 
+        else:
3559
 
+            query += (' AND state = \'%s\'' % options.state)
3560
 
+
3561
 
+    if(stateSpecial is not None):
3562
 
+        query += (' AND %s' % stateSpecial)
3563
 
+
3564
 
+    cursor.execute(query)
3565
 
+
3566
 
+    scenarioIds = [ entry[0] for entry in cursor.fetchall() ]
3567
 
+
3568
 
+    if(options.expression is not None):
3569
 
+        scenarioIds = openwns.wrowser.Tools.objectFilter(options.expression, scenarioIds, viewGetter=__parametersDict)
3570
 
+
3571
 
+    scenarioIds.sort()
3572
 
+
3573
 
+    return scenarioIds
3574
 
+
3575
 
+def createDatabase(arg = 'unused'):
3576
 
+    subprocess.call(['python ./campaignConfiguration.py'], shell = True)
3577
 
+    print 'Database entries successfully created.'
3578
 
+
3579
 
+
3580
 
+def createScenarios(arg = 'unused'):
3581
 
+    cursor = db.Database.getCursor()
3582
 
+    scenarioIds = __getFilteredScenarioIds(cursor)
3583
 
+    cursor.connection.commit()
3584
 
+
3585
 
+    wdir = getWrowserDir()
3586
 
+    if wdir is None:
3587
 
+        print "ERROR: Cannot find Wrowser directory! Exiting..."
3588
 
+        return
3589
 
+
3590
 
+
3591
 
+    for scenario in scenarioIds:
3592
 
+        simId = str(scenario)
3593
 
+        simPath = os.path.abspath(os.path.join(os.getcwd(), simId))
3594
 
+        if os.path.exists(simPath):
3595
 
+            if options.forceOverwrite:
3596
 
+                shutil.rmtree(simPath)
3597
 
+            else:
3598
 
+                print "Skipping %s, it already exists (consider --force switch)" % simPath
3599
 
+                continue
3600
 
+        os.mkdir(simPath)
3601
 
+        os.symlink(os.path.join('..', '..', 'sandbox', options.flavor, 'bin', 'openwns'), os.path.join(simPath, 'openwns'))
3602
 
+        if options.flavor == 'opt':
3603
 
+            os.symlink(os.path.join('..', '..', 'sandbox', 'dbg', 'bin', 'openwns'), os.path.join(simPath, 'openwns-dbg'))
3604
 
+
3605
 
+            os.symlink(os.path.join(wdir, 'openwns', 'wrowser', 'simdb', 'SimConfig.py'),
3606
 
+                       os.path.join(simPath, 'SimConfig.py'))
3607
 
+
3608
 
+
3609
 
+        os.symlink(os.path.join('..', '.campaign.conf'), os.path.join(simPath, '.campaign.conf'))
3610
 
+
3611
 
+        for f in os.listdir(os.getcwd()):
3612
 
+            if f.endswith('.py') or f.endswith('.probes') or f.endswith('.ini'):
3613
 
+                if not f == 'simcontrol.py' and not f == 'campaignConfiguration.py' and not f == 'ProbeDB.py':
3614
 
+                    os.symlink(os.path.join('..', f), os.path.join(simPath, f))
3615
 
+
3616
 
+    if not os.path.exists(os.path.join(os.getcwd(), 'ProbeDB.py')):
3617
 
+        os.symlink(os.path.join(wdir, 'openwns', 'wrowser', 'simdb', 'ProbeDB.py'),
3618
 
+                   os.path.join(os.getcwd(), 'ProbeDB.py'))
3619
 
+
3620
 
+
3621
 
+    print 'Scenarios successfully created.'
3622
 
+
3623
 
+
3624
 
+def removeDatabase(arg = 'unused'):
3625
 
+    db.Database.truncateCampaign(config.campaignId)
3626
 
+    print 'Campaign results successfully removed from database.'
3627
 
+
3628
 
+
3629
 
+def removeScenarios(arg = 'unused'):
3630
 
+    cursor = db.Database.getCursor()
3631
 
+    scenarioIds = __getFilteredScenarioIds(cursor)
3632
 
+    cursor.connection.commit()
3633
 
+
3634
 
+    for scenarioId in scenarioIds:
3635
 
+        simPath = os.path.abspath(os.path.join(os.getcwd(), str(scenarioId)))
3636
 
+        if os.path.exists(simPath):
3637
 
+            shutil.rmtree(simPath)
3638
 
+    print 'Scenarios successfully removed.'
3639
 
+
3640
 
+def __submitJob(scenarioId):
3641
 
+    cursor = db.Database.getCursor()
3642
 
+    cursor.execute('SELECT state FROM scenarios WHERE id = %d AND campaign_id = %d' % (scenarioId, config.campaignId))
3643
 
+    state = cursor.fetchone()[0]
3644
 
+
3645
 
+    if state == 'Queued':
3646
 
+        print >>sys.stderr, 'ERROR: Job is already in queue'
3647
 
+    elif state == 'Running':
3648
 
+        print >>sys.stderr, 'ERROR: Job is currently running'
3649
 
+    simId = str(scenarioId)
3650
 
+    simPath = os.path.abspath(os.path.join(os.getcwd(), simId))
3651
 
+    if simPath.startswith('/local'):
3652
 
+        raise Exception('\n\nYour current dir starts with "/local/...". You must chdir to /net/<hostname>/.... Otherwise your simulations will fail.\n')
3653
 
+    print 'Submitting job with scenario id ' + simId
3654
 
+    command = os.path.abspath(os.path.join('..', 'sim.py')) + ' -p ' + os.path.abspath(os.getcwd()) + ' -i ' + simId
3655
 
+    if options.skipNullTrials == True:
3656
 
+        command += ' -n'
3657
 
+    process = subprocess.Popen(['qsub -q %s -N job%s -l s_cpu=%i:%i:00 -l h_cpu=%i:%i:00 -o %s -e %s -m a -M %s@comnets.rwth-aachen.de -v PYTHONPATH=%s %s' % (options.queue,
3658
 
+                                                                                                                                             simId,
3659
 
+                                                                                                                                             options.cpuTime,
3660
 
+                                                                                                                                             options.cpuMinutes,
3661
 
+                                                                                                                                             options.cpuTime,
3662
 
+                                                                                                                                             options.cpuMinutes + 15,
3663
 
+                                                                                                                                             os.path.join(simPath, 'stdout'),
3664
 
+                                                                                                                                             os.path.join(simPath, 'stderr'),
3665
 
+                                                                                                                                             pwd.getpwuid(os.getuid())[0],
3666
 
+                                                                                                                                             os.environ['PYTHONPATH'],
3667
 
+                                                                                                                                             command)],
3668
 
+                         stdout = subprocess.PIPE,
3669
 
+                         stderr = subprocess.STDOUT,
3670
 
+                         shell = True)
3671
 
+    status = process.wait()
3672
 
+    if not status == 0:
3673
 
+        print >>sys.stderr, 'ERROR: qsub failed!'
3674
 
+        print >>sys.stderr, process.stdout.read()
3675
 
+        sys.exit(1)
3676
 
+    state = 'Queued'
3677
 
+    startDate = None
3678
 
+    stopDate = None
3679
 
+    hostname = None
3680
 
+    try:
3681
 
+        jobId = int(process.stdout.read().split()[2])
3682
 
+    except:
3683
 
+        print >>sys.stderr, 'ERROR: Could not get job id. Output of qsub has probably changed'
3684
 
+        sys.exit(1)
3685
 
+
3686
 
+    cursor.execute('UPDATE scenarios SET state = \'Queued\', max_sim_time = 0.0, current_sim_time = 0.0, sim_time_last_write = 0.0 WHERE id = %d AND campaign_id = %d' % (scenarioId, config.campaignId))
3687
 
+    cursor.execute('INSERT INTO jobs (campaign_id, scenario_id, sge_job_id, queue_date, start_date, stop_date, hostname, stdout, stderr) VALUES ' \
3688
 
+                   '(%d, %d, %d, \'%s\', \'1900-01-01\' , \'1900-01-01\', \'\', \'\', \'\')' % (config.campaignId, scenarioId, jobId, datetime.datetime.today().isoformat()))
3689
 
+    cursor.connection.commit()
3690
 
+
3691
 
+def queueSingleScenario(scenarioId):
3692
 
+    cursor = db.Database.getCursor()
3693
 
+    cursor.execute('SELECT state FROM scenarios WHERE campaign_id = %d AND id = %d' % (config.campaignId, scenarioId))
3694
 
+    state = cursor.fetchone()[0]
3695
 
+    cursor.connection.commit()
3696
 
+    if state == 'Queued' or state == 'Running':
3697
 
+        print >>sys.stderr, 'Job already queued/running.'
3698
 
+        sys.exit(1)
3699
 
+    __submitJob(scenarioId)
3700
 
+
3701
 
+
3702
 
+def __parametersDict(scenarioId):
3703
 
+    cursor = db.Database.getCursor()
3704
 
+    cursor.execute('SELECT state FROM scenarios WHERE campaign_id = %d AND id = %d' % (config.campaignId, scenarioId))
3705
 
+    state = cursor.fetchone()[0]
3706
 
+    cursor.connection.commit()
3707
 
+
3708
 
+    p = params.Parameters()
3709
 
+    parameters = dict([[paramName, param.getValue()] for paramName, param in p.read(scenarioId).items()])
3710
 
+    parameters['state'] = state
3711
 
+    parameters['id'] = scenarioId
3712
 
+    return parameters
3713
 
+
3714
 
+
3715
 
+def queueScenarios(stringexpression):
3716
 
+    if(options.state == 'Queued' or options.state == 'Running'):
3717
 
+        print >> sys.stderr, 'Cannot queue jobs which are already queue/running.'
3718
 
+        sys.exit(1)