Ejemplo n.º 1
0
class RemoveColumnDialog(QDialog):
    def __init__(self, pm, parent=None):
        super(RemoveColumnDialog, self).__init__(parent)
        self.pm = pm
        self.combo = QComboBox(self)
        cols = ['']
        cols.extend(self.pm.get_custom_columns())
        self.combo.addItems(cols)
        self.message = QLabel('', self)
        self.combo.currentTextChanged.connect(self.update_message)
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Close, self)
        self.buttons.setEnabled(False)
        self.buttons.accepted.connect(self.handle_remove)
        self.buttons.rejected.connect(self.close)
        self.setWindowTitle('Remove Column')
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint
                            | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowTitleHint)

        vertical_layout = QVBoxLayout(self)
        vertical_layout.addWidget(self.combo)
        vertical_layout.addWidget(self.message)
        vertical_layout.addWidget(self.buttons)

    def update_message(self):
        if self.combo.itemText(0) == '':
            self.combo.removeItem(0)
        self.message.setText(f"Remove {self.combo.currentText()} column?")
        self.buttons.setEnabled(True)

    def handle_remove(self):
        self.pm.remove_column(self.combo.currentText())
        self.accept()
Ejemplo n.º 2
0
class UiColormapDialog(object):
    """
    UiAddMicrographDialog
    User interface for the add micrograph dialog which is used to import a micrograph into the program.
    """
    def __init__(self, colormap_dialog):

        # set window title, object name and window size
        colormap_dialog.setWindowTitle("Choose Colormap")
        colormap_dialog.setObjectName("ColormapDialog")
        colormap_dialog.setFixedWidth(455)
        colormap_dialog.setFixedHeight(100)

        # button box
        self.button_box = QDialogButtonBox(colormap_dialog)
        self.button_box.setEnabled(True)
        self.button_box.setGeometry(QRect(10, 60, 435, 30))
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.button_box.setObjectName("button_box")

        # colormap selector
        self.colormap_combobox = QComboBox(colormap_dialog)
        self.colormap_combobox.setGeometry(QRect(10, 10, 435, 30))
        self.colormap_combobox.setIconSize(QSize(435, 20))

        # connect accept and reject
        self.button_box.accepted.connect(colormap_dialog.accept)
        self.button_box.rejected.connect(colormap_dialog.reject)
Ejemplo n.º 3
0
class DecisionDialog(QDialog):
    def __init__(self, df: pandas.DataFrame):

        super().__init__(flags=Qt.Window | Qt.WindowTitleHint
                         | Qt.CustomizeWindowHint)

        # instance variables
        self.df = df
        # numberOfTraces = len(self.df['case:concept:name'].drop_duplicates())
        self.selectedTrace = None

        # dialog settings
        self.setWindowTitle("Decision point")
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # table to display dataframe
        self.table = QtWidgets.QTableView()
        self.table.setModel(TableModel(df))
        # select entire row
        self.table.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        # select only one row
        self.table.setSelectionMode(
            QtWidgets.QAbstractItemView.SingleSelection)
        # enable button when a row is selected
        # self.table.selectionModel().selectionChanged.connect(self.on_selection_changed)

        # button to select trace
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)
        # enabled only when a row is selected
        # self.buttonBox.setEnabled(False)
        self.buttonBox.accepted.connect(self.handleReturn)

        # layout
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(QLabel(f"Which trace do you want to execute?"))
        mainLayout.addWidget(self.table)
        mainLayout.addWidget(self.buttonBox)
        self.setLayout(mainLayout)

    def on_selection_changed(self):
        self.buttonBox.setEnabled(
            bool(self.table.selectionModel().selectedRows()))

    def handleReturn(self):
        # close dialog
        self.accept()
        try:
            # get index of selected row in pyqt table
            index = [
                i.row()
                for i in sorted(self.table.selectionModel().selectedRows())
            ][0]
        except IndexError:
            index = 0
        # caseID of chosen trace
        self.selectedTrace = self.df.at[index, 'case:concept:name']
Ejemplo n.º 4
0
    def createButtonBox(self):
        buttonBox = QDialogButtonBox(self)
        buttonBox.setEnabled(True)
        buttonBox.setOrientation(Qt.Horizontal)
        buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)

        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        return buttonBox
Ejemplo n.º 5
0
    def __init__(self, parent=None):
        super(ToolOffsetDialog, self).__init__(parent)
        self._color = QColor(0, 0, 0, 150)
        self._state = False
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowFlags(self.windowFlags() | Qt.Tool |
                            Qt.Dialog |
                            Qt.WindowStaysOnTopHint | Qt.WindowSystemMenuHint)
        self.setMinimumSize(200, 200)
        buttonBox = QDialogButtonBox()
        buttonBox.setEnabled(False)
        STATUS.connect('not-all-homed', lambda w, axis: buttonBox.setEnabled(False))
        STATUS.connect('all-homed', lambda w: buttonBox.setEnabled(True))
        STATUS.connect('state-estop', lambda w: buttonBox.setEnabled(False))
        STATUS.connect('state-estop-reset', lambda w: buttonBox.setEnabled(STATUS.machine_is_on()
                                                                           and STATUS.is_all_homed()))
        for i in('X', 'Y', 'Z'):
            b = 'button_%s' % i
            self[b] = QPushButton('Zero %s' % i)
            self[b].clicked.connect(self.zeroPress('%s' % i))
            buttonBox.addButton(self[b], 3)

        v = QVBoxLayout()
        h = QHBoxLayout()
        self._o = TOOLVIEW_WIDGET()
        self._o._hal_init()
        self.setLayout(v)
        v.addWidget(self._o)
        b = QPushButton('OK')
        b.clicked.connect(lambda: self.close())
        h.addWidget(b)
        h.addWidget(buttonBox)
        v.addLayout(h)
        self.setModal(True)
Ejemplo n.º 6
0
class AutoBaselineDialog(QtWidgets.QDialog):

    filesUpdated = QtCore.pyqtSignal()

    def __init__(self, expt, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.controller = AutoBaselineController(expt)
        self.layout()
        self.connect()
        self.controller.experimentLoaded.emit(self.controller.expt)

        self.setWindowIcon(QtGui.QIcon(":/icons/dna.png"))
        self.setWindowTitle("Auto-Detect Baseline")
        self.setMinimumWidth(650)

    def layout(self):
        gbox = QtWidgets.QGridLayout()
        gbox.setColumnStretch(1, 1)
        self.setLayout(gbox)

        gbox.addWidget(BaselineModelGroupBox(self.controller), 0, 0)
        gbox.addWidget(BaselineGmmCanvas(self.controller), 0, 1)
        gbox.addWidget(BaselineHmmCanvas(self.controller), 1, 0, 1, 2)
        gbox.addWidget(widgets.NavBar(self.controller), 2, 0, 1, 2)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        gbox.addWidget(self.buttonBox, 3, 0, 1, 2)

    def connect(self):
        self.controller.gmmTrainingThread.trainingStarted.connect(
            lambda: self.buttonBox.setEnabled(False))
        self.controller.gmmTrained.connect(
            lambda: self.buttonBox.setEnabled(True))
        self.controller.hmmTrainingThread.trainingStarted.connect(
            lambda: self.buttonBox.setEnabled(False))
        self.controller.hmmTrained.connect(
            lambda: self.buttonBox.setEnabled(True))
Ejemplo n.º 7
0
class CreatorGroupWidget(QWidget):
    '''
    Create a group widget inside the main window. Add a top group box,
    a tab widget in the middle and a bottom group box. The group widget
    and the top and the bottom group box get a grid layout.
    '''
    def __init__(self, parent):
        super(QWidget, self).__init__(parent)
        self.layout = QGridLayout(self)
        self.topgroupbox = QGroupBox(self.tr('LibreOffice Extension Creator'))
        topgridbox = QGridLayout()
        self.topgroupbox.setLayout(topgridbox)
        self.topgroupbox.setObjectName('topgroupbox')
        self.toplabel = QLabel(
            self.tr('You can use this program to create '
                    'a new non-code LibreOffice extension.'))
        self.toplabel.setObjectName('toplabel')
        topgridbox.addWidget(self.toplabel, 1, 0)
        self.tab_widget = CreatorTabWidget(self)
        self.bottomgroupbox = QGroupBox()
        bottomgridbox = QGridLayout()
        self.bottomgroupbox.setLayout(bottomgridbox)
        self.bottomgroupbox.setObjectName('bottomgroupbox')
        self.button_label = QLabel()
        self.button_label.setText(
            self.tr('Once you are finished with the data '
                    'fields, you could create the extension by clicking the '
                    'OK button.'))
        bottomgridbox.addWidget(self.button_label, 0, 0)
        QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.setEnabled(False)
        self.buttonBox.accepted.connect(self.tab_widget.accept)
        self.buttonBox.rejected.connect(self.tab_widget.reject)
        bottomgridbox.addWidget(self.buttonBox, 0, 1)
        self.layout.addWidget(self.topgroupbox, 0, 0)

        self.layout.addWidget(self.tab_widget, 1, 0)
        self.layout.addWidget(self.bottomgroupbox, 2, 0)
Ejemplo n.º 8
0
class RenameColumnDialog(QDialog):
    def __init__(self, pm, parent=None):
        super(RenameColumnDialog, self).__init__(parent)
        self.pm = pm
        self.column_to_rename = QLabel('column to rename:', self)
        self.combo = QComboBox(self)
        cols = ['']
        cols.extend(self.pm.get_custom_columns())
        self.combo.addItems(cols)
        self.combo.currentTextChanged.connect(self.handle_combo_change)
        self.new_name_label = QLabel('new name:', self)
        self.new_name_field = QLineEdit(self)
        self.new_name_field.textChanged.connect(self.handle_text_change)
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Close, self)
        self.buttons.setEnabled(False)
        self.buttons.accepted.connect(self.handle_rename)
        self.buttons.rejected.connect(self.close)
        self.setWindowTitle('Rename Column')
        self.setWindowFlags(QtCore.Qt.WindowCloseButtonHint
                            | QtCore.Qt.WindowSystemMenuHint
                            | QtCore.Qt.WindowTitleHint)

        grid_layout = QGridLayout(self)
        grid_layout.addWidget(self.column_to_rename, 0, 0)
        grid_layout.addWidget(self.combo, 0, 1)
        grid_layout.addWidget(self.new_name_label, 1, 0)
        grid_layout.addWidget(self.new_name_field, 1, 1)
        grid_layout.addWidget(self.buttons, 2, 0, 1, 2)

    def handle_combo_change(self):
        if self.combo.itemText(0) == '':
            self.combo.removeItem(0)
        if self.new_name_field.text() != '':
            self.buttons.setEnabled(True)

    def handle_text_change(self):
        if self.new_name_field.text() != '' and self.combo.itemText(0) != '':
            self.buttons.setEnabled(True)
        else:
            self.buttons.setEnabled(False)

    def handle_rename(self):
        self.pm.rename_column(self.combo.currentText(),
                              self.new_name_field.text())
        self.accept()
