Ejemplo n.º 1
0
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__(parent=parent)
        self.UI = Ui_MainWindow()
        self.UI.setupUi(self)

        self.add_to_log("OpenIMU - Prêt à travailler.", LogTypes.LOGTYPE_INFO)

        startWindow = StartWindow()

        if startWindow.exec() == QDialog.Rejected:
            # User closed the dialog - exits!
            exit(0)

        # Init database manager
        self.currentFileName = startWindow.fileName
        self.dbMan = DBManager(self.currentFileName)

        # Setup signals and slots
        self.setup_signals()

        # Maximize window
        self.showMaximized()

        # Load data
        self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO)
        self.currentDataSet = self.dbMan.get_dataset()
        self.load_data_from_dataset()
        self.UI.treeDataSet.setCurrentItem(None)

        # self.loadDemoData()
        self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE)

        # If we need to import data, show the import dialog
        if startWindow.importing:
            self.importRequested()
Ejemplo n.º 2
0
    def ok_clicked(self):
        # Create and save file
        db = DBManager(filename=self.UI.txtFileName.text())

        if self.dataSet is None:
            self.dataSet = DataSet()
            self.dataSet.creation_date = datetime.now()

        self.dataSet.name = self.UI.txtName.text()
        self.dataSet.description = self.UI.txtDesc.toPlainText()
        self.dataSet.author = self.UI.txtAuthor.text()

        self.dataSet.upload_date = self.UI.calendarUploadDate.selectedDate(
        ).toPyDate()

        db.set_dataset_infos(name=self.dataSet.name,
                             desc=self.dataSet.description,
                             author=self.dataSet.author,
                             creation_date=self.dataSet.creation_date,
                             upload_date=self.dataSet.upload_date)

        self.fileName = self.UI.txtFileName.text()

        if self.validate():
            self.accept()
Ejemplo n.º 3
0
    def test_get_all_sensors(self):

        manager = DBManager(filename='openimu.db', overwrite=True)

        # Sensor information
        id_sensor_type = SensorType.ACCELEROMETER
        name = 'Accelerometer'
        hw_name = 'OpenIMU-HW'
        location = 'wrist'
        sampling_rate = 30.0
        data_rate = 1
        count = 10

        sensors = []

        for i in range(0, count):
            sensors.append(
                manager.add_sensor(id_sensor_type, name, hw_name, location,
                                   sampling_rate, data_rate))

        all_sensors = manager.get_all_sensors()
        self.assertEqual(len(all_sensors), len(sensors))

        # Wrong type
        self.assertEqual(0, len(manager.get_all_sensors(SensorType.BATTERY)))

        # Compare content
        for i in range(0, count):
            self.assertEqual(sensors[i], all_sensors[i])
Ejemplo n.º 4
0
    def ok_clicked(self):
        # Only create file if validate
        if self.validate():

            try:
                # Create and save file
                db = DBManager(filename=self.UI.txtFileName.text(),
                               newfile=True)

                if self.dataSet is None:
                    self.dataSet = DataSet()
                    self.dataSet.creation_date = datetime.now()

                self.dataSet.name = self.UI.txtName.text()
                self.dataSet.description = self.UI.txtDesc.toPlainText()
                self.dataSet.author = self.UI.txtAuthor.text()
                self.dataSet.upload_date = self.UI.dateData.date().toPyDate()

                db.set_dataset_infos(name=self.dataSet.name,
                                     desc=self.dataSet.description,
                                     author=self.dataSet.author,
                                     creation_date=self.dataSet.creation_date,
                                     upload_date=self.dataSet.upload_date)

                self.fileName = self.UI.txtFileName.text()

                self.accept()

            except (DBAPIError, DataError, DatabaseError):
                print('Error!')
                box = QMessageBox()
                box.setText(
                    'Erreur de création de DB, s.v.p. choisir une répertoire valide'
                )
                box.exec()
Ejemplo n.º 5
0
    def test_get_all_participants(self):
        manager = DBManager(filename='openimu.db', overwrite=True)
        # This will add participants

        # Participant information
        group = manager.update_group(
            Group(name='My Group', description='My Group Description'))
        name = 'Participant Name'
        description = 'Participant Description'

        participants = []

        # Multiple participants, all the same info...
        for i in range(0, 10):
            participants.append(
                manager.update_participant(
                    Participant(name=name,
                                description=description,
                                group=group)))

        # Read back list of participants
        all_participants = manager.get_participants_for_group(group)

        # Compare size
        self.assertEqual(len(participants), len(all_participants))

        # Compare content
        for i in range(0, len(participants)):
            self.assertEqual(participants[i], all_participants[i])
Ejemplo n.º 6
0
    def show_start_window(self):
        self.clear_main_widgets()
        self.showMinimized()
        start_window = StartWindow(self)

        if start_window.exec() == QDialog.Rejected:
            # User closed the dialog - exits!
            sys.exit(0)

        # Init database manager
        self.currentFileName = start_window.fileName
        self.dbMan = DBManager(self.currentFileName)

        # Maximize window
        self.showMaximized()

        # Load data
        self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO)
        self.currentDataSet = self.dbMan.get_dataset()
        self.load_data_from_dataset()
        self.UI.treeDataSet.setCurrentItem(None)
        self.UI.treeDataSet.owner = self

        # self.loadDemoData()
        self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE)

        # If we need to import data, show the import dialog
        if start_window.importing:
            self.import_requested()
            gc.collect()
class ActigraphDBTest2(unittest.TestCase):
    @timing
    def setUp(self):
        np.set_printoptions(suppress=True)
        print(__file__ + ' Creating database')

        # Will read already existing file
        self.db = DBManager('actigraph.db', False, False)

    @timing
    def tearDown(self):
        self.db.commit()

    def test_read_all_participant(self):
        participants = self.db.get_all_participants()
        print(participants)
        for participant in participants:
            print(participant, participant.group)

    def test_read_all_data(self):
        recordsets = self.db.get_all_recordsets()

        for record in recordsets:
            all_data = self.db.get_all_sensor_data(record, convert=True)

            for data in all_data:
                for time in data.to_time_series()['time']:
                    print('time', time)
                break
 def setUp(self):
     np.set_printoptions(suppress=True)
     print(__file__ + ' Creating database')
     self.db = DBManager('actigraph.db', True, False)
     self.group = self.db.add_group('MyGroup', 'MyDescription')
     self.participant = self.db.add_participant(group=self.group,
                                                name='Anonymous',
                                                description='Participant')
