def __init__(self, parent=None):
        """
        :Parameters:
            parent : QObject
                The QT framework parent.
                Default=None
        """

        # super and ui setup
        super(SimulationGui, self).__init__(parent)
        self.setupUi(self)

        # internal member - simulation and event delegate
        self._sim_gui_handle = SimQt4Delegate(parent=self)
        self._sim = BaseSimulation(externals=[self._sim_gui_handle])
        self._timer = QtCore.QTimer()

        # gui member - models
        self._log_model = QtGui.QStringListModel()
        self.lst_log.setModel(self._log_model)
        self._scene_model = QtGui.QStandardItemModel()
        self._trn_sim = QtGui.QStandardItem('Simulation')
        self._scene_model.appendRow(self._trn_sim)
        self._trn_ndata = QtGui.QStandardItem('NeuronData')
        self._scene_model.appendRow(self._trn_ndata)
        self._trn_nrn = QtGui.QStandardItem('Neurons')
        self._scene_model.appendRow(self._trn_nrn)
        self._trn_rec = QtGui.QStandardItem('Recorders')
        self._scene_model.appendRow(self._trn_rec)
        self._scene_model.setHorizontalHeaderLabels(['Name', 'Value'])
        self.tre_scene.setModel(self._scene_model)
        self._io_model = QtGui.QStandardItemModel()
        self.tre_output.setModel(self._io_model)

        # gui members - reusable dialogs
        self._err = QtGui.QErrorMessage.qtHandler()
        self.progress.setVisible(False)
        self.progress.reset()

        # connections - sim internals
        self._timer.timeout.connect(self._sim.simulate)

        # connections - control panel
        self.btn_reset.clicked.connect(self.on_input_cmdpnl_reset)
        self.btn_steps.clicked.connect(self.on_input_cmdpnl_steps)
        self.btn_timer.clicked.connect(self.on_input_cmdpnl_timer)
        self.cb_frame_size.activated.connect(self.on_input_cmdpnl_frame_size)
        self.cb_sample_rate.activated.connect(self.on_input_cmdpnl_sample_rate)

        # connections - scene dock
        self.btn_dscene_sc_load.clicked.connect(self.scene_load)
        self.btn_dscene_sc_save.clicked.connect(self.scene_save)
        self.btn_dscene_neuron.clicked.connect(self.scene_add_neuron)
        self.btn_dscene_neuron_data.clicked.connect(self.scene_add_neuron_data)
        self.btn_dscene_recorder.clicked.connect(self.scene_add_recorder)
        self.btn_dscene_refresh.clicked.connect(self.scene_build_model)
        self.btn_dscene_remove.clicked.connect(self.scene_remove)

        # connections - output dock
        self.btn_dio_restart.clicked.connect(self.io_restart)
        self.btn_dio_refresh.clicked.connect(self.io_build_model)

        # connections - actions
        self.actionAbout.triggered.connect(self.on_about)
        self.actionAbout_Qt.triggered.connect(self.on_about_qt)
        self.actionPreferences.triggered.connect(self.comming_soon)

        # init gui
        self.on_input_cmdpnl_reset()
