Exemple #1
0
    def _loadSettings(self):

        settings = QSettings()

        # Recent documents
        size = settings.beginReadArray("RecentDocuments")
        for idx in range(size-1, -1, -1):
            settings.setArrayIndex(idx)
            canonicalName = QFileInfo(settings.value("Document")).canonicalFilePath()
            self._updateRecentDocuments(canonicalName)
        settings.endArray()

        # Application properties: Geometry
        geometry = settings.value("Application/Geometry", QByteArray()) if self._preferences.restoreApplicationGeometry() else QByteArray()
        if not geometry.isEmpty():
            self.restoreGeometry(geometry)
        else:
            availableGeometry = self.screen().availableGeometry()
            self.resize(availableGeometry.width() * 2/3, availableGeometry.height() * 2/3)
            self.move((availableGeometry.width() - self.width()) / 2, (availableGeometry.height() - self.height()) / 2)

        # Application properties: State
        state = settings.value("Application/State", QByteArray()) if self._preferences.restoreApplicationState() else QByteArray()
        if not state.isEmpty():
            self.restoreState(state)
        else:
            self._toolbarApplication.setVisible(True)
            self._toolbarDocument.setVisible(True)
            self._toolbarEdit.setVisible(True)
            self._toolbarTools.setVisible(True)
            self._toolbarView.setVisible(False)
            self._toolbarHelp.setVisible(False)
Exemple #2
0
def _rename_step(workflow_location, old_name, new_name, new_src_uri):
    updated = False
    workflow_conf_location = os.path.join(workflow_location,
                                          DEFAULT_WORKFLOW_PROJECT_FILENAME)
    workflow_conf = QSettings(workflow_conf_location, QSettings.IniFormat)

    workflow_conf.beginGroup('nodes')
    node_count = workflow_conf.beginReadArray('nodelist')

    name_indices = []
    for i in range(node_count):
        workflow_conf.setArrayIndex(i)
        name = workflow_conf.value('name')
        if name == old_name:
            name_indices.append(i)

    workflow_conf.endArray()
    workflow_conf.beginWriteArray('nodelist')

    for i in range(node_count):
        workflow_conf.setArrayIndex(i)
        if i in name_indices:
            workflow_conf.setValue('name', new_name)
            workflow_conf.setValue('source_uri', new_src_uri)
            updated = True

    workflow_conf.endArray()
    workflow_conf.endGroup()

    return updated
Exemple #3
0
 def __init__(self, profiles,  parent=None):
     """
     Constructor
     
     @param parent reference to the parent widget
     @type QWidget
     """
     super(ProfilesDialog, self).__init__(parent)
     self.setupUi(self)
     self.model = ProfilesModel(profiles)
     self.view = self.table_view
     self.view.setModel(self.model)
     settings = QSettings()
     settings.beginGroup('ProfilesDialog')
     geom = settings.value('geom')
     if geom is not None:
         self.restoreGeometry(geom)
     sz = settings.beginReadArray('col_size')
     for i in range(sz):
         settings.setArrayIndex(i)
         w = settings.value('col')
         self.view.setColumnWidth(i, w)
     settings.endArray()
     settings.endGroup()
     self.view.horizontalHeader().setStretchLastSection(True)
    def load(self) -> None:
        settings = QSettings(self.config_path)

        size = settings.beginReadArray("downloads")
        for i in range(size):
            settings.setArrayIndex(i)
            self.add_download(Download.unpack(settings.value("download")))
        settings.endArray()
Exemple #5
0
    def test_save_settings(self, temp_settings):
        settings = temp_settings
        settings.exercises = [['sample3', [0, 0, 0]]]
        settings.instrument = 99
        settings.save_settings()

        q_settings = QSettings()
        saved_instrument = q_settings.value('instrument')
        saved_exercises = []
        q_settings.beginReadArray('exercises')
        for ex in q_settings.allKeys():
            if ex == 'size':
                continue
            saved_exercises.append([ex, q_settings.value(ex)])
        q_settings.endArray()

        assert saved_instrument == 99
        assert saved_exercises == [['sample3', [0, 0, 0]]]
    def load(self) -> None:
        settings = QSettings(self.config_path, QSettings.NativeFormat)

        size = settings.beginReadArray("predownloads")
        for i in range(size):
            settings.setArrayIndex(i)
            self.add_predownload(
                PreDownload.unpack(settings.value("predownload")))
        settings.endArray()