Ejemplo n.º 9
0
    def test_add_group(self):
        manager = DBManager(filename=DBManagerTest.TESTDB_NAME, overwrite=True)

        # Group information
        group = Group(name='Group Name', description='Group Description')
        manager.update_group(group)

        group2 = manager.get_group(group.id_group)
        self.assertEqual(group.id_group, group2.id_group)
        self.assertEqual(group.name, group2.name)
Ejemplo n.º 10
0
    def test_load(self):
        manager = DBManager('test.db', overwrite=True)
        participant = Participant(name='My Participant', description='Participant Description')
        manager.update_participant(participant)

        # Import to database
        importer = OpenIMUImporter(manager, participant)
        results = importer.load('../../../resources/samples/openimu_sample.oimu')
        # print('results', results)
        importer.import_to_database(results)
Ejemplo n.º 11
0
    def test_add_channel(self):
        manager = DBManager(filename='openimu.db', overwrite=True)

        # Create sensor in DB
        sensor = manager.add_sensor(SensorType.ACCELEROMETER, 'Sensor Name',
                                    'Hardware Name', 'Wrist', 30.0, 1)
        channel = manager.add_channel(sensor, Units.GRAVITY_G,
                                      DataFormat.FLOAT32, 'Accelerometer_X')
        channel2 = manager.get_channel(channel.id_channel)
        self.assertEqual(channel, channel2)
Ejemplo n.º 12
0
    def test_load_zip_file():
        # Testing

        manager = DBManager('applewatch.oi', overwrite=True, newfile=True)
        participant = Participant(name='My Participant', description='Participant Description')
        manager.update_participant(participant)
        importer = AppleWatchImporter(manager, participant)
        results = importer.load('/Users/dominic/WA/OpenIMU.git/python/applewatch_data.zip')
        # print('results', results)
        importer.import_to_database(results)
Ejemplo n.º 13
0
def import_data_from_wimu_file(filename):
    # This will create the database (or overwrite it)s

    manager = DBManager(db_filename, overwrite=True)
    participant = Participant(name='My Participant', description='Participant Description')
    manager.update_participant(participant)

    importer = WIMUImporter(manager, participant)
    # Load content of the file to the database
    results = importer.load(filename)
    importer.import_to_database(results)
Ejemplo n.º 14
0
    def test_load_data_file():
        # Testing

        manager = DBManager('applewatch.oi', overwrite=True)
        participant = Participant(name='My Participant', description='Participant Description')
        manager.update_participant(participant)
        importer = AppleWatchImporter(manager, participant)

        results = importer.load('/Users/dominic/Documents/working_area/OpenIMU.git/python/watch_ProcessedMotion.data')
        # print('results', results)
        importer.import_to_database(results)
Ejemplo n.º 15
0
    def test_load_zip_file(self):
        # Testing

        manager = DBManager('applewatch.db', overwrite=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)
        importer = AppleWatchImporter(manager, participant)

        results = importer.load('../../../resources/samples/AppleWatch.zip')
        # print('results', results)
        importer.import_to_database(results)
Ejemplo n.º 16
0
    def test_loading(self):

        manager = DBManager('test.db', overwrite=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)

        # Import to database
        importer = ActigraphImporter(manager, participant)
        results = importer.load('../../../resources/samples/test.gt3x')

        samples = 0
        for activity in results[1]['activity']:
            samples += 3 * len(activity[1])

        print('samples imported (each channels)', samples)

        importer.import_to_database(results)

        # Reload from database
        manager = DBManager('test.db')

        recordsets = manager.get_all_recordsets()
        self.assertGreater(len(recordsets), 0)

        loaded_samples = 0

        for record in recordsets:
            # Get all sensors in record
            sensors = manager.get_all_sensors()
            for sensor in sensors:
                if sensor.id_sensor_type == SensorType.ACCELEROMETER:
                    channels = manager.get_all_channels(sensor=sensor)
                    for channel in channels:
                        print('processing channel: ', channel)
                        self.assertEqual(channel.id_sensor, sensor.id_sensor,
                                         "id_sensor test for channel")
                        # Will get all data (converted to floats)
                        channel_data = manager.get_all_sensor_data(
                            recordset=record, convert=True, channel=channel)
                        print('channel_data_length', len(channel_data))

                        for sensor_data in channel_data:
                            self.assertEqual(sensor_data.id_channel,
                                             channel.id_channel,
                                             "id_channel test for data")
                            self.assertEqual(sensor_data.id_sensor,
                                             sensor.id_sensor,
                                             "id_sensor test data")
                            loaded_samples += len(sensor_data.data)

        self.assertEqual(samples, loaded_samples)
Ejemplo n.º 17
0
    def import_data():

        manager = DBManager(db_filename)

        # Create participant
        participant = manager.update_participant(Participant(name='Participant', description='No description'))

        # Create importer
        importer = ActigraphImporter(manager, participant)

        # Load content of the file to the database
        results = importer.load('../../resources/samples/test.gt3x')
        importer.import_to_database(results)
Ejemplo n.º 18
0
    def calculate(self, manager: DBManager, recordsets: list):
        results = []

        for record in recordsets:
            # Get all sensors in record
            sensors = manager.get_all_sensors(
                id_sensor_type=SensorType.ACCELEROMETER)

            for sensor in sensors:
                # print('Found Accelerometer')
                channels = manager.get_all_channels(sensor=sensor)
                samples_num = 0
                # print('Found channels: ', channels)
                all_channels_data = {
                    'Accelerometer_X': [],
                    'Accelerometer_Y': [],
                    'Accelerometer_Z': []
                }
                for channel_index, channel in enumerate(channels):
                    # if channel.label == 'Accelerometer_Y':
                    # print('Processing Channel :', channel)
                    # Will get all data (converted to floats)
                    channel_data = manager.get_all_sensor_data(
                        recordset=record,
                        convert=True,
                        sensor=sensor,
                        channel=channel)
                    if len(channel_data) > 0:
                        for data in channel_data:
                            all_channels_data[channel.label].append(data)
                            if channel_index == 0:  # Compute number of samples total, if we are at the first channel
                                samples_num += len(data.data)

                if len(all_channels_data['Accelerometer_X']) > 0:
                    # Process all sensor data
                    result = {
                        'id_recordset':
                        record.id_recordset,
                        'result_name':
                        record.name + ' (' + sensor.location + '/' +
                        sensor.name + ')',
                        'id_sensor':
                        sensor.id_sensor,
                        'result':
                        self.do_calculation(all_channels_data,
                                            sensor.sampling_rate, samples_num)
                    }
                    results.append(result)

        # Return an array with results for each recordset
        return results
