source: trunk/brainstorms/Puzzlebox/Brainstorms/Interface.py @ 226

Last change on this file since 226 was 226, checked in by sc, 11 years ago

trunk/brainstorms/Puzzlebox/Brainstorms/Interface.py:

  • Helicopter control buttons handled appropriately by connect sequence
  • Helicopter Hover control added
  • Helicopter Fly Forward control added
  • Helicopter Land control added
File size: 39.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Client Interface - Qt
5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
10
11__changelog__ = """\
12Last Update: 2010.11.28
13
14"""
15
16__todo__ = """
17 - server may not correctly handle multiple clients connected
18      to an embedded Brainstorms server
19 - disable autorepeating on shortcut keys
20 - update configuration.ini file with settings entered into interface
21
22"""
23
24import os, sys
25import urllib
26
27if (sys.platform == 'win32'):
28        import _winreg as winreg
29        import itertools
30        import re
31        import serial
32else:
33        import bluetooth
34
35try:
36        import PySide as PyQt4
37        from PySide import QtCore, QtGui, QtNetwork
38except:
39        print "Using PyQt4 module"
40        from PyQt4 import QtCore, QtGui, QtNetwork
41else:
42        print "Using PySide module"
43
44#from PyQt4 import QtCore, QtGui, QtNetwork
45#from PySide import QtCore, QtGui, QtNetwork
46
47from Interface_Design import Ui_Form as Design
48
49import simplejson as json
50
51import Configuration as configuration
52import Client as brainstorms_client
53import Puzzlebox.Brainstorms.ThinkGear.Client as thinkgear_client
54#import puzzlebox_logger
55
56#####################################################################
57# Globals
58#####################################################################
59
60DEBUG = 1
61
62THINKGEAR_POWER_THRESHOLDS = configuration.THINKGEAR_POWER_THRESHOLDS
63
64BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
65
66NXT_BLUETOOTH_DEVICE = configuration.NXT_BLUETOOTH_DEVICE
67
68DEFAULT_NXT_POWER_LEVEL = configuration.DEFAULT_NXT_POWER_LEVEL
69
70THINKGEAR_SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
71THINKGEAR_SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
72
73BRAINSTORMS_FEEDBACK_URL = 'http://brainstorms.puzzlebox.info/contact_cgi.php'
74
75DEVICE_PATH = '/dev'
76PATH_TO_HCITOOL = '/usr/bin/hcitool'
77
78#####################################################################
79# Classes
80#####################################################################
81
82class puzzlebox_brainstorms_client_interface(QtGui.QWidget, Design):
83       
84        def __init__(self, log, server=None, DEBUG=DEBUG, parent = None):
85               
86                self.log = log
87                self.DEBUG = DEBUG
88               
89                QtGui.QWidget.__init__(self, parent)
90                self.setupUi(self)
91               
92                self.configureSettings()
93                self.connectWidgets()
94               
95                self.name = "Brainstorms Interface"
96               
97                self.brainstormsServer = server
98                self.brainstormsClient = None
99               
100                self.drive_state = 'stop_motors'
101                self.current_speed = 0
102       
103       
104        ##################################################################
105       
106        def configureSettings(self):
107               
108                # Brainstorms Interface
109               
110                icon = QtGui.QIcon()
111                icon.addPixmap(QtGui.QPixmap("images/puzzlebox.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
112                self.setWindowIcon(icon)
113               
114                self.pushButtonTurnLeft.setEnabled(False)
115                self.pushButtonForward.setEnabled(False)
116                self.pushButtonTurnRight.setEnabled(False)
117                self.pushButtonTurnLeftReverse.setEnabled(False)
118                self.pushButtonReverse.setEnabled(False)
119                self.pushButtonTurnRightReverse.setEnabled(False)
120               
121                self.pushButtonConcentrationEnable.setDown(True)
122                self.pushButtonRelaxationEnable.setDown(True)
123                self.pushButtonSpeedEnable.setDown(True)
124               
125               
126                # Search for available Serial and Bluetooth devices
127                self.searchForDevices()
128               
129               
130                # LEGO Mindstorms
131                self.textLabelNXTStatus.setText("Status: Disconnected")
132               
133                # Display communication port for LEGO Mindstorms NXT device
134                #self.lineEditNXTPort.setText(NXT_BLUETOOTH_DEVICE)
135                self.comboBoxNXTPortSelect.setEnabled(True)
136               
137               
138                # RC Helicopter
139                self.textLabelHelicopterStatus.setText("Status: Disconnected")
140               
141               
142                # EEG Headset
143               
144                # Display Host for ThinkGear Connect Socket Server
145                self.lineEditThinkGearHost.setText(THINKGEAR_SERVER_HOST)
146                #self.lineEditThinkGearHost.setEnabled(False)
147               
148                # Display Port for ThinkGear Connect Socket Server
149                self.lineEditThinkGearPort.setText('%i' % THINKGEAR_SERVER_PORT)
150                #self.lineEditThinkGearPort.setEnabled(False)
151               
152               
153                # Control Panel
154                self.lineEditLeftMotorPort.setText( \
155                   configuration.NXT_MOTOR_PORT_LEFT.upper() )
156                self.lineEditRightMotorPort.setText(   \
157                   configuration.NXT_MOTOR_PORT_RIGHT.upper() )
158                self.checkBoxMotorSpinReversed.setChecked( \
159                   configuration.NXT_MOTORS_MOUNTED_BACKWARDS)
160       
161       
162        ##################################################################
163       
164        def getMinimumThreshold(self, threshold):
165               
166                '''Return the minimum detection level which results
167                in a non-zero power setting'''
168               
169                minimum = 100
170               
171                threshold_keys = threshold.keys()
172                threshold_keys.sort()
173                threshold_keys.reverse()
174               
175                for key in threshold_keys:
176                       
177                        if ((threshold[key] < minimum) and \
178                                 (threshold[key] > 0)):
179                                minimum = key
180               
181               
182                return(minimum)
183       
184       
185        ##################################################################
186       
187        def configureNetworkBrainstorms(self):
188               
189                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
190               
191                self.brainstormsClient = \
192                   brainstorms_client.puzzlebox_brainstorms_network_client( \
193                           self.log, \
194                           bluetooth_device=bluetooth_device, \
195                           parent=self)
196               
197                self.brainstormsClient.sendCommand('connect', \
198                                                   bluetooth_device=bluetooth_device)
199       
200       
201        ##################################################################
202       
203        def connectToBrainstormsServer(self):
204               
205                # Prevent attempting to connect to a device which no longer exists
206                if (sys.platform != 'win32'):
207                        device = str(self.comboBoxNXTPortSelect.currentText())
208                        if ((not device.startswith(DEVICE_PATH)) or \
209                            (not os.path.exists(device))):
210                                self.searchForDevices()
211                                return
212               
213               
214                if self.DEBUG:
215                        print "<---- [%s] Connecting to Brainstorms Server" % self.name
216               
217                self.configureNetworkBrainstorms()
218               
219                #if (self.brainstormsClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
220                        #QtGui.QMessageBox.information(self, \
221                                                                #self.brainstormsClient.socket.name, \
222                                           #"Failed to connect to Brainstorms socket server")
223               
224                #else:
225                self.disconnect(self.pushButtonNXTConnect, \
226                                                        QtCore.SIGNAL("clicked()"), \
227                                                        self.connectToBrainstormsServer)
228               
229                self.connect(self.pushButtonNXTConnect, \
230                                                        QtCore.SIGNAL("clicked()"), \
231                                                        self.disconnectFromBrainstormsServer)
232               
233                self.textLabelNXTStatus.setText("Status: Connected")
234                self.pushButtonNXTConnect.setText('Disconnect')
235               
236                self.comboBoxNXTPortSelect.setEnabled(False)
237                self.pushButtonNXTSearch.setEnabled(False)
238               
239                self.pushButtonTurnLeft.setEnabled(True)
240                self.pushButtonForward.setEnabled(True)
241                self.pushButtonTurnRight.setEnabled(True)
242                self.pushButtonTurnLeftReverse.setEnabled(True)
243                self.pushButtonReverse.setEnabled(True)
244                self.pushButtonTurnRightReverse.setEnabled(True)
245               
246                self.pushButtonNXTMessageOne.setEnabled(True)
247                self.pushButtonNXTMessageTwo.setEnabled(True)
248                self.pushButtonNXTMessageThree.setEnabled(True)
249                self.pushButtonNXTMessageFour.setEnabled(True)
250                self.pushButtonNXTMessageFive.setEnabled(True)
251                self.pushButtonNXTMessageSix.setEnabled(True)
252               
253                self.pushButtonConcentrationEnable.setEnabled(True)
254                self.pushButtonRelaxationEnable.setEnabled(True)
255                self.pushButtonSpeedEnable.setEnabled(True)
256               
257                self.pushButtonMessageOne.setEnabled(True)
258                self.pushButtonMessageTwo.setEnabled(True)
259                self.pushButtonMessageThree.setEnabled(True)
260                self.pushButtonMessageFour.setEnabled(True)
261                self.pushButtonMessageFive.setEnabled(True)
262                self.pushButtonMessageSix.setEnabled(True)
263               
264                self.pushButtonHelicopterConcentrationEnable.setEnabled(True)
265                self.pushButtonHelicopterRelaxationEnable.setEnabled(True)
266                self.pushButtonHelicopterSpeedEnable.setEnabled(True)
267       
268       
269        ##################################################################
270       
271        def disconnectFromBrainstormsServer(self):
272               
273                if self.DEBUG:
274                        print "- - [%s] Disconnecting from Brainstorms Server" % self.name
275               
276                self.stopMotors()
277               
278                # Ensure the stopMotors command has been received by the server
279                # so the NXT robot will stop before the client disconnects
280                self.brainstormsClient.socket.flush()
281               
282                self.brainstormsClient.socket.disconnectFromHost()
283               
284                self.disconnect(self.pushButtonNXTConnect, \
285                                  QtCore.SIGNAL("clicked()"), \
286                                  self.disconnectFromBrainstormsServer)
287               
288                self.connect(self.pushButtonNXTConnect, \
289                                  QtCore.SIGNAL("clicked()"), \
290                                  self.connectToBrainstormsServer)
291               
292                self.textLabelNXTStatus.setText("Status: Disconnected")
293                self.pushButtonNXTConnect.setText('Connect')
294               
295                self.comboBoxNXTPortSelect.setEnabled(True)
296                self.pushButtonNXTSearch.setEnabled(True)
297               
298                self.pushButtonTurnLeft.setEnabled(False)
299                self.pushButtonForward.setEnabled(False)
300                self.pushButtonTurnRight.setEnabled(False)
301                self.pushButtonTurnLeftReverse.setEnabled(False)
302                self.pushButtonReverse.setEnabled(False)
303                self.pushButtonTurnRightReverse.setEnabled(False)
304               
305                self.pushButtonNXTMessageOne.setEnabled(False)
306                self.pushButtonNXTMessageTwo.setEnabled(False)
307                self.pushButtonNXTMessageThree.setEnabled(False)
308                self.pushButtonNXTMessageFour.setEnabled(False)
309                self.pushButtonNXTMessageFive.setEnabled(False)
310                self.pushButtonNXTMessageSix.setEnabled(False)
311               
312                self.pushButtonConcentrationEnable.setEnabled(False)
313                self.pushButtonRelaxationEnable.setEnabled(False)
314                self.pushButtonSpeedEnable.setEnabled(False)
315               
316                self.pushButtonMessageOne.setEnabled(False)
317                self.pushButtonMessageTwo.setEnabled(False)
318                self.pushButtonMessageThree.setEnabled(False)
319                self.pushButtonMessageFour.setEnabled(False)
320                self.pushButtonMessageFive.setEnabled(False)
321                self.pushButtonMessageSix.setEnabled(False)
322               
323                self.brainstormsClient = None
324               
325                self.searchForDevices()
326       
327       
328        ##################################################################
329       
330        def connectToThinkGearHost(self):
331               
332                if self.DEBUG:
333                        print "Connecting to ThinkGear Host"
334               
335                server_host = str(self.lineEditThinkGearHost.text())
336                server_port = int(self.lineEditThinkGearPort.text())
337               
338                self.thinkgearClient = \
339                   thinkgear_client.puzzlebox_brainstorms_network_client_thinkgear( \
340                           self.log, \
341                           server_host=server_host, \
342                           server_port=server_port, \
343                           DEBUG=0, \
344                           parent=self)
345               
346                if (self.thinkgearClient.socket.state() != QtNetwork.QAbstractSocket.ConnectedState):
347                        QtGui.QMessageBox.information(self, \
348                                                                self.thinkgearClient.socket.name, \
349                                           "Failed to connect to ThinkGear socket server")
350               
351                else:
352                        self.disconnect(self.pushButtonThinkGearConnect, \
353                                                         QtCore.SIGNAL("clicked()"), \
354                                                         self.connectToThinkGearHost)
355                       
356                        self.connect(self.pushButtonThinkGearConnect, \
357                                                         QtCore.SIGNAL("clicked()"), \
358                                                         self.disconnectFromThinkGearHost)
359                       
360                        self.pushButtonThinkGearConnect.setText('Disconnect')
361                       
362                        self.comboBoxEEGHeadsetModel.setEnabled(False)
363                        self.comboBoxEEGSource.setEnabled(False)
364                        self.lineEditThinkGearHost.setEnabled(False)
365                        self.lineEditThinkGearPort.setEnabled(False)
366       
367       
368        ##################################################################
369       
370        def disconnectFromThinkGearHost(self):
371               
372                if self.DEBUG:
373                        print "Disconnecting from ThinkGear Host"
374               
375                self.thinkgearClient.disconnectFromHost()
376               
377                self.disconnect(self.pushButtonThinkGearConnect, \
378                                  QtCore.SIGNAL("clicked()"), \
379                                  self.disconnectFromThinkGearHost)
380               
381                self.connect(self.pushButtonThinkGearConnect, \
382                                  QtCore.SIGNAL("clicked()"), \
383                                  self.connectToThinkGearHost)
384               
385                self.pushButtonForward.emit(QtCore.SIGNAL("released()"))
386               
387                self.pushButtonThinkGearConnect.setText('Connect')
388               
389                self.comboBoxEEGHeadsetModel.setEnabled(True)
390                self.comboBoxEEGSource.setEnabled(True)
391                self.lineEditThinkGearHost.setEnabled(True)
392                self.lineEditThinkGearPort.setEnabled(True)
393               
394                self.progressBarConcentration.setValue(0)
395                self.progressBarRelaxation.setValue(0)
396                self.progressBarSpeed.setValue(0)
397       
398                self.progressBarHelicopterConcentration.setValue(0)
399                self.progressBarHelicopterRelaxation.setValue(0)
400                self.progressBarHelicopterSpeed.setValue(0)
401       
402       
403        ##################################################################
404       
405        def connectToRCHelicopter(self):
406               
407                self.disconnect(self.pushButtonHelicopterConnect, \
408                                  QtCore.SIGNAL("clicked()"), \
409                                  self.connectToRCHelicopter)
410               
411                self.connect(self.pushButtonHelicopterConnect, \
412                                  QtCore.SIGNAL("clicked()"), \
413                                  self.disconnectFromRCHelicopter)
414               
415                self.pushButtonHelicopterConnect.setText('Disconnect')
416               
417                self.comboBoxHelicopterTransmitter.setEnabled(False)
418                self.comboBoxHelicopterPortSelect.setEnabled(False)
419                self.pushButtonHelicopterSearch.setEnabled(False)
420               
421                self.pushButtonHelicopterHover.setEnabled(True)
422                self.pushButtonHelicopterFlyForward.setEnabled(True)
423                self.pushButtonHelicopterLand.setEnabled(True)
424                self.pushButtonHelicopterThrottle.setEnabled(True)
425                self.verticalSliderHelicopterThrottle.setEnabled(True)
426                self.pushButtonHelicopterElevatorForward.setEnabled(True)
427                self.verticalSliderHelicopterElevatorForward.setEnabled(True)
428                self.pushButtonHelicopterElevatorReverse.setEnabled(True)
429                self.verticalSliderHelicopterElevatorReverse.setEnabled(True)
430                self.pushButtonHelicopterRudderLeft.setEnabled(True)
431                self.horizontalSliderHelicopterRudderLeft.setEnabled(True)
432                self.pushButtonHelicopterRudderRight.setEnabled(True)
433                self.horizontalSliderHelicopterRudderRight.setEnabled(True)
434                self.pushButtonHelicopterAileronLeft.setEnabled(True)
435                self.horizontalSliderHelicopterAileronLeft.setEnabled(True)
436                self.pushButtonHelicopterAileronRight.setEnabled(True)
437                self.horizontalSliderHelicopterAileronRight.setEnabled(True)
438       
439       
440        ##################################################################
441       
442        def disconnectFromRCHelicopter(self):
443               
444                self.disconnect(self.pushButtonHelicopterConnect, \
445                                  QtCore.SIGNAL("clicked()"), \
446                                  self.disconnectFromRCHelicopter)
447               
448                self.connect(self.pushButtonHelicopterConnect, \
449                                  QtCore.SIGNAL("clicked()"), \
450                                  self.connectToRCHelicopter)
451               
452                self.pushButtonHelicopterConnect.setText('Connect')
453               
454                self.comboBoxHelicopterTransmitter.setEnabled(True)
455                self.comboBoxHelicopterPortSelect.setEnabled(True)
456                self.pushButtonHelicopterSearch.setEnabled(True)
457               
458                self.pushButtonHelicopterHover.setEnabled(False)
459                self.pushButtonHelicopterFlyForward.setEnabled(False)
460                self.pushButtonHelicopterLand.setEnabled(False)
461                self.pushButtonHelicopterThrottle.setEnabled(False)
462                self.verticalSliderHelicopterThrottle.setEnabled(False)
463                self.pushButtonHelicopterElevatorForward.setEnabled(False)
464                self.verticalSliderHelicopterElevatorForward.setEnabled(False)
465                self.pushButtonHelicopterElevatorReverse.setEnabled(False)
466                self.verticalSliderHelicopterElevatorReverse.setEnabled(False)
467                self.pushButtonHelicopterRudderLeft.setEnabled(False)
468                self.horizontalSliderHelicopterRudderLeft.setEnabled(False)
469                self.pushButtonHelicopterRudderRight.setEnabled(False)
470                self.horizontalSliderHelicopterRudderRight.setEnabled(False)
471                self.pushButtonHelicopterAileronLeft.setEnabled(False)
472                self.horizontalSliderHelicopterAileronLeft.setEnabled(False)
473                self.pushButtonHelicopterAileronRight.setEnabled(False)
474                self.horizontalSliderHelicopterAileronRight.setEnabled(False)
475       
476       
477        ##################################################################
478       
479        def updateConcentrationButton(self):
480               
481                if self.pushButtonConcentrationEnable.isChecked():
482                       
483                        self.pushButtonConcentrationEnable.setText('Enabled')
484               
485                else:
486                       
487                        self.pushButtonConcentrationEnable.setText('Disabled')
488                        self.progressBarConcentration.setValue(0)
489               
490               
491                self.updateSpeed()
492       
493       
494        ##################################################################
495       
496        def updateRelaxationButton(self):
497               
498                if self.pushButtonRelaxationEnable.isChecked():
499               
500                        self.pushButtonRelaxationEnable.setText('Enabled')
501               
502                else:
503                       
504                        self.pushButtonRelaxationEnable.setText('Disabled')
505                        self.progressBarRelaxation.setValue(0)
506               
507               
508                self.updateNXTSpeed()
509       
510       
511        ##################################################################
512       
513        def updateSpeedButton(self):
514               
515                if self.pushButtonSpeedEnable.isChecked():
516               
517                        self.pushButtonSpeedEnable.setText('Enabled')
518                        self.updateSpeed()
519               
520                else:
521                       
522                        self.pushButtonSpeedEnable.setText('Disabled')
523                        self.progressBarSpeed.setValue(0)
524                        self.stopMotors()
525       
526       
527        ##################################################################
528       
529        def updateHelicopterConcentrationButton(self):
530               
531                if self.pushButtonHelicopterConcentrationEnable.isChecked():
532                       
533                        self.pushButtonHelicopterConcentrationEnable.setText('Enabled')
534               
535                else:
536                       
537                        self.pushButtonHelicopterConcentrationEnable.setText('Disabled')
538                        self.progressBarHelicopterConcentration.setValue(0)
539               
540               
541                self.updateHelicopterSpeed()
542       
543       
544        ##################################################################
545       
546        def updateHelicopterRelaxationButton(self):
547               
548                if self.pushButtonHelicopterRelaxationEnable.isChecked():
549               
550                        self.pushButtonHelicopterRelaxationEnable.setText('Enabled')
551               
552                else:
553                       
554                        self.pushButtonHelicopterRelaxationEnable.setText('Disabled')
555                        self.progressBarHelicopterRelaxation.setValue(0)
556               
557               
558                self.updateHelicopterSpeed()
559       
560       
561        ##################################################################
562       
563        def updateHelicopterSpeedButton(self):
564               
565                if self.pushButtonHelicopterSpeedEnable.isChecked():
566               
567                        self.pushButtonHelicopterSpeedEnable.setText('Enabled')
568                        self.updateHelicopterSpeed()
569               
570                else:
571                       
572                        self.pushButtonHelicopterSpeedEnable.setText('Disabled')
573                        self.progressBarHelicopterSpeed.setValue(0)
574                        self.stopMotors()
575       
576       
577        ##################################################################
578       
579        def connectWidgets(self):
580               
581                # LEGO Mindstorms Buttons
582                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("pressed()"), \
583                             self.turnLeft)
584                self.connect(self.pushButtonTurnLeft, QtCore.SIGNAL("released()"), \
585                             self.stopMotors)
586               
587                self.connect(self.pushButtonForward, QtCore.SIGNAL("pressed()"), \
588                             self.driveForward)
589                self.connect(self.pushButtonForward, QtCore.SIGNAL("released()"), \
590                             self.stopMotors)
591               
592                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("pressed()"), \
593                             self.turnRight)
594                self.connect(self.pushButtonTurnRight, QtCore.SIGNAL("released()"), \
595                             self.stopMotors)
596               
597                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("pressed()"), \
598                             self.turnLeftInReverse)
599                self.connect(self.pushButtonTurnLeftReverse, QtCore.SIGNAL("released()"), \
600                             self.stopMotors)
601               
602                self.connect(self.pushButtonReverse, QtCore.SIGNAL("pressed()"), \
603                             self.driveReverse)
604                self.connect(self.pushButtonReverse, QtCore.SIGNAL("released()"), \
605                             self.stopMotors)
606               
607                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("pressed()"), \
608                             self.turnRightInReverse)
609                self.connect(self.pushButtonTurnRightReverse, QtCore.SIGNAL("released()"), \
610                             self.stopMotors)
611               
612               
613                self.connect(self.pushButtonNXTSearch, \
614                                  QtCore.SIGNAL("clicked()"), \
615                                  self.searchForDevices)
616               
617                self.connect(self.pushButtonNXTConnect, \
618                                  QtCore.SIGNAL("clicked()"), \
619                                  self.connectToBrainstormsServer)
620               
621               
622                self.connect(self.pushButtonConcentrationEnable, \
623                                  QtCore.SIGNAL("clicked()"), \
624                                  self.updateConcentrationButton)
625               
626                self.connect(self.pushButtonRelaxationEnable, \
627                                  QtCore.SIGNAL("clicked()"), \
628                                  self.updateRelaxationButton)
629               
630                self.connect(self.pushButtonSpeedEnable, \
631                                  QtCore.SIGNAL("clicked()"), \
632                                  self.updateSpeedButton)
633               
634               
635                self.connect(self.pushButtonNXTMessageOne, QtCore.SIGNAL("pressed()"), \
636                             self.sendMessageOne)
637               
638                self.connect(self.pushButtonNXTMessageTwo, QtCore.SIGNAL("pressed()"), \
639                             self.sendMessageTwo)
640               
641                self.connect(self.pushButtonNXTMessageThree, QtCore.SIGNAL("pressed()"), \
642                             self.sendMessageThree)
643               
644                self.connect(self.pushButtonNXTMessageFour, QtCore.SIGNAL("pressed()"), \
645                             self.sendMessageFour)
646               
647                self.connect(self.pushButtonNXTMessageFive, QtCore.SIGNAL("pressed()"), \
648                             self.sendMessageFive)
649               
650                self.connect(self.pushButtonNXTMessageSix, QtCore.SIGNAL("pressed()"), \
651                             self.sendMessageSix)
652               
653               
654               
655                # RC Helicopter Buttons
656                self.connect(self.pushButtonHelicopterSearch, \
657                                  QtCore.SIGNAL("clicked()"), \
658                                  self.searchForDevices)
659               
660                self.connect(self.pushButtonHelicopterConnect, \
661                                  QtCore.SIGNAL("clicked()"), \
662                                  self.connectToRCHelicopter)
663               
664               
665                self.connect(self.pushButtonHelicopterConcentrationEnable, \
666                                  QtCore.SIGNAL("clicked()"), \
667                                  self.updateHelicopterConcentrationButton)
668               
669                self.connect(self.pushButtonHelicopterRelaxationEnable, \
670                                  QtCore.SIGNAL("clicked()"), \
671                                  self.updateHelicopterRelaxationButton)
672               
673                self.connect(self.pushButtonHelicopterSpeedEnable, \
674                                  QtCore.SIGNAL("clicked()"), \
675                                  self.updateHelicopterSpeedButton)
676               
677               
678                self.connect(self.pushButtonHelicopterHover, \
679                                  QtCore.SIGNAL("clicked()"), \
680                                  self.enableHelicopterHover)
681               
682                self.connect(self.pushButtonHelicopterFlyForward, \
683                                  QtCore.SIGNAL("clicked()"), \
684                                  self.enableHelicopterFlyForward)
685               
686                self.connect(self.pushButtonHelicopterLand, \
687                                  QtCore.SIGNAL("clicked()"), \
688                                  self.landHelicopter)
689               
690               
691               
692                # Control Panel Buttons
693                self.connect(self.pushButtonMessageOne, QtCore.SIGNAL("pressed()"), \
694                             self.sendMessageOne)
695               
696                self.connect(self.pushButtonMessageTwo, QtCore.SIGNAL("pressed()"), \
697                             self.sendMessageTwo)
698               
699                self.connect(self.pushButtonMessageThree, QtCore.SIGNAL("pressed()"), \
700                             self.sendMessageThree)
701               
702                self.connect(self.pushButtonMessageFour, QtCore.SIGNAL("pressed()"), \
703                             self.sendMessageFour)
704               
705                self.connect(self.pushButtonMessageFive, QtCore.SIGNAL("pressed()"), \
706                             self.sendMessageFive)
707               
708                self.connect(self.pushButtonMessageSix, QtCore.SIGNAL("pressed()"), \
709                             self.sendMessageSix)
710               
711               
712                self.connect(self.pushButtonThinkGearConnect, \
713                                  QtCore.SIGNAL("clicked()"), \
714                                  self.connectToThinkGearHost)
715               
716                self.connect(self.pushButtonSendFeedback, \
717                                  QtCore.SIGNAL("clicked()"), \
718                                  self.sendFeedback)
719               
720               
721                #shortcut = QtGui.QShortcut(self)
722                #shortcut.setKey(tr("Down"))
723                #self.connect(shortcut, QtCore.SIGNAL("pressed()"), self.driveReverse)
724               
725               
726                action = QtGui.QAction(self)
727                action.setShortcut(QtGui.QKeySequence("W"))
728                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
729                self.addAction(action)
730               
731                action = QtGui.QAction(self)
732                action.setShortcut(QtGui.QKeySequence("Up"))
733                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonForward, QtCore.SLOT("animateClick()"))
734                self.addAction(action)
735               
736               
737                action = QtGui.QAction(self)
738                action.setShortcut(QtGui.QKeySequence("Left"))
739                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
740                self.addAction(action)
741               
742                action = QtGui.QAction(self)
743                action.setShortcut(QtGui.QKeySequence("A"))
744                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeft, QtCore.SLOT("animateClick()"))
745                self.addAction(action)
746               
747               
748                action = QtGui.QAction(self)
749                action.setShortcut(QtGui.QKeySequence("S"))
750                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
751                self.addAction(action)
752               
753                action = QtGui.QAction(self)
754                action.setShortcut(QtGui.QKeySequence("Down"))
755                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonReverse, QtCore.SLOT("animateClick()"))
756                self.addAction(action)
757               
758               
759                action = QtGui.QAction(self)
760                action.setShortcut(QtGui.QKeySequence("D"))
761                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
762                self.addAction(action)
763               
764                action = QtGui.QAction(self)
765                action.setShortcut(QtGui.QKeySequence("Right"))
766                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRight, QtCore.SLOT("animateClick()"))
767                self.addAction(action)
768               
769               
770                action = QtGui.QAction(self)
771                action.setShortcut(QtGui.QKeySequence("Z"))
772                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnLeftReverse, QtCore.SLOT("animateClick()"))
773                self.addAction(action)
774               
775               
776                action = QtGui.QAction(self)
777                action.setShortcut(QtGui.QKeySequence("C"))
778                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonTurnRightReverse, QtCore.SLOT("animateClick()"))
779                self.addAction(action)
780               
781               
782                # Control Panel Buttons
783               
784                action = QtGui.QAction(self)
785                action.setShortcut(QtGui.QKeySequence("1"))
786                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageOne, QtCore.SLOT("animateClick()"))
787                self.addAction(action)
788               
789                action = QtGui.QAction(self)
790                action.setShortcut(QtGui.QKeySequence("2"))
791                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageTwo, QtCore.SLOT("animateClick()"))
792                self.addAction(action)
793               
794                action = QtGui.QAction(self)
795                action.setShortcut(QtGui.QKeySequence("3"))
796                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageThree, QtCore.SLOT("animateClick()"))
797                self.addAction(action)
798               
799                action = QtGui.QAction(self)
800                action.setShortcut(QtGui.QKeySequence("4"))
801                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFour, QtCore.SLOT("animateClick()"))
802                self.addAction(action)
803               
804                action = QtGui.QAction(self)
805                action.setShortcut(QtGui.QKeySequence("5"))
806                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageFive, QtCore.SLOT("animateClick()"))
807                self.addAction(action)
808               
809                action = QtGui.QAction(self)
810                action.setShortcut(QtGui.QKeySequence("6"))
811                self.connect(action, QtCore.SIGNAL("activated()"), self.pushButtonNXTMessageSix, QtCore.SLOT("animateClick()"))
812                self.addAction(action)
813               
814               
815                #self.pushButtonForward.setAutoRepeat(False)
816                #self.pushButtonForward.setAutoRepeatDelay(0)
817                #self.pushButtonForward.setAutoRepeatInterval(0)
818       
819       
820        ##################################################################
821       
822        def searchForDevices(self):
823               
824                nxt_devices = []
825                rc_helicopter_devices = []
826               
827                #if (sys.platform != 'win32'):
828                if False: # temporarily disabled
829                       
830                        # Bluetooth module doesn't compile properly under Windows
831                       
832                        bluetooth_devices = []
833                       
834                        try:
835                                bluetooth_devices = bluetooth.discover_devices( \
836                                                       duration=5, \
837                                                       flush_cache=True, \
838                                                       lookup_names=False)
839                        except:
840                                #command = '%s con' % PATH_TO_HCITOOL
841                                command = '%s scan' % PATH_TO_HCITOOL
842                               
843                                output = os.popen(command, 'r')
844                               
845                                for line in output.readlines():
846                                        print line
847                                        try:
848                                                address = line.split(' ')[2]
849                                        except:
850                                                pass
851                                        else:
852                                                bluetooth_devices.append(address)
853                       
854                        for address in bluetooth_devices:
855                                device_name = bluetooth.lookup_name(address)
856                                if ((device_name == 'NXT') and \
857                                    (address not in nxt_devices)):
858                                        nxt_devices.append(address)
859                       
860                       
861                        if self.DEBUG:
862                                print "Bluetooth NXT devices found:",
863                                print nxt_devices
864               
865               
866                # List all serial devices
867                serial_devices = self.enumerateSerialPorts()
868               
869                for serial_device in serial_devices:
870                        #serial_device = self.fullPortName(serial_device)
871                        nxt_devices.append(serial_device)
872                        rc_helicopter_devices.append(serial_device)
873               
874               
875                # Configure combo boxes
876                if nxt_devices == []:
877                        nxt_devices.append('N/A')
878               
879                if rc_helicopter_devices == []:
880                        rc_helicopter_devices.append('N/A')
881               
882               
883                # Don't reset combo boxes if already connected
884                if self.pushButtonNXTConnect.text != 'Disconnect':
885                       
886                        self.comboBoxNXTPortSelect.clear()
887                       
888                        #nxt_devices.reverse()
889                        for nxt_device in nxt_devices:
890                                self.comboBoxNXTPortSelect.addItem(nxt_device)
891               
892               
893                if self.pushButtonHelicopterConnect.text != 'Disconnect':
894                       
895                        self.comboBoxHelicopterPortSelect.clear()
896                       
897                        #rc_helicopter_devices.reverse()
898                        for rc_helicopter in rc_helicopter_devices:
899                                self.comboBoxHelicopterPortSelect.addItem(rc_helicopter)
900       
901       
902        ##################################################################
903       
904        def enumerateSerialPorts(self):
905               
906                """ Uses the Win32 registry to return an
907                iterator of serial (COM) ports
908                existing on this computer.
909               
910                from http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
911                """
912               
913                serial_ports = []
914               
915                if (sys.platform == 'win32'):
916                       
917                        path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
918                        try:
919                                key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
920                        except WindowsError:
921                                #raise IterationError
922                                #return
923                                pass
924                       
925                        for i in itertools.count():
926                                try:
927                                        val = winreg.EnumValue(key, i)
928                                        #yield str(val[1])
929                                        serial_ports.append( str(val[1]) )
930                                except EnvironmentError:
931                                        break
932               
933               
934                else:
935                       
936                        if os.path.exists(DEVICE_PATH):
937                                device_list = os.listdir(DEVICE_PATH)
938                               
939                                device_list.sort()
940                       
941                                for device in device_list:
942                                        if device.startswith('ttyUSB'):
943                                                serial_ports.append( DEVICE_PATH + '/' + device )
944                                        if device.startswith('rfcomm'):
945                                                serial_ports.append( DEVICE_PATH + '/' + device )
946                                        if device.startswith('ttyACM'):
947                                                serial_ports.append( DEVICE_PATH + '/' + device )
948                                        if device.startswith('ttyS'):
949                                                serial_ports.append( DEVICE_PATH + '/' + device )
950               
951               
952                return(serial_ports)
953       
954       
955        ##################################################################
956       
957        def fullPortName(self, portname):
958               
959                """ Given a port-name (of the form COM7,
960                COM12, CNCA0, etc.) returns a full
961                name suitable for opening with the
962                Serial class.
963                """
964               
965                m = re.match('^COM(\d+)$', portname)
966                if m and int(m.group(1)) < 10:
967                        return portname
968               
969                return '\\\\.\\' + portname
970       
971       
972        ##################################################################
973       
974        def turnLeft(self):
975                self.brainstormsClient.sendCommand('turn_left')
976                self.drive_state = 'turn_left'
977       
978        def driveForward(self):
979                #if self.DEBUG:
980                        #print "driveForward"
981                self.pushButtonForward.setDown(True)
982                if (self.drive_state != 'drive_forward'):
983                        self.updateNXTSpeed(new_speed=DEFAULT_NXT_POWER_LEVEL)
984                self.brainstormsClient.sendCommand('drive_forward', power=self.current_speed)
985                self.drive_state = 'drive_forward'
986       
987        def turnRight(self):
988                self.brainstormsClient.sendCommand('turn_right')
989                self.drive_state = 'turn_right'
990       
991        def turnLeftInReverse(self):
992                self.brainstormsClient.sendCommand('turn_left_in_reverse')
993                self.drive_state = 'turn_left_in_reverse'
994       
995        def driveReverse(self):
996                self.brainstormsClient.sendCommand('drive_reverse')
997                self.drive_state = 'drive_reverse'
998       
999        def turnRightInReverse(self):
1000                self.brainstormsClient.sendCommand('turn_right_in_reverse')
1001                self.drive_state = 'turn_right_in_reverse'
1002       
1003        def stopMotors(self):
1004                self.pushButtonForward.setDown(False)
1005                if (self.current_speed != 0):
1006                        self.updateNXTSpeed(new_speed=0)
1007                if self.brainstormsClient != None:
1008                        self.brainstormsClient.sendCommand('stop_motors')
1009                self.drive_state = 'stop_motors'
1010       
1011        def sendMessageOne(self):
1012                message = str(self.lineEditMessageOne.text())
1013                self.brainstormsClient.sendCommand('send_message_1')
1014       
1015        def sendMessageTwo(self):
1016                message = str(self.lineEditMessageTwo.text())
1017                self.brainstormsClient.sendCommand('send_message_2')
1018       
1019        def sendMessageThree(self):
1020                message = str(self.lineEditMessageThree.text())
1021                self.brainstormsClient.sendCommand('send_message_3')
1022       
1023        def sendMessageFour(self):
1024                message = str(self.lineEditMessageFour.text())
1025                self.brainstormsClient.sendCommand('send_message_4')
1026       
1027        def sendMessageFive(self):
1028                message = str(self.lineEditMessageFive.text())
1029                self.brainstormsClient.sendCommand('send_message_5')
1030       
1031        def sendMessageSix(self):
1032                message = str(self.lineEditMessageSix.text())
1033                self.brainstormsClient.sendCommand('send_message_6')
1034       
1035       
1036        ##################################################################
1037       
1038        def enableHelicopterHover(self):
1039               
1040                print "enable Hover"
1041               
1042                self.disconnect(self.pushButtonHelicopterHover, \
1043                                                        QtCore.SIGNAL("clicked()"), \
1044                                                        self.enableHelicopterHover)
1045               
1046                self.connect(self.pushButtonHelicopterHover, \
1047                                  QtCore.SIGNAL("clicked()"), \
1048                                  self.disableHelicopterHover)
1049               
1050                if self.pushButtonHelicopterFlyForward.isChecked():
1051                        self.pushButtonHelicopterFlyForward.toggle()
1052                        self.disableHelicopterFlyForward()
1053       
1054       
1055        ##################################################################
1056       
1057        def disableHelicopterHover(self):
1058               
1059                print "disable Hover"
1060               
1061                self.disconnect(self.pushButtonHelicopterHover, \
1062                                                        QtCore.SIGNAL("clicked()"), \
1063                                                        self.disableHelicopterHover)
1064               
1065                self.connect(self.pushButtonHelicopterHover, \
1066                                  QtCore.SIGNAL("clicked()"), \
1067                                  self.enableHelicopterHover)
1068       
1069       
1070        ##################################################################
1071       
1072        def enableHelicopterFlyForward(self):
1073               
1074                print "enable Fly"
1075               
1076                self.disconnect(self.pushButtonHelicopterFlyForward, \
1077                                                        QtCore.SIGNAL("clicked()"), \
1078                                                        self.enableHelicopterFlyForward)
1079               
1080                self.connect(self.pushButtonHelicopterFlyForward, \
1081                                  QtCore.SIGNAL("clicked()"), \
1082                                  self.disableHelicopterFlyForward)
1083               
1084                if self.pushButtonHelicopterHover.isChecked():
1085                        self.pushButtonHelicopterHover.toggle()
1086                        self.disableHelicopterHover()
1087       
1088       
1089        ##################################################################
1090       
1091        def disableHelicopterFlyForward(self):
1092               
1093                print "disable Fly"
1094               
1095                self.disconnect(self.pushButtonHelicopterFlyForward, \
1096                                                        QtCore.SIGNAL("clicked()"), \
1097                                                        self.disableHelicopterFlyForward)
1098               
1099                self.connect(self.pushButtonHelicopterFlyForward, \
1100                                  QtCore.SIGNAL("clicked()"), \
1101                                  self.enableHelicopterFlyForward)
1102       
1103       
1104        ##################################################################
1105       
1106        def landHelicopter(self):
1107               
1108                print "land"
1109               
1110                if self.pushButtonHelicopterHover.isChecked():
1111                        self.pushButtonHelicopterHover.toggle()
1112                        self.disableHelicopterHover()
1113                if self.pushButtonHelicopterFlyForward.isChecked():
1114                        self.pushButtonHelicopterFlyForward.toggle()
1115                        self.disableHelicopterFlyForward()
1116       
1117       
1118        ##################################################################
1119       
1120       
1121        def updateNXTSpeed(self, new_speed=None):
1122               
1123                if new_speed == None:
1124               
1125                        concentration=self.progressBarConcentration.value()
1126                        relaxation=self.progressBarRelaxation.value()
1127                       
1128                        new_speed = self.calculateSpeed(concentration, relaxation)
1129               
1130               
1131                # Update GUI
1132                if self.pushButtonSpeedEnable.isChecked():
1133                        self.progressBarSpeed.setValue(new_speed)
1134               
1135               
1136                # If there is a change between the new and current speeds
1137                # and either the robot is currently driving forward
1138                # or the "speed control" button is enabled,
1139                # then send the updated speed to the robot
1140                if ((self.current_speed != new_speed) and \
1141                         ((self.drive_state == 'drive_forward') or \
1142                          (self.pushButtonSpeedEnable.isChecked()))):
1143                       
1144                        if (new_speed == 0):
1145                                self.current_speed = new_speed
1146                                self.stopMotors()
1147                        else:
1148                                if ((self.brainstormsClient != None) and \
1149                                    (self.pushButtonSpeedEnable.isChecked())):
1150                                        self.pushButtonForward.setDown(True)
1151                                        self.brainstormsClient.sendCommand('drive_forward', power=new_speed)
1152               
1153               
1154                self.current_speed = new_speed
1155       
1156       
1157        ##################################################################
1158       
1159        def updateHelicopterSpeed(self, new_speed=None):
1160               
1161                if new_speed == None:
1162               
1163                        concentration=self.progressBarHelicopterConcentration.value()
1164                        relaxation=self.progressBarHelicopterRelaxation.value()
1165                       
1166                        new_speed = self.calculateSpeed(concentration, relaxation)
1167               
1168               
1169                # Update GUI
1170                if self.pushButtonHelicopterSpeedEnable.isChecked():
1171                        self.progressBarHelicopterSpeed.setValue(new_speed)
1172               
1173               
1174                self.current_speed = new_speed
1175       
1176       
1177        ##################################################################
1178       
1179        def calculateSpeed(self, concentration, relaxation):
1180               
1181                speed = 0
1182               
1183                thresholds = THINKGEAR_POWER_THRESHOLDS
1184               
1185                match = int(concentration)
1186               
1187                while ((match not in thresholds['concentration'].keys()) and \
1188                            (match >= 0)):
1189                        match -= 1
1190               
1191               
1192                if match in thresholds['concentration'].keys():
1193                        speed = thresholds['concentration'][match]
1194               
1195               
1196                match = int(relaxation)
1197               
1198                while ((match not in thresholds['relaxation'].keys()) and \
1199                            (match >= 0)):
1200                        match -= 1
1201               
1202                if match in thresholds['relaxation'].keys():
1203                        speed = speed + thresholds['relaxation'][match]
1204               
1205               
1206                # LEGO Mindstorms power settings cannot exceed 100
1207                # and don't drive well with levels less than 50
1208                if (speed > 100):
1209                        speed = 100
1210                elif (speed < 50):
1211                        speed = 0
1212               
1213               
1214                return(speed)
1215       
1216       
1217        ##################################################################
1218       
1219        def processPacketThinkGear(self, packet):
1220               
1221                if ('eSense' in packet.keys()):
1222                       
1223                        if ('attention' in packet['eSense'].keys()):
1224                                if self.pushButtonConcentrationEnable.isChecked():
1225                                        self.progressBarConcentration.setValue(packet['eSense']['attention'])
1226                                if self.pushButtonHelicopterConcentrationEnable.isChecked():
1227                                        self.progressBarHelicopterConcentration.setValue(packet['eSense']['attention'])
1228                       
1229                        if ('meditation' in packet['eSense'].keys()):
1230                                if self.pushButtonRelaxationEnable.isChecked():
1231                                        self.progressBarRelaxation.setValue(packet['eSense']['meditation'])
1232                                if self.pushButtonHelicopterRelaxationEnable.isChecked():
1233                                        self.progressBarHelicopterRelaxation.setValue(packet['eSense']['meditation'])
1234               
1235               
1236                self.updateNXTSpeed()
1237                self.updateHelicopterSpeed()
1238       
1239       
1240        ##################################################################
1241
1242        def sendFeedback(self):
1243               
1244                values = {}
1245
1246                values['name'] = str(self.lineEditFeedbackName.text())
1247                values['email'] = str(self.lineEditFeedbackEmail.text())
1248                values['comment'] = str(self.textEditFeedback.toPlainText())
1249               
1250                values['subject'] = '[brainstorms feedback]'
1251                values['capcha_contact'] = 'brainstorms'
1252               
1253               
1254                url_data = urllib.urlencode(values)
1255               
1256                try:
1257                        page = urllib.urlopen(BRAINSTORMS_FEEDBACK_URL, url_data)
1258                       
1259                        reply = QtGui.QMessageBox.information( \
1260                              self, \
1261                              'Feedback Sent', \
1262                              'Thank you for your feedback', \
1263                              'OK')
1264                       
1265                        self.lineEditFeedbackName.setText('')
1266                        self.lineEditFeedbackEmail.setText('')
1267                        self.textEditFeedback.setText('')
1268               
1269                except:
1270                        reply = QtGui.QMessageBox.information( \
1271                              self, \
1272                              'Feedback Sent', \
1273                              'We\'re sorry but there was an error submitting your feedback.\nPlease email contact@puzzlebox.info instead.', \
1274                              'OK')
1275       
1276       
1277        ##################################################################
1278       
1279        def closeEvent(self, event):
1280               
1281                quit_message = "Are you sure you want to exit the program?"
1282               
1283                reply = QtGui.QMessageBox.question( \
1284                           self, \
1285                          'Quit Puzzlebox Brainstorms', \
1286                           quit_message, \
1287                           QtGui.QMessageBox.Yes, \
1288                           QtGui.QMessageBox.No)
1289               
1290                if reply == QtGui.QMessageBox.Yes:
1291                       
1292                        if self.brainstormsClient != None:
1293                                self.stopMotors()
1294                                self.brainstormsClient.socket.flush()
1295                               
1296                                if self.brainstormsServer != None:
1297                                       
1298                                        if self.brainstormsServer.rc == None:
1299                                               
1300                                                bluetooth_device = str(self.comboBoxNXTPortSelect.currentText())
1301                                                self.brainstormsServer.executeCommand( \
1302                                                        'stop_motors', \
1303                                                        bluetooth_device=bluetooth_device)
1304                                               
1305                                        else:
1306                                                self.brainstormsServer.rc.run('stop_motors')
1307                       
1308                       
1309                        event.accept()
1310               
1311                else:
1312                        event.ignore()
1313
1314
1315#####################################################################
1316# Functions
1317#####################################################################
1318
1319#####################################################################
1320# Main
1321#####################################################################
1322
1323if __name__ == '__main__':
1324       
1325        #log = puzzlebox_logger.puzzlebox_logger(logfile='client_interface')
1326        log = None
1327       
1328        app = QtGui.QApplication(sys.argv)
1329       
1330        window = puzzlebox_brainstorms_client_interface(log, DEBUG)
1331        window.show()
1332       
1333        sys.exit(app.exec_())
1334
Note: See TracBrowser for help on using the repository browser.