class SimulationGui(QtGui.QMainWindow, Ui_SimGui):
    """a BaseSimulation instance with a control and info gui"""

    ## constructor

    def __init__(self, parent=None):
        """
        :Parameters:
            parent : QObject
                The QT framework parent.
                Default=None
        """

        # super and ui setup
        super(SimulationGui, self).__init__(parent)
        self.setupUi(self)

        # internal member - simulation and event delegate
        self._sim_gui_handle = SimQt4Delegate(parent=self)
        self._sim = BaseSimulation(externals=[self._sim_gui_handle])
        self._timer = QtCore.QTimer()

        # gui member - models
        self._log_model = QtGui.QStringListModel()
        self.lst_log.setModel(self._log_model)
        self._scene_model = QtGui.QStandardItemModel()
        self._trn_sim = QtGui.QStandardItem('Simulation')
        self._scene_model.appendRow(self._trn_sim)
        self._trn_ndata = QtGui.QStandardItem('NeuronData')
        self._scene_model.appendRow(self._trn_ndata)
        self._trn_nrn = QtGui.QStandardItem('Neurons')
        self._scene_model.appendRow(self._trn_nrn)
        self._trn_rec = QtGui.QStandardItem('Recorders')
        self._scene_model.appendRow(self._trn_rec)
        self._scene_model.setHorizontalHeaderLabels(['Name', 'Value'])
        self.tre_scene.setModel(self._scene_model)
        self._io_model = QtGui.QStandardItemModel()
        self.tre_output.setModel(self._io_model)

        # gui members - reusable dialogs
        self._err = QtGui.QErrorMessage.qtHandler()
        self.progress.setVisible(False)
        self.progress.reset()

        # connections - sim internals
        self._timer.timeout.connect(self._sim.simulate)

        # connections - control panel
        self.btn_reset.clicked.connect(self.on_input_cmdpnl_reset)
        self.btn_steps.clicked.connect(self.on_input_cmdpnl_steps)
        self.btn_timer.clicked.connect(self.on_input_cmdpnl_timer)
        self.cb_frame_size.activated.connect(self.on_input_cmdpnl_frame_size)
        self.cb_sample_rate.activated.connect(self.on_input_cmdpnl_sample_rate)

        # connections - scene dock
        self.btn_dscene_sc_load.clicked.connect(self.scene_load)
        self.btn_dscene_sc_save.clicked.connect(self.scene_save)
        self.btn_dscene_neuron.clicked.connect(self.scene_add_neuron)
        self.btn_dscene_neuron_data.clicked.connect(self.scene_add_neuron_data)
        self.btn_dscene_recorder.clicked.connect(self.scene_add_recorder)
        self.btn_dscene_refresh.clicked.connect(self.scene_build_model)
        self.btn_dscene_remove.clicked.connect(self.scene_remove)

        # connections - output dock
        self.btn_dio_restart.clicked.connect(self.io_restart)
        self.btn_dio_refresh.clicked.connect(self.io_build_model)

        # connections - actions
        self.actionAbout.triggered.connect(self.on_about)
        self.actionAbout_Qt.triggered.connect(self.on_about_qt)
        self.actionPreferences.triggered.connect(self.comming_soon)

        # init gui
        self.on_input_cmdpnl_reset()

    ## delegate event slots

    def on_update_info_internal(self, info):
        """update internal infos"""
        pass

    def on_update_info_ndata(self, info):
        """update neuron data infos"""
        pass

    def on_update_info_neuron(self, info):
        """update neuron infos"""
        pass

    def on_update_info_recorder(self, info):
        """update recorder infos"""
        pass

    def on_update_info_complete(self, info):
        """update complete infos"""
        pass

    @QtCore.pyqtSlot(str)
    def on_append_log(self, log_str):
        """log a sting"""

        if self._log_model.rowCount() > LOG_BUF_LEN:
            self._log_model.removeRow(0)
        self._log_model.insertRow(self._log_model.rowCount())
        self._log_model.setData(
            self._log_model.index(self._log_model.rowCount() - 1),
            str(log_str)
        )
        self.lst_log.scrollTo(
            self._log_model.index(self._log_model.rowCount() - 1)
        )

    @QtCore.pyqtSlot(long)
    def on_update_frame(self, frame):
        """update frame index"""

        self.edt_frame.setText(str(frame))

    @QtCore.pyqtSlot(int)
    def on_update_frame_size(self, frame_size):
        """update frame size"""

        if self.cb_frame_size.findText(str(frame_size)) < 0:
            self.cb_frame_size.addItem(str(frame_size))
        self.cb_frame_size.setCurrentIndex(
            self.cb_frame_size.findText(str(frame_size))
        )

    @QtCore.pyqtSlot(float)
    def on_update_sample_rate(self, sample_rate):
        """update sample rate"""

        if self.cb_sample_rate.findText(str(sample_rate)) < 0:
            self.cb_sample_rate.addItem(str(sample_rate))
        self.cb_sample_rate.setCurrentIndex(
            self.cb_sample_rate.findText(str(sample_rate))
        )

    ## gui user input slots - command panel

    @QtCore.pyqtSlot(int)
    def on_input_cmdpnl_frame_size(self, inp):

        try:
            self._sim.frame_size = float(self.cb_frame_size.itemText(inp))
        finally:
            self.cb_frame_size.clearFocus()
            self.scene_build_model()

    @QtCore.pyqtSlot(int)
    def on_input_cmdpnl_sample_rate(self, inp):

        try:
            self._sim.sample_rate = float(self.cb_sample_rate.itemText(inp))
        finally:
            self.cb_sample_rate.clearFocus()
            self.scene_build_model()

    @QtCore.pyqtSlot()
    def on_input_cmdpnl_reset(self):

        if self._timer.isActive():
            self.on_input_cmdpnl_timer()
        self._log_model.removeRows(0, self._log_model.rowCount())
        self._sim.initialize()
        self.scene_build_model()
        self.io_build_model()

    @QtCore.pyqtSlot()
    def on_input_cmdpnl_steps(self):

        try:
            nframes = int(self.edt_steps.text())
        except:
            return

        # progress dialog for longer stuff
        self.progress.reset()
        self.progress.setRange(0, nframes)
        self.progress.setValue(0)
        self.progress.setVisible(True)

        for i in xrange(nframes):
            self._sim.simulate()
            self.progress.setValue(i + 1)
        self.progress.reset()
        self.progress.setVisible(False)

    @QtCore.pyqtSlot()
    def on_input_cmdpnl_timer(self):
        if self._timer.isActive():
            # stop timer
            self._timer.stop()
            self._set_enabled(True)
            self.btn_timer.setText('Start Timer')
            self.on_append_log('Timer stopped!')
        else:
            # start timer
            try:
                step_size = int(self.edt_timer.text())
                self._timer.setInterval(step_size)
            except:
                return
            self._set_enabled(False)
            self.btn_timer.setText('Stop Timer')
            self.on_append_log('Timer started!')
            self._timer.start()

    ## scene dock slots

    @QtCore.pyqtSlot()
    def scene_add_neuron_data(self):

        try:
            # chose files
            rval = QtGui.QFileDialog.getOpenFileNames(
                self,
                'Select one or more archives to open'
            )
            if len(rval) == 0:
                return
            rval = map(str, rval)

            # progress dialog
            self.progress.reset()
            self.progress.setRange(0, len(rval))
            self.progress.setValue(0)
            self.progress.setVisible(True)

            # load neuron data
            nfiles = self._sim.neuron_data.insert(rval)
            self.progress.setValue(self.progress.value() + 1)
            self.progress.reset()
            self.progress.setVisible(False)
            self.scene_build_model()
            QtGui.QMessageBox.information(
                self,
                'Info',
                'found %d neuron data archives' % nfiles
            )

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_add_neuron(self):

        try:

            # do we have neuron data?
            if len(self._sim.neuron_data) == 0:
                QtGui.QMessageBox.warning(
                    self,
                    'REMINDER',
                    'No NeuronData loaded! Please load NeuronData first.'
                )
                return

            # user input
            dialog = AddNeuronDialog(self, self._sim.neuron_data)
            dialog.show()
            dialog.raise_()
            dialog.activateWindow()
            if dialog.exec_() == 0:
                return

            # build parameters
            kwargs = {}
            if str(dialog.edt_name.text()) != '':
                val = str(dialog.edt_name.text())
                kwargs.update(name=val)
            if str(dialog.edt_position.text()) != '':
                val = map(float, str(dialog.edt_position.text()).split(' '))
                kwargs.update(position=val)
            if str(dialog.edt_orientation.text()) != '':
                val = str(dialog.edt_orientation.text())
                if val.lower() == 'false':
                    val = False
                elif val.lower() == 'true':
                    val = True
                else:
                    val = map(float, val.split(' '))
                kwargs.update(orientation=val)
            kwargs.update(neuron_data=str(dialog.cb_data.currentText()))
            if str(dialog.edt_frate.text()) != '':
                val = float(dialog.edt_frate.text())
                kwargs.update(rate_of_fire=val)
            if str(dialog.edt_ampl.text()) != '':
                val = float(dialog.edt_ampl.text())
                kwargs.update(amplitude=val)
            if str(dialog.edt_cluster.text()) != '':
                val = int(dialog.edt_cluster.text())
                kwargs.update(cluster=val)

            # build neuron
            rval = self._sim.register_neuron(**kwargs)
            self.scene_build_model()
            QtGui.QMessageBox.information(
                self,
                'Neuron added',
                'Neuron: %s\n\nCalled with:\n%s' % (rval, kwargs)
            )

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_add_recorder(self):

        try:

            # user input
            dialog = AddRecorderDialog(self)
            dialog.show()
            dialog.raise_()
            dialog.activateWindow()
            if dialog.exec_() == 0:
                return

            # build parameters
            kwargs = {}
            if str(dialog.edt_name.text()) != '':
                val = str(dialog.edt_name.text())
                kwargs.update(name=val)
            if str(dialog.edt_position.text()) != '':
                val = map(float, str(dialog.edt_position.text()).split(' '))
                kwargs.update(position=val)
            if str(dialog.edt_orientation.text()) != '':
                val = map(float, str(dialog.edt_orientation.text()).split(' '))
                kwargs.update(orientation=val)
            if str(dialog.edt_snr.text()) != '':
                val = float(dialog.edt_snr.text())
                kwargs.update(snr=val)

            # build recorder
            rval = self._sim.register_recorder(**kwargs)
            self.scene_build_model()
            QtGui.QMessageBox.information(
                self,
                'Recorder added',
                'Recorder: %s\n\nCalled with:\n%s' % (rval, kwargs)
            )

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_load(self):

        try:

            rval = str(QtGui.QFileDialog.getOpenFileName(self))
            if rval == '' or rval == 'None' or rval is None:
                return
            self._sim.scene_config_load(rval)
            self.scene_build_model()

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_save(self):

        try:

            rval = str(QtGui.QFileDialog.getSaveFileName(self))
            if rval == '' or rval == 'None' or rval is None:
                return
            self._sim.scene_config_save(rval)

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_remove(self):

        try:

            # get model index
            try:
                idx = self.tre_scene.selectedIndexes()[0]
                sel_node = self._scene_model.itemFromIndex(idx)
            except:
                return

            # find corret parent node
            rm_node = None
            if sel_node.type() in [1001, 1002]:
                rm_node = sel_node
            else:
                if sel_node.parent() is not None:
                    if sel_node.parent().type() in [1001, 1002]:
                        rm_node = sel_node.parent()
            if rm_node is None:
                return

            # find neuron for node
            for key, obj in self._sim.items():
                if obj.name == str(rm_node.child(0, 1).text()):
                    break

            # remove
            if self._sim.remove_object(key) is False:
                raise ValueError('deletion was not successfull :(')
            self.scene_build_model()

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def scene_build_model(self):

        try:

            # sim
            self._trn_sim.removeRows(0, self._trn_sim.rowCount())
            self._trn_sim.appendRow([
                QtGui.QStandardItem('Name'),
                QtGui.QStandardItem(str(self._sim))
            ])
            self._trn_sim.appendRow([
                QtGui.QStandardItem('Sample Rate'),
                QtGui.QStandardItem(str(self._sim.sample_rate))
            ])
            self._trn_sim.appendRow([
                QtGui.QStandardItem('Current Frame'),
                QtGui.QStandardItem(str(self._sim.frame))
            ])
            self._trn_sim.appendRow([
                QtGui.QStandardItem('Frame Size'),
                QtGui.QStandardItem(str(self._sim.frame_size))
            ])
            dbg = QtGui.QStandardItem('#DEBUG#')
            for k in self._sim.__dict__.keys():
                dbg.appendRow([
                    QtGui.QStandardItem(str(k)),
                    QtGui.QStandardItem(str(self._sim.__dict__[k]))
                ])
            self._trn_sim.appendRow(dbg)
            # TODO: more usefull infos from sim?!

            # neuron data cache
            self._trn_ndata.removeRows(0, self._trn_ndata.rowCount())
            for k in self._sim.neuron_data.keys():
                ndata_node = QtGui.QStandardItem(str(k))
                ndata = self._sim.neuron_data[k]
                dbg = QtGui.QStandardItem('#DEBUG#')
                for key, value in ndata.__dict__.items():
                    dbg.appendRow([
                        QtGui.QStandardItem(str(key)),
                        QtGui.QStandardItem(str(value))
                    ])
                ndata_node.appendRow(dbg)
                self._trn_ndata.appendRow(ndata_node)

            # neurons
            self._trn_nrn.removeRows(0, self._trn_nrn.rowCount())
            for nrn_key in self._sim.neuron_keys:

                n = self._sim[nrn_key]
                nrn = NeuronNode(str(n))
                self._trn_nrn.appendRow(nrn)
                nrn.appendRow([
                    QtGui.QStandardItem('Name'),
                    QtGui.QStandardItem(str(n.name))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Ident'),
                    QtGui.QStandardItem(str(nrn_key))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Position'),
                    QtGui.QStandardItem(str(n.position))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Orientation'),
                    QtGui.QStandardItem(str(n.orientation))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Rate of Fire'),
                    QtGui.QStandardItem(str(n.rate_of_fire))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Amplitude'),
                    QtGui.QStandardItem(str(n.amplitude))
                ])
                nrn.appendRow([
                    QtGui.QStandardItem('Active'),
                    QtGui.QStandardItem(str(n.active))
                ])
                dbg = QtGui.QStandardItem('#DEBUG#')
                for k in n.__dict__.keys():
                    dbg.appendRow([
                        QtGui.QStandardItem(str(k)),
                        QtGui.QStandardItem(str(n.__dict__[k]))
                    ])
                nrn.appendRow(dbg)

            # recorders
            self._trn_rec.removeRows(0, self._trn_rec.rowCount())
            for rec_key in self._sim.recorder_keys:

                r = self._sim[rec_key]
                rec = RecorderNode(str(r))
                self._trn_rec.appendRow(rec)
                rec.appendRow([
                    QtGui.QStandardItem('Name'),
                    QtGui.QStandardItem(str(r.name))
                ])
                rec.appendRow([
                    QtGui.QStandardItem('Ident'),
                    QtGui.QStandardItem(str(rec_key))
                ])
                rec.appendRow([
                    QtGui.QStandardItem('Position'),
                    QtGui.QStandardItem(str(r.position))
                ])
                rec.appendRow([
                    QtGui.QStandardItem('Orientation'),
                    QtGui.QStandardItem(str(r.orientation))
                ])
                rec.appendRow([
                    QtGui.QStandardItem('Active'),
                    QtGui.QStandardItem(str(r.active))
                ])
                rec.appendRow([
                    QtGui.QStandardItem('Points'),
                    QtGui.QStandardItem(str(r.points))
                ])
                dbg = QtGui.QStandardItem('#DEBUG#')
                for k in r.__dict__.keys():
                    dbg.appendRow([
                        QtGui.QStandardItem(str(k)),
                        QtGui.QStandardItem(str(r.__dict__[k]))
                    ])
                rec.appendRow(dbg)

        except:
            self.error_dialog()

    ## output dock slots

    @QtCore.pyqtSlot()
    def io_restart(self):

        try:

            self._sim.io_man.initialize()
            self.io_build_model()

        except:
            self.error_dialog()

    @QtCore.pyqtSlot()
    def io_build_model(self):

        try:

            self._io_model.clear()
            self._io_model.setHorizontalHeaderLabels(['Name', 'Value'])
            dbg = QtGui.QStandardItem('#DEBUG#')
            for k, v in self._sim.io_man.__dict__.items():
                dbg.appendRow([
                    QtGui.QStandardItem(str(k)),
                    QtGui.QStandardItem(str(v))
                ])
            self._io_model.appendRow(dbg)

        except:
            self.error_dialog()

    ## dialog spawners

    @QtCore.pyqtSlot()
    def on_about(self):
        QtGui.QMessageBox.about(
            self,
            'About Neural Simulation',
            """
            NEURAL SIMULATION

            (c) 2010 Philipp Meier

            Berlin Institute of Technology
            School for Electrical Engineering and Computer Science
            Neural Information Processing Group

            GNU Public License v3

            Software and source code available on request:
            pmeier82 [at] googlemail [dot] com
            """
        )

    @QtCore.pyqtSlot()
    def on_about_qt(self):

        QtGui.QMessageBox.aboutQt(self)

    @QtCore.pyqtSlot()
    def comming_soon(self):

        QtGui.QMessageBox.information(
            self,
            'Ooouuups..',
            'Coming soon..\n..promissed :-)'
        )

    def error_dialog(self):
        try:
#            from debug_helpers import print_top_100
#            print_top_100()
            ei = sys.exc_info()

            QtGui.QMessageBox.critical(
                self,
                'EXCEPTION',
                '\n'.join(traceback.format_exception(*ei))
            )
        finally:
            del ei
            sys.exc_clear()

    ## events

    def closeEvent(self, evt):

        if self._timer.isActive():
            self.on_input_cmdpnl_timer()
        self.on_append_log('')
        self.on_append_log('..shutting down!')
        self._sim.finalize()
        QtGui.QMessageBox.information(
            self,
            'Shutdown',
            'Shutdown was successful'
        )

    ## methods private

    def _set_enabled(self, toggle=True):

        # gui elements to toggle in a list
        gui_list = [
            self.gb_steps,
            self.edt_timer,
            self.cb_frame_size,
            self.cb_sample_rate
        ]
        gui_list.extend(self.findChildren(QtGui.QDockWidget))

        # set enabled state for components
        for gui_item in gui_list:
            try:
                gui_item.setEnabled(toggle)
            except:
                pass