Ejemplo n.º 19
0
    def test_add_recordset(self):
        manager = DBManager(filename='openimu.db', overwrite=True, echo=False)

        # Participant information
        group = manager.update_group(
            Group(name='My Group', description='My Group Description'))
        name = 'Participant Name'
        description = 'Participant Description'
        participant = manager.update_participant(
            Participant(name=name, description=description, group=group))
        # This gives datetime from seconds from epoch
        time1 = datetime.datetime.fromtimestamp(
            datetime.datetime.now().timestamp())
        time2 = datetime.datetime.fromtimestamp(
            datetime.datetime.now().timestamp() + 1)
        recordset = manager.add_recordset(participant, 'Record Name', time1,
                                          time2)
        recordset2 = manager.get_recordset(recordset.id_recordset)

        self.assertGreater(recordset.id_recordset, 0)
        self.assertEqual(recordset.participant, participant)
        self.assertEqual(recordset.name, 'Record Name')
        self.assertEqual(recordset.start_timestamp, time1)
        self.assertEqual(recordset.end_timestamp, time2)
        self.assertEqual(recordset, recordset2)

        manager.close()
Ejemplo n.º 20
0
    def test_load(self):
        manager = DBManager('openimu.oi', overwrite=True, newfile=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)

        # Import to database
        importer = OpenIMUImporter(manager, participant)
        results = importer.load(
            '../../../resources/samples/openimu_sample.oimu')
        # results = importer.load('/Users/dominic/Desktop/35.DAT')
        # print('results', results)
        importer.import_to_database(results)

        self.assertTrue(True)
Ejemplo n.º 21
0
    def test_loading(self):
        manager = DBManager('test.db', overwrite=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)

        # Import to database
        importer = WIMUImporter(manager, participant)
        # results = importer.load('../../../resources/samples/WIMU_ACC_GPS_GYRO_PreProcess.zip')
        results = importer.load(
            '../../../resources/samples/REPAR_Sujet7_Semaine_T4.zip')
        importer.import_to_database(results)

        recordsets = manager.get_all_recordsets(participant)
        print('recordsets', recordsets)
        self.assertGreater(len(recordsets), 0)
Ejemplo n.º 22
0
    def test_load(self):
        manager = DBManager('openimu.oi', overwrite=True, newfile=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)

        # Import to database
        importer = OpenIMUImporter(manager, participant)
        results = importer.load(
            '../../../resources/samples/openimu_sample.oimu')

        # results = importer.load('/Volumes/MINILOGGER/log_20190101_000034/record_20190101_000034.mdat')
        # print('results', results)
        importer.import_to_database(results)

        self.assertTrue(True)
Ejemplo n.º 23
0
    def calculate(self, manager: DBManager, recordsets: list):
        print('FreedsonAdult1998.calculate')
        print('Using recordsets', recordsets)

        results = []

        for record in recordsets:
            # Get all sensors in record
            sensors = manager.get_all_sensors(
                id_sensor_type=SensorType.ACCELEROMETER)

            for sensor in sensors:
                # print('Found Accelerometer')
                channels = manager.get_all_channels(sensor=sensor)
                # print('Found channels: ', channels)
                for channel in channels:
                    if channel.label == 'Accelerometer_Y':
                        # print('Processing Channel :', channel)
                        # Will get all data (converted to floats)
                        channel_data = manager.get_all_sensor_data(
                            recordset=record,
                            convert=True,
                            sensor=sensor,
                            channel=channel)
                        if len(channel_data) > 0:
                            # Process all sensor data
                            result = {
                                'id_recordset':
                                record.id_recordset,
                                'result_name':
                                record.name + ' (' + sensor.location + '/' +
                                sensor.name + ')',
                                'id_sensor':
                                sensor.id_sensor,
                                'result':
                                freedson_adult_1998(channel_data,
                                                    sensor.sampling_rate)
                            }
                            results.append(result)

        # Return an array with results for each recordset
        return results
Ejemplo n.º 24
0
    def test_add_sensor(self):
        manager = DBManager(filename='openimu.db', overwrite=True)

        # Sensor information
        id_sensor_type = SensorType.ACCELEROMETER
        name = 'Accelerometer'
        hw_name = 'OpenIMU-HW'
        location = 'wrist'
        sampling_rate = 30.0
        data_rate = 1

        sensor = manager.add_sensor(id_sensor_type, name, hw_name, location,
                                    sampling_rate, data_rate)
        sensor2 = manager.get_sensor(sensor.id_sensor)

        self.assertEqual(sensor.id_sensor, sensor2.id_sensor)
        self.assertEqual(sensor.id_sensor_type, sensor2.id_sensor_type)
        self.assertEqual(sensor.name, sensor2.name)
        self.assertEqual(sensor.hw_name, sensor2.hw_name)
        self.assertEqual(sensor.location, sensor2.location)
        self.assertEqual(sensor.sampling_rate, sensor2.sampling_rate)
        self.assertEqual(sensor.data_rate, sensor2.data_rate)
Ejemplo n.º 25
0
    def test_async_loading(self):

        manager = DBManager('test.db', overwrite=True)
        participant = Participant(name='My Participant',
                                  description='Participant Description')
        manager.update_participant(participant)

        importer = ActigraphImporter(manager, participant)

        print('Starting threads...')
        # Start threads
        threads = []
        for i in range(0, 1):
            threads.append(
                importer.async_load('../../../resources/samples/test.gt3x'))

        print('Waiting for threads...')
        # Wait for threads
        for t in threads:
            t.join()

        recordsets = manager.get_all_recordsets(participant)
        print('recordsets', recordsets)
        self.assertGreater(len(recordsets), 0)
Ejemplo n.º 26
0
    def test_get_all_channels(self):
        manager = DBManager(filename='openimu.db', overwrite=True)

        # Create sensor in DB
        sensor = manager.add_sensor(SensorType.ACCELEROMETER, 'Sensor Name',
                                    'Hardware Name', 'Wrist', 30.0, 1)
        channelx = manager.add_channel(sensor, Units.GRAVITY_G,
                                       DataFormat.FLOAT32, 'Accelerometer_X')
        channely = manager.add_channel(sensor, Units.GRAVITY_G,
                                       DataFormat.FLOAT32, 'Accelerometer_Y')
        channelz = manager.add_channel(sensor, Units.GRAVITY_G,
                                       DataFormat.FLOAT32, 'Accelerometer_Z')

        # Get all channels (from all sensor)
        channels = manager.get_all_channels()
        self.assertEqual(len(channels), 3)

        # Get all channels (from valid sensor)
        channels = manager.get_all_channels(sensor=sensor)
        self.assertEqual(len(channels), 3)

        # Get all channels (from invalid sensor)
        channels = manager.get_all_channels(sensor=Sensor())
        self.assertEqual(len(channels), 0)