Exemple #7
0
 def _recentProjectFiles(self):
     projects = []
     settings = QSettings()
     settings.beginGroup("RecentFiles")
     size = settings.beginReadArray("Projects")
     for i in range(size):
         settings.setArrayIndex(i)
         p = settings.value("filepath")
         if p:
             projects.append(p)
     settings.endArray()
     return projects
Exemple #8
0
class NotebookManager:
    def __init__(self):
        self.settings = QSettings(ORGANIZATION_STR)        
        self.allNotebooks = []

        self.readConfig()

    def notebook(self, name):
        for notebook in self.allNotebooks:
            if notebook.name == name:
                return notebook
        
        raise KeyError(name)

    def notebooks(self):
        return self.allNotebooks

    def createNewNotebook(self, name, storagePath):
        ok = QDir(storagePath).mkpath(".")
        nb = Notebook(name, storagePath)

        self.allNotebooks.append(nb)
        self.writeConfig()

        return nb

    def readConfig(self):
        notebookCount = self.settings.beginReadArray("notebooks")

        for i in range(notebookCount):
            self.settings.setArrayIndex(i)
            name = self.settings.value("name")
            storagePath = self.settings.value("storagePath")

            self.allNotebooks.append(Notebook(name, storagePath))

        self.settings.endArray()

    def writeConfig(self):
        #self.settings.beginGroup("notebooks")

        self.settings.beginWriteArray("notebooks")
        for i, notebook in enumerate(self.allNotebooks):
            self.settings.setArrayIndex(i)
            self.settings.setValue("name", notebook.name)
            self.settings.setValue("storagePath", notebook.localStoragePath)

        self.settings.endArray()
        self.settings.sync()
        #self.settings.endGroup()
Exemple #9
0
    def load(cls, settings: QSettings):
        settings.beginGroup("gui")
        gui = GuiConfig.load(settings)
        settings.endGroup()

        repo_count = settings.beginReadArray("repos")
        repos = []
        for i in range(repo_count):
            settings.setArrayIndex(i)
            repos.append(RepositoryConfig.load(settings))
        settings.endArray()

        return cls(
            gui=gui,
            repositories=repos,
        )
Exemple #10
0
 def load(self, ini_check):
     settings = QSettings()
     settings.beginGroup(self.__class__.__name__)
     sz = settings.beginReadArray('col_size')
     for i in range(sz):
         settings.setArrayIndex(i)
         w = settings.value('col', type=int)
         if w is not None:
             self.setColumnWidth(i, w)
     settings.endArray()
     if ini_check:
         display = settings.value('display_images', type=bool)
         self.images_display.setCheckState(
             Qt.Checked if display else Qt.Unchecked)
         self.use_cache = settings.value('use_cache', True, type=bool)
         self.cache_size = settings.value('cache_size', 1000)
     else:
         display = self.images_display
     if not display:
         self.setColumnHidden(0, True)
     settings.endGroup()
     delegate = ImageDelegate(self)
     self.setItemDelegateForColumn(0, delegate)
     self.pre_load(delegate)
Exemple #11
0
 def test_exercises_exist(self):
     settings_reader = QSettings()
     settings_reader.beginReadArray('exercises')
     assert len(settings_reader.allKeys()) > 1
     settings_reader.endArray()