Ejemplo n.º 9
0
    def __init__(self, parent=None):
        super(ToolOffsetDialog, self).__init__(parent)
        self._color = QColor(0, 0, 0, 150)
        self._state = False
        self._request_name = 'TOOLOFFSET'

        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowFlags(self.windowFlags() | Qt.Tool | Qt.Dialog
                            | Qt.WindowStaysOnTopHint
                            | Qt.WindowSystemMenuHint)
        self.setMinimumSize(200, 200)
        buttonBox = QDialogButtonBox()
        buttonBox.setEnabled(False)
        STATUS.connect('not-all-homed',
                       lambda w, axis: buttonBox.setEnabled(False))
        STATUS.connect('all-homed', lambda w: buttonBox.setEnabled(True))
        STATUS.connect('state-estop', lambda w: buttonBox.setEnabled(False))
        STATUS.connect(
            'state-estop-reset', lambda w: buttonBox.setEnabled(
                STATUS.machine_is_on() and STATUS.is_all_homed()))
        for i in ('X', 'Y', 'Z'):
            b = 'button_%s' % i
            self[b] = QPushButton('Zero %s' % i)
            self[b].clicked.connect(self.zeroPress('%s' % i))
            buttonBox.addButton(self[b], 3)

        v = QVBoxLayout()
        h = QHBoxLayout()
        self._o = TOOLVIEW_WIDGET()
        self._o._hal_init()
        self.setLayout(v)
        v.addWidget(self._o)
        b = QPushButton('OK')
        b.clicked.connect(lambda: self.close())
        h.addWidget(b)
        h.addWidget(buttonBox)
        v.addLayout(h)
        self.setModal(True)