Ejemplo n.º 27
0
    def test_add_participant(self):
        manager = DBManager(filename='openimu.db', overwrite=True)

        # Participant information
        group_name = 'My Group'
        group_description = 'My Group Description'
        group = Group(name=group_name, description=group_description)
        manager.update_group(group)

        participant_name = 'Participant'
        participant_description = 'Participant Description'
        participant = Participant(name=participant_name,
                                  description=participant_description,
                                  group=group)
        manager.update_participant(participant)
        participant2 = manager.get_participant(participant.id_participant)

        self.assertEqual(participant.group, group)
        self.assertEqual(participant.name, participant_name)
        self.assertEqual(participant.description, participant_description)
        self.assertGreater(participant.id_participant, 0)
        self.assertEqual(participant, participant2)

        manager.close()
Ejemplo n.º 28
0
        # Create participant
        participant = db_manager.update_participant(
            Participant(name='Participant', description='No description'))

        # Create importer
        importer = ActigraphImporter(db_manager, participant)

        # Load content of the file to the database
        data_results = importer.load('../../resources/samples/test.gt3x')
        importer.import_to_database(data_results)

    if not os.path.isfile(db_filename):
        print('importing actigraph data')
        import_data()

    manager = DBManager(db_filename)

    # Get recordsets
    recordsets = manager.get_all_recordsets()

    for record in recordsets:
        # Get all sensors in record
        sensors = manager.get_all_sensors()
        for sensor in sensors:
            if sensor.id_sensor_type == SensorType.ACCELEROMETER:
                print('Found Accelerometer')
                channels = manager.get_all_channels(sensor=sensor)
                for channel in channels:

                    if channel.label == 'Accelerometer_Y':
                        print('Processing Channel :', channel)