Exemple #12
0
class SettingsDialog(QtWidgets.QDialog):
    validator = QRegExpValidator(QRegExp("[A-Za-z0-9_]{6,16}"))

    def __init__(self, parent=None):
        super(SettingsDialog, self).__init__(parent)

        self.settings = QSettings(
            QStandardPaths.writableLocation(QStandardPaths.ConfigLocation) +
            "/settings.ini", QSettings.IniFormat)

        self.usernames = set()
        self.engines = set()

        self.newUsername = ""
        self.newEnginePath = ""

        self._loadSettings()

        self.mainLayout = QtWidgets.QFormLayout()

        self.usernameLineEdit = QtWidgets.QLineEdit(self.newUsername)
        self.usernameLineEdit.setPlaceholderText("Username (a-zA-Z0-9_)")
        self.usernameLineEdit.setMinimumHeight(35)
        self.usernameLineEdit.setValidator(self.validator)
        self.usernameLineEdit.textChanged.connect(self.validateFields)
        self.usernameLineEdit.selectAll()
        self.usernameLineEdit.setCompleter(
            QtWidgets.QCompleter(list(self.usernames), self))

        self.engineEdit = _EngineEdit(self.newEnginePath)
        self.engineEdit.pathEdit.textChanged.connect(self.validateFields)
        self.engineEdit.pathEdit.selectAll()
        self.engineEdit.pathEdit.setCompleter(
            QtWidgets.QCompleter(list(self.engines), self))

        self.resetButton = QtWidgets.QPushButton("Reset")
        self.resetButton.clicked.connect(self._reset)

        buttonBox = QtWidgets.QDialogButtonBox()
        self.okButton = buttonBox.addButton(
            "Ok", QtWidgets.QDialogButtonBox.AcceptRole)
        self.cancelButton = buttonBox.addButton(
            "Cancel", QtWidgets.QDialogButtonBox.RejectRole)
        self.okButton.clicked.connect(self._ok)
        self.cancelButton.clicked.connect(self.reject)

        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.setAlignment(Qt.AlignBottom)
        self.mainLayout.addRow("Username", self.usernameLineEdit)
        self.mainLayout.addRow("Engine", self.engineEdit)
        self.mainLayout.addWidget(self.resetButton)
        self.mainLayout.addWidget(buttonBox)
        self.setLayout(self.mainLayout)

        self.validateFields()

    def _validateEnginePath(self, path):
        return QFile.exists(path) and QFileInfo(path).isFile()

    @Slot(str)
    def validateFields(self):
        usernameValid = self.validator.validate(self.usernameLineEdit.text(), 0) and \
                        6 <= len(self.usernameLineEdit.text()) <= 16
        pathValid = self._validateEnginePath(self.engineEdit.pathEdit.text())

        if not usernameValid or not pathValid:
            if self.okButton.isEnabled():
                self.okButton.setDisabled(True)
        else:
            if not self.okButton.isEnabled():
                self.okButton.setDisabled(False)

        if not usernameValid:
            self.usernameLineEdit.setStyleSheet("border: 1px solid red;")
        else:
            self.usernameLineEdit.setStyleSheet("border: 1px solid green;")

        if not pathValid:
            self.engineEdit.pathEdit.setStyleSheet("border: 1px solid red;")
        else:
            self.engineEdit.pathEdit.setStyleSheet("border: 1px solid green;")

    def _loadSettings(self):
        i = self.settings.beginReadArray("usernames")
        currentUsername = ""
        for j in range(i):
            self.settings.setArrayIndex(j)
            currentUsername = self.settings.value("usernames", "")
            self.usernames.add(currentUsername)
        self.newUsername = currentUsername
        self.settings.endArray()

        i = self.settings.beginReadArray("engines")
        currentEngine = ""
        for j in range(i):
            self.settings.setArrayIndex(j)
            currentEngine = self.settings.value("engines", "")
            self.engines.add(currentEngine)
        self.newEnginePath = currentEngine
        self.settings.endArray()

    @Slot()
    def _reset(self):
        status = QtWidgets.QMessageBox.warning(
            self,
            "Reset",
            "Are you sure to reset the settings?",
            buttons=QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.Ok,
            defaultButton=QtWidgets.QMessageBox.Ok)

        if status == QtWidgets.QMessageBox.Ok:
            self.usernameLineEdit.clear()
            self.engineEdit.pathEdit.clear()
            self.usernames.clear()
            self.engines.clear()
            self.usernameLineEdit.setCompleter(QtWidgets.QCompleter())
            self.engineEdit.pathEdit.setCompleter(QtWidgets.QCompleter())
            self.settings.clear()
            self._loadSettings()

    @Slot()
    def _ok(self):
        if self.validator.validate(self.usernameLineEdit.text(), 0):
            self.newUsername = self.usernameLineEdit.text()
        else:
            QtWidgets.QMessageBox.critical(self, "Error", "Invalid username")
            self.reject()

        if self._validateEnginePath(self.engineEdit.pathEdit.text()):
            self.newEnginePath = self.engineEdit.pathEdit.text()
        else:
            QtWidgets.QMessageBox.critical(
                self, "Error", "The specified engine's path does not exist.")
            self.reject()

        self.settings.beginWriteArray("usernames")
        self.usernames.add(self.newUsername)
        for i, username in enumerate(self.usernames):
            self.settings.setArrayIndex(i)
            self.settings.setValue("usernames", username)
        self.settings.endArray()

        self.settings.beginWriteArray("engines")
        self.engines.add(self.newEnginePath)
        for i, path in enumerate(self.engines):
            self.settings.setArrayIndex(i)
            self.settings.setValue("engines", path)
        self.settings.endArray()

        self.accept()