Ejemplo n.º 10
0
class OWLTranslationForm(QDialog):
    """
    This class implements the form used to perform Graphol -> OWL ontology translation.
    """
    def __init__(self, scene, filepath, parent=None):
        """
        Initialize the form dialog.
        :type scene: DiagramScene
        :type filepath: str
        :type parent: QWidget
        """
        super().__init__(parent)

        self.scene = scene
        self.filepath = filepath
        self.worker = None
        self.workerThread = None

        self.iriField = StringField(self)
        self.iriField.setFixedWidth(300)
        self.iriField.setValidator(QRegExpValidator(QRegExp('[\w:\/\[\]=?%#~\.\-\+]*'), self))

        self.prefixField = StringField(self)
        self.prefixField.setFixedWidth(300)
        self.prefixField.setValidator(QRegExpValidator(QRegExp('[\w]*'), self))

        self.syntaxField = ComboBox(self)
        for syntax in OWLSyntax:
            self.syntaxField.addItem(syntax.value, syntax)
        self.syntaxField.setCurrentIndex(0)

        self.progressBar = QProgressBar(self)
        self.progressBar.setAlignment(Qt.AlignHCenter)
        self.progressBar.setRange(0, 100)
        self.progressBar.setValue(0)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.buttonBox.button(QDialogButtonBox.Ok).setDisabled(True)

        self.mainLayout = QFormLayout(self)
        self.mainLayout.addRow('IRI', self.iriField)
        self.mainLayout.addRow('Prefix', self.prefixField)
        self.mainLayout.addRow('Syntax', self.syntaxField)
        self.mainLayout.addRow(self.progressBar)
        self.mainLayout.addRow(self.buttonBox)

        self.setWindowTitle('OWL Translation')
        self.setWindowIcon(QIcon(':/images/eddy'))
        self.setFixedSize(self.sizeHint())

        connect(self.buttonBox.accepted, self.run)
        connect(self.buttonBox.rejected, self.reject)
        connect(self.iriField.textChanged, self.iriChanged)

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    @pyqtSlot(Exception)
    def errored(self, exception):
        """
        Executed whenever the translation errors.
        :type exception: Exception
        """
        if isinstance(exception, MalformedDiagramError):

            msgbox = QMessageBox(self)
            msgbox.setIconPixmap(QPixmap(':/icons/warning'))
            msgbox.setWindowIcon(QIcon(':/images/eddy'))
            msgbox.setWindowTitle('Malformed Diagram')
            msgbox.setText('Malformed expression detected on {}: {}'.format(exception.item, exception))
            msgbox.setInformativeText('Do you want to see the error in the diagram?')
            msgbox.setStandardButtons(QMessageBox.Yes|QMessageBox.No)
            S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            L = msgbox.layout()
            L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
            msgbox.exec_()

            if msgbox.result() == QMessageBox.Yes:
                for view in self.scene.views():
                    if isinstance(view, MainView):
                        view.centerOn(exception.item)

        else:

            msgbox = QMessageBox(self)
            msgbox.setIconPixmap(QPixmap(':/icons/error'))
            msgbox.setWindowIcon(QIcon(':/images/eddy'))
            msgbox.setWindowTitle('Unhandled exception!')
            msgbox.setStandardButtons(QMessageBox.Close)
            msgbox.setText('Diagram translation could not be completed!')
            msgbox.setInformativeText('Please <a href="{}">submit a bug report</a> with detailed information.'.format(BUG_TRACKER))
            msgbox.setDetailedText(''.join(traceback.format_exception(type(exception), exception, exception.__traceback__)))
            S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
            L = msgbox.layout()
            L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
            msgbox.exec_()

        self.workerThread.quit()
        self.reject()

    @pyqtSlot()
    def completed(self):
        """
        Executed whenever the translation completes.
        """
        self.workerThread.quit()

        file = File(path=self.filepath)
        file.write(string=self.worker.export(syntax=self.syntaxField.currentData()))

        msgbox = QMessageBox(self)
        msgbox.setIconPixmap(QPixmap(':/icons/info'))
        msgbox.setWindowIcon(QIcon(':/images/eddy'))
        msgbox.setText('Translation completed!')
        msgbox.setInformativeText('Do you want to open the OWL ontology?')
        msgbox.setStandardButtons(QMessageBox.Yes|QMessageBox.No)
        S = QSpacerItem(400, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
        L = msgbox.layout()
        L.addItem(S, L.rowCount(), 0, 1, L.columnCount())
        msgbox.exec_()

        if msgbox.result() == QMessageBox.Yes:
            openPath(self.filepath)

        self.accept()

    @pyqtSlot(int, int)
    def progress(self, current, total):
        """
        Update the progress bar showing the translation advancement.
        :type current: int
        :type total: int
        """
        self.progressBar.setRange(0, total)
        self.progressBar.setValue(current)

    @pyqtSlot()
    def iriChanged(self):
        """
        Executed whenever the value of the prefix field changes.
        """
        button = self.buttonBox.button(QDialogButtonBox.Ok)
        button.setEnabled(not isEmpty(self.iriField.value()))

    @pyqtSlot()
    def run(self):
        """
        Perform the Graphol -> OWL translation in a separate thread.
        """
        ontoIRI = self.iriField.value()
        ontoPrefix = self.prefixField.value()

        self.buttonBox.setEnabled(False)
        self.syntaxField.setEnabled(False)

        if not ontoIRI.endswith('#'):
            ontoIRI = '{0}#'.format(ontoIRI)

        self.workerThread = QThread()
        self.worker = OWLExporter(scene=self.scene, ontoIRI=ontoIRI, ontoPrefix=ontoPrefix)
        self.worker.moveToThread(self.workerThread)

        connect(self.worker.completed, self.completed)
        connect(self.worker.errored, self.errored)
        connect(self.worker.progress, self.progress)
        connect(self.workerThread.started, self.worker.work)

        self.workerThread.start()
class RoisToolbox(QDialog):
    def __init__(self, parent=None, QApplication=None):
        super().__init__(parent)
        self.setWindowTitle(' Creating Rois')
        vbox = QVBoxLayout(self)
        grid = QGridLayout()
        # Init
        self.spi = None
        self.atlas = None
        self.data_lut = None
        self.palette = None
        self.output_directory = None
        # SPI file
        grid.addWidget(QLabel('Source space:'), 0, 0)
        self.QLineEdit_spi = QLineEdit()
        grid.addWidget(self.QLineEdit_spi, 0, 1)
        self.QPushButton_spi = QPushButton('Open')
        self.QPushButton_spi.clicked.connect(self.open_spi)
        grid.addWidget(self.QPushButton_spi, 0, 3)
        # MRI file
        grid.addWidget(QLabel('Atlas mask:'), 1, 0)
        self.QLineEdit_atlas = QLineEdit()
        grid.addWidget(self.QLineEdit_atlas, 1, 1)
        self.QPushButton_atlas = QPushButton('Open')
        self.QPushButton_atlas.clicked.connect(self.open_atlas)
        grid.addWidget(self.QPushButton_atlas, 1, 3)
        # SPI file
        grid.addWidget(QLabel('LookUp Table:'), 2, 0)
        self.QLineEdit_lut = QLineEdit()
        grid.addWidget(self.QLineEdit_lut, 2, 1)
        self.QPushButton_lut = QPushButton('Open')
        self.QPushButton_lut.clicked.connect(self.open_lut)
        grid.addWidget(self.QPushButton_lut, 2, 3)
        # outputdir
        grid.addWidget(QLabel('Output directory:'), 3, 0)
        self.QLineEdit_output_dir = QLineEdit()
        self.output_directory = os.getcwd()
        self.QLineEdit_output_dir.setText(self.output_directory)
        grid.addWidget(self.QLineEdit_output_dir, 3, 1)
        self.QPushButton_open_output_dir = QPushButton('Open')
        self.QPushButton_open_output_dir.clicked.connect(
            self.open_output_directory)
        grid.addWidget(self.QPushButton_open_output_dir, 3, 3)
        # run
        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        grid.addWidget(self.buttonbox, 4, 1, 1, 4)
        self.buttonbox.accepted.connect(self.run)
        self.buttonbox.rejected.connect(self.reject)
        self.buttonbox.setEnabled(False)
        vbox.addLayout(grid)

    def data_changed(self):
        if any(x is None for x in [
                self.spi, self.atlas, self.data_lut, self.palette,
                self.output_directory
        ]):
            self.buttonbox.setEnabled(False)
        else:
            self.buttonbox.setEnabled(True)

    def open_spi(self):
        filter = "spi(*.spi)"
        fname, _ = QFileDialog.getOpenFileName(self,
                                               'Open Source Space',
                                               filter=filter)
        if fname:
            self.fname_spi = fname
            with open(self.fname_spi) as f:
                self.spi = pycartool.source_space.read_spi(self.fname_spi)
        else:
            self.fname_spi = None
        self.QLineEdit_spi.setText(self.fname_spi)
        self.data_changed()
        return ()

    def open_atlas(self):
        filter = "Nifti(*.nii)"
        fname, _ = QFileDialog.getOpenFileName(self,
                                               'Open Atlas',
                                               filter=filter)
        if fname:
            self.fname_atlas = fname
            with open(self.fname_atlas) as f:
                self.atlas = nib.load(self.fname_atlas)
        else:
            self.fname_atlas = None
        self.QLineEdit_atlas.setText(self.fname_atlas)
        self.data_changed()
        return ()

    def open_lut(self):
        filter = "LookUp Table(*.txt)"
        fname, _ = QFileDialog.getOpenFileName(self, 'Open LUT', filter=filter)
        if fname:
            self.fname_lut = fname
            with open(self.fname_lut) as f:
                self.data_lut, self.palette = open_lut(self.fname_lut)
        else:
            self.fname_lut = None

        self.QLineEdit_lut.setText(self.fname_lut)
        self.data_changed()
        return ()

    def open_output_directory(self):
        dirname = QFileDialog.getExistingDirectory(self, 'Output directory')
        if dirname:
            self.output_directory = dirname
        else:
            self.output_directory = None
        self.QLineEdit_output_dir.setText(self.output_directory)
        self.data_changed()
        return ()

    def run(self):
        try:
            base_name_spi = os.path.basename(self.fname_spi)
            base_name_spi = os.path.splitext(base_name_spi)[0]

            base_name_atlas = os.path.basename(self.fname_atlas)
            base_name_atlas = os.path.splitext(base_name_atlas)[0]

            base_name = base_name_atlas + '__' + base_name_spi
            base_name = os.path.join(self.output_directory, base_name)

            fname_rois = base_name + '.rois'
            fname_source_mri = base_name + '.nii'
            fname_rois_spi = base_name + '_rois.spi'
            QApplication.setOverrideCursor(Qt.WaitCursor)
            rois, img, rois_spi = create_region_of_interest(
                self.atlas, self.spi, self.data_lut, self.palette)
            save_rois(rois, fname_rois)
            img.to_filename(fname_source_mri)
            rois_spi.save(fname_rois_spi)
            QApplication.restoreOverrideCursor()
            self.QMessageBox_finnish = QMessageBox()
            self.QMessageBox_finnish.setWindowTitle("Finished")
            self.QMessageBox_finnish.setText("Done.")
            self.QMessageBox_finnish.exec_()
        except Exception as e:
            QApplication.restoreOverrideCursor()
            self.QErrorMessage = QErrorMessage()
            self.QErrorMessage.showMessage(str(e))
class RoisTcToolbox(QDialog):
    def __init__(self, parent=None, QApplication=None):
        super().__init__(parent)
        self.setWindowTitle(' Compute Rois time course')
        vbox = QVBoxLayout(self)
        grid = QGridLayout()
        # Init
        self.fname_rois = None
        self.rois = None
        self.ris_files = None
        self.output_directory = None
        self.scalings = {"None": "none",
                         "Eigenvalue": "Eigenvalues"}
        # Ris files
        grid.addWidget(QLabel('Ris files:'), 0, 0)
        self.QListWidget_ris = QListWidget()
        grid.addWidget(self.QListWidget_ris, 0, 1)
        self.QPushButton_ris = QPushButton('Open')
        self.QPushButton_ris.clicked.connect(self.open_ris)
        grid.addWidget(self.QPushButton_ris, 0, 3)
        # ROI file
        grid.addWidget(QLabel('ROI file:'), 1, 0)
        self.QLineEdit_rois = QLineEdit()
        grid.addWidget(self.QLineEdit_rois, 1, 1)
        self.QPushButton_rois = QPushButton('Open')
        self.QPushButton_rois.clicked.connect(self.open_rois)
        grid.addWidget(self.QPushButton_rois, 1, 3)
        # scaling
        grid.addWidget(QLabel('Scaling:'), 4, 0)
        self.QComboBox_scaling = QComboBox()
        self.QComboBox_scaling.addItems(self.scalings.keys())
        self.QComboBox_scaling.setCurrentText('None')
        grid.addWidget(self.QComboBox_scaling, 4, 1)
        # outputdir
        grid.addWidget(QLabel('Output directory:'), 5, 0)
        self.QLineEdit_output_dir = QLineEdit()
        self.output_directory = os.getcwd()
        self.QLineEdit_output_dir.setText(self.output_directory)
        grid.addWidget(self.QLineEdit_output_dir, 5, 1)
        self.QPushButton_open_output_dir = QPushButton('Open')
        self.QPushButton_open_output_dir.clicked.connect(
                                                   self.open_output_directory)
        grid.addWidget(self.QPushButton_open_output_dir, 5, 3)
        # run
        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                          QDialogButtonBox.Cancel)
        grid.addWidget(self.buttonbox, 6, 1, 1, 4)
        self.buttonbox.accepted.connect(self.run)
        self.buttonbox.rejected.connect(self.reject)
        # self.buttonbox.setEnabled(False)

        vbox.addLayout(grid)

    def open_ris(self):
        filter = "RIS (*.ris)"
        names, _ = QFileDialog.getOpenFileNames(self, "Open RIS files",
                                                filter=filter)
        self.ris_files = names
        self.QListWidget_ris.clear()
        self.QListWidget_ris.insertItems(0, self.ris_files)
        self.data_changed()
        return()

    def open_rois(self):
        filter = "ROIs(*.rois)"
        fname, _ = QFileDialog.getOpenFileName(self,
                                               'Open ROI',
                                               filter=filter)
        if fname:
            self.fname_rois = fname
            try:
                with open(self.fname_rois) as f:
                    self.rois = pycartool.regions_of_interest.read_roi(self.fname_rois)
            except Exception as e:
                QApplication.restoreOverrideCursor()
                self.QErrorMessage = QErrorMessage()
                self.QErrorMessage.showMessage(str(e))
        else:
            self.fname_rois = None
            self.rois = None
        self.QLineEdit_rois.setText(self.fname_rois)
        self.data_changed()
        return()

    def open_output_directory(self):
        dirname = QFileDialog.getExistingDirectory(self, 'Output directory')
        if dirname:
            self.output_directory = dirname
        else:
            self.output_directory = None
        self.QLineEdit_output_dir.setText(self.output_directory)
        self.data_changed()
        return()

    def data_changed(self):
        if any(x is None for x in [self.rois, self.fname_rois,
                                   self.ris_files,
                                   self.output_directory]):
            self.buttonbox.setEnabled(False)
        else:
            self.buttonbox.setEnabled(True)
        return()

    def run(self):
        try:
            QApplication.setOverrideCursor(Qt.WaitCursor)
            transform_svds(self.ris_files,
                           self.rois,
                           self.QComboBox_scaling.currentText(),
                           self.output_directory)
            QApplication.restoreOverrideCursor()
            self.QMessageBox_finnish = QMessageBox()
            self.QMessageBox_finnish.setWindowTitle("Finished")
            self.QMessageBox_finnish.setText("Done.")
            self.QMessageBox_finnish.exec_()
        except Exception as e:
            QApplication.restoreOverrideCursor()
            self.QErrorMessage = QErrorMessage()
            self.QErrorMessage.showMessage(str(e))