Ejemplo n.º 29
0
class MainWindow(QMainWindow):
    currentFileName = ''
    dbMan = []
    currentDataSet = DataSet()
    currentRecordsets = []

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.UI = Ui_MainWindow()
        self.UI.setupUi(self)
        self.UI.dockToolBar.setTitleBarWidget(QWidget())
        self.UI.dockLog.hide()

        self.add_to_log("OpenIMU - Prêt à travailler.", LogTypes.LOGTYPE_INFO)

        # Setup signals and slots
        self.setup_signals()

        self.show_start_window()

    def __del__(self):
        # Restore sys.stdout
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

    def show_start_window(self):
        self.clear_main_widgets()
        self.showMinimized()
        start_window = StartWindow(self)

        if start_window.exec() == QDialog.Rejected:
            # User closed the dialog - exits!
            sys.exit(0)

        # Init database manager
        self.currentFileName = start_window.fileName
        self.dbMan = DBManager(self.currentFileName)

        # Maximize window
        self.showMaximized()

        # Load data
        self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO)
        self.currentDataSet = self.dbMan.get_dataset()
        self.load_data_from_dataset()
        self.UI.treeDataSet.setCurrentItem(None)
        self.UI.treeDataSet.owner = self

        # self.loadDemoData()
        self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE)

        # If we need to import data, show the import dialog
        if start_window.importing:
            self.import_requested()
            gc.collect()

    def setup_signals(self):
        self.UI.treeDataSet.itemClicked.connect(self.tree_item_clicked)
        self.UI.btnDataSetInfos.clicked.connect(self.infos_requested)
        self.UI.btnAddGroup.clicked.connect(self.new_group_requested)
        self.UI.btnAddParticipant.clicked.connect(
            self.new_participant_requested)
        self.UI.treeDataSet.participantDragged.connect(
            self.participant_was_dragged)
        self.UI.btnDelete.clicked.connect(self.delete_requested)
        self.UI.btnImport.clicked.connect(self.import_requested)
        self.UI.btnExportCSV.clicked.connect(self.export_csv_requested)
        self.UI.dockDataset.visibilityChanged.connect(
            self.UI.btnShowDataset.setChecked)
        # self.UI.dockLog.visibilityChanged.connect(self.toggle_log)
        self.UI.btnShowDataset.clicked.connect(self.toggle_dataset)
        self.UI.btnShowLog.clicked.connect(self.toggle_log)
        self.UI.btnTransfer.clicked.connect(self.transfer_requested)
        self.UI.btnClose.clicked.connect(self.db_close_requested)
        self.UI.btnCompact.clicked.connect(self.db_compact_requested)
        self.UI.btnProcess.clicked.connect(self.process_data_requested)

    def console_log_normal(self, text):
        self.add_to_log(text, LogTypes.LOGTYPE_DEBUG)

    def console_log_error(self, text):
        self.add_to_log(text, LogTypes.LOGTYPE_ERROR)

    @pyqtSlot()
    def load_data_from_dataset(self):
        self.UI.treeDataSet.clear()
        self.clear_main_widgets()

        # Groups
        groups = self.dbMan.get_all_groups()
        for group in groups:
            self.UI.treeDataSet.update_group(group)

        # Participants
        participants = self.dbMan.get_all_participants()
        for participant in participants:
            self.UI.treeDataSet.update_participant(participant)

        # Recordsets
        recordsets = self.dbMan.get_all_recordsets()
        for recordset in recordsets:
            self.UI.treeDataSet.update_recordset(recordset)

        # Results
        results = self.dbMan.get_all_processed_data()
        for result in results:
            self.UI.treeDataSet.update_result(result)

    def update_group(self, group):
        item = self.UI.treeDataSet.update_group(group)
        self.UI.treeDataSet.setCurrentItem(item)

    def update_participant(self, participant):
        item = self.UI.treeDataSet.update_participant(participant)
        self.UI.treeDataSet.setCurrentItem(item)

    def clear_main_widgets(self):
        for i in reversed(range(self.UI.frmMain.layout().count())):
            self.UI.frmMain.layout().itemAt(i).widget().setParent(None)

    def show_group(self, group=None):
        self.clear_main_widgets()

        group_widget = GroupWindow(dbManager=self.dbMan, group=group)
        self.UI.frmMain.layout().addWidget(group_widget)

        group_widget.dataSaved.connect(self.data_was_saved)
        group_widget.dataCancelled.connect(self.data_was_cancelled)

    def show_participant(self, participant=None, base_group=None):
        self.clear_main_widgets()

        part_widget = ParticipantWindow(dbManager=self.dbMan,
                                        participant=participant,
                                        default_group=base_group)
        self.UI.frmMain.layout().addWidget(part_widget)

        part_widget.dataSaved.connect(self.data_was_saved)
        part_widget.dataCancelled.connect(self.data_was_cancelled)

    @pyqtSlot('QString', int)
    def add_to_log(self, text, log_type):
        if text == ' ' or text == '\n':
            return

        log_format = ""
        if log_type == LogTypes.LOGTYPE_INFO:
            log_format = "<span style='color:black'>"
        if log_type == LogTypes.LOGTYPE_WARNING:
            log_format = "<span style='color:orange;font-style:italic'>"
        if log_type == LogTypes.LOGTYPE_ERROR:
            log_format = "<span style='color:red;font-weight:bold'>"
        if log_type == LogTypes.LOGTYPE_DEBUG:
            log_format = "<span style='color:grey;font-style:italic'>"
        if log_type == LogTypes.LOGTYPE_DONE:
            log_format = "<span style='color:green;font-weight:bold'>"

        self.UI.txtLog.append("<span style='color:grey'>" +
                              datetime.now().strftime("%H:%M:%S.%f") +
                              " </span>" + log_format + text + "</span>")
        self.UI.txtLog.ensureCursorVisible()
        QApplication.processEvents()

    def get_current_widget_data_type(self):
        # TODO: checks!
        return self.UI.frmMain.layout().itemAt(0).widget().data_type

    ######################
    @pyqtSlot(bool)
    def toggle_dataset(self, visibility):
        self.UI.dockDataset.setVisible(visibility)

    @pyqtSlot(bool)
    def toggle_log(self, visibility):
        self.UI.dockLog.setVisible(visibility)
        # self.UI.btnShowLog.setChecked(visibility)

        if visibility:
            sys.stdout = StdConsoleLogger(self.console_log_normal)
            sys.stderr = StdConsoleLogger(self.console_log_error)
        else:
            sys.stdout = sys.__stdout__
            sys.stderr = sys.__stderr__

        # print("Test!")

    @pyqtSlot()
    def import_requested(self):
        importer = ImportBrowser(data_manager=self.dbMan)
        importer.participant_added.connect(self.load_data_from_dataset)
        importer.log_request.connect(self.add_to_log)
        importer.setStyleSheet(self.styleSheet())
        if importer.exec() == QDialog.Accepted:
            self.load_data_from_dataset()
            gc.collect()

    @pyqtSlot()
    def export_csv_requested(self):
        exporter = ExportWindow(self.dbMan, self)
        exporter.setStyleSheet(self.styleSheet())
        if exporter.exec() == QDialog.Accepted:
            print("Accepted")

    @pyqtSlot()
    def infos_requested(self):
        infos_window = ImportWindow(dataset=self.currentDataSet,
                                    filename=self.currentFileName)
        infos_window.setStyleSheet(self.styleSheet())
        infos_window.noImportUI = True
        infos_window.infosOnly = True

        if infos_window.exec() != QDialog.Rejected:
            self.currentDataSet.name = infos_window.dataSet.name

    @pyqtSlot()
    def process_data_requested(self):
        if self.currentRecordsets:

            # Display Process Window
            proc_window = ProcessSelectWindow(
                data_manager=self.dbMan,
                recordsets=self.currentRecordsets,
                parent=self)

            if proc_window.exec() == QDialog.Accepted:
                self.UI.treeDataSet.update_item("result",
                                                proc_window.processed_data)
                self.UI.treeDataSet.select_item(
                    "result", proc_window.processed_data.id_processed_data)

    @pyqtSlot()
    def db_close_requested(self):
        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Question)
        msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}")

        msg.setText(
            "Cet ensemble de données sera fermé. Désirez-vous poursuivre?")
        msg.setWindowTitle("Fermeture?")
        msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        rval = msg.exec()
        if rval == QMessageBox.Yes:
            self.dbMan.close()
            self.add_to_log("Fichier " + self.currentFileName + " fermé.",
                            LogTypes.LOGTYPE_INFO)
            self.hide()

            self.show_start_window()

    @pyqtSlot()
    def db_compact_requested(self):
        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Question)
        msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}")

        msg.setText(
            "Le fichier de données sera nettoyé. Ceci peut prendre un certain temps. \n"
            "Désirez-vous poursuivre?")
        msg.setWindowTitle("Compactage des données")
        msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        rval = msg.exec()
        if rval == QMessageBox.Yes:
            task = SimpleTask("Compactage des données", self.dbMan.compact)
            process = BackgroundProcess([task])
            dialog = ProgressDialog(process, 'Nettoyage', self)
            process.start()
            dialog.exec()

    @pyqtSlot()
    def new_group_requested(self):
        self.show_group()

    @pyqtSlot()
    def new_participant_requested(self):
        # Check if we can get a root item (group) for the current selected item or not
        item = self.UI.treeDataSet.currentItem()
        if item is not None:
            while item.parent() is not None:
                item = item.parent()

        default_group = None
        if self.UI.treeDataSet.get_item_type(item) == "group":
            default_group = self.UI.treeDataSet.groups[
                self.UI.treeDataSet.get_item_id(item)]

        self.show_participant(base_group=default_group)

    @pyqtSlot(Participant)
    def participant_was_dragged(self, participant):
        self.dbMan.update_participant(participant)
        self.update_participant(participant)

    @pyqtSlot(QTreeWidgetItem, int)
    def tree_item_clicked(self, item: QTreeWidgetItem, _: int):
        # print(item.text(column))
        item_id = self.UI.treeDataSet.get_item_id(item)
        item_type = self.UI.treeDataSet.get_item_type(item)

        # Clear all widgets
        self.clear_main_widgets()
        self.UI.btnProcess.setEnabled(False)
        self.currentRecordsets = []

        if item_type == "group":
            self.show_group(self.UI.treeDataSet.groups[item_id])
            # groupWidget = GroupWindow(dbManager=self.dbMan, group = self.UI.treeDataSet.groups[item_id])
            # self.UI.frmMain.layout().addWidget(groupWidget)

        if item_type == "participant":
            self.show_participant(self.UI.treeDataSet.participants[item_id])

        if item_type == "recordsets" or item_type == "recordset" or item_type == "subrecord" or item_type == "date":
            if item_type == "recordsets":
                part = self.UI.treeDataSet.participants[
                    self.UI.treeDataSet.get_item_id(item.parent())]
                self.currentRecordsets = self.dbMan.get_all_recordsets(
                    participant=part)
            elif item_type == "date":
                # Find associated participant
                id_participant = self.UI.treeDataSet.get_item_id(
                    item.parent().parent())
                part = self.UI.treeDataSet.participants[id_participant]
                search_date = self.UI.treeDataSet.dates[
                    Treedatawidget.get_date_id(item.text(0), id_participant)]
                self.currentRecordsets = self.dbMan.get_all_recordsets(
                    participant=part, start_date=search_date)
            else:
                self.currentRecordsets = [
                    self.UI.treeDataSet.recordsets[item_id]
                ]

            records_widget = RecordsetWindow(manager=self.dbMan,
                                             recordset=self.currentRecordsets,
                                             parent=self)
            # records_widget.setStyleSheet(self.styleSheet() + records_widget.styleSheet())
            self.UI.frmMain.layout().addWidget(records_widget)
            records_widget.dataDisplayRequest.connect(
                self.UI.treeDataSet.select_item)
            records_widget.dataUpdateRequest.connect(
                self.UI.treeDataSet.update_item)
            self.UI.btnProcess.setEnabled(True)

        if item_type == "result":
            result_widget = ResultWindow(
                manager=self.dbMan,
                results=self.UI.treeDataSet.results[item_id],
                parent=self)
            self.UI.frmMain.layout().addWidget(result_widget)

        item.setExpanded(True)
        # self.UI.frmMain.update()

    @pyqtSlot()
    def data_was_saved(self):
        item_type = self.get_current_widget_data_type()

        if item_type == "group":
            group = self.UI.frmMain.layout().itemAt(0).widget().group
            self.update_group(group)
            self.add_to_log("Groupe " + group.name + " mis à jour.",
                            LogTypes.LOGTYPE_DONE)

        if item_type == "participant":
            part = self.UI.frmMain.layout().itemAt(0).widget().participant
            self.update_participant(part)
            self.add_to_log("Participant " + part.name + " mis à jour.",
                            LogTypes.LOGTYPE_DONE)

    @pyqtSlot()
    def data_was_cancelled(self):
        item_type = self.get_current_widget_data_type()

        if item_type == "group":
            if self.UI.frmMain.layout().itemAt(0).widget().group is None:
                self.clear_main_widgets()

        if item_type == "participant":
            if self.UI.frmMain.layout().itemAt(0).widget().participant is None:
                self.clear_main_widgets()

    @pyqtSlot()
    def delete_requested(self):
        item_id = self.UI.treeDataSet.get_item_id(
            self.UI.treeDataSet.currentItem())
        item_type = self.UI.treeDataSet.get_item_type(
            self.UI.treeDataSet.currentItem())

        # if item_type == "recordsets" or item_type == "results":
        #     return

        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Question)
        msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}")

        msg.setText("Désirez-vous vraiment supprimer \"" +
                    self.UI.treeDataSet.currentItem().text(0) +
                    "\" et tous les éléments associés?")
        msg.setWindowTitle("Confirmation de suppression")
        msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        rval = msg.exec()
        if rval == QMessageBox.Yes:
            item_name = self.UI.treeDataSet.currentItem().text(0)
            tasks = []

            if item_type == "group":
                group = self.UI.treeDataSet.groups[item_id]
                self.UI.treeDataSet.remove_group(group)
                task = SimpleTask("Suppression de '" + group.name + "'",
                                  self.dbMan.delete_group, group)
                tasks.append(task)

            if item_type == "participant":
                part = self.UI.treeDataSet.participants[item_id]
                self.UI.treeDataSet.remove_participant(part)
                task = SimpleTask("Suppression de '" + part.name + "'",
                                  self.dbMan.delete_participant, part)
                tasks.append(task)

            if item_type == "recordset":
                # Find and remove all related results
                for result in self.UI.treeDataSet.results.values():
                    if result is not None:
                        for ref in result.processed_data_ref:
                            if ref.recordset.id_recordset == item_id:
                                self.UI.treeDataSet.remove_result(result)
                                task = SimpleTask(
                                    "Suppression de '" + result.name + "'",
                                    self.dbMan.delete_processed_data, result)
                                tasks.append(task)
                                # self.dbMan.delete_processed_data(result)
                                break

                recordset = self.UI.treeDataSet.recordsets[item_id]
                task = SimpleTask("Suppression de '" + recordset.name + "'",
                                  self.dbMan.delete_recordset, recordset)
                tasks.append(task)
                # self.dbMan.delete_recordset(recordset)
                self.UI.treeDataSet.remove_recordset(recordset)

            if item_type == "result":
                result = self.UI.treeDataSet.results[item_id]
                task = SimpleTask("Suppression de '" + result.name + "'",
                                  self.dbMan.delete_processed_data, result)
                tasks.append(task)
                self.UI.treeDataSet.remove_result(result)
                # self.dbMan.delete_processed_data(result)

            if item_type == "date":
                # Delete all recordsets related to that date
                id_participant = self.UI.treeDataSet.get_item_id(
                    self.UI.treeDataSet.currentItem().parent().parent())
                search_date = self.UI.treeDataSet.dates[
                    Treedatawidget.get_date_id(
                        self.UI.treeDataSet.currentItem().text(0),
                        id_participant)]
                recordsets = self.dbMan.get_all_recordsets(
                    start_date=search_date)
                part_id = None
                for recordset in recordsets:
                    if part_id is None:
                        part_id = recordset.id_participant
                    task = SimpleTask(
                        "Suppression de '" + recordset.name + "'",
                        self.dbMan.delete_recordset, recordset)
                    tasks.append(task)
                    self.UI.treeDataSet.remove_recordset(recordset)
                self.UI.treeDataSet.remove_date(
                    self.UI.treeDataSet.currentItem().text(0), part_id)

            if item_type == "recordsets":
                # Delete all recordsets for that participant
                participant = self.UI.treeDataSet.participants[
                    self.UI.treeDataSet.get_item_id(
                        self.UI.treeDataSet.currentItem().parent())]
                recordsets = self.dbMan.get_all_recordsets(
                    participant=participant)
                for recordset in recordsets:
                    task = SimpleTask(
                        "Suppression de '" + recordset.name + "'",
                        self.dbMan.delete_recordset, recordset)
                    tasks.append(task)
                    self.UI.treeDataSet.remove_recordset(recordset)

                # Remove all dates from the view
                self.UI.treeDataSet.remove_dates_for_participant(
                    participant.id_participant)

            if item_type == "results":
                pass

            if tasks:
                process = BackgroundProcess(tasks)
                # Create progress dialog
                dialog = ProgressDialog(process, 'Suppression', self)
                # Start tasks
                process.start()
                dialog.exec()
                # self.dbMan.clean_db()

            self.add_to_log(item_name + " a été supprimé.",
                            LogTypes.LOGTYPE_DONE)
            self.clear_main_widgets()