Exemple #13
0
class Warmuppy:

    def __init__(self):

        super().__init__()

        pygame.init()

        # Instance variables
        self.settings = QSettings()
        self.timers = []
        self.exercises = []
        self.notes = NOTES

        # Load settings
        self.bpm = int(self.settings.value('bpm', DEFAULT_BPM))
        self.cut = float(self.settings.value('cut', DEFAULT_CUT))
        self.step = int(self.settings.value('step', DEFAULT_STEP))
        prev = self.settings.value('preview', DEFAULT_PREVIEW)
        self.preview = prev in ['true', True]
        prolonged = self.settings.value('prolong', DEFAULT_PROLONG)
        self.prolong = prolonged in ['true', True]
        self.preview_time = int(
            self.settings.value('preview_time', DEFAULT_PREVIEW_TIME)
        )
        self.prolong_time = int(
            self.settings.value('prolong_time', DEFAULT_PROLONG_TIME)
        )
        self.note = int(self.settings.value('note', 0))
        self.octave = int(self.settings.value('octave', 3))
        self.instrument = int(
            self.settings.value('instrument', DEFAULT_INSTRUMENT)
        )

        self.settings.beginReadArray('exercises')
        for ex in self.settings.allKeys():
            if ex == 'size':
                continue
            exv = self.settings.value(ex)
            if isinstance(exv,str):
                exv = [exv]
            self.exercises.append([
                ex,
                exv
            ])
        self.settings.endArray()
        if not self.exercises:
            self.settings.beginWriteArray('exercises')
            for ex in DEFAULT_EXERCISES:
                self.exercises.append(ex)
                self.settings.setValue(ex[0], ex[1])
            self.settings.endArray()
        self.exercise = DEFAULT_EXERCISE
        self.settings.setValue('instrument', self.instrument)

    def change_note(self, note):
        note_id = self.notes.index(note)
        logging.debug(f"New note is {note} ({note_id})")
        self.note = note_id
        self.settings.setValue('note', note_id)

    def change_octave(self, octave):
        logging.debug(f"New octave is {octave}")
        self.octave = octave
        self.settings.setValue('octave', octave)

    def change_exercise(self, i):
        if not self.exercises:
            logging.debug("No exercise to change to, skipping")
            return
        try:
            ex = self.exercises[i]
            self.exercise = i
        except IndexError:
            ex = self.exercises[0]
            self.exercise = 0
        logging.debug(f"Selected exercise {ex[0]} ({ex[1]})")

    # Generate boilerplate setters
    for x in "bpm cut step preview_time prolong_time".split():
        exec(f'''def change_{x}(self,{x}):
                    logging.debug("New {x} : %s",{x})
                    self.settings.setValue('{x}',{x})
                    self.{x} = {x}''')

    def change_preview(self, p):
        logging.debug(f"Setting preview as {p}")
        self.preview = p
        self.settings.setValue('preview', p)

    def change_prolong(self, p):
        logging.debug(f"Setting prolong as {p}")
        self.prolong = p
        self.settings.setValue('prolong', p)

    # Go {step} semitones up or down
    def bump_note(self, up):

        # Beginning of 3rd octave + selected octave * semitones + note
        base_note = 24 + (self.octave - 1) * 12 + self.note
        logging.debug(f"Current note: {base_note}")
        # Highest playable note is the last of the 8th octave
        max_note = 8 * 12 + 24
        # Lowest is C3
        min_note = 25

        # Compute new note
        if up:
            if base_note < max_note:
                base_note += self.step
        else:
            if base_note > min_note:
                base_note -= self.step
        logging.debug(f"New note: {base_note}")

        # Compute new octave
        octave = (base_note - 24) // 12 + 1
        logging.debug(f"New octave should be #{octave}")

        # Compute relative note for the UI
        note_id = (base_note - 24) % 12
        note = self.notes[note_id]
        logging.debug(f"New note should be #{note}")

        return octave, note

    # Generate a midi with the exercise and then play it
    def play_exercise(self):
        self.stop()

        # Load selected exercise
        ex = self.exercises[self.exercise]
        name = ex[0]
        seq = ex[1]
        logging.debug(f"Starting exercise '{name}' (pattern: {seq})")

        # Init midi file
        midi_file = tempfile.NamedTemporaryFile(delete=False)
        mid = MidiFile()
        track = MidiTrack()
        mid.tracks.append(track)
        track.append(
            Message('program_change', program=self.instrument, time=0)
        )

        # Compute starting note: octave * semitones + relative note
        base_note = 24 + (self.octave - 1) * 12 + self.note
        # Seconds per beat
        seconds = 60 / self.bpm
        # Note duration is one beat minus the cut, in milliseconds
        base_duration = (seconds - self.cut) * 1000

        # Prepend the base note to the midi if the preview is selected
        timer_delay = 0
        if self.preview:
            timer_delay = int(base_duration*self.preview_time)
            track.append(
                Message('note_on', note=base_note, velocity=100, time=0)
            )
            track.append(
                Message('note_off', note=base_note, time=timer_delay)
            )

        timer_data = []
        # Add the rest of the notes
        for idx, p in enumerate(seq):

            # Normalise the note step as a string
            item = str(p)

            # Extract the step
            step = int(sub(r'[^0-9]','',item))

            # If the number has dashes or dots, add half a beat or a quarter beat for each, respectively
            duration = base_duration * (1 + item.count('-')*0.5 + item.count('.')*0.25)

            # Calculate percentage of current step
            current_index = idx + 1
            percent = (current_index / len(seq)) * 100

            # If this is the last note and the user wants to, prolong it
            if current_index == len(seq) and self.prolong:
                logging.debug(f"prolonging {step}")
                delay = int(base_duration*self.prolong_time)
            else:
                delay = int(duration)

            # Append the note to the midi
            track.append(
                Message('note_on', note=(base_note+step), velocity=100, time=0)
            )
            track.append(
                Message('note_off', note=(base_note+step), time=delay)
            )
            timer_data.append([percent, timer_delay])
            timer_delay += duration

        # Save midi file and load it with pygame separately,
        #   to avoid race conditions
        mid.save(file=midi_file)
        midi_file.flush()
        midi_file.close()
        pygame.mixer.music.load(midi_file.name)

        pygame.mixer.music.play()

        # Cleanup
        if 'WARMUPPY_KEEP_MIDI' in os.environ:
            copyfile(midi_file.name, os.environ['WARMUPPY_KEEP_MIDI'])
        os.remove(midi_file.name)

        return timer_data

    def stop(self):
        # Stop the music
        pygame.mixer.music.stop()

    # Settings window told us that something changed, so reload everything
    def reload_settings(self):
        logging.debug("Settings saved, reloading")
        self.instrument = int(
            self.settings.value('instrument', DEFAULT_INSTRUMENT)
        )
        self.exercises = []
        self.settings.beginReadArray('exercises')
        for ex in self.settings.allKeys():
            if ex == 'size':
                continue
            self.exercises.append([
                ex,
                self.settings.value(ex)
            ])
        self.settings.endArray()
