~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:07:12 UTC
  • Revision ID: me@daniel-bueltmann.de-20101024140712-jf18y58ujtu7e0mg
Initial import of packaging information for wrowser (./debian directory)

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
+