#    def closeEvent(self, event):
#        return

    def create_chart_view(self, test_data=False):
        chart_view = IMUChartView(self)
        if test_data is True:
            chart_view.add_test_data()
        return chart_view

    @pyqtSlot()
    def transfer_requested(self):
        # import_man = ImportManager(dbmanager=self.dbMan, dirs=True, stream=True, parent=self)
        # # TODO: More intelligent refresh!
        # import_man.participant_added.connect(self.load_data_from_dataset)
        #
        # if import_man.exec() == QDialog.Accepted:
        stream_diag = StreamWindow(parent=self)
        stream_diag.exec()

        # Do the actual import
        # msg = QMessageBox(self)
        # msg.setIcon(QMessageBox.Question)
        # msg.setStyleSheet("QPushButton{min-width: 100px; min-height: 40px;}")
        #
        # msg.setText("Procéder à l'importation des données?")
        # msg.setWindowTitle("Importer?")
        # msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
        #
        # rval = msg.exec()
        # if rval == QMessageBox.Yes:

        if stream_diag.folders_to_import:
            # Match windows
            matcher = ImportMatchDialog(dbmanager=self.dbMan,
                                        datas=stream_diag.folders_to_import,
                                        parent=self)
            if matcher.exec() == QDialog.Accepted:
                # for file_name, file_dataname in file_list.items():
                #     part = matcher.data_match[file_dataname]
                #     file_match[file_name] = part

                # Build import list
                files = matcher.get_files_match(
                    stream_diag.get_data_save_path())

                # Start import process
                import_browser = ImportBrowser(data_manager=self.dbMan,
                                               parent=self)
                import_browser.log_request.connect(self.add_to_log)

                importer_id = StreamerTypes.value_importer_types[
                    stream_diag.get_streamer_type()]
                importer_name = ImporterTypes.value_names[importer_id]
                for file_name, file_part in files.items():
                    import_browser.add_file_to_list(file_name, importer_name,
                                                    importer_id, file_part)

                import_browser.ok_clicked()

                # Delete files after transfer?
                import shutil
                if not stream_diag.get_delete_files_after_import():
                    # Move files to "Imported" folder
                    import os
                    target_dir = stream_diag.get_base_data_save_path(
                    ) + os.sep + "Imported"
                    FileManager.merge_folders(stream_diag.get_data_save_path(),
                                              target_dir)

                # Remove transfered files
                shutil.rmtree(stream_diag.get_data_save_path())
                self.load_data_from_dataset()