Exemple #14
0
class Settings:
    def __init__(self):

        # Standard constructor stuff
        super().__init__()
        self.settings = QSettings()

        if not pygame.get_init():
            pygame.init()
        # Instance variables
        self.exercises = []
        self.instrument = int(self.settings.value('instrument'))

        # Load exercises from stored settings
        self.settings.beginReadArray('exercises')
        for ex in self.settings.allKeys():
            if ex == 'size':
                continue
            self.exercises.append([ex, self.settings.value(ex)])
        self.settings.endArray()

    def remove_exercise(self, exercise_name):
        # Replace self.exercises with a copy without the selected exercise
        new_exercises = []
        for ex in self.exercises:
            if ex[0] != exercise_name:
                new_exercises.append(ex)
        self.exercises = new_exercises

    def reload_exercise(self, exercise_name, exercise_text):
        # Load all exercise names
        exercise_names = []
        for ex in self.exercises:
            exercise_names.append(ex[0])
        new_exercises = []
        # If the reloaded exercise is existing then update it in memory,
        #   otherwise just add it
        exercise_contents = exercise_text.split()
        if exercise_name in exercise_names:
            for ex in self.exercises:
                if ex[0] == exercise_name:
                    new_exercises.append([ex[0], exercise_contents])
                else:
                    new_exercises.append([ex[0], ex[1]])
            self.exercises = new_exercises
        else:
            self.exercises.append([exercise_name, exercise_contents])

    def set_instrument(self, instrument_id):
        self.instrument = instrument_id

    def save_settings(self):
        self.settings.beginWriteArray('exercises')
        for key in self.settings.allKeys():
            self.settings.remove(key) if key != 'size' else None
        for ex in self.exercises:
            self.settings.setValue(ex[0], ex[1])
        self.settings.endArray()
        self.settings.setValue('instrument', self.instrument)
        self.settings.sync()

    def preview(self):
        pygame.mixer.music.stop()
        midi_file = tempfile.NamedTemporaryFile(delete=False)
        mid = MidiFile()
        track = MidiTrack()
        mid.tracks.append(track)
        instrument = self.instrument
        track.append(Message('program_change', program=instrument, time=0))
        note = 60
        track.append(Message('note_on', note=note, velocity=100, time=0))
        track.append(Message('note_off', note=note, time=2000))
        mid.save(file=midi_file)
        midi_file.flush()
        midi_file.close()
        pygame.mixer.music.load(midi_file.name)
        pygame.mixer.music.play()
        if 'WARMUPPY_KEEP_MIDI' in os.environ:
            copyfile(midi_file.name, os.environ['WARMUPPY_KEEP_MIDI'])
        os.remove(midi_file.name)