Ejemplo n.º 13
0
class SetupDialog(QDialog):
    """ This dialog consists of two parts/tabs: The first one is supposed to help choosing
        container, device name and mount point to unlock an existing container.
        The second tab assists in creating a new encrypted LUKS container.
    """
    def __init__(self, parent):
        """ :param parent: The parent window/dialog used to enable modal behaviour
            :type parent: :class:`PyQt4.QtGui.QWidget`
        """
        super(SetupDialog,
              self).__init__(parent,
                             Qt.WindowCloseButtonHint | Qt.WindowTitleHint)
        self.setWindowTitle(_('luckyLUKS'))

        self.worker = parent.worker
        self.is_busy = False

        # build ui
        self.layout = QVBoxLayout()
        self.layout.setSizeConstraint(QLayout.SetFixedSize)
        style = QApplication.style()
        # set up stacked layout: initially only the main tab pane (unlock/create)
        self.main_pane = QStackedWidget()
        self.tab_pane = QTabWidget()
        self.main_pane.addWidget(self.tab_pane)
        self.layout.addWidget(self.main_pane)
        self.create_pane = None  # init in on_create_container()

        # Unlock Tab
        unlock_grid = QGridLayout()
        unlock_grid.setColumnMinimumWidth(1, 220)
        uheader = QLabel(
            _('<b>Unlock an encrypted container</b>\n') +
            _('Please select container file and name'))
        uheader.setContentsMargins(0, 10, 0, 10)
        unlock_grid.addWidget(uheader, 0, 0, 1, 3, Qt.AlignCenter)

        label = QLabel(_('container file'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 1, 0)
        self.unlock_container_file = QLineEdit()
        unlock_grid.addWidget(self.unlock_container_file, 1, 1)
        button_choose_file = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '', self)
        button_choose_file.setToolTip(_('choose file'))
        unlock_grid.addWidget(button_choose_file, 1, 2)
        button_choose_file.clicked.connect(self.on_select_container_clicked)

        label = QLabel(_('device name'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 2, 0)
        self.unlock_device_name = QLineEdit()
        unlock_grid.addWidget(self.unlock_device_name, 2, 1)
        # advanced settings
        a_settings = QExpander(_('Advanced'), self, False)
        unlock_grid.addWidget(a_settings, 3, 0, 1, 3)

        label = QLabel(_('key file'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 4, 0)
        self.unlock_keyfile = QLineEdit()
        unlock_grid.addWidget(self.unlock_keyfile, 4, 1)
        button_choose_uKeyfile = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_uKeyfile.setToolTip(_('choose keyfile'))
        unlock_grid.addWidget(button_choose_uKeyfile, 4, 2)
        button_choose_uKeyfile.clicked.connect(
            lambda: self.on_select_keyfile_clicked('Unlock'))
        a_settings.addWidgets([
            unlock_grid.itemAtPosition(4, column).widget()
            for column in range(0, 3)
        ])

        label = QLabel(_('mount point'))
        label.setIndent(5)
        unlock_grid.addWidget(label, 5, 0)
        self.unlock_mountpoint = QLineEdit()
        unlock_grid.addWidget(self.unlock_mountpoint, 5, 1)
        button_choose_mountpoint = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_mountpoint.setToolTip(_('choose folder'))
        unlock_grid.addWidget(button_choose_mountpoint, 5, 2)
        button_choose_mountpoint.clicked.connect(
            self.on_select_mountpoint_clicked)
        a_settings.addWidgets([
            unlock_grid.itemAtPosition(5, column).widget()
            for column in range(0, 3)
        ])

        unlock_grid.setRowStretch(6, 1)
        unlock_grid.setRowMinimumHeight(6, 10)
        button_help_unlock = QPushButton(
            style.standardIcon(QStyle.SP_DialogHelpButton), _('Help'))
        button_help_unlock.clicked.connect(self.show_help_unlock)
        unlock_grid.addWidget(button_help_unlock, 7, 2)

        unlock_tab = QWidget()
        unlock_tab.setLayout(unlock_grid)
        self.tab_pane.addTab(unlock_tab, _('Unlock Container'))

        # Create Tab
        create_grid = QGridLayout()
        cheader = QLabel(
            _('<b>Create a new encrypted container</b>\n') +
            _('Please choose container file, name and size'))
        cheader.setContentsMargins(0, 10, 0, 10)
        create_grid.addWidget(cheader, 0, 0, 1, 3, Qt.AlignCenter)

        label = QLabel(_('container file'))
        label.setIndent(5)
        create_grid.addWidget(label, 1, 0)
        self.create_container_file = QLineEdit()
        create_grid.addWidget(self.create_container_file, 1, 1)
        button_choose_file = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_file.setToolTip(_('set file'))
        create_grid.addWidget(button_choose_file, 1, 2)
        button_choose_file.clicked.connect(self.on_save_container_clicked)

        label = QLabel(_('device name'))
        label.setIndent(5)
        create_grid.addWidget(label, 2, 0)
        self.create_device_name = QLineEdit()
        create_grid.addWidget(self.create_device_name, 2, 1)

        label = QLabel(_('container size'))
        label.setIndent(5)
        create_grid.addWidget(label, 3, 0)
        self.create_container_size = QSpinBox()
        self.create_container_size.setRange(1, 1000000000)
        self.create_container_size.setValue(1)
        create_grid.addWidget(self.create_container_size, 3, 1)

        self.create_size_unit = QComboBox()
        self.create_size_unit.addItems(['MB', 'GB'])
        self.create_size_unit.setCurrentIndex(1)
        create_grid.addWidget(self.create_size_unit, 3, 2)
        # advanced settings
        a_settings = QExpander(_('Advanced'), self, False)
        create_grid.addWidget(a_settings, 4, 0, 1, 3)

        label = QLabel(_('key file'))
        label.setIndent(5)
        create_grid.addWidget(label, 5, 0)
        self.create_keyfile = QLineEdit()
        create_grid.addWidget(self.create_keyfile, 5, 1)
        button_choose_cKeyfile = QPushButton(
            style.standardIcon(QStyle.SP_DialogOpenButton), '')
        button_choose_cKeyfile.setToolTip(_('choose keyfile'))
        create_grid.addWidget(button_choose_cKeyfile, 5, 2)
        button_choose_cKeyfile.clicked.connect(
            lambda: self.on_select_keyfile_clicked('Create'))
        a_settings.addWidgets([
            create_grid.itemAtPosition(5, column).widget()
            for column in range(0, 3)
        ])

        button_create_keyfile = QPushButton(_('Create key file'))
        button_create_keyfile.clicked.connect(self.on_create_keyfile)
        create_grid.addWidget(button_create_keyfile, 6, 1)
        a_settings.addWidgets([button_create_keyfile])

        label = QLabel(_('format'))
        label.setIndent(5)
        create_grid.addWidget(label, 7, 0)
        self.create_encryption_format = QComboBox()
        self.create_encryption_format.addItem('LUKS')
        self.create_encryption_format.addItem('TrueCrypt')
        if not is_installed('tcplay'):
            self.create_encryption_format.setEnabled(False)
        self.create_encryption_format.setCurrentIndex(0)
        create_grid.addWidget(self.create_encryption_format, 7, 1)
        a_settings.addWidgets([
            create_grid.itemAtPosition(7, column).widget()
            for column in range(0, 2)
        ])

        label = QLabel(_('filesystem'))
        label.setIndent(5)
        create_grid.addWidget(label, 8, 0)
        filesystems = ['ext4', 'ext2', 'ntfs']
        self.create_filesystem_type = QComboBox()
        for filesystem in filesystems:
            if is_installed('mkfs.' + filesystem):
                self.create_filesystem_type.addItem(filesystem)
        self.create_filesystem_type.setCurrentIndex(0)
        create_grid.addWidget(self.create_filesystem_type, 8, 1)
        a_settings.addWidgets([
            create_grid.itemAtPosition(8, column).widget()
            for column in range(0, 2)
        ])

        create_grid.setRowStretch(9, 1)
        create_grid.setRowMinimumHeight(9, 10)
        button_help_create = QPushButton(
            style.standardIcon(QStyle.SP_DialogHelpButton), _('Help'))
        button_help_create.clicked.connect(self.show_help_create)
        create_grid.addWidget(button_help_create, 10, 2)

        create_tab = QWidget()
        create_tab.setLayout(create_grid)
        self.tab_pane.addTab(create_tab, _('Create New Container'))
        self.tab_pane.currentChanged.connect(self.on_switchpage_event)

        # OK and Cancel buttons
        self.buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                        | QDialogButtonBox.Cancel,
                                        parent=self)
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))
        self.buttons.accepted.connect(self.on_accepted)
        self.buttons.rejected.connect(self.reject)
        self.layout.addWidget(self.buttons)

        # ui built, add to widget
        self.setLayout(self.layout)

    def on_create_container(self):
        """ Triggered by clicking create.
            Hides the unlock/create pane and switches to a status pane
            where the progress in creating the new container can be followed step by step.
            This shows the header and the first step:
            Initializing the container file with random data
        """
        self.init_create_pane()

        header = QLabel(
            _('<b>Creating new container</b>\n') +
            _('patience .. this might take a while'))
        header.setContentsMargins(0, 10, 0, 10)
        self.create_status_grid.addWidget(header, 0, 0, 1, 3, Qt.AlignCenter)

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 1/3</b>'), 1, 0)
        self.create_status_grid.addWidget(
            QLabel(_('Initializing Container File')), 1, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[0].setRange(0, 100)
        self.create_status_grid.addWidget(self.create_progressbars[0], 2, 0, 1,
                                          3)
        self.create_status_grid.setRowStretch(7, 1)  # top align
        # add to stack widget and switch display
        self.main_pane.addWidget(self.create_pane)
        self.main_pane.setCurrentIndex(1)

        # calculate designated container size for worker and progress indicator
        size = self.create_container_size.value()
        size = size * (
            1024 * 1024 * 1024 if self.create_size_unit.currentIndex() == 1
            else 1024 * 1024)  # GB vs MB
        location = self.encode_qt_output(self.create_container_file.text())
        if not os.path.dirname(location):
            location = os.path.join(os.path.expanduser('~'), location)
            self.create_container_file.setText(location)
        # start timer for progressbar updates during container creation
        self.create_timer.timeout.connect(
            lambda: self.display_progress_percent(location, size))
        self.create_timer.start(500)

        self.worker.execute(command={
            'type':
            'request',
            'msg':
            'create',
            'device_name':
            self.encode_qt_output(self.create_device_name.text()),
            'container_path':
            location,
            'container_size':
            size,
            'key_file':
            self.encode_qt_output(self.create_keyfile.text())
            if self.create_keyfile.text() != '' else None,
            'filesystem_type':
            str(self.create_filesystem_type.currentText()),
            'encryption_format':
            str(self.create_encryption_format.currentText()),
        },
                            success_callback=self.on_luksFormat_prompt,
                            error_callback=lambda msg: self.
                            display_create_failed(msg, stop_timer=True))

    def on_luksFormat_prompt(self, msg):
        """ Triggered after the container file is created on disk
            Shows information about the next step and asks the user
            for the passphrase to be used with the new container
        """
        self.set_progress_done(self.create_timer, self.create_progressbars[0])

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 2/3</b>'), 3, 0)
        self.create_status_grid.addWidget(QLabel(_('Initializing Encryption')),
                                          3, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[1].setRange(0, 0)
        self.create_status_grid.addWidget(self.create_progressbars[1], 4, 0, 1,
                                          3)

        if msg == 'getPassword':
            try:
                self.worker.execute(
                    command={
                        'type': 'response',
                        'msg': FormatContainerDialog(self).get_password()
                    },
                    success_callback=self.on_creating_filesystem,
                    error_callback=self.display_create_failed)
            except UserInputError:  # user cancelled dlg
                self.worker.execute({
                    'type': 'abort',
                    'msg': ''
                }, None, None)  # notify worker process
                self.display_create_failed(_('Initialize container aborted'))
        else:  # using keyfile
            self.worker.execute(command={
                'type': 'response',
                'msg': ''
            },
                                success_callback=self.on_creating_filesystem,
                                error_callback=self.display_create_failed)

    def on_creating_filesystem(self, msg):
        """ Triggered after LUKS encryption got initialized.
            Shows information about the last step
        """
        self.set_progress_done(progressbar=self.create_progressbars[1])

        self.create_status_grid.addWidget(
            QLabel('<b>' + _('Step') + ' 3/3</b>'), 5, 0)
        self.create_status_grid.addWidget(QLabel(_('Initializing Filesystem')),
                                          5, 1)
        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[2].setRange(0, 0)
        self.create_status_grid.addWidget(self.create_progressbars[2], 6, 0, 1,
                                          3)

        self.worker.execute(command={
            'type': 'response',
            'msg': ''
        },
                            success_callback=self.display_create_success,
                            error_callback=self.display_create_failed)

    def display_create_success(self, msg):
        """ Triggered after successful creation of a new container """
        self.set_progress_done(progressbar=self.create_progressbars[2])
        # copy values of newly created container to unlock dlg und reset create values
        self.unlock_container_file.setText(self.create_container_file.text())
        self.unlock_device_name.setText(self.create_device_name.text())
        self.unlock_keyfile.setText(self.create_keyfile.text())
        show_info(
            self,
            _('<b>{device_name}\nsuccessfully created!</b>\nClick on unlock to use the new container'
              ).format(device_name=self.encode_qt_output(
                  self.create_device_name.text())), _('Success'))
        # reset create ui and switch to unlock tab
        self.create_container_file.setText('')
        self.create_device_name.setText('')
        self.create_container_size.setValue(1)
        self.create_size_unit.setCurrentIndex(1)
        self.create_keyfile.setText('')
        self.create_encryption_format.setCurrentIndex(0)
        self.create_filesystem_type.setCurrentIndex(0)
        self.display_create_done()
        self.tab_pane.setCurrentIndex(0)

    def display_create_failed(self, errormessage, stop_timer=False):
        """ Triggered when an error happend during the create process
            :param errormessage: errormessage to be shown
            :type errormessage: str
            :param stop_timer: stop a progress indicator?
            :type stop_timer: bool
        """
        if stop_timer:
            self.set_progress_done(self.create_timer)
        show_alert(self, errormessage)
        self.display_create_done()

    def display_create_done(self):
        """ Helper to hide the create process informations and show the unlock/create pane """
        self.is_busy = False
        self.main_pane.setCurrentIndex(0)
        self.buttons.setEnabled(True)

    def set_progress_done(self, timeout=None, progressbar=None):
        """ Helper to end stop the progress indicator
            :param timeout: Timer to stop
            :type timeout: QTimer or None
            :param progressbar: progressbar widget to set to 'Done'
            :type progressbar: :class:`QProgressBar` or None
        """
        if timeout is not None:
            timeout.stop()
        if progressbar is not None:
            if not progressbar.maximum():
                progressbar.setRange(0, 100)
            progressbar.setValue(100)
            progressbar.setFormat(_('Done'))

    def on_accepted(self):
        """ Event handler for response:
            Start unlock or create action
        """
        try:
            if self.tab_pane.currentIndex() == 1:

                self.on_create_container()

            else:
                UnlockContainerDialog(
                    self, self.worker, self.get_luks_device_name(),
                    self.get_encrypted_container(), self.get_keyfile(),
                    self.get_mount_point()).communicate()  # blocks

                # optionally create startmenu entry
                self.show_create_startmenu_entry()
                # all good, now switch to main window
                self.accept()

        except UserInputError as error:
            show_alert(self, format_exception(error))

    def init_create_pane(self):
        """ Helper that initializes the ui for the progress indicators shown while creating containers or keyfiles """
        self.is_busy = True
        self.create_progressbars = []
        self.create_timer = QTimer(self)

        self.buttons.setEnabled(False)

        if self.main_pane.count() > 1:  # remove previous create display if any
            self.main_pane.removeWidget(self.create_pane)

        # built ui
        self.create_pane = QWidget()
        self.create_status_grid = QGridLayout()
        self.create_pane.setLayout(self.create_status_grid)
        self.create_status_grid.setVerticalSpacing(5)

    def on_create_keyfile(self):
        """ Triggered by clicking the `create key file` button below the key file text field (create)
            Asks for key file location if not already provided, creates the progress ui and starts a create-thread
        """
        if self.create_keyfile.text() == '':
            key_file = self.encode_qt_output(
                self.on_save_file(_('new_keyfile.bin')))
        else:
            key_file = self.encode_qt_output(self.create_keyfile.text())

        if not os.path.dirname(key_file):
            key_file = os.path.join(os.path.expanduser('~'), key_file)

        self.init_create_pane()

        header = QLabel(_('<b>Creating key file</b>'))
        self.create_status_grid.addWidget(header, 1, 0, 1, 3, Qt.AlignCenter)
        header.setContentsMargins(0, 30, 0, 10)

        self.create_progressbars.append(QProgressBar())
        self.create_progressbars[0].setRange(0, 100)
        self.create_status_grid.addWidget(self.create_progressbars[0], 2, 0, 1,
                                          3)
        info = QLabel(
            _('This might take a while. Since computers are deterministic machines\n'
              'it is quite a challenge to generate real random data for the key.\n'
              '\n'
              'You can speed up the process by typing, moving the mouse\n'
              'and generally use the computer while the key gets generated.'))
        info.setContentsMargins(0, 10, 0, 10)
        self.create_status_grid.addWidget(info, 3, 0, 1, 3, Qt.AlignCenter)

        self.create_status_grid.setRowStretch(4, 2)  # vertical align
        # add to stack widget and switch display
        self.main_pane.addWidget(self.create_pane)
        self.main_pane.setCurrentIndex(1)

        # start timer for progressbar updates during keyfile creation
        self.create_timer.timeout.connect(
            lambda: self.display_progress_percent(key_file, 1024))
        self.create_timer.start(500)

        # run QThread with keyfile creation
        from luckyLUKS.utils import KeyfileCreator

        self.create_thread = KeyfileCreator(self, key_file)
        self.create_thread.start()

    def on_keyfile_created(self, key_file_path):
        """ Triggered when key file creation was successful. Restores the normal setup ui """
        self.set_progress_done(self.create_timer,
                               progressbar=self.create_progressbars[0])
        show_info(
            self,
            _('<b>{key_file}\nsuccessfully created!</b>\n'
              'You can use this key file now,\n'
              'to create a new container.').format(key_file=key_file_path),
            _('Success'))
        self.display_create_done()
        self.create_keyfile.setText(key_file_path)

    def show_create_startmenu_entry(self):
        """ Shown after successfull unlock with setup dialog -> ask for shortcut creation """
        message = (_('<b>Successfully unlocked!</b>\n\n'
                     'Do you want to create\n'
                     'a startup menu entry for <b>{device_name}</b>?\n\n'
                     '-> Your password will NOT be saved!\n'
                     '   This just creates a shortcut,\n'
                     '   to the unlock container dialog.\n').format(
                         device_name=self.get_luks_device_name()))
        mb = QMessageBox(QMessageBox.Question, '', message,
                         QMessageBox.Ok | QMessageBox.Cancel, self)
        mb.button(QMessageBox.Ok).setText(_('Create shortcut'))
        mb.button(QMessageBox.Cancel).setText(_('No, thanks'))
        if mb.exec_() == QMessageBox.Ok:
            self.create_startmenu_entry()

    def create_startmenu_entry(self):
        """ Creates a startmenu entry that lets the user skip the setup dialog and go directly to the main UI
            Includes a workaround for the safety net some desktop environments create around the startupmenu
        """
        import random
        import string
        # command to be saved in shortcut: calling the script with the arguments entered in the dialog
        # put all arguments in single quotes and escape those in the strings (shell escape ' -> '\'')
        cmd = os.path.abspath(sys.argv[0])
        cmd += " -c '" + self.get_encrypted_container().replace("'",
                                                                "'\\'''") + "'"
        cmd += " -n '" + self.get_luks_device_name().replace("'",
                                                             "'\\'''") + "'"
        if self.get_mount_point() is not None:
            cmd += " -m '" + self.get_mount_point().replace("'",
                                                            "'\\'''") + "'"
        if self.get_keyfile() is not None:
            cmd += " -k '" + self.get_keyfile().replace("'", "'\\'''") + "'"

        # create .desktop-file
        filename = _('luckyLUKS') + '-' + ''.join(
            i for i in self.get_luks_device_name() if i not in ' \/:*?<>|'
        )  # xdg-desktop-menu has problems with some special chars
        if is_installed('xdg-desktop-menu'
                        ):  # create in tmp and add freedesktop menu entry
            # some desktop menus dont delete the .desktop files if a user removes items from the menu but keep track of those files instead
            # those items wont be readded later, the random part of the filename works around this behaviour
            desktop_file_path = os.path.join(
                '/tmp', filename + '-' +
                ''.join(random.choice(string.ascii_letters)
                        for i in range(4)) + '.desktop')
        else:  # or create in users home dir
            desktop_file_path = os.path.join(os.path.expanduser('~'),
                                             filename + '.desktop')

        desktop_file = codecs.open(desktop_file_path, 'w', 'utf-8')

        entry_name = _('Unlock {device_name}').format(
            device_name=self.get_luks_device_name())
        desktop_file.write("[Desktop Entry]\n")
        desktop_file.write("Name=" + entry_name + "\n")
        desktop_file.write("Comment=" + self.get_luks_device_name() + " " +
                           _('Encrypted Container Tool') + "\n")
        desktop_file.write("GenericName=" + _('Encrypted Container') + "\n")
        desktop_file.write("Categories=Utility;\n")
        desktop_file.write("Exec=" + cmd + "\n")
        desktop_file.write("Icon=dialog-password\n")
        desktop_file.write("NoDisplay=false\n")
        desktop_file.write("StartupNotify=false\n")
        desktop_file.write("Terminal=0\n")
        desktop_file.write("TerminalOptions=\n")
        desktop_file.write("Type=Application\n\n")
        desktop_file.close()

        os.chmod(desktop_file_path,
                 0o700)  # some distros need the xbit to trust the desktop file

        if is_installed('xdg-desktop-menu'):
            # safest way to ensure updates: explicit uninstall followed by installing a new desktop file with different random part
            import glob
            for desktopfile in glob.glob(
                    os.path.expanduser('~') + '/.local/share/applications/' +
                    filename + '-*.desktop'):
                with open(os.devnull) as DEVNULL:
                    subprocess.call(
                        ['xdg-desktop-menu', 'uninstall', desktopfile],
                        stdout=DEVNULL,
                        stderr=subprocess.STDOUT)
            try:
                subprocess.check_output([
                    'xdg-desktop-menu', 'install', '--novendor',
                    desktop_file_path
                ],
                                        stderr=subprocess.STDOUT,
                                        universal_newlines=True)
                os.remove(desktop_file_path)  # remove from tmp
                show_info(
                    self,
                    _('<b>` {name} `</b>\nadded to start menu').format(
                        name=entry_name), _('Success'))
            except subprocess.CalledProcessError as cpe:
                home_dir_path = os.path.join(
                    os.path.expanduser('~'),
                    os.path.basename(desktop_file_path))
                # move to homedir instead
                from shutil import move
                move(desktop_file_path, home_dir_path)
                show_alert(self, cpe.output)
                show_info(
                    self,
                    _('Adding to start menu not possible,\nplease place your shortcut manually.\n\nDesktop file saved to\n{location}'
                      ).format(location=home_dir_path))
        else:
            show_info(
                self,
                _('Adding to start menu not possible,\nplease place your shortcut manually.\n\nDesktop file saved to\n{location}'
                  ).format(location=desktop_file_path))

    def reject(self):
        """ Event handler cancel: Ask for confirmation while creating container """
        if self.confirm_close():
            super(SetupDialog, self).reject()

    def closeEvent(self, event):
        """ Event handler close: ask for confirmation while creating container """
        if not self.confirm_close():
            event.ignore()

    def confirm_close(self):
        """ Displays a confirmation dialog if currently busy creating container or keyfile
            :returns: The users decision or True if no create process running
            :rtype: bool
        """
        if self.is_busy:
            message = _(
                'Currently processing your request!\nDo you really want to quit?'
            )
            mb = QMessageBox(QMessageBox.Question, '', message,
                             QMessageBox.Ok | QMessageBox.Cancel, self)
            mb.button(QMessageBox.Ok).setText(_('Quit'))
            return mb.exec_() == QMessageBox.Ok
        else:
            return True

    def on_switchpage_event(self, index):
        """ Event handler for tab switch: change text on OK button (Unlock/Create) """
        new_ok_label = _('Unlock')
        if index == 1:  # create
            if self.create_filesystem_type.currentText() == '':
                show_alert(
                    self,
                    _('No tools to format the filesystem found\n'
                      'Please install, eg for Debian/Ubuntu\n'
                      '`apt-get install e2fslibs ntfs-3g`'))
            new_ok_label = _('Create')
        self.buttons.button(QDialogButtonBox.Ok).setText(new_ok_label)

    def on_select_container_clicked(self):
        """ Triggered by clicking the select button next to container file (unlock) """
        file_path = QFileDialog.getOpenFileName(
            self, _('Please choose a container file'), os.getenv("HOME"))
        if isinstance(file_path,
                      tuple):  # qt5 returns tuple path/selected filter
            file_path = file_path[0]
        self.unlock_container_file.setText(file_path)
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))

    def on_select_mountpoint_clicked(self):
        """ Triggered by clicking the select button next to mount point """
        self.unlock_mountpoint.setText(
            QFileDialog.getExistingDirectory(
                self, _('Please choose a folder as mountpoint'),
                os.getenv("HOME")))
        self.buttons.button(QDialogButtonBox.Ok).setText(_('Unlock'))

    def on_select_keyfile_clicked(self, tab):
        """ Triggered by clicking the select button next to key file (both unlock and create tab) """
        file_path = QFileDialog.getOpenFileName(self,
                                                _('Please choose a key file'),
                                                os.getenv("HOME"))
        if isinstance(file_path,
                      tuple):  # qt5 returns tuple path/selected filter
            file_path = file_path[0]
        if tab == 'Unlock':
            self.unlock_keyfile.setText(file_path)
        elif tab == 'Create':
            self.create_keyfile.setText(file_path)
        self.buttons.button(QDialogButtonBox.Ok).setText(_(tab))

    def on_save_container_clicked(self):
        """ Triggered by clicking the select button next to container file (create)
            Uses a file dialog to set the path of the container file to be created
        """
        self.create_container_file.setText(
            self.on_save_file(_('new_container.bin')))

    def on_save_file(self, default_filename):
        """ Opens a native file dialog and returns the chosen path of the file to be saved
            The dialog does not allow overwriting existing files - to get this behaviour
            while using native dialogs the QFileDialog has to be reopened on overwrite.
            A bit weird but enables visual consistency with the other file choose dialogs
            :param default_filename: The default filename to be used in the Qt file dialog
            :type default_filename: str/unicode
            :returns: The designated key file path
            :rtype: str/unicode
        """
        def_path = os.path.join(os.getenv("HOME"), default_filename)

        while True:
            save_path = QFileDialog.getSaveFileName(
                self,
                _('Please create a new file'),
                def_path,
                options=QFileDialog.DontConfirmOverwrite)

            save_path = self.encode_qt_output(save_path[0]) if isinstance(
                save_path, tuple) else self.encode_qt_output(save_path)
            self.buttons.button(QDialogButtonBox.Ok).setText(
                _('Create'))  # qt keeps changing this..

            if os.path.exists(save_path):
                show_alert(
                    self,
                    _('File already exists:\n{filename}\n\n'
                      '<b>Please create a new file!</b>').format(
                          filename=save_path))
                def_path = os.path.join(os.path.basename(save_path),
                                        default_filename)
            else:
                return save_path

    def display_progress_percent(self, location, size):
        """ Update value on the container creation progress bar
            :param location: The path of the container file currently being created
            :type location: str
            :param size: The final size the new container in bytes
            :type size: int
        """
        try:
            new_value = int(os.path.getsize(location) / size * 100)
        except Exception:
            new_value = 0
        self.create_progressbars[0].setValue(new_value)

    def get_encrypted_container(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The container file path
            :rtype: str/unicode
        """
        return self.encode_qt_output(self.unlock_container_file.text())

    def get_luks_device_name(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The device name
            :rtype: str/unicode
        """
        return self.encode_qt_output(self.unlock_device_name.text())

    def get_keyfile(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The mount point path
            :rtype: str/unicode or None
        """
        kf = self.encode_qt_output(self.unlock_keyfile.text())
        return kf if kf != '' else None

    def get_mount_point(self):
        """ Getter for QLineEdit text returns python unicode (instead of QString in py2)
            :returns: The mount point path
            :rtype: str/unicode or None
        """
        mp = self.encode_qt_output(self.unlock_mountpoint.text())
        return mp if mp != '' else None

    def encode_qt_output(self, qstring_or_str):
        """ Normalize output from QLineEdit
            :param qstring_or_str: Output from QLineEdit.text()
            :type qstring_or_str: str/QString
            :returns: python unicode (instead of QString in py2)
            :rtype: str/unicode
        """
        try:
            return qstring_or_str.strip()
        except AttributeError:  # py2: 'QString' object has no attribute strip
            return unicode(qstring_or_str.trimmed().toUtf8(), encoding="UTF-8")

    def show_help_create(self):
        """ Triggered by clicking the help button (create tab) """
        header_text = _('<b>Create a new encrypted container</b>\n')
        basic_help = _(
            'Enter the path of the <b>new container file</b> in the textbox '
            'or click the button next to the box for a graphical create file dialog.'
            '\n\n'
            'The <b>device name</b> will be used to identify the unlocked container. '
            'It can be any name up to 16 unicode characters, as long as it is unique.'
            '\n\n'
            'The <b>size</b> of the container can be provided in GB or MB. The container '
            'will get initialized with random data, this can take quite a while - '
            '1 hour for a 10GB container on an external drive is nothing unusual.'
        )
        advanced_topics = [{
            'head':
            _('key file'),
            'text':
            _('A key file can be used to allow access to an encrypted container instead of a password. '
              'Using a key file resembles unlocking a door with a key in the real world - anyone with '
              'access to the key file can open your encrypted container. Make sure to store it at a '
              'protected location. Its okay to store it on your computer if you are using an already '
              'encrypted harddrive or a digital keystore. Having the key file on a '
              '<a href="https://www.google.com/search?q=keychain+usb+drive">small USB drive</a> '
              'attached to your real chain of keys would be an option as well.\n'
              'Since you dont have to enter a password, using a key file can be a convenient way to '
              'access your encrypted container. Just make sure you dont lose the key (file) ;)'
              ) +
            _('\n\n'
              'Although basically any file could be used as a key file, a file with predictable content '
              'leads to similar problems as using weak passwords. Audio files or pictures are a good choice. '
              'If unsure use the `create key file` button to generate a small key file filled with random data.'
              )
        }, {
            'head':
            _('encryption format'),
            'text':
            _('The standard disk encryption format on Linux is called LUKS. '
              'With <a href="https://github.com/t-d-k/doxbox">doxbox</a> you can use LUKS containers on Windows as well. '
              'The TrueCrypt format is quite popular on Windows/Mac, and can be created '
              'on Linux if `tcplay` is installed. Please note, that "hidden" TrueCrypt '
              'partitions are not supported by luckyLUKS!')
        }, {
            'head':
            _('filesystem'),
            'text':
            _('Choose the ntfs filesystem to be able to access your data from Linux, '
              'Windows and Mac OSX. Since access permissions cannot be mapped from '
              'ntfs to Linux, access to ntfs devices is usually not restricted '
              '-> take care when using unlocked ntfs devices in a multiuser environment!'
              )
        }]
        hd = HelpDialog(self, header_text, basic_help, advanced_topics)
        hd.exec_()

    def show_help_unlock(self):
        """ Triggered by clicking the help button (unlock tab) """
        header_text = _('<b>Unlock an encrypted container</b>\n')
        basic_help = _(
            'Select the encrypted <b>container file</b> by clicking the button next to '
            'the textbox. Both LUKS and Truecrypt containers are supported!'
            '\n\n'
            'The <b>device name</b> will be used to identify the unlocked container. '
            'It can be any name up to 16 unicode characters, as long as it is unique '
            '-> you cannot give two unlocked containers the same name')
        advanced_topics = [{
            'head':
            _('key file'),
            'text':
            _('A key file can be used to allow access to an encrypted container instead of a password. '
              'Using a key file resembles unlocking a door with a key in the real world - anyone with '
              'access to the key file can open your encrypted container. Make sure to store it at a '
              'protected location. Its okay to store it on your computer if you are using an already '
              'encrypted harddrive or a digital keystore. Having the key file on a '
              '<a href="https://www.google.com/search?q=keychain+usb+drive">small USB drive</a> '
              'attached to your real chain of keys would be an option as well.\n'
              'Since you dont have to enter a password, using a key file can be a convenient way to '
              'access your encrypted container. Just make sure you dont lose the key (file) ;)'
              )
        }, {
            'head':
            _('mount point'),
            'text':
            _('The mount point is the folder on your computer, where you can '
              'access the files inside the container after unlocking. '
              'If automatic mounting is configured on your system (eg with udisks), '
              'explicitly setting a mountpoint is not neccessary (but still possible).'
              )
        }]
        hd = HelpDialog(self, header_text, basic_help, advanced_topics)
        hd.exec_()
Ejemplo n.º 14
0
class WorkDialog(QDialog):
    ''' Dialog to display work and result '''

    send_files = pyqtSignal(list)

    def __init__(self, files):
        super(WorkDialog, self).__init__()

        self.progress = MyProgressBar()
        self.progress.setRange(0, 0)
        self.progress.set_text("Wait a minute, please...")
        self.button_box = QDialogButtonBox(QDialogButtonBox.Ok)
        self.button_box.setEnabled(True)
        self.create_groupbox(files)

        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(10, 10, 10, 10)
        self.layout.addWidget(self.form_groupbox)
        self.layout.addWidget(self.progress)
        self.setLayout(self.layout)
        self.setWindowTitle("Your TimeBag status")

        # setup thread and worker
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)

        # signal and slot connections
        self.send_files.connect(self.worker.real_job)
        self.worker.request_pathname.connect(self.get_save_filename)
        self.worker.result.connect(self.update_groupbox)
        self.worker.finished.connect(self.thread.quit)
        self.button_box.accepted.connect(self.accept)

        # start
        self.thread.start()
        self.send_files.emit(files)



    def get_save_filename(self):
        ''' Ask for a filename to save new timebag '''

        # explain to the user what we need
        msg = "Please choose a name for the new TimeBag zip file.\n" \
                "For example: 'timebag.zip'\n"
        alert = QMessageBox()
        alert.setText(msg)
        alert.exec_()

        # get the pathfile name
        home = os.path.expanduser("~")
        dialog = QFileDialog(self)
        # DontConfirmOverwrite because is managed later and rejected
        options = (QFileDialog.DontConfirmOverwrite)
        filename, _ = dialog.getSaveFileName(self, "Choose a new name for your TimeBags",
                                             home, 'Zip File (*.zip)', None, options)
        # check if already exists
        while os.path.exists(filename):
            msg = "File %s already exist!\nPlease use a different name." % filename
            alert = QMessageBox()
            alert.setText(msg)
            alert.exec_()
            filename, _ = dialog.getSaveFileName(self, "Choose a new name for your TimeBags",
                                                 home, 'Zip File (*.zip)', None, options)

        # update label in the groupbox
        self.data['pathfile'].setText(filename)

        # make it visible to worker thread
        global pathname
        pathname = filename


    def create_groupbox(self, files):
        ''' Form to display the result '''

        # set empty data structure
        self.data = dict(pathfile=QLabel(""),
                         result=QLabel(""),
                         tsa=QLabel(""),
                         tst=QLabel(""),
                         btc=QLabel(""))

        # pathfile can be very long
        self.data['pathfile'].setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.data['pathfile'].setMinimumWidth(300)
        self.data['pathfile'].setWordWrap(True)

        # if the selection is single file with zip extension display it
        if len(files) == 1 and files[0].lower().endswith(".zip"):
            self.data['pathfile'].setText(files[0])

        # set groupbox layout
        self.form_groupbox = QGroupBox("Report")
        layout = QFormLayout()
        layout.addRow(QLabel("File:"), self.data['pathfile'])
        layout.addRow(QLabel("Status:"), self.data['result'])
        layout.addRow(QLabel("Time Stamp Authority:"), self.data['tsa'])
        layout.addRow(QLabel("Time Stamped (UTC):"), self.data['tst'])
        layout.addRow(QLabel("Bitcoin Blocks:"), self.data['btc'])
        self.form_groupbox.setLayout(layout)


    @pyqtSlot(dict)
    def update_groupbox(self, status):
        ''' Form to display the result '''

        if status is None:
            msg = "Some error occurred.\nSee the log file for details."
            alert = QMessageBox()
            alert.setText(msg)
            alert.exec_()

        else:
            # get data
            btc_blocks = []
            for attestation in status['dat-ots'][1] + status['tst-ots'][1]:
                btc_blocks += [attestation[0]]
            tsa_url = status['dat-tst'][1]
            tsa = "<a href=\"%s\">%s</a>" % (tsa_url, tsa_url)

            # update displayed data
            self.data['pathfile'].setText(status['pathfile'])
            self.data['result'].setText(status['result'])
            self.data['tsa'].setText(tsa)
            self.data['tsa'].setOpenExternalLinks(True)
            self.data['tst'].setText(str(status['dat-tst'][0]))
            self.data['btc'].setText(repr(sorted(set(btc_blocks))))

        self.layout.removeWidget(self.progress)
        self.progress.deleteLater()
        self.progress = None
        self.layout.addWidget(self.button_box)
Ejemplo n.º 15
0
class FlashingDialog(QDialog):
    def __init__(self, parent):
        super().__init__()
        self.setWindowTitle("Tasmotizing...")

        esptool.sw.read_start.connect(self.read_start)
        esptool.sw.read_progress.connect(self.read_progress)
        esptool.sw.read_finished.connect(self.read_finished)

        esptool.sw.erase_start.connect(self.erase_start)
        esptool.sw.erase_finished.connect(self.erase_finished)

        esptool.sw.write_start.connect(self.write_start)
        esptool.sw.write_progress.connect(self.write_progress)
        esptool.sw.write_finished.connect(self.write_finished)

        self.setFixedWidth(400)

        self.nrBinFile = QNetworkRequest()
        self.parent = parent

        vl = VLayout(10, 10)
        self.setLayout(vl)

        self.bin_data = b""
        self.error_msg = None

        self.progress_task = QProgressBar()
        self.progress_task.setFixedHeight(45)
        self.task = QLabel()

        self.erase_timer = QTimer()
        self.erase_timer.setSingleShot(False)
        self.erase_timer.timeout.connect(self.erase_progress)

        self.btns = QDialogButtonBox(QDialogButtonBox.Abort)

        vl.addWidgets([
            QLabel("Tasmotizing in progress..."), self.task,
            self.progress_task, self.btns
        ])

        self.btns.rejected.connect(self.abort)

        # process starts
        if parent.mode in (1, 2):
            self.bin_file = parent.cbHackboxBin.currentData().split(";")[1]
            self.nrBinFile.setUrl(
                QUrl(parent.cbHackboxBin.currentData().split(";")[0]))
            self.bin_reply = parent.nam.get(self.nrBinFile)
            self.task.setText("Downloading binary from thehackbox.org...")
            self.bin_reply.readyRead.connect(self.appendBinFile)
            self.bin_reply.downloadProgress.connect(self.updateBinProgress)
            self.bin_reply.finished.connect(self.saveBinFile)
        else:
            self.bin_file = parent.bin_file
            self.run_esptool()

    def appendBinFile(self):
        self.bin_data += self.bin_reply.readAll()

    def saveBinFile(self):
        if self.bin_reply.error() == QNetworkReply.NoError:
            with open(self.bin_file, "wb") as f:
                f.write(self.bin_data)
            self.progress_task.setValue(0)
            self.task.setText("Connecting to ESP...")
            self.run_esptool()
        else:
            QMessageBox.critical(self, "Network error",
                                 self.bin_reply.errorString())

    def updateBinProgress(self, recv, total):
        self.progress_task.setValue(recv // total * 100)

    def read_start(self):
        self.progress_task.setValue(0)
        self.task.setText("Saving image backup...")

    def read_progress(self, value):
        self.progress_task.setValue(value)

    def read_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Writing done.")

    def erase_start(self):
        self.btns.setEnabled(False)
        self.progress_task.setValue(0)
        self.task.setText("Erasing flash... (this may take a while)")
        self.erase_timer.start(1000)

    def erase_progress(self):
        self.progress_task.setValue(self.progress_task.value() + 5)

    def erase_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Erasing done.")
        self.erase_timer.stop()
        self.btns.setEnabled(True)

    def write_start(self):
        self.progress_task.setValue(0)
        self.task.setText("Writing image...")

    def write_progress(self, value):
        self.progress_task.setValue(value)

    def write_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Writing done.")
        self.accept()

    def run_esptool(self):
        self.espthread = QThread()
        self.espworker = ESPWorker(self.parent.cbxPort.currentData(),
                                   self.bin_file,
                                   self.parent.cbBackup.isChecked(),
                                   self.parent.cbErase.isChecked())

        self.espworker.port_error.connect(self.error)
        self.espworker.moveToThread(self.espthread)
        self.espthread.started.connect(self.espworker.execute)
        self.espthread.start()

    def abort(self):
        self.espworker.stop()
        self.espthread.quit()
        self.espthread.wait(2000)
        self.reject()

    def error(self, e):
        self.error_msg = e
        self.reject()

    def accept(self):
        self.espworker.stop()
        self.espthread.quit()
        self.espthread.wait(2000)
        self.done(QDialog.Accepted)
Ejemplo n.º 16
0
class UiAddMicrographDialog(object):
    """
    UiAddMicrographDialog
    User interface for the add micrograph dialog which is used to import a micrograph into the program.
    """
    def __init__(self, add_micrograph_dialog):

        # set window title, object name and window size
        add_micrograph_dialog.setWindowTitle("Add Micrograph")
        add_micrograph_dialog.setObjectName("add_micrograph_dialog")
        add_micrograph_dialog.setFixedWidth(960)
        add_micrograph_dialog.setFixedHeight(480)

        # button box
        self.button_box = QDialogButtonBox(add_micrograph_dialog)
        self.button_box.setEnabled(True)
        self.button_box.setGeometry(QRect(415, 440, 535, 32))
        self.button_box.setOrientation(Qt.Horizontal)
        self.button_box.setStandardButtons(QDialogButtonBox.Cancel
                                           | QDialogButtonBox.Ok)
        self.button_box.setObjectName("button_box")

        # widget for the two plots
        self.plot_widget = QWidget(add_micrograph_dialog)
        self.plot_widget.setGeometry(QRect(10, 10, 940, 350))
        self.plot_widget.setObjectName("plot_widget")

        # widget for the toolbar
        self.toolbar_widget = QWidget(add_micrograph_dialog)
        self.toolbar_widget.setGeometry(QRect(10, 430, 400, 50))
        self.toolbar_widget.setObjectName("toolbar_widget")

        # widget for buttons controlling the points on the plots
        self.button_widget = QWidget(add_micrograph_dialog)
        self.button_widget.setGeometry(QRect(10, 365, 940, 32))
        self.button_widget.setObjectName("button_widget")

        # button to remove all moving points
        self.clear_all_moving_push_button = QPushButton(self.button_widget)
        self.clear_all_moving_push_button.setEnabled(False)
        self.clear_all_moving_push_button.setGeometry(QRect(580, 2, 100, 28))
        self.clear_all_moving_push_button.setObjectName(
            "clear_all_moving_push_button")
        self.clear_all_moving_push_button.setText("Clear All")

        # button to remove last moving point
        self.clear_last_moving_push_button = QPushButton(self.button_widget)
        self.clear_last_moving_push_button.setEnabled(False)
        self.clear_last_moving_push_button.setGeometry(QRect(475, 2, 100, 28))
        self.clear_last_moving_push_button.setObjectName(
            "clear_last_moving_push_button")
        self.clear_last_moving_push_button.setText("Clear Last")

        # button to remove all fixed points
        self.clear_all_fixed_push_button = QPushButton(self.button_widget)
        self.clear_all_fixed_push_button.setEnabled(False)
        self.clear_all_fixed_push_button.setGeometry(QRect(110, 2, 100, 28))
        self.clear_all_fixed_push_button.setObjectName(
            "clear_all_fixed_push_button")
        self.clear_all_fixed_push_button.setText("Clear All")

        # button to remove last fixed point
        self.clear_last_fixed_push_button = QPushButton(self.button_widget)
        self.clear_last_fixed_push_button.setEnabled(False)
        self.clear_last_fixed_push_button.setGeometry(QRect(5, 2, 100, 28))
        self.clear_last_fixed_push_button.setObjectName(
            "clear_last_fixed_push_button")
        self.clear_last_fixed_push_button.setText("Clear Last")

        # connect accept and reject
        self.button_box.accepted.connect(add_micrograph_dialog.accept)
        self.button_box.rejected.connect(add_micrograph_dialog.reject)
Ejemplo n.º 17
0
class FlashingDialog(QDialog):
    def __init__(self, parent):
        super().__init__()
        self.setWindowTitle("Flashing...")
        esptool.sw.read_start.connect(self.read_start)
        esptool.sw.read_progress.connect(self.read_progress)
        esptool.sw.read_finished.connect(self.read_finished)
        esptool.sw.erase_start.connect(self.erase_start)
        esptool.sw.erase_finished.connect(self.erase_finished)
        esptool.sw.write_start.connect(self.write_start)
        esptool.sw.write_progress.connect(self.write_progress)
        esptool.sw.write_finished.connect(self.write_finished)
        self.setFixedWidth(400)
        self.nrBinFile = QNetworkRequest()
        self.parent = parent
        vl = VLayout(10, 10)
        self.setLayout(vl)
        self.bin_data = b""
        self.error_msg = None
        self.progress_task = QProgressBar()
        self.progress_task.setFixedHeight(45)
        self.task = QLabel()
        self.erase_timer = QTimer()
        self.erase_timer.setSingleShot(False)
        self.erase_timer.timeout.connect(self.erase_progress)
        self.btns = QDialogButtonBox(QDialogButtonBox.Abort)
        self.dlgText = QLabel(
            "Press the Boot button for a few seconds to start the flashing process"
        )
        vl.addWidgets([self.dlgText, self.task, self.progress_task, self.btns])
        self.btns.rejected.connect(self.abort)
        # process starts
        self.bin_file = parent.bin_file
        self.run_esptool()

    def updateBinProgress(self, recv, total):
        self.progress_task.setValue(recv // total * 100)

    def read_start(self):
        self.progress_task.setValue(0)
        self.task.setText("Saving image backup...")

    def read_progress(self, value):
        self.progress_task.setValue(value)

    def read_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Writing done.")

    def erase_start(self):
        self.btns.setEnabled(False)
        self.progress_task.setValue(0)
        self.task.setText("Erasing flash... (this may take a while)")
        self.erase_timer.start(1000)

    def erase_progress(self):
        self.progress_task.setValue(self.progress_task.value() + 5)

    def erase_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Erasing done.")
        self.erase_timer.stop()
        self.btns.setEnabled(True)

    def write_start(self):
        self.dlgText.setText("Flashing in progress...")
        self.progress_task.setValue(0)
        self.task.setText("Writing image...")

    def write_progress(self, value):
        self.progress_task.setValue(value)

    def write_finished(self):
        self.progress_task.setValue(100)
        self.task.setText("Writing done.")
        self.accept()

    def run_esptool(self):
        self.espthread = QThread()
        self.espworker = ESPWorker(self.parent.cbxPort.currentData(),
                                   self.bin_file)
        self.espworker.port_error.connect(self.error)
        self.espworker.moveToThread(self.espthread)
        self.espthread.started.connect(self.espworker.execute)
        self.espthread.start()

    def abort(self):
        self.espworker.stop()
        self.espthread.quit()
        self.espthread.wait(2000)
        self.reject()

    def error(self, e):
        self.error_msg = e
        self.reject()

    def accept(self):
        self.espworker.stop()
        self.espthread.quit()
        self.espthread.wait(2000)
        self.done(QDialog.Accepted)