Ejemplo n.º 30
0
class MainWindow(QMainWindow):
    currentFileName = ''
    dbMan = []
    currentDataSet = DataSet()

    def __init__(self, parent=None):
        super(QMainWindow, self).__init__(parent=parent)
        self.UI = Ui_MainWindow()
        self.UI.setupUi(self)

        self.add_to_log("OpenIMU - Prêt à travailler.", LogTypes.LOGTYPE_INFO)

        startWindow = StartWindow()

        if startWindow.exec() == QDialog.Rejected:
            # User closed the dialog - exits!
            exit(0)

        # Init database manager
        self.currentFileName = startWindow.fileName
        self.dbMan = DBManager(self.currentFileName)

        # Setup signals and slots
        self.setup_signals()

        # Maximize window
        self.showMaximized()

        # Load data
        self.add_to_log("Chargement des données...", LogTypes.LOGTYPE_INFO)
        self.currentDataSet = self.dbMan.get_dataset()
        self.load_data_from_dataset()
        self.UI.treeDataSet.setCurrentItem(None)

        # self.loadDemoData()
        self.add_to_log("Données chargées!", LogTypes.LOGTYPE_DONE)

        # If we need to import data, show the import dialog
        if startWindow.importing:
            self.importRequested()

    def setup_signals(self):
        self.UI.treeDataSet.itemClicked.connect(self.tree_item_clicked)
        self.UI.btnDataSetInfos.clicked.connect(self.infosRequested)
        self.UI.btnAddGroup.clicked.connect(self.newGroupRequested)
        self.UI.btnAddParticipant.clicked.connect(self.newParticipantRequested)
        self.UI.treeDataSet.participantDragged.connect(
            self.participant_was_dragged)
        self.UI.btnDelete.clicked.connect(self.delete_requested)
        self.UI.btnImport.clicked.connect(self.importRequested)

    def load_data_from_dataset(self):
        self.UI.treeDataSet.clear()

        # Groups
        groups = self.dbMan.get_all_groups()
        for group in groups:
            self.UI.treeDataSet.update_group(group)

        # Participants
        participants = self.dbMan.get_all_participants()
        for participant in participants:
            self.UI.treeDataSet.update_participant(participant)

        # Recordsets
        recordsets = self.dbMan.get_all_recordsets()
        for recordset in recordsets:
            self.UI.treeDataSet.update_recordset(recordset)

    """def create_subrecord_item(self, name, id):
        item = QTreeWidgetItem()
        item.setText(0, name)
        item.setIcon(0, QIcon(':/OpenIMU/icons/subrecord.png'))
        item.setData(0, Qt.UserRole, id)
        item.setData(1, Qt.UserRole, 'subrecord')
        item.setFont(0, QFont('Helvetica', 12, QFont.Bold))
        return item

    def create_sensor_item(self, name, id):
        item = QTreeWidgetItem()
        item.setText(0, name)
        item.setIcon(0, QIcon(':/OpenIMU/icons/sensor.png'))
        item.setData(0, Qt.UserRole, id)
        item.setData(1, Qt.UserRole, 'sensor')
        item.setFont(0, QFont('Helvetica', 12))
        return item

    def create_result_item(self, name, id):
        item = QTreeWidgetItem()
        item.setText(0, name)
        item.setIcon(0, QIcon(':/OpenIMU/icons/result.png'))
        item.setData(0, Qt.UserRole, id)
        item.setData(1, Qt.UserRole, 'result')
        item.setFont(0, QFont('Helvetica', 12))
        return item
"""

    def update_group(self, group):
        item = self.UI.treeDataSet.update_group(group)
        self.UI.treeDataSet.setCurrentItem(item)

    def update_participant(self, participant):
        item = self.UI.treeDataSet.update_participant(participant)
        self.UI.treeDataSet.setCurrentItem(item)

    def clear_main_widgets(self):
        for i in reversed(range(self.UI.frmMain.layout().count())):
            self.UI.frmMain.layout().itemAt(i).widget().setParent(None)

    def show_group(self, group=None):
        self.clear_main_widgets()

        groupWidget = GroupWindow(dbManager=self.dbMan, group=group)
        self.UI.frmMain.layout().addWidget(groupWidget)

        groupWidget.dataSaved.connect(self.dataWasSaved)
        groupWidget.dataCancelled.connect(self.dataWasCancelled)

    def show_participant(self, participant=None, base_group=None):
        self.clear_main_widgets()

        partWidget = ParticipantWindow(dbManager=self.dbMan,
                                       participant=participant,
                                       default_group=base_group)
        self.UI.frmMain.layout().addWidget(partWidget)

        partWidget.dataSaved.connect(self.dataWasSaved)
        partWidget.dataCancelled.connect(self.dataWasCancelled)

    def add_to_log(self, text, log_type):
        format = ""
        if log_type == LogTypes.LOGTYPE_INFO:
            format = "<span style='color:black'>"
        if log_type == LogTypes.LOGTYPE_WARNING:
            format = "<span style='color:orange;font-style:italic'>"
        if log_type == LogTypes.LOGTYPE_ERROR:
            format = "<span style='color:red;font-weight:bold'>"
        if log_type == LogTypes.LOGTYPE_DEBUG:
            format = "<span style='color:grey;font-style:italic'>"
        if log_type == LogTypes.LOGTYPE_DONE:
            format = "<span style='color:green;font-weight:bold'>"

        self.UI.txtLog.append("<span style='color:grey'>" +
                              datetime.now().strftime("%H:%M:%S.%f") +
                              " </span>" + format + text + "</span>")
        self.UI.txtLog.ensureCursorVisible()

    def get_current_widget_data_type(self):
        # TODO: checks!
        return self.UI.frmMain.layout().itemAt(0).widget().data_type

    ######################
    @pyqtSlot(QUrl)
    def urlChanged(self, url):
        print('url: ', url)

    @pyqtSlot()
    def importRequested(self):
        importer = ImportBrowser(dataManager=self.dbMan)
        if importer.exec() == QDialog.Accepted:
            self.load_data_from_dataset()

    @pyqtSlot()
    def infosRequested(self):
        infosWindow = ImportWindow(dataset=self.currentDataSet,
                                   filename=self.currentFileName)
        infosWindow.noImportUI = True
        infosWindow.infosOnly = True

        if infosWindow.exec() != QDialog.Rejected:
            # TODO: Save data
            self.currentDataSet.name = infosWindow.dataSet.name

    @pyqtSlot()
    def newGroupRequested(self):
        self.show_group()

    @pyqtSlot()
    def newParticipantRequested(self):
        # Check if we can get a root item (group) for the current selected item or not
        item = self.UI.treeDataSet.currentItem()
        if item is not None:
            while item.parent() is not None:
                item = item.parent()

        default_group = None
        if self.UI.treeDataSet.get_item_type(item) == "group":
            default_group = self.UI.treeDataSet.groups[
                self.UI.treeDataSet.get_item_id(item)]

        self.show_participant(base_group=default_group)

    @pyqtSlot(Participant)
    def participant_was_dragged(self, participant):
        self.dbMan.update_participant(participant)
        self.update_participant(participant)

    @pyqtSlot(QTreeWidgetItem, int)
    def tree_item_clicked(self, item, column):
        # print(item.text(column))
        item_id = self.UI.treeDataSet.get_item_id(item)
        item_type = self.UI.treeDataSet.get_item_type(item)

        # Clear all widgets
        self.clear_main_widgets()

        if item_type == "group":
            self.show_group(self.UI.treeDataSet.groups[item_id])
            # groupWidget = GroupWindow(dbManager=self.dbMan, group = self.UI.treeDataSet.groups[item_id])
            # self.UI.frmMain.layout().addWidget(groupWidget)

        if item_type == "participant":
            self.show_participant(self.UI.treeDataSet.participants[item_id])

        if item_type == "recordsets" or item_type == "recordset" or item_type == "subrecord":
            if item_type == "recordsets":
                part = self.UI.treeDataSet.participants[
                    self.UI.treeDataSet.get_item_id(item.parent())]
                records = self.dbMan.get_all_recordsets(part)
            else:
                records = [self.UI.treeDataSet.recordsets[item_id]]

            recordsWidget = RecordsetWindow(manager=self.dbMan,
                                            recordset=records)
            self.UI.frmMain.layout().addWidget(recordsWidget)

        if item_type == "result":
            resultWidget = ResultWindow()
            self.UI.frmMain.layout().addWidget(resultWidget)

        self.UI.frmMain.update()

    @pyqtSlot()
    def dataWasSaved(self):
        item_type = self.get_current_widget_data_type()

        if item_type == "group":
            group = self.UI.frmMain.layout().itemAt(0).widget().group
            self.update_group(group)
            self.add_to_log("Groupe " + group.name + " mis à jour.",
                            LogTypes.LOGTYPE_DONE)

        if item_type == "participant":
            part = self.UI.frmMain.layout().itemAt(0).widget().participant
            self.update_participant(part)
            self.add_to_log("Participant " + part.name + " mis à jour.",
                            LogTypes.LOGTYPE_DONE)

    @pyqtSlot()
    def dataWasCancelled(self):
        item_type = self.get_current_widget_data_type()

        if item_type == "group":
            if self.UI.frmMain.layout().itemAt(0).widget().group is None:
                self.clear_main_widgets()

        if item_type == "participant":
            if self.UI.frmMain.layout().itemAt(0).widget().participant is None:
                self.clear_main_widgets()

    @pyqtSlot()
    def delete_requested(self):
        item_id = self.UI.treeDataSet.get_item_id(
            self.UI.treeDataSet.currentItem())
        item_type = self.UI.treeDataSet.get_item_type(
            self.UI.treeDataSet.currentItem())

        if item_type == "recordsets" or item_type == "results":
            return

        msg = QMessageBox()
        msg.setIcon(QMessageBox.Question)

        msg.setText("Désirez-vous vraiment supprimer " +
                    self.UI.treeDataSet.currentItem().text(0) +
                    " et tous les éléments associés?")
        msg.setWindowTitle("Confirmation de suppression")
        msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        rval = msg.exec()
        if rval == QMessageBox.Yes:
            item_name = self.UI.treeDataSet.currentItem().text(0)
            if item_type == "group":
                group = self.UI.treeDataSet.groups[item_id]
                self.dbMan.delete_group(group)
                self.UI.treeDataSet.remove_group(group)

            if item_type == "participant":
                part = self.UI.treeDataSet.participants[item_id]
                self.dbMan.delete_participant(part)
                self.UI.treeDataSet.remove_participant(part)

            if item_type == "recordset":
                recordset = self.UI.treeDataSet.recordsets[item_id]
                self.dbMan.delete_recordset(recordset)
                self.UI.treeDataSet.remove_recordset(recordset)

            self.add_to_log(item_name + " a été supprimé.",
                            LogTypes.LOGTYPE_DONE)
            self.clear_main_widgets()

    def closeEvent(self, event):
        print('closeEvent')
        """self.jupyter.stop()
        del self.jupyter
        self.jupyter = None
        """

    def __del__(self):
        print('Done!')

    def create_chart_view(self, test_data=False):
        chart_view = IMUChartView(self)
        if test_data is True:
            chart_view.add_test_data()
        return chart_view