Exemple #15
0
class Process(QObject):
    def __init__(self, engine):
        QObject.__init__(self)
        self.m_engine = engine
        self.project_name = ''
        self.process_name = list()
        self.process_description = list()
        self.action_name = list()
        self.settings = QSettings("Nebula")
        self.dat = dict()

    @Slot(str, str, result='QString')
    def process_settings(self, project_name, action_name):
        self.project_name = project_name
        self.action_name.append(action_name)
        self.settings = QSettings("Nebula", self.project_name)
        self.settings.beginGroup("ProcessInfo")
        self.settings.beginWriteArray(action_name)
        s = [str(i) for i in self.dat[project_name]]
        res = ",".join(s)
        for i in range(len(self.process_name)):
            self.settings.setArrayIndex(i)
            self.settings.setValue("Name", self.process_name[i])
            self.settings.setValue("Description", self.process_description[i])
            self.settings.setValue("Value", res)
        self.settings.endArray()
        self.settings.endGroup()
        print(self.settings.fileName())
        return self.settings.fileName()

    def process_info(self, name="", description=""):
        self.process_name.append(name)
        self.process_description.append(description)

    @Slot(str, result=bool)
    def generate_pdf(self, project_name):
        self.settings = QSettings("Nebula", project_name)

        pdf = CustomPDF()
        pdf.alias_nb_pages()
        pdf.add_page()
        pdf.set_font('Times', 'B', 15)
        pdf.cell(0, 5, 'Project details', ln=1)
        pdf.set_font('Times', '', 10)
        self.settings.beginGroup("Project")
        pdf.cell(0,
                 10,
                 txt="Name: {}".format(self.settings.value("Name")),
                 ln=1)
        pdf.cell(0,
                 10,
                 txt="Project creation date: {}".format(
                     self.settings.value("Date")),
                 ln=1)
        pdf.cell(0,
                 10,
                 txt="Inform creation date: {}".format(
                     self.settings.value("LastEdit")),
                 ln=1)
        pdf.cell(0, 10, txt=" ", ln=1)
        self.settings.endGroup()
        pdf.set_font('Times', 'B', 15)
        pdf.cell(0, 5, 'Signals', ln=1)
        pdf.set_font('Times', '', 10)
        self.settings.beginGroup("SignalFiles")
        pdf.cell(0,
                 10,
                 txt="Signals path: {}".format(self.settings.value("Path")),
                 ln=1)
        path = self.settings.value("Path")
        pdf.cell(0, 10, txt=" ", ln=1)
        self.settings.endGroup()
        pdf.set_font('Times', 'B', 15)
        pdf.cell(0, 5, 'Information', ln=1)
        pdf.set_font('Times', '', 10)
        self.settings.beginGroup("Info")
        size = self.settings.beginReadArray("sfreq")
        for i in range(size):
            self.settings.setArrayIndex(i)
            pdf.cell(0,
                     10,
                     txt="{}. sfreq: {}".format(i,
                                                self.settings.value("sfreq")),
                     ln=1)
        self.settings.endArray()
        size = self.settings.beginReadArray("SubjectInfo")
        for i in range(size):
            self.settings.setArrayIndex(i)
            pdf.cell(0,
                     10,
                     txt="{}. id: {}".format(i, self.settings.value("id")),
                     ln=1)
            pdf.cell(0,
                     10,
                     txt="{}. First name: {}".format(
                         i, self.settings.value("first_name")),
                     ln=1)
            pdf.cell(0,
                     10,
                     txt="{}. Last name: {}".format(
                         i, self.settings.value("last_name")),
                     ln=1)
            pdf.cell(0,
                     10,
                     txt="{}. Hand: {}".format(i, self.settings.value("hand")),
                     ln=1)
            pdf.cell(0,
                     10,
                     txt="{}. Sex: {}".format(i, self.settings.value("sex")),
                     ln=1)
        self.settings.endArray()
        self.settings.endGroup()
        pdf.cell(0, 10, txt=" ", ln=1)
        pdf.set_font('Times', 'B', 15)
        pdf.cell(0, 5, 'Process', ln=1)
        pdf.set_font('Times', '', 10)
        self.settings.beginGroup("ProcessInfo")
        for action_name in self.action_name:
            size = self.settings.beginReadArray(action_name)
            for i in range(size):
                self.settings.setArrayIndex(i)
                pdf.cell(0,
                         10,
                         txt="{}. Name: {}".format(
                             i, self.settings.value("Name")),
                         ln=1)
                pdf.cell(0,
                         10,
                         txt="{}. Description: {}".format(
                             i, self.settings.value("Description")),
                         ln=1)
                pdf.cell(0,
                         10,
                         txt="{}. Value: {}".format(
                             i, self.settings.value("Value")),
                         ln=1)
            self.settings.endArray()
        self.settings.endGroup()
        pdf.cell(0, 10, txt=" ", ln=1)
        print(path)
        pdf.output('{}_report.pdf'.format(project_name))
        print(f'PDF: {project_name}')
        return True

    @Slot(QObject, result="QVariantList")
    def add_chart_bar(self, chart_view):
        # https://stackoverflow.com/questions/57536401/how-to-add-qml-scatterseries-to-existing-qml-defined-chartview
        context = QQmlContext(self.m_engine.rootContext())
        context.setContextProperty("chart_view", chart_view)
        # context.setContextProperty("type", SeriesType.SeriesTypeBar.value)
        context.setContextProperty("type", SeriesType.SeriesTypePie.value)

        script = """chart_view.createSeries(type, "Pie series");"""
        expression = QQmlExpression(context, chart_view, script)
        serie = expression.evaluate()[0]
        if expression.hasError():
            print(expression.error())
            return
        print(serie, expression)
        data = self.dat[self.project_name]
        print(f'FROM ADD PIE CHART {data} and type {type(data)}')
        serie.append("a", 10.0)
        serie.append("b", 80.0)
        # serie.append("a", data[0] * 1000)
        # serie.append("b", data[1] * 1000)
        # serie.append("c", data[2] * 1000)
        # serie.append("b", data)
        return data

    @Slot(QtCharts.QAbstractSeries)
    def fill_serie(self, serie):
        import random
        mx, Mx = 0, 10
        my, My = -100, 100
        data = self.dat[self.project_name]
        serie.append(1, data[0] * 1000)
        serie.append(2, data[1] * 1000)
        serie.append(3, data[2] * 1000)
        # for _ in range(100):
        #     x = random.uniform(mx, Mx)
        #     y = random.uniform(my, My)
        #     serie.append(x, y)
        # https://doc.qt.io/qt-5/qml-qtcharts-scatterseries.html#borderColor-prop
        serie.setProperty("borderColor", QtGui.QColor("salmon"))
        # https://doc.qt.io/qt-5/qml-qtcharts-scatterseries.html#brush-prop
        serie.setProperty("brush", QtGui.QBrush(QtGui.QColor("green")))
        # https://doc.qt.io/qt-5/qml-qtcharts-scatterseries.html#borderColor-prop
        serie.setProperty("borderWidth", 4.0)

    # Process Example
    @Slot(str, result="QVariantList")
    def my_process_1(self, project_name):
        import statistics
        self.process_info("process_1", "std, variance and mean from channel 0")
        data = get_data_path(project_name)
        print(data, data[0])
        data = get_data(data[0])
        print(data.shape)
        var = statistics.variance(data[0, :])
        mean = statistics.mean(data[0, :])
        std = statistics.stdev(data[0, :])
        value = [std * 1000, float(var) * 1000, float(mean) * 1000]
        self.dat[project_name] = value
        print(value)
        return value