Ejemplo n.º 1
0
class GalleryDownloaderUrlExtracter(QWidget):

	url_emit = pyqtSignal(str)

	def __init__(self, parent=None):
		super().__init__(parent, flags=Qt.Window|Qt.WindowStaysOnTopHint)
		self.main_layout = QVBoxLayout(self)
		self.text_area = QPlainTextEdit(self)
		self.text_area.setPlaceholderText("URLs are seperated by a newline")
		self.main_layout.addWidget(self.text_area)
		self.text_area.setWordWrapMode(QTextOption.NoWrap)
		add_to_queue = QPushButton('Add to queue')
		add_to_queue.adjustSize()
		add_to_queue.setFixedWidth(add_to_queue.width())
		add_to_queue.clicked.connect(self.add_to_queue)
		self.main_layout.addWidget(add_to_queue, 0, Qt.AlignRight)
		self.setWindowIcon(QIcon(app_constants.APP_ICO_PATH))
		self.show()

	def add_to_queue(self):
		txt = self.text_area.document().toPlainText()
		urls = txt.split('\n')
		for u in urls:
			if u:
				self.url_emit.emit(u)
		self.close()
Ejemplo n.º 2
0
Archivo: wizard.py Proyecto: khuno/rpg
    def __init__(self, Wizard, parent=None):
        super(RequiresPage, self).__init__(parent)

        self.base = Wizard.base

        self.setTitle(self.tr("Requires page"))
        self.setSubTitle(self.tr("Write requires and provides"))

        buildRequiresLabel = QLabel("BuildRequires: ")
        self.bRequiresEdit = QPlainTextEdit()
        self.bRequiresEdit.setMaximumHeight(40)

        requiresLabel = QLabel("Requires: ")
        self.requiresEdit = QPlainTextEdit()
        self.requiresEdit.setMaximumHeight(40)

        preovidesLabel = QLabel("Provides: ")
        self.previdesEdit = QPlainTextEdit()

        grid = QGridLayout()
        grid.addWidget(buildRequiresLabel, 0, 0)
        grid.addWidget(self.bRequiresEdit, 1, 0)
        grid.addWidget(requiresLabel, 2, 0)
        grid.addWidget(self.requiresEdit, 3, 0,)
        grid.addWidget(preovidesLabel, 4, 0)
        grid.addWidget(self.previdesEdit, 5, 0)
        self.setLayout(grid)
Ejemplo n.º 3
0
Archivo: wizard.py Proyecto: khuno/rpg
    def __init__(self, Wizard, parent=None):
        super(ScriptsPage, self).__init__(parent)

        self.base = Wizard.base

        self.setTitle(self.tr("Scripts page"))
        self.setSubTitle(self.tr("Write scripts"))

        prepareLabel = QLabel("%prepare: ")
        self.prepareEdit = QPlainTextEdit()

        buildLabel = QLabel("%build: ")
        self.buildEdit = QPlainTextEdit()

        installLabel = QLabel("%install: ")
        self.installEdit = QPlainTextEdit()

        checkLabel = QLabel("%check: ")
        self.checkEdit = QPlainTextEdit()

        buildArchLabel = QLabel("BuildArch: ")
        self.buildArchCheckbox = QCheckBox("noarch")

        grid = QGridLayout()
        grid.addWidget(prepareLabel, 0, 0)
        grid.addWidget(self.prepareEdit, 0, 1)
        grid.addWidget(buildLabel, 1, 0)
        grid.addWidget(self.buildEdit, 1, 1)
        grid.addWidget(installLabel, 2, 0)
        grid.addWidget(self.installEdit, 2, 1)
        grid.addWidget(checkLabel, 3, 0)
        grid.addWidget(self.checkEdit, 3, 1)
        grid.addWidget(buildArchLabel, 4, 0)
        grid.addWidget(self.buildArchCheckbox, 4, 1)
        self.setLayout(grid)
Ejemplo n.º 4
0
def show_info_dialog( caption, parent, initial_text ):
    dialog = QDialog( parent )
    dialog.setWindowTitle( caption )
    # Create OK and Cancel buttons in a horizontal box.
    ok_button = QPushButton("OK")
    ok_button.setDefault(True)
    ok_button.clicked.connect(dialog.accept)
    cancel_button = QPushButton("Cancel")
    cancel_button.setDefault(False)
    cancel_button.clicked.connect(dialog.reject)
    hbox = QHBoxLayout()
    hbox.addWidget(cancel_button,0)
    hbox.addStretch()
    hbox.addWidget(ok_button,0)
    # Lay out a Plain Text Edit above the buttons.
    vbox = QVBoxLayout()
    pt_editor = QPlainTextEdit()
    pt_editor.document().setPlainText( initial_text )
    vbox.addWidget(pt_editor,1)
    vbox.addLayout(hbox,0)
    dialog.setLayout(vbox)
    result = dialog.exec_()
    if result :
        return pt_editor.document().toPlainText()
    else :
        return None
Ejemplo n.º 5
0
    def keyPressEvent(self, e):
        if self.isReadOnly():
            return

        if self.is_special_key(e):
            e.ignore()
            return

        QPlainTextEdit.keyPressEvent(self, e)

        ctrlOrShift = e.modifiers() and (Qt.ControlModifier or Qt.ShiftModifier)
        if self.completer is None or (ctrlOrShift and not e.text()):
            return

        if not self.suggestions_enabled:
            return

        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="
        hasModifier = (e.modifiers() != Qt.NoModifier) and not ctrlOrShift
        completionPrefix = self.text_under_cursor()

        if hasModifier or not e.text() or len(completionPrefix) < 1 or eow.find(e.text()[-1]) >= 0:
            self.completer.popup().hide()
            return

        if completionPrefix != self.completer.completionPrefix():
            self.completer.setCompletionPrefix(completionPrefix)
            self.completer.popup().setCurrentIndex(self.completer.completionModel().index(0, 0))

        cr = self.cursorRect()
        cr.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width())
        self.completer.complete(cr)
Ejemplo n.º 6
0
    def __init__(self, parent=None, text=None, EditorHighlighterClass=PythonHighlighter, indenter=PythonCodeIndenter):
        QPlainTextEdit.__init__(self, parent)
        self.setFrameStyle(QFrame.NoFrame)
        self.setTabStopWidth(4)
        self.setLineWrapMode(QPlainTextEdit.NoWrap)
        font = QFont()
        font.setFamily("lucidasanstypewriter")
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.highlighter = EditorHighlighterClass(self)
        if text:
            self.setPlainText(text)
        self.frame_style = self.frameStyle()
        self.draw_line = True
        self.print_width = self.fontMetrics().width("x" * 78)
        self.line_pen = QPen(QColor("lightgrey"))
        self.last_row = self.last_col = -1
        self.last_block = None
        self.highlight_line = True
        self.highlight_color = self.palette().highlight().color().light(175)
        self.highlight_brush = QBrush(QColor(self.highlight_color))
        self.cursorPositionChanged.connect(self.onCursorPositionChanged)
        self.indenter = indenter(RopeEditorWrapper(self))
        # True if you want to catch Emacs keys in actions
        self.disable_shortcuts = False

        self.prj = get_no_project()
        self.prj.root = None
        self.calltip = CallTip(self)
        self.autocomplete = AutoComplete(self)
Ejemplo n.º 7
0
class PackageTab(QWidget):
    configChanged = pyqtSignal()
    def __init__(self):
        super(QWidget, self).__init__()
        layout = QFormLayout()
        self.setLayout(layout)

        self.buildDependencies = QPlainTextEdit()
        self.buildDependencies.textChanged.connect(self.buildDependenciesChanged)
        self.buildDependencies.setMinimumHeight(70)
        layout.addRow('Build Dependencies', self.buildDependencies)

        self.runDependencies = QPlainTextEdit()
        self.runDependencies.textChanged.connect(self.runDependenciesChanged)
        self.runDependencies.setMinimumHeight(70)
        layout.addRow('Run Dependencies', self.runDependencies)

    def buildDependenciesChanged(self):
        if self.config is not None:
            self.config.setBuildDependencies(self.buildDependencies.toPlainText())
            self.configChanged.emit()

    def runDependenciesChanged(self):
        if self.config is not None:
            self.config.setRunDependencies(self.runDependencies.toPlainText())
            self.configChanged.emit()

    def setConfig(self, config):
        self.config = config
        self.buildDependencies.setPlainText(self.config.getBuildDependenciesAsText())
        self.runDependencies.setPlainText(self.config.getRunDependenciesAsText())
class Window(QWidget):

    def __init__(self):
        super().__init__()

        # Make widgets #################

        self.edit = QPlainTextEdit()
        self.btn = QPushButton("Print")

        self.edit.setPlaceholderText("Type something here and press the 'Print' button")

        # Set button slot ##############

        self.btn.clicked.connect(self.printText)

        # Set the layout ###############

        vbox = QVBoxLayout()

        vbox.addWidget(self.edit)
        vbox.addWidget(self.btn)

        self.setLayout(vbox)

    def printText(self):
        print(self.edit.toPlainText())
Ejemplo n.º 9
0
    def previewWidget(self):
        t = QTabWidget()
        t.setDocumentMode(True)
        t.setStyleSheet("""
            QTabBar::tab{
                background-color: #BBB;
                padding: 3px 25px;
                border: none;
            }

            QTabBar::tab:selected, QTabBar::tab:hover{
                background-color:skyblue;
            }
        """)
        w0 = QPlainTextEdit()
        w0.setFrameShape(QFrame.NoFrame)
        w0.setReadOnly(True)
        w1 = QPlainTextEdit()
        w1.setFrameShape(QFrame.NoFrame)
        w1.setReadOnly(True)
        t.addTab(w0, qApp.translate("Export", "Markdown source"))
        t.addTab(w1, qApp.translate("Export", "HTML Source"))
        
        if webView:
            w2 = webView()
            t.addTab(w2, qApp.translate("Export", "HTML Output"))

        t.setCurrentIndex(2)
        return t
Ejemplo n.º 10
0
    def __init__(self):
        """ Widget initialization
        """

        super().__init__('Show changes')

        self.beforePTE = QPlainTextEdit()
        self.afterPTE = QPlainTextEdit()

        # widgets are read-only
        self.beforePTE.setReadOnly(True)
        self.afterPTE.setReadOnly(True)

        # bind the scroll position of the two widgets
        beforeScrollbar = self.beforePTE.verticalScrollBar()
        afterScrollbar = self.afterPTE.verticalScrollBar()
        beforeScrollbar.valueChanged.connect(afterScrollbar.setValue)
        afterScrollbar.valueChanged.connect(beforeScrollbar.setValue)

        hbox = QHBoxLayout()
        hbox.addWidget(self.beforePTE)
        hbox.addWidget(self.afterPTE)

        widget = QWidget()
        widget.setLayout(hbox)

#        # sizeHint for the widget
#        def sizeHint(self):
#            return QSize(self.width(), 150)
#        widget.sizeHint = types.MethodType(sizeHint, widget)

        self.setWidget(widget)
Ejemplo n.º 11
0
class QTextInputDialog(QDialog):

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

        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMaximumSize(400, 230)
        self.setMinimumSize(400, 230)
        self.resize(400, 230)

        self.scrollArea = QScrollArea(self)
        self.scrollArea.setGeometry(QtCore.QRect(5, 5, 390, 190))
        self.scrollArea.setWidgetResizable(True)

        self.plainTextEdit = QPlainTextEdit()
        self.plainTextEdit.setGeometry(QtCore.QRect(0, 0, 390, 190))
        self.plainTextEdit.setPlainText(initial)

        self.scrollArea.setWidget(self.plainTextEdit)

        self.acceptButton = QPushButton(self)
        self.acceptButton.setGeometry(QtCore.QRect(280, 200, 100, 25))
        self.acceptButton.setText("Ok")

        self.rejectButton = QPushButton(self)
        self.rejectButton.setGeometry(QtCore.QRect(160, 200, 100, 25))
        self.rejectButton.setText("Cancel")

        self.rejectButton.clicked.connect(self.reject)
        self.acceptButton.clicked.connect(self.accept)
Ejemplo n.º 12
0
 def keyPressEvent(self, event):
     if self.isReadOnly():
         return
     modifiers = event.modifiers()
     if modifiers in (Qt.AltModifier, Qt.ControlModifier):
         return
     if modifiers == Qt.ShiftModifier:
         if not event.text():
             return
     key = event.key()
     if key == Qt.Key_Backspace:
         text_selected = self.textCursor().selectedText()
         if text_selected:
             del self.__input[-len(text_selected):]
         else:
             try:
                 self.__input.pop()
             except IndexError:
                 return
     elif key in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Up, Qt.Key_Down,
                  Qt.Key_CapsLock):
         return
     elif key in (Qt.Key_Enter, Qt.Key_Return):
         data = "".join(self.__input)
         self.inputRequested.emit(data)
         self.__input.clear()
     else:
         self.__input.append(event.text())
     QPlainTextEdit.keyPressEvent(self, event)
Ejemplo n.º 13
0
 def mousePressEvent(self, event):
     """
     When the execution fail, allow to press the links in the traceback,
     to go to the line when the error occur.
     """
     QPlainTextEdit.mousePressEvent(self, event)
     self.go_to_error(event)
Ejemplo n.º 14
0
    def __init__(self):
        super(self.__class__, self).__init__()

        self.name_label = QLabel("Name (optional):")

        self.name_line_edit = QLineEdit()

        self.introducer_label = QLabel("Introducer fURL:")

        self.introducer_text_edit = QPlainTextEdit()
        self.introducer_text_edit.setMaximumHeight(70)
        self.introducer_text_edit.setTabChangesFocus(True)

        self.description_label = QLabel("Description (optional):")

        self.description_text_edit = QPlainTextEdit()
        self.description_text_edit.setMaximumHeight(70)
        self.description_text_edit.setTabChangesFocus(True)

        self.push_button = QPushButton("Save")

        form = QFormLayout()
        form.setWidget(0, QFormLayout.LabelRole, self.name_label)
        form.setWidget(0, QFormLayout.FieldRole, self.name_line_edit)
        form.setWidget(1, QFormLayout.LabelRole, self.introducer_label)
        form.setWidget(1, QFormLayout.FieldRole, self.introducer_text_edit)
        #form.setWidget(2, QFormLayout.LabelRole, self.description_label)
        #form.setWidget(2, QFormLayout.FieldRole, self.description_text_edit)
        form.setWidget(3, QFormLayout.FieldRole, self.push_button)

        hbox = QHBoxLayout(self)
        #hbox.addItem(QSpacerItem(100, 0, QSizePolicy.Preferred, 0))
        hbox.addLayout(form)
Ejemplo n.º 15
0
    def keyPressEvent(self, event):
        #if self.completer.popup().isVisible():
            #if event.key() in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Tab):
                #event.ignore()
                #self.completer.popup().hide()
                #return
            #elif event.key in (Qt.Key_Space, Qt.Key_Escape, Qt.Key_Backtab):
                #self.completer.popup().hide()

        self._check_event_on_selection(event)
        if self._pre_key_press.get(event.key(), lambda x: False)(event):
            return

        if event.text() in (set(BRACES.values()) - set(["'", '"'])):
            cursor = self.textCursor()
            cursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor)
            brace = cursor.selection().toPlainText()
            cursor = self.textCursor()
            cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor)
            braceClose = cursor.selection().toPlainText()
            if BRACES.get(brace, False) == event.text() and \
              braceClose == event.text():
                self.moveCursor(QTextCursor.Right)
                return

        QPlainTextEdit.keyPressEvent(self, event)

        if event.text() in BRACES:
            cursor = self.textCursor()
            cursor.movePosition(QTextCursor.StartOfLine,
                QTextCursor.KeepAnchor)
            self.textCursor().insertText(
                BRACES[event.text()])
            self.moveCursor(QTextCursor.Left)
Ejemplo n.º 16
0
 def resizeEvent(self, e):
     QPlainTextEdit.resizeEvent(self, e)
     self.cr = self.contentsRect()
     self.lineNumberArea.setGeometry(self.cr.left(),
                                     self.cr.top(),
                                     self.lineNumberAreaWidth(),
                                     self.cr.height())
Ejemplo n.º 17
0
 def wheelEvent(self, event):
     if (event.modifiers() & Qt.ControlModifier):
         self.y = event.angleDelta() / 120
         # print('wheel is ',self.x.y())
         delta = self.y.y()
         self.zoomOption(delta)
     else:
         QPlainTextEdit.wheelEvent(self, event)
Ejemplo n.º 18
0
class QPlainTextEditLogger(logging.Handler):
    def __init__(self, parent):
        super().__init__()
        self.widget = QPlainTextEdit(parent)
        self.widget.setReadOnly(True)

    def emit(self, record):
        msg = self.format(record)
        self.widget.appendPlainText(msg)
Ejemplo n.º 19
0
 def mouseMoveEvent(self, event):
     cursor = self.cursorForPosition(event.pos())
     text = cursor.block().text()
     if text:
         if self.patLink.match(text):
             self.viewport().setCursor(Qt.PointingHandCursor)
         else:
             self.viewport().setCursor(Qt.IBeamCursor)
     QPlainTextEdit.mouseMoveEvent(self, event)
Ejemplo n.º 20
0
Archivo: util.py Proyecto: jopohl/urh
def create_textbox_dialog(content: str, title: str, parent) -> QDialog:
    d = QDialog(parent)
    d.resize(800, 600)
    d.setWindowTitle(title)
    layout = QVBoxLayout(d)
    text_edit = QPlainTextEdit(content)
    text_edit.setReadOnly(True)
    layout.addWidget(text_edit)
    d.setLayout(layout)
    return d
Ejemplo n.º 21
0
 def __init_layout(self) -> QVBoxLayout:
     self.__sql_input = QPlainTextEdit()
     self.__sql_input.setFixedHeight(self.__SQL_INPUT_HEIGHT)
     self.__output = QPlainTextEdit()
     vbox = QVBoxLayout()
     vbox.addLayout(self.__init_sql_query_layout())
     vbox.addWidget(self.__sql_input)
     vbox.addLayout(self.__init_sql_template_button_layout())
     vbox.addWidget(self.__output)
     return vbox
Ejemplo n.º 22
0
 def __init__(self):
     QPlainTextEdit.__init__(self)
     EditorMixin.__init__(self)
     # Word separators
     # Can be used by code completion and the link emulator
     self.word_separators = "`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?"
     # Style
     self.__init_style()
     self.__apply_style()
     self.__visible_blocks = []
Ejemplo n.º 23
0
class CommentEditor(QWidget):
    textChanged = pyqtSignal()

    def __init__(self, comments=""):
        """
        Just holds a TextEdit and a label
        """
        super(CommentEditor, self).__init__()
        self.top_layout = WidgetUtils.addLayout(vertical=True)
        self.setLayout(self.top_layout)
        self.editor = QPlainTextEdit(self)
        self.editor.resize(10, 10)
        self.editor.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.editor.setPlainText(comments)
        self.label = WidgetUtils.addLabel(self.top_layout, self, "Comment")
        self.top_layout.addWidget(self.editor)
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(0, 20)
        self.editor.textChanged.connect(self.textChanged)

    def setComments(self, comments):
        self.editor.setPlainText(comments)

    def getComments(self):
        return str(self.editor.toPlainText())
Ejemplo n.º 24
0
class ErrorReportDialog(QDialog):
    def __init__(self, parent, github_url, error, **kwargs):
        flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
        super().__init__(parent, flags, **kwargs)
        self._setupUi()
        name = QCoreApplication.applicationName()
        version = QCoreApplication.applicationVersion()
        errorText = "Application Name: {}\nVersion: {}\n\n{}".format(name, version, error)
        # Under windows, we end up with an error report without linesep if we don't mangle it
        errorText = errorText.replace('\n', os.linesep)
        self.errorTextEdit.setPlainText(errorText)
        self.github_url = github_url
        
        self.sendButton.clicked.connect(self.goToGithub)
        self.dontSendButton.clicked.connect(self.reject)
    
    def _setupUi(self):
        self.setWindowTitle(tr("Error Report"))
        self.resize(553, 349)
        self.verticalLayout = QVBoxLayout(self)
        self.label = QLabel(self)
        self.label.setText(tr("Something went wrong. How about reporting the error?"))
        self.label.setWordWrap(True)
        self.verticalLayout.addWidget(self.label)
        self.errorTextEdit = QPlainTextEdit(self)
        self.errorTextEdit.setReadOnly(True)
        self.verticalLayout.addWidget(self.errorTextEdit)
        msg = tr(
            "Error reports should be reported as Github issues. You can copy the error traceback "
            "above and paste it in a new issue (bonus point if you run a search to make sure the "
            "issue doesn't already exist). What usually really helps is if you add a description "
            "of how you got the error. Thanks!"
            "\n\n"
            "Although the application should continue to run after this error, it may be in an "
            "unstable state, so it is recommended that you restart the application."
        )
        self.label2 = QLabel(msg)
        self.label2.setWordWrap(True)
        self.verticalLayout.addWidget(self.label2)
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.addItem(horizontalSpacer())
        self.dontSendButton = QPushButton(self)
        self.dontSendButton.setText(tr("Close"))
        self.dontSendButton.setMinimumSize(QSize(110, 0))
        self.horizontalLayout.addWidget(self.dontSendButton)
        self.sendButton = QPushButton(self)
        self.sendButton.setText(tr("Go to Github"))
        self.sendButton.setMinimumSize(QSize(110, 0))
        self.sendButton.setDefault(True)
        self.horizontalLayout.addWidget(self.sendButton)
        self.verticalLayout.addLayout(self.horizontalLayout)
    
    def goToGithub(self):
        open_url(self.github_url)
Ejemplo n.º 25
0
 def paintEvent(self, event):
     painter = QPainter(self.viewport())
     if self.highlight_line:
         r = self.cursorRect()
         r.setX(0)
         r.setWidth(self.viewport().width())
         painter.fillRect(r, self.highlight_brush)
     if self.draw_line:
         painter.setPen(self.line_pen)
         painter.drawLine(self.line)
     painter.end()
     QPlainTextEdit.paintEvent(self, event)
Ejemplo n.º 26
0
class TracebackWidget(QWidget):
    """
    Represents a python traceback
    """

    def __init__(self, traceback_msg):
        super(TracebackWidget, self).__init__()
        vbox = QVBoxLayout(self)
        self._editor = QPlainTextEdit()
        vbox.addWidget(QLabel(_translate("TracebackWidget", 'Traceback')))
        vbox.addWidget(self._editor)
        self._editor.setReadOnly(True)
        self._editor.insertPlainText(traceback_msg)
Ejemplo n.º 27
0
Archivo: wizard.py Proyecto: khuno/rpg
class ScriptsPage(QtWidgets.QWizardPage):
    def __init__(self, Wizard, parent=None):
        super(ScriptsPage, self).__init__(parent)

        self.base = Wizard.base

        self.setTitle(self.tr("Scripts page"))
        self.setSubTitle(self.tr("Write scripts"))

        prepareLabel = QLabel("%prepare: ")
        self.prepareEdit = QPlainTextEdit()

        buildLabel = QLabel("%build: ")
        self.buildEdit = QPlainTextEdit()

        installLabel = QLabel("%install: ")
        self.installEdit = QPlainTextEdit()

        checkLabel = QLabel("%check: ")
        self.checkEdit = QPlainTextEdit()

        buildArchLabel = QLabel("BuildArch: ")
        self.buildArchCheckbox = QCheckBox("noarch")

        grid = QGridLayout()
        grid.addWidget(prepareLabel, 0, 0)
        grid.addWidget(self.prepareEdit, 0, 1)
        grid.addWidget(buildLabel, 1, 0)
        grid.addWidget(self.buildEdit, 1, 1)
        grid.addWidget(installLabel, 2, 0)
        grid.addWidget(self.installEdit, 2, 1)
        grid.addWidget(checkLabel, 3, 0)
        grid.addWidget(self.checkEdit, 3, 1)
        grid.addWidget(buildArchLabel, 4, 0)
        grid.addWidget(self.buildArchCheckbox, 4, 1)
        self.setLayout(grid)

    def validatePage(self):
        self.base.spec.scripts['%prep'] = Command(self.prepareEdit.toPlainText())
        self.base.spec.scripts['%build'] = Command(self.buildEdit.toPlainText())
        self.base.spec.scripts['%install'] = Command(self.installEdit.toPlainText())
        self.base.spec.scripts['%check'] = Command(self.checkEdit.toPlainText())
        if self.buildArchCheckbox.isChecked():
            self.base.spec.tags['BuildArch'] = "noarch"
        else:
            self.base.spec.tags.pop('BuildArch', None)
        return True

    def nextId(self):
        return Wizard.PageRequires
Ejemplo n.º 28
0
class GalleryListEdit(misc.BasePopup):
    apply = pyqtSignal()
    def __init__(self, parent=None):
        super().__init__(parent, blur=False)
        main_layout = QFormLayout(self.main_widget)
        self.name_edit = QLineEdit(self)
        main_layout.addRow("Name:", self.name_edit)
        self.filter_edit = QPlainTextEdit(self)
        self.filter_edit.setPlaceholderText("tag1, namespace:tag2, namespace2:[tag1, tag2] ...")
        self.filter_edit.setFixedHeight(100)
        what_is_filter = misc.ClickedLabel("What is Filter/Enforce? (Hover)")
        what_is_filter.setToolTip(app_constants.WHAT_IS_FILTER)
        what_is_filter.setToolTipDuration(9999999999)
        self.enforce = QCheckBox(self)
        self.regex = QCheckBox(self)
        self.case = QCheckBox(self)
        self.strict = QCheckBox(self)
        main_layout.addRow(what_is_filter)
        main_layout.addRow("Filter", self.filter_edit)
        main_layout.addRow("Enforce", self.enforce)
        main_layout.addRow("Regex", self.regex)
        main_layout.addRow("Case sensitive", self.case)
        main_layout.addRow("Match whole terms", self.strict)
        main_layout.addRow(self.buttons_layout)
        self.add_buttons("Close")[0].clicked.connect(self.hide)
        self.add_buttons("Apply")[0].clicked.connect(self.accept)
        old_v = self.width()
        self.adjustSize()
        self.resize(old_v, self.height())

    def set_list(self, gallery_list, item):
        self.gallery_list = gallery_list
        self.name_edit.setText(gallery_list.name)
        self.enforce.setChecked(gallery_list.enforce)
        self.regex.setChecked(gallery_list.regex)
        self.case.setChecked(gallery_list.case)
        self.strict.setChecked(gallery_list.strict)
        self.item = item
        if gallery_list.filter:
            self.filter_edit.setPlainText(gallery_list.filter)
        else:
            self.filter_edit.setPlainText('')

    def accept(self):
        name = self.name_edit.text()
        self.item.setText(name)
        self.gallery_list.name = name
        self.gallery_list.filter = self.filter_edit.toPlainText()
        self.gallery_list.enforce = self.enforce.isChecked()
        self.gallery_list.regex = self.regex.isChecked()
        self.gallery_list.case = self.case.isChecked()
        self.gallery_list.strict = self.strict.isChecked()
        gallerydb.execute(gallerydb.ListDB.modify_list, True, self.gallery_list)
        self.apply.emit()
        self.hide()
Ejemplo n.º 29
0
class ConfigFile:
    def __init__(self, display_name, absolute_name, tab, deletable=True):
        self.display_name   = display_name # is unique
        self.absolute_name  = absolute_name # is also unique
        self.tab            = tab
        self.deletable      = deletable
        self.index          = -1
        self.modified       = False
        self.content        = None
        self.edit           = QPlainTextEdit()

        font = QFont('monospace')
        font.setStyleHint(QFont.TypeWriter)

        self.edit.setWordWrapMode(QTextOption.NoWrap)
        self.edit.setFont(font)
        self.edit.textChanged.connect(self.check_content)

    def check_content(self):
        self.set_modified(self.content != self.edit.toPlainText())

    def set_modified(self, modified):
        if self.modified == modified:
            return

        self.modified = modified

        self.tab.combo_config.setItemText(self.index, self.get_combo_item())
        self.tab.update_ui_state()

    def set_content(self, content):
        # FIXME: QPlainTextEdit does not preserve the original line endings, but
        #        converts all line endings to \n. this results in a difference
        #        between self.content and the content stored in the QPlainTextEdit
        #        even if the user did not edit the content. avoid this problem
        #        by converting all line endings to \n before setting the content
        #        of the QPlainTextEdit
        content = content.replace('\r\n', '\n')

        if self.content == None:
            self.edit.setPlainText(content)

        self.content = content

        self.check_content()

    def get_combo_item(self):
        if self.modified:
            return self.display_name + ' (modified)'
        else:
            return self.display_name

    def discard_changes(self):
        self.edit.setPlainText(self.content)
        self.set_modified(False)
Ejemplo n.º 30
0
    def __init__(self):
        super(QWidget, self).__init__()
        layout = QFormLayout()
        self.setLayout(layout)

        self.buildDependencies = QPlainTextEdit()
        self.buildDependencies.textChanged.connect(self.buildDependenciesChanged)
        self.buildDependencies.setMinimumHeight(70)
        layout.addRow('Build Dependencies', self.buildDependencies)

        self.runDependencies = QPlainTextEdit()
        self.runDependencies.textChanged.connect(self.runDependenciesChanged)
        self.runDependencies.setMinimumHeight(70)
        layout.addRow('Run Dependencies', self.runDependencies)
Ejemplo n.º 31
0
 def previewWidget(self):
     w = QPlainTextEdit()
     w.setFrameShape(QFrame.NoFrame)
     w.setReadOnly(True)
     return w
Ejemplo n.º 32
0
    def initUI(self):
        # Creating an Automaton class instance
        self.Automaton = Automaton()
        # Creating a Input_String class instance
        self.Strings = Input_Strings()
        # Creating a Configuration_Setting instance
        self.Config_Setting = Configuration_Settings()
        # A attribute to remember the def_path
        self.def_path = ''
        # A attribute to remember if the automaton was opened
        self.automaton_open = False

        self.setWindowTitle("Pushdown Automaton")
        self.resize(640, 480)

        self.mainMenu = self.menuBar()

        self.fileMenu = self.mainMenu.addMenu("File")
        self.fileMenu.addAction("Open Automaton     Ctrl+O",
                                self.open_automaton_action)
        self.openShorcut = QShortcut(QKeySequence("Ctrl+O"), self)
        self.openShorcut.activated.connect(self.open_automaton_action)
        #self.fileMenu.addAction("View Automaton", self.view_automaton_action)
        self.fileMenu.addAction("Quit                            Ctrl+Shift+Q",
                                self.quit_action)
        self.quitAppShorcut = QShortcut(QKeySequence("Ctrl+Shift+Q"), self)
        self.quitAppShorcut.activated.connect(self.quit_action)

        self.helpMenu = self.mainMenu.addMenu("Help")
        self.helpMenu.addAction("User Manual        Ctrl+H",
                                self.user_manual_action)
        self.userManualShorcut = QShortcut(QKeySequence("Ctrl+H"), self)
        self.userManualShorcut.activated.connect(self.user_manual_action)

        self.inputStringLabel = QLabel(self)
        self.inputStringLabel.setGeometry(20, 40, 111, 16)
        self.inputStringLabel.setText("Input String")

        self.inputStringLineEdit = QLineEdit(self)
        self.inputStringLineEdit.setGeometry(20, 60, 231, 20)

        self.addToListPushButton = QPushButton(self)
        self.addToListPushButton.setGeometry(80, 90, 111, 23)
        self.addToListPushButton.setText("Add to List")
        self.addToListPushButton.clicked.connect(self.add_to_list_clicked)
        self.addToListShorcut = QShortcut(QKeySequence("Ctrl+Shift+A"), self)
        self.addToListShorcut.activated.connect(self.add_to_list_clicked)
        self.addToListPushButton.setToolTip("Ctrl+Shift+A")

        self.inputStringListLabel = QLabel(self)
        self.inputStringListLabel.setGeometry(20, 125, 111, 16)
        self.inputStringListLabel.setText("Input String List")

        self.inputStringListWidget = QListWidget(self)
        self.inputStringListWidget.setGeometry(20, 145, 231, 260)

        self.runStringPushButton = QPushButton(self)
        self.runStringPushButton.setGeometry(80, 415, 111, 23)
        self.runStringPushButton.setText("Run String")
        self.runStringPushButton.clicked.connect(self.run_string_clicked)
        self.runStringShorcut = QShortcut(QKeySequence("Ctrl+R"), self)
        self.runStringShorcut.activated.connect(self.run_string_clicked)
        self.runStringPushButton.setToolTip("Ctrl+R")

        self.fileNameLabel = QLabel(self)
        self.fileNameLabel.setGeometry(440, 40, 160, 16)
        self.fileNameLabel.setText("Automaton Title")
        self.fileNameLabel.setStyleSheet("color: blue")

        self.outputLabel = QLabel(self)
        self.outputLabel.setGeometry(300, 60, 47, 16)
        self.outputLabel.setText("Output")

        self.maxTransitionsLabel = QLabel(self)
        self.maxTransitionsLabel.setGeometry(370, 60, 80, 16)
        self.maxTransitionsLabel.setText("Max. Transitions")

        self.maxTransitionsSpinBox = QSpinBox(self)
        self.maxTransitionsSpinBox.setGeometry(455, 57, 42, 20)
        self.maxTransitionsSpinBox.setMinimum(1)
        #access value with self.maxTransitionsSpinBox.value

        self.displayPathsCheckBox = QCheckBox(self)
        self.displayPathsCheckBox.setGeometry(530, 60, 101, 17)
        self.displayPathsCheckBox.setText("Display Paths")
        #access true or false with self.displayPathsCheckBox.checked

        self.outputPlainTextEdit = QPlainTextEdit(self)
        self.outputPlainTextEdit.setGeometry(300, 80, 271,
                                             253)  #300, 80, 281, 283

        self.stackPlainTextEdit = QPlainTextEdit(self)
        self.stackPlainTextEdit.setGeometry(581, 80, 30, 253)

        self.pathLabel = QLabel(self)
        self.pathLabel.setGeometry(300, 335, 47, 16)
        self.pathLabel.setText("Path")

        self.pathPlainTextEdit = QPlainTextEdit(self)
        self.pathPlainTextEdit.setGeometry(300, 355, 311, 50)

        self.quitRunningStringPushButton = QPushButton(self)
        self.quitRunningStringPushButton.setGeometry(335, 415, 111, 23)
        self.quitRunningStringPushButton.setText("Quit Running String")
        self.quitRunningStringPushButton.clicked.connect(
            self.quit_running_string_clicked)
        self.quitRunningStringShorcut = QShortcut(QKeySequence("Ctrl+Q"), self)
        self.quitRunningStringShorcut.activated.connect(
            self.quit_running_string_clicked)
        self.quitRunningStringPushButton.setToolTip("Ctrl+Q")

        self.closeAutomatonPushButton = QPushButton(self)
        self.closeAutomatonPushButton.setGeometry(465, 415, 111, 23)
        self.closeAutomatonPushButton.setText("Close Automaton")
        self.closeAutomatonPushButton.clicked.connect(
            self.close_automaton_clicked)
        self.closeAutomatonShorcut = QShortcut(QKeySequence("Ctrl+Alt+C"),
                                               self)
        self.closeAutomatonShorcut.activated.connect(
            self.close_automaton_clicked)
        self.closeAutomatonPushButton.setToolTip("Ctrl+Alt+C")

        # Style for status label text
        self.styleError = 'font: 15pt Arial; color: maroon'
        self.styleNormal = 'font:15pt Arial; color: green'

        self.statusBar = self.statusBar()
        self.statusLabel = QLabel(
            "application status messages will go here (when something completes, etc.)"
        )
        self.statusLabel.setStyleSheet(self.styleNormal)
        self.statusBar.addPermanentWidget(self.statusLabel)

        self.show()
Ejemplo n.º 33
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.commandslist = []
        self.tracker = 0
        os.chdir(os.path.expanduser("~"))
        #        print(os.getcwd())
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.setWindowTitle('PyQt5Terminal')
        self.setWindowIcon(QIcon.fromTheme("terminal-emulator"))
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.process.readyRead.connect(self.dataReady)
        self.process.readyReadStandardError.connect(
            self.onReadyReadStandardError)
        self.process.readyReadStandardOutput.connect(
            self.onReadyReadStandardOutput)
        self.process.finished.connect(self.isFinished)
        self.process.setWorkingDirectory(os.getcwd())
        self.createStatusBar()

        self.commandfield = QPlainTextEdit()
        self.commandfield.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.commandfield.setFixedHeight(44)
        self.commandfield.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.commandfield.setAcceptDrops(True)
        self.cursor = self.commandfield.textCursor()

        self.textWindow = QPlainTextEdit(self)
        self.setStyleSheet(mystylesheet(self))

        self.textWindow.setReadOnly(True)
        layout = QVBoxLayout()
        layout.addWidget(self.textWindow)
        layout.addWidget(self.commandfield)
        self.wid = QWidget()
        self.wid.setLayout(layout)
        self.setCentralWidget(self.wid)
        self.setGeometry(0, 0, 600, 500)
        self.commandfield.setPlainText(self.name)
        self.cursorEnd()
        self.commandfield.setFocus()

        self.copySelectedTextAction = QAction(QIcon.fromTheme("edit-copy"),
                                              "Copy",
                                              shortcut="Shift+Ctrl+c",
                                              triggered=self.copyText)
        self.textWindow.addAction(self.copySelectedTextAction)
        self.pasteTextAction = QAction(QIcon.fromTheme("edit-paste"),
                                       "Copy",
                                       shortcut="Shift+Ctrl+v",
                                       triggered=self.pasteText)
        self.commandfield.addAction(self.pasteTextAction)
        #
        self.cancelAction = QAction("Cancel",
                                    shortcut="Ctrl+c",
                                    triggered=self.killProcess)
        self.textWindow.addAction(self.cancelAction)

        self.commandfield.installEventFilter(self)
        #        self.textWindow.installEventFilter(self)
        QApplication.setCursorFlashTime(1000)
        self.cursorEnd()
        print(self.process.workingDirectory())
        self.settings = QSettings("QTerminal", "QTerminal")
        self.readSettings()

    def closeEvent(self, e):
        self.writeSettings()

    def cursorEnd(self):
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.commandfield.setPlainText(self.name)
        cursor = self.commandfield.textCursor()
        cursor.movePosition(11, 0)
        self.commandfield.setTextCursor(cursor)
        self.commandfield.setFocus()

    def eventFilter(self, source, event):
        if source == self.commandfield:
            if (event.type() == QEvent.DragEnter):
                event.accept()
                return True
            elif (event.type() == QEvent.Drop):
                print('Drop')
                self.setDropEvent(event)
                return True
            elif (event.type() == QEvent.KeyPress):
                cursor = self.commandfield.textCursor()
                #                print('key press:', (event.key(), event.text()))
                if event.key() == Qt.Key_Backspace:
                    if cursor.positionInBlock() <= len(self.name):
                        return True
                    else:
                        return False

                elif event.key() == Qt.Key_Return:
                    self.run()
                    return True

                elif event.key() == Qt.Key_Left:
                    if cursor.positionInBlock() <= len(self.name):
                        return True
                    else:
                        return False

                elif event.key() == Qt.Key_Delete:
                    if cursor.positionInBlock() <= len(self.name) - 1:
                        return True
                    else:
                        return False

                elif event.modifiers() == Qt.ControlModifier and event.key(
                ) == Qt.Key_C:
                    self.killProcess()
                    return True

                elif event.key() == Qt.Key_Up:
                    try:
                        if self.tracker != 0:
                            cursor.select(QTextCursor.BlockUnderCursor)
                            cursor.removeSelectedText()
                            self.commandfield.appendPlainText(self.name)

                        self.commandfield.insertPlainText(
                            self.commandslist[self.tracker])
                        self.tracker -= 1

                    except IndexError:
                        self.tracker = 0
                    return True

                elif event.key() == Qt.Key_Down:
                    try:
                        if self.tracker != 0:
                            cursor.select(QTextCursor.BlockUnderCursor)
                            cursor.removeSelectedText()
                            self.commandfield.appendPlainText(self.name)

                        self.commandfield.insertPlainText(
                            self.commandslist[self.tracker])
                        self.tracker += 1

                    except IndexError:
                        self.tracker = 0
                    return True

                else:
                    return False
            else:
                return False
        else:
            return False

    def copyText(self):
        self.textWindow.copy()

    def pasteText(self):
        self.commandfield.paste()

    def killProcess(self):
        print("cancelled")
        self.process.kill()
        self.textWindow.appendPlainText("cancelled")
        self.cursorEnd()

    def createStatusBar(self):
        sysinfo = QSysInfo()
        myMachine = "current CPU Architecture: " + sysinfo.currentCpuArchitecture(
        ) + " *** " + sysinfo.prettyProductName(
        ) + " *** " + sysinfo.kernelType() + " " + sysinfo.kernelVersion()
        self.statusBar().showMessage(myMachine, 0)

    def setDropEvent(self, event):
        self.commandfield.setFocus()
        if event.mimeData().hasUrls():
            f = str(event.mimeData().urls()[0].toLocalFile())
            print("is file:", f)
            if " " in f:
                self.commandfield.insertPlainText("'{}'".format(f))
            else:
                self.commandfield.insertPlainText(f)
            event.accept()
        elif event.mimeData().hasText():
            ft = event.mimeData().text()
            print("is text:", ft)
            if " " in ft:
                self.commandfield.insertPlainText("'{}'".format(ft))
            else:
                self.commandfield.insertPlainText(ft)
        else:
            event.ignore()

    def run(self):
        print("started")
        cli = []
        cmd = ""
        t = ""
        self.textWindow.setFocus()
        self.textWindow.appendPlainText(self.commandfield.toPlainText())
        cli = shlex.split(self.commandfield.toPlainText().replace(
            self.name, '').replace("'", '"'),
                          posix=False)
        cmd = str(cli[0])  ### is the executable

        if cmd == "exit":
            quit()

        elif cmd == "cd":
            del cli[0]
            path = " ".join(cli)
            os.chdir(os.path.abspath(path))
            self.process.setWorkingDirectory(os.getcwd())
            print("workingDirectory:", self.process.workingDirectory())
            self.cursorEnd()
        else:
            self.process.setWorkingDirectory(os.getcwd())
            print("workingDirectory", self.process.workingDirectory())
            del cli[0]
            if (QStandardPaths.findExecutable(cmd)):
                self.commandslist.append(
                    self.commandfield.toPlainText().replace(self.name, ""))
                print("command", cmd, "found")
                t = " ".join(cli)
                if self.process.state() != 2:
                    self.process.waitForStarted()
                    self.process.waitForFinished()
                    if "|" in t or ">" in t or "<" in t:
                        print("special characters")
                        self.process.start('sh -c "' + cmd + ' ' + t + '"')
                        print("running", ('sh -c "' + cmd + ' ' + t + '"'))
                    else:
                        self.process.start(cmd + " " + t)
                        print("running", (cmd + " " + t))
            else:
                print("command not found ...")
                self.textWindow.appendPlainText("command not found ...")
                self.cursorEnd()

    def dataReady(self):
        out = ""
        try:
            out = str(self.process.readAll(), encoding='utf8').rstrip()
        except TypeError:
            out = str(self.process.readAll()).rstrip()
            self.textWindow.moveCursor(self.cursor.Start)  ### changed
        self.textWindow.appendPlainText(out)

    def onReadyReadStandardError(self):
        self.error = self.process.readAllStandardError().data().decode()
        self.textWindow.appendPlainText(self.error.strip('\n'))
        self.cursorEnd()

    def onReadyReadStandardOutput(self):
        self.result = self.process.readAllStandardOutput().data().decode()
        self.textWindow.appendPlainText(self.result.strip('\n'))
        self.cursorEnd()
        self.state = self.process.state()

    def isFinished(self):
        print("finished")
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.commandfield.setPlainText(self.name)
        self.cursorEnd()

    def readSettings(self):
        if self.settings.contains("commands"):
            self.commandslist = self.settings.value("commands")
        if self.settings.contains("pos"):
            pos = self.settings.value("pos", QPoint(200, 200))
            self.move(pos)
        if self.settings.contains("size"):
            size = self.settings.value("size", QSize(400, 400))
            self.resize(size)

    def writeSettings(self):
        self.settings.setValue("commands", self.commandslist)
        self.settings.setValue("pos", self.pos())
        self.settings.setValue("size", self.size())
Ejemplo n.º 34
0
 def resizeEvent(self, e):
     o = QPlainTextEdit.resizeEvent(self, e)
     self.resizeButtons()
     return o
Ejemplo n.º 35
0
class DebugWindow(QMainWindow):
    """A main window to edit text and examine the generated token structure.

    Example::

        from PyQt5.Qt import *
        a=QApplication([])

        from parceqt.debug import DebugWindow
        w = DebugWindow()
        w.resize(1200,900)
        w.show()

        w.set_theme("default", True)

        from parce.lang.css import *
        w.set_root_lexicon(Css.root)
        w.set_text(open("path/to/parce/themes/default.css").read())

    In the debug window you can edit the text at the left and directly at the
    right examine the tree structure. Along the top of the window the path to
    the token at the current cursor position is displayed, from the root
    lexicon upto the token, from which the action is displayed.

    Clicking a button selects the associated range of the context or token in
    the text view. Clicking an item in the tree also selects that range in the
    text.

    Moving the cursor in the text updates the current item in the tree,
    and the displayed ancestor path.

    """

    show_updated_region_enabled = False

    def __init__(self, parent=None):
        super().__init__(parent, windowTitle="parceqt debugger")

        f = self._updated_format = QTextCharFormat()
        c = QColor("palegreen")
        c.setAlpha(64)
        f.setBackground(c)
        f = self._currentline_format = QTextCharFormat()
        f.setProperty(QTextCharFormat.FullWidthSelection, True)

        self._actions = Actions(self)
        self._actions.add_menus(self.menuBar())

        widget = QWidget(self)
        self.setCentralWidget(widget)
        layout = QVBoxLayout(margin=4, spacing=2)
        widget.setLayout(layout)

        top_layout = QHBoxLayout(margin=0, spacing=0)

        self.guessButton = QToolButton(self,
                                       clicked=self.guess_root_lexicon,
                                       toolTip="Guess Language",
                                       icon=self.style().standardIcon(
                                           QStyle.SP_BrowserReload))
        self.lexiconChooser = LexiconChooser(self)
        self.ancestorView = AncestorView(self)
        top_layout.addWidget(self.guessButton)
        top_layout.addWidget(self.lexiconChooser)
        top_layout.addWidget(self.ancestorView)
        top_layout.addStretch(10)
        layout.addLayout(top_layout)
        self.guessButton.setFixedHeight(
            self.lexiconChooser.sizeHint().height())

        splitter = QSplitter(self, orientation=Qt.Horizontal)
        layout.addWidget(splitter, 100)

        self.textEdit = QPlainTextEdit(lineWrapMode=QPlainTextEdit.NoWrap,
                                       cursorWidth=2)
        self.treeView = QTreeView()

        splitter.addWidget(self.textEdit)
        splitter.addWidget(self.treeView)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 2)

        self.extraSelectionManager = ExtraSelectionManager(self.textEdit)

        self.document = d = self.textEdit.document()
        self.textEdit.setDocument(self.document)

        self.worker = w = parceqt.worker(d)
        self.builder = b = w.builder()
        w.debugging = True

        self.setStatusBar(QStatusBar())
        self.create_model()

        # signal connections
        self.textEdit.viewport().installEventFilter(self)
        self.textEdit.installEventFilter(self)
        self.lexiconChooser.lexicon_changed.connect(
            self.slot_root_lexicon_changed)
        self.ancestorView.node_clicked.connect(self.slot_node_clicked)
        w.started.connect(self.slot_build_started)
        w.tree_updated.connect(self.slot_build_updated)
        self.textEdit.cursorPositionChanged.connect(
            self.slot_cursor_position_changed)
        self.treeView.clicked.connect(self.slot_item_clicked)

        self.textEdit.setFocus()
        self.set_theme()

        # somewhat larger font by default
        font = self.textEdit.font()
        font.setPointSizeF(11)
        self.textEdit.setFont(font)

    def create_model(self):
        """Instantiate a tree model for the tree view."""
        m = self.treeView.model()
        if not m:
            m = parceqt.treemodel.TreeModel(self.builder.root)
            m.connect_debugging_builder(self.builder)
            self.treeView.setModel(m)

    def delete_model(self):
        """Delete the model and remove it from the tree."""
        m = self.treeView.model()
        if m:
            m.disconnect_debugging_builder(self.builder)
            self.treeView.setModel(None)
            m.deleteLater()

    def set_text(self, text):
        """Set the text in the text edit."""
        self.document.setPlainText(text)

    def set_root_lexicon(self, lexicon):
        """Set the root lexicon to use."""
        self.lexiconChooser.set_root_lexicon(lexicon)

    def guess_root_lexicon(self):
        """Again choose the root lexicon based on the text."""
        text = self.document.toPlainText()
        if text:
            self.set_root_lexicon(parce.find(contents=text))

    def open_file(self, filename):
        """Read a file from disk and guess the language."""
        text = read_file(filename)
        root_lexicon = parce.find(filename=filename, contents=text)
        self.set_text(text)
        self.set_root_lexicon(root_lexicon)
        c = self.textEdit.textCursor()
        c.setPosition(0)
        self.textEdit.setTextCursor(c)

    def set_theme(self, theme="default", adjust_widget=True):
        """Set the theme to use for the text edit."""
        if isinstance(theme, str):
            theme = parce.theme_by_name(theme)
        formatter = parceqt.formatter.Formatter(theme) if theme else None
        if adjust_widget:
            if formatter:
                font = formatter.font(self)
                self.textEdit.setPalette(formatter.palette(self))
            else:
                font = QApplication.font(self)
                self.textEdit.setPalette(QApplication.palette(self))
            font.setPointSizeF(self.textEdit.font().pointSizeF())  # keep size
            self.textEdit.setFont(font)
            self.highlight_current_line()
        h = parceqt.highlighter.SyntaxHighlighter.instance(self.worker)
        h.set_formatter(formatter)

    def slot_build_started(self):
        """Called when the tree builder has started a build."""
        self.treeView.setCursor(Qt.BusyCursor)

    def slot_build_updated(self):
        """Called when the tree builder has finished a build."""
        self.treeView.unsetCursor()
        self.slot_cursor_position_changed()
        self.statusBar().showMessage(", ".join(
            lexicon_names(self.builder.lexicons)))
        tree = self.worker.get_root()
        self.lexiconChooser.setToolTip(
            parceqt.treemodel.TreeModel.node_tooltip(tree))
        if self.show_updated_region_enabled:
            self.show_updated_region()

    def slot_cursor_position_changed(self):
        """Called when the text cursor moved."""
        tree = self.worker.get_root()
        if tree:
            pos = self.textEdit.textCursor().position()
            doc = parceqt.document.Document(self.document)
            token = doc.token(pos)
            if token:
                self.ancestorView.set_token_path(token)
                model = self.treeView.model()
                if model:
                    index = model.get_model_index(token)
                    self.treeView.setCurrentIndex(index)
        elif tree is not None:
            self.ancestorView.clear()
        self.highlight_current_line()

    def slot_item_clicked(self, index):
        """Called when a node in the tree view is clicked."""
        tree = self.worker.get_root()
        if tree:
            model = self.treeView.model()
            if model:
                node = self.treeView.model().get_node(index)
                cursor = self.textEdit.textCursor()
                cursor.setPosition(node.end)
                cursor.setPosition(node.pos, QTextCursor.KeepAnchor)
                self.textEdit.setTextCursor(cursor)
        self.textEdit.setFocus()

    def slot_node_clicked(self, node):
        """Called when a button in the ancestor view is clicked."""
        tree = self.worker.get_root()
        if tree and node.root() is tree:
            cursor = self.textEdit.textCursor()
            cursor.setPosition(node.end)
            cursor.setPosition(node.pos, QTextCursor.KeepAnchor)
            self.textEdit.setTextCursor(cursor)
            self.textEdit.setFocus()
            model = self.treeView.model()
            if model:
                index = model.get_model_index(node)
                self.treeView.expand(index)
                self.treeView.setCurrentIndex(index)

    def slot_root_lexicon_changed(self, lexicon):
        """Called when the root lexicon is changed."""
        parceqt.set_root_lexicon(self.document, lexicon)

    def highlight_current_line(self):
        """Highlight the current line."""
        group = QPalette.Active if self.textEdit.hasFocus(
        ) else QPalette.Inactive
        p = self.textEdit.palette()
        color = p.color(group, QPalette.AlternateBase)
        self._currentline_format.setBackground(color)
        if color != p.color(group, QPalette.Base):
            c = self.textEdit.textCursor()
            c.clearSelection()
            self.extraSelectionManager.highlight(self._currentline_format, [c])
        else:
            self.extraSelectionManager.clear(self._currentline_format)

    def show_updated_region(self):
        """Highlight the updated region for 2 seconds."""
        end = self.builder.end
        if end >= self.document.characterCount() - 1:
            end = self.document.characterCount() - 1
            if self.builder.start == 0:
                return
        c = QTextCursor(self.document)
        c.setPosition(end)
        c.setPosition(self.builder.start, QTextCursor.KeepAnchor)
        self.extraSelectionManager.highlight(self._updated_format, [c],
                                             msec=2000)

    def clear_updated_region(self):
        self.extraSelectionManager.clear(self._updated_format)

    def eventFilter(self, obj, ev):
        """Implemented to support Ctrl+wheel zooming and keybfocus handling."""
        if obj == self.textEdit:
            if ev.type() in (QEvent.FocusIn, QEvent.FocusOut):
                self.highlight_current_line()
        else:  # viewport
            if ev.type() == QEvent.Wheel and ev.modifiers(
            ) == Qt.ControlModifier:
                if ev.angleDelta().y() > 0:
                    self.textEdit.zoomIn()
                elif ev.angleDelta().y() < 0:
                    self.textEdit.zoomOut()
                return True
        return False
Ejemplo n.º 36
0
class RemoteWidget(QWidget):
    """Main Widget."""

    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self._connected_sensors = {}
        self.resize(700, 500)

        # Varibles for PowerReport
        self.window_power_r = None
        self.power_config_name = []
        self.power_config_id = []
        self.power_th = []
        self.power_pol = []
        self.power_data_acc = False

        # debug messages
        self.debug_label = QLabel(self.tr('Debug'))
        self.debug_textedit = QPlainTextEdit()
        self.debug_textedit.setReadOnly(True)
        self.debug_label.setBuddy(self.debug_textedit)

        self._debug = CustomDebug(self.debug_textedit)

        # Refresh COM Ports
        self.refresh_com_ports_btn = QPushButton(self.tr('Refresh'))
        self.refresh_com_ports_btn.pressed.connect(self.update_com_ports)

        # Refresh COM Ports
        self.connect_btn = QPushButton(self.tr('Connect'))
        self.connect_btn.pressed.connect(self.on_connect_btn_pressed)

        # Port Combobox
        self.port_label = QLabel(self.tr('COM Port:'))
        self.port_combobox = QComboBox()
        self.port_label.setBuddy(self.port_combobox)
        self.port_combobox.currentIndexChanged.connect(
            self.on_port_combobox_change)
        self.update_com_ports()

        # Connect and Disconnect Buttons
        self.connect_btn = QPushButton(self.tr('Connect'))
        self.disconnect_btn = QPushButton(self.tr('Disconnect'))
        self.disconnect_btn.setVisible(False)
        self.connect_btn.pressed.connect(self.on_connect_btn_pressed)
        self.disconnect_btn.pressed.connect(self.on_disconnect_btn_pressed)

        # New Configuration Button
        self.new_config_btn = QPushButton(self.tr('New'))
        self.new_config_btn.setVisible(False)
        self.new_config_btn.pressed.connect(self.on_new_config_pressed)

        # Test connection
        self.test_btn = QPushButton(self.tr('Test'))
        self.test_btn.setVisible(False)
        self.connect_btn.pressed.connect(self.on_test_btn_pressed)

        # poll messages
        # Enabled?
        # self.poll_checkbox = QCheckBox("Poll?", self)
        # self.poll_checkbox.stateChanged.connect(self.click_poll_sensor)
        # Seconds
        self.poll_label = QLabel(self.tr('Poll interval (minutes):'))
        self.poll_lineedit = QLineEdit()
        self.poll_label.setBuddy(self.poll_lineedit)
        self.poll_label.setVisible(False)
        self.poll_lineedit.setEnabled(True)
        self.poll_lineedit.setVisible(False)
        # self.poll_lineedit.returnPressed.connect(self.)

        # threshold
        # per metric
        # Enabled?
        self.threshold_label_1 = QLabel(self.tr('Metric 1:'))

        self.threshold_label_2 = QLabel(self.tr('Metric 2:'))
        self.threshold_label_2.setVisible(False)

        self.threshold_label_3 = QLabel(self.tr('Metric 3:'))
        self.threshold_label_3.setVisible(True)

        self.threshold_label_4 = QLabel(self.tr('Metric 4:'))
        self.threshold_label_4.setVisible(True)

        self.threshold_checkbox_1 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_1.stateChanged.connect(
            self.click_threshold_checkbox_1)
        self.threshold_checkbox_1.setVisible(False)

        self.threshold_checkbox_2 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_2.stateChanged.connect(
            self.click_threshold_checkbox_2)
        self.threshold_checkbox_2.setVisible(False)

        self.threshold_checkbox_3 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_3.stateChanged.connect(
            self.click_threshold_checkbox_3)
        self.threshold_checkbox_3.setVisible(False)

        self.threshold_checkbox_4 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_4.stateChanged.connect(
            self.click_threshold_checkbox_4)
        self.threshold_checkbox_4.setVisible(False)

        # threshold high
        self.threshold_high_label_1 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_1 = QLineEdit()
        self.threshold_high_label_1.setBuddy(self.threshold_high_lineedit_1)
        self.threshold_high_lineedit_1.setEnabled(True)

        self.threshold_high_label_2 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_2 = QLineEdit()
        self.threshold_high_label_2.setBuddy(self.threshold_high_lineedit_2)
        self.threshold_high_lineedit_2.setEnabled(True)

        self.threshold_high_label_3 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_3 = QLineEdit()
        self.threshold_high_label_3.setBuddy(self.threshold_high_lineedit_3)
        self.threshold_high_lineedit_3.setEnabled(True)

        self.threshold_high_label_4 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_4 = QLineEdit()
        self.threshold_high_label_4.setBuddy(self.threshold_high_lineedit_4)
        self.threshold_high_lineedit_4.setEnabled(True)

        # threshold Low
        self.threshold_low_label_1 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_1 = QLineEdit()
        self.threshold_low_label_1.setBuddy(self.threshold_low_lineedit_1)
        self.threshold_low_lineedit_1.setEnabled(True)

        self.threshold_low_label_2 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_2 = QLineEdit()
        self.threshold_low_label_2.setBuddy(self.threshold_low_lineedit_2)
        self.threshold_low_lineedit_2.setEnabled(True)

        self.threshold_low_label_3 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_3 = QLineEdit()
        self.threshold_low_label_3.setBuddy(self.threshold_low_lineedit_3)
        self.threshold_low_lineedit_3.setEnabled(True)

        self.threshold_low_label_4 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_4 = QLineEdit()
        self.threshold_low_label_4.setBuddy(self.threshold_low_lineedit_4)
        self.threshold_low_lineedit_4.setEnabled(True)

        # Sensor Combobox
        self.sensor_label = QLabel(self.tr('Sensor:'))
        self.sensor_combobox = QComboBox()
        self.sensor_label.setBuddy(self.sensor_combobox)
        self.sensor_combobox.currentIndexChanged.connect(
            self.on_sensor_combobox_change)
        self.update_com_ports()
        self.sensor_btn = QPushButton(self.tr('Load'))
        self.sensor_btn.setVisible(False)
        self.sensor_btn.pressed.connect(self.on_sensor_btn_pressed)

        # Save and Disconnect Buttons
        self.save_btn = QPushButton(self.tr('Save'))
        # disable visivibility and only show when there is a connection
        self.save_btn.setVisible(False)
        self.disconnect_btn = QPushButton(self.tr('Disconnect'))
        self.disconnect_btn.setVisible(False)
        self.save_btn.pressed.connect(self.on_save_btn_pressed)
        self.disconnect_btn.pressed.connect(self.on_disconnect_btn_pressed)

        # Power Report Button
        # self.power_report_btn = QPushButton(self.tr('Power Report'))
        # self.power_report_btn.setVisible(False)
        # self.power_report_btn.pressed.connect(self.on_power_report_btn_pressed)

        # Data Accumulation Enabling/Disabling
        self.accumulation_checkbox = QCheckBox("Data Accumulation ?", self)
        self.accumulation_checkbox.stateChanged.connect(self.click_accumulation_checkbox)
        self.accumulation_checkbox.setVisible(False)

        # Arrange Layout
        layout = QGridLayout()

        # COM Port line
        layout.addWidget(self.port_label, 0, 0)
        layout.addWidget(self.port_combobox, 0, 1, 1, 3)
        layout.addWidget(self.connect_btn, 0, 4)
        layout.addWidget(self.refresh_com_ports_btn, 0, 5)
        # layout.addWidget(self.port_motherboard, 0, 1, 2)

        # Sensors line
        layout.addWidget(self.sensor_label, 1, 0)
        layout.addWidget(self.sensor_combobox, 1, 1, 1, 3)
        layout.addWidget(self.sensor_btn, 1, 4)
        layout.addWidget(self.save_btn, 1, 5)

        # Polling line

        # layout.addWidget(self.poll_checkbox, 2, 0)
        layout.addWidget(self.poll_label, 3, 1)
        layout.addWidget(self.poll_lineedit, 3, 2)

        # threshold line

        layout.addWidget(self.threshold_label_1, 4, 0)
        layout.addWidget(self.threshold_checkbox_1, 4, 1)
        layout.addWidget(self.threshold_high_label_1, 4, 2)
        layout.addWidget(self.threshold_high_lineedit_1, 4, 3)
        layout.addWidget(self.threshold_low_label_1, 4, 4)
        layout.addWidget(self.threshold_low_lineedit_1, 4, 5)

        layout.addWidget(self.threshold_label_2, 5, 0)
        layout.addWidget(self.threshold_checkbox_2, 5, 1)
        layout.addWidget(self.threshold_high_label_2, 5, 2)
        layout.addWidget(self.threshold_high_lineedit_2, 5, 3)
        layout.addWidget(self.threshold_low_label_2, 5, 4)
        layout.addWidget(self.threshold_low_lineedit_2, 5, 5)

        layout.addWidget(self.threshold_label_3, 6, 0)
        layout.addWidget(self.threshold_checkbox_3, 6, 1)
        layout.addWidget(self.threshold_high_label_3, 6, 2)
        layout.addWidget(self.threshold_high_lineedit_3, 6, 3)
        layout.addWidget(self.threshold_low_label_3, 6, 4)
        layout.addWidget(self.threshold_low_lineedit_3, 6, 5)

        layout.addWidget(self.threshold_label_4, 7, 0)
        layout.addWidget(self.threshold_checkbox_4, 7, 1)
        layout.addWidget(self.threshold_high_label_4, 7, 2)
        layout.addWidget(self.threshold_high_lineedit_4, 7, 3)
        layout.addWidget(self.threshold_low_label_4, 7, 4)
        layout.addWidget(self.threshold_low_lineedit_4, 7, 5)

        # Debug
        layout.addWidget(self.debug_label, 8, 0)
        layout.addWidget(self.debug_textedit, 9, 0, 1, 6)

        # Save and disconnect layout
        layout.addWidget(self.disconnect_btn, 10, 4)
        layout.addWidget(self.test_btn, 10, 5)

        # Power Report Button
        # layout.addWidget(self.power_report_btn, 10, 0)

        # Accumulation Checkbox
        layout.addWidget(self.accumulation_checkbox, 2, 1)

        # New Configuration Button
        layout.addWidget(self.new_config_btn, 10, 4)

        self.remove_metric_rows_from_gui()

        self.setLayout(layout)

        # self._load_settings()

        self._debug.write("GUI", "Application started successfully")
        self._debug.write("GUI", VERSION)
        self.update_com_ports()

    # def _load_settings(self) -> None:
    #     """Load settings on startup."""
    #     settings = QSettings()

    #     # port name
    #     port_name = settings.value(SETTING_PORT_NAME)
    #     if port_name is not None:
    #         index = self.port_combobox.findData(port_name)
    #         if index > -1:
    #             self.port_combobox.setCurrentIndex(index)

    #     # last message
    #     msg = settings.value(SETTING_MESSAGE)
    #     if msg is not None:
    #         self.msg_lineedit.setText(msg)

    # def _save_settings(self) -> None:
    #     """Save settings on shutdown."""
    #     settings = QSettings()
    #     settings.setValue(SETTING_PORT_NAME, self.port)
    #     settings.setValue(SETTING_MESSAGE, self.msg_lineedit.text())

    def on_test_btn_pressed(self):
        self._debug.write(
            "GUI", F"TODO")

    def show_error_message(self, msg: str) -> None:
        """Show a Message Box with the error message."""
        QMessageBox.critical(self, QApplication.applicationName(), str(msg))

    def update_com_ports(self) -> None:
        """Update COM Port list in GUI."""
        self._debug.write("COM", "Searching for COM ports")
        self.port_combobox.clear()
        for name, device in gen_serial_ports():
            self.port_combobox.addItem(name, device)
            self._debug.write("COM", F"Found name: {name}, device: {device}")

    def on_sensor_combobox_change(self, i):
        # TODO
        pass

    def on_port_combobox_change(self, i):
        self._debug.write(
            "GUI", F"Selected {self.port_combobox.currentText()} COM ports")

    def remove_metric_rows_from_gui(self):
        self.poll_lineedit.setVisible(False)
        self.poll_label.setVisible(False)

        self.threshold_label_1.setVisible(False)
        self.threshold_label_2.setVisible(False)
        self.threshold_label_3.setVisible(False)
        self.threshold_label_4.setVisible(False)

        self.threshold_checkbox_1.setVisible(False)
        self.threshold_checkbox_2.setVisible(False)
        self.threshold_checkbox_3.setVisible(False)
        self.threshold_checkbox_4.setVisible(False)

        self.threshold_high_label_1.setVisible(False)
        self.threshold_high_label_2.setVisible(False)
        self.threshold_high_label_3.setVisible(False)
        self.threshold_high_label_4.setVisible(False)

        self.threshold_low_label_1.setVisible(False)
        self.threshold_low_label_2.setVisible(False)
        self.threshold_low_label_3.setVisible(False)
        self.threshold_low_label_4.setVisible(False)

        self.threshold_high_lineedit_1.setVisible(False)
        self.threshold_high_lineedit_2.setVisible(False)
        self.threshold_high_lineedit_3.setVisible(False)
        self.threshold_high_lineedit_4.setVisible(False)

        self.threshold_low_lineedit_1.setVisible(False)
        self.threshold_low_lineedit_2.setVisible(False)
        self.threshold_low_lineedit_3.setVisible(False)
        self.threshold_low_lineedit_4.setVisible(False)

    def on_sensor_btn_pressed(self):
        self.save_btn.setVisible(True)

        self.remove_metric_rows_from_gui()
        sensor_str = self.sensor_combobox.currentText()
        selected_sensor = self._connected_sensors[sensor_str]
        self._debug.write("APP", F"Loading sensor data from {selected_sensor}")
        Motherboard.load_data(selected_sensor, self._debug, ser)
        # self.poll_checkbox.setCheckState(selected_sensor._polling_enabled)
        if selected_sensor.get_name() == 'Button Sensor':
            self.poll_label.setVisible(False)
            self.poll_lineedit.setVisible(False)
            self.poll_lineedit.setEnabled(False)
        else:
            self.poll_label.setVisible(True)
            self.poll_lineedit.setVisible(True)
            self.poll_lineedit.setEnabled(True)
            self.poll_lineedit.setText(str(selected_sensor._polling_interval_sec // 60))

        for idx, (th_e, th_h, th_l, label) in enumerate(zip(selected_sensor._thresholds_enabled,
                                                            selected_sensor.get_thresholds(which_th=Motherboard.TH_HIGH,
                                                                                           to_machine=False),
                                                            selected_sensor.get_thresholds(which_th=Motherboard.TH_LOW,
                                                                                           to_machine=False),
                                                            selected_sensor._metric_labels)):
            th_h = str(th_h)
            th_l = str(th_l)

            if idx == 0:
                self.threshold_label_1.setText(label)
                self.threshold_label_1.setVisible(True)
                self.threshold_checkbox_1.setCheckState(th_e)
                self.threshold_checkbox_1.setVisible(True)
                self.threshold_high_lineedit_1.setText(th_h)
                self.threshold_high_lineedit_1.setVisible(True)
                self.threshold_low_lineedit_1.setText(th_l)
                self.threshold_low_lineedit_1.setVisible(True)
                self.threshold_low_label_1.setVisible(True)
                self.threshold_high_label_1.setVisible(True)
            if idx == 1:
                self.threshold_label_2.setText(label)
                self.threshold_label_2.setVisible(True)
                self.threshold_checkbox_2.setCheckState(th_e)
                self.threshold_checkbox_2.setVisible(True)
                self.threshold_high_lineedit_2.setText(th_h)
                self.threshold_high_lineedit_2.setVisible(True)
                self.threshold_low_lineedit_2.setText(th_l)
                self.threshold_low_lineedit_2.setVisible(True)
                self.threshold_low_label_2.setVisible(True)
                self.threshold_high_label_2.setVisible(True)
            if idx == 2:
                self.threshold_label_3.setText(label)
                self.threshold_label_3.setVisible(True)
                self.threshold_checkbox_3.setCheckState(th_e)
                self.threshold_checkbox_3.setVisible(True)
                self.threshold_high_lineedit_3.setText(th_h)
                self.threshold_high_lineedit_3.setVisible(True)
                self.threshold_low_lineedit_3.setText(th_l)
                self.threshold_low_lineedit_3.setVisible(True)
                self.threshold_low_label_3.setVisible(True)
                self.threshold_high_label_3.setVisible(True)
            if idx == 3:
                self.threshold_label_4.setText(label)
                self.threshold_label_4.setVisible(True)
                self.threshold_checkbox_4.setCheckState(th_e)
                self.threshold_checkbox_4.setVisible(True)
                self.threshold_high_lineedit_4.setText(th_h)
                self.threshold_high_lineedit_4.setVisible(True)
                self.threshold_low_lineedit_4.setText(th_l)
                self.threshold_low_lineedit_4.setVisible(True)
                self.threshold_low_label_4.setVisible(True)
                self.threshold_high_label_4.setVisible(True)

    def on_power_report_btn_pressed(self):
        """Display Power Measurement for the selected configuration """
        # TODO
        if self.window_power_r is None:
            self.power_report_btn.setVisible(False)
            nb_bd = len(self.power_config_id)

            if nb_bd == 0:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc)
            elif nb_bd == 1:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0])
            elif nb_bd == 2:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0],
                                                              id_config_2=self.power_config_id[1],
                                                              poll_interval_2=self.power_pol[1],
                                                              thresholds_2=self.power_th[1])
            elif nb_bd == 3:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0],
                                                              id_config_2=self.power_config_id[1],
                                                              poll_interval_2=self.power_pol[1],
                                                              thresholds_2=self.power_th[1],
                                                              id_config_3=self.power_config_id[2],
                                                              poll_interval_3=self.power_pol[2],
                                                              thresholds_3=self.power_th[2])
            elif nb_bd == 4:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0],
                                                              id_config_2=self.power_config_id[1],
                                                              poll_interval_2=self.power_pol[1],
                                                              thresholds_2=self.power_th[1],
                                                              id_config_3=self.power_config_id[2],
                                                              poll_interval_3=self.power_pol[2],
                                                              thresholds_3=self.power_th[2],
                                                              id_config_4=self.power_config_id[3],
                                                              poll_interval_4=self.power_pol[3],
                                                              thresholds_4=self.power_th[3])
            elif nb_bd == 5:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0],
                                                              id_config_2=self.power_config_id[1],
                                                              poll_interval_2=self.power_pol[1],
                                                              thresholds_2=self.power_th[1],
                                                              id_config_3=self.power_config_id[2],
                                                              poll_interval_3=self.power_pol[2],
                                                              thresholds_3=self.power_th[2],
                                                              id_config_4=self.power_config_id[3],
                                                              poll_interval_4=self.power_pol[3],
                                                              thresholds_4=self.power_th[3],
                                                              id_config_5=self.power_config_id[4],
                                                              poll_interval_5=self.power_pol[4],
                                                              thresholds_5=self.power_th[4])
            elif nb_bd == 6:
                self.window_power_r = PowerReport.PowerReport(data_acc=self.power_data_acc,
                                                              id_config_1=self.power_config_id[0],
                                                              poll_interval_1=self.power_pol[0],
                                                              thresholds_1=self.power_th[0],
                                                              id_config_2=self.power_config_id[1],
                                                              poll_interval_2=self.power_pol[1],
                                                              thresholds_2=self.power_th[1],
                                                              id_config_3=self.power_config_id[2],
                                                              poll_interval_3=self.power_pol[2],
                                                              thresholds_3=self.power_th[2],
                                                              id_config_4=self.power_config_id[3],
                                                              poll_interval_4=self.power_pol[3],
                                                              thresholds_4=self.power_th[3],
                                                              id_config_5=self.power_config_id[4],
                                                              poll_interval_5=self.power_pol[4],
                                                              thresholds_5=self.power_th[4],
                                                              id_config_6=self.power_config_id[5],
                                                              poll_interval_6=self.power_pol[5],
                                                              thresholds_6=self.power_th[5])
            self.window_power_r.show()

    @property
    def port(self) -> str:
        """Return the current serial port."""
        return self.port_combobox.currentData()

    def closeEvent(self, event: QCloseEvent) -> None:
        """Handle Close event of the Widget."""
        if ser.is_open:
            ser.close()

        # self._save_settings()

        event.accept()

    def click_poll_sensor(self):
        # TODO
        pass

    def click_threshold_checkbox_1(self):
        pass
        # TODO

    def click_threshold_checkbox_2(self):
        pass
        # TODO

    def click_threshold_checkbox_3(self):
        pass
        # TODO

    def click_threshold_checkbox_4(self):
        pass
        # TODO

    def click_accumulation_checkbox(self):
        (err, acc_confirm) = Motherboard.set_accumulation(
            ser, self._debug, enable=self.accumulation_checkbox.isChecked())
        if (not err):
            self._debug.write("APP", F"Accumulation {acc_confirm}")
        self.power_data_acc = self.accumulation_checkbox.isChecked()

    def on_save_btn_pressed(self):
        sensor_str = self.sensor_combobox.currentText()
        selected_sensor = self._connected_sensors[sensor_str]
        self._debug.write("APP", F"Saving data from {sensor_str}")
        # check which metrics are visible
        # update data from input to selected_sensor object
        # update motherboard

        # selected_sensor._polling_enabled = self.poll_checkbox.isChecked()
        if selected_sensor.get_name() != 'Button Sensor':
            selected_sensor._polling_interval_sec = int(self.poll_lineedit.text()) * 60

        if self.threshold_label_1.isVisible():
            # read data from threshold 1

            selected_sensor._thresholds_enabled[0] = self.threshold_checkbox_1.isChecked(
            )

            selected_sensor.set_threshold(float(self.threshold_high_lineedit_1.text(
            )), metric_idx=0, to_machine=True, which_th=Motherboard.TH_HIGH)
            selected_sensor.set_threshold(float(self.threshold_low_lineedit_1.text(
            )), metric_idx=0, to_machine=True, which_th=Motherboard.TH_LOW)

            self._debug.write("APP", F"Saving metric 1 from {sensor_str}")

            # metric 2 is only visible when 1 is also visible
            if self.threshold_label_2.isVisible():
                selected_sensor._thresholds_enabled[1] = self.threshold_checkbox_2.isChecked(
                )
                selected_sensor.set_threshold(float(self.threshold_high_lineedit_2.text(
                )), metric_idx=1, to_machine=True, which_th=Motherboard.TH_HIGH)
                selected_sensor.set_threshold(float(self.threshold_low_lineedit_2.text(
                )), metric_idx=1, to_machine=True, which_th=Motherboard.TH_LOW)

                self._debug.write(
                    "APP", F"Saving metric 2 from {sensor_str}")
                if self.threshold_label_3.isVisible():
                    selected_sensor._thresholds_enabled[2] = self.threshold_checkbox_3.isChecked(
                    )
                    selected_sensor.set_threshold(float(self.threshold_high_lineedit_3.text(
                    )), metric_idx=2, to_machine=True, which_th=Motherboard.TH_HIGH)
                    selected_sensor.set_threshold(float(self.threshold_low_lineedit_3.text(
                    )), metric_idx=2, to_machine=True, which_th=Motherboard.TH_LOW)

                    self._debug.write(
                        "APP", F"Saving metric 3 from {sensor_str}")
                    if self.threshold_label_4.isVisible():
                        selected_sensor._thresholds_enabled[3] = self.threshold_checkbox_4.isChecked(
                        )
                        selected_sensor.set_threshold(float(self.threshold_high_lineedit_4.text(
                        )), metric_idx=3, to_machine=True, which_th=Motherboard.TH_HIGH)
                        selected_sensor.set_threshold(float(self.threshold_low_lineedit_4.text(
                        )), metric_idx=3, to_machine=True, which_th=Motherboard.TH_LOW)

                        self._debug.write(
                            "APP", F"Saving metric 4 from {sensor_str}")

        Motherboard.upload_sensor(selected_sensor, ser, self._debug)

        # For the power report -----------------------------------------------------------------------------------------
        idc = self.power_config_name.index(selected_sensor.get_name())
        if selected_sensor.get_polling_interval_sec() != 65535:
            if selected_sensor.get_polling_interval_sec() != 0:
                self.power_pol[idc] = int(selected_sensor.get_polling_interval_sec() / 60)
        flag = False
        for metrics in range(selected_sensor.get_num_metrics()):
            if selected_sensor.get_thresholds_enabled(metrics) is True:
                flag = True
                break
        if flag is True:
            self.power_th[idc] = True
            if selected_sensor.get_name() == 'Power Sensor':
                self.power_config_id[idc] = 3
            elif selected_sensor.get_name() == 'Sound Sensor':
                self.power_config_id[idc] = 5
            elif selected_sensor.get_name() == 'Environmental Sensor':
                self.power_config_id[idc] = 7
        else:
            self.power_th[idc] = False
            if selected_sensor.get_name() == 'Power Sensor':
                self.power_config_id[idc] = 2
            elif selected_sensor.get_name() == 'Sound Sensor':
                self.power_config_id[idc] = 4
            elif selected_sensor.get_name() == 'Environmental Sensor':
                self.power_config_id[idc] = 6

        if self.window_power_r is not None:
            self.window_power_r = None
            self.power_report_btn.setVisible(True)
        # --------------------------------------------------------------------------------------------------------------

    def on_connect_btn_pressed(self) -> None:
        """Open serial connection to the specified port."""
        self._debug.write(
            "APP", F"Trying to access motherbaord on port {self.port}")
        if ser.is_open:
            ser.close()
        ser.port = self.port

        try:
            ser.open()
        except Exception as e:
            self.show_error_message(str(e))

        if ser.is_open:
            self._debug.write(
                "COM", F"Serial port {self.port} is open.")

            (err, motherboard_id) = Motherboard.handle_ping(ser, self._debug)

            if not err:
                self._debug.write("COM", F"Connected to {motherboard_id}")
                self.connect_btn.setEnabled(False)
                self.test_btn.setVisible(True)
                self.disconnect_btn.setVisible(True)
                self.disconnect_btn.pressed.connect(self.on_disconnect_btn_pressed)
                self.sensor_btn.pressed.connect(self.on_sensor_btn_pressed)
                self.save_btn.pressed.connect(self.on_save_btn_pressed)
                self.port_combobox.setDisabled(True)
                self.save_btn.setEnabled(True)
                self.load_sensors()

            (err2, acc_state) = Motherboard.request_acc(ser, self._debug)

            if (not err2):
                self.accumulation_checkbox.setVisible(True)
                self.accumulation_checkbox.setCheckState(acc_state)

        else:
            self._debug.write(
                "ERR", F"Serial port {self.port} is not open :(.")

            # loop.create_task(self.receive_serial_async())

    def load_sensors(self):
        self._connected_sensors = {}
        """request the connected sensors on the motherboard"""

        _sensors = []
        (_err, _sensors) = Motherboard.request_sensors(ser, self._debug)

        if (not _err):
            if len(_sensors) > 0:
                self.sensor_btn.setVisible(True)

            for s in _sensors:
                _name = s.get_name()
                _id = s.get_addr()

                # For the power report ---------------------------------------------------------------------------------
                self.power_config_name.append(_name)
                if _name == 'Button Sensor':
                    self.power_config_id.append(1)
                elif _name == 'Power Sensor':
                    self.power_config_id.append(2)
                elif _name == 'Sound Sensor':
                    self.power_config_id.append(4)
                elif _name == 'Environmental Sensor':
                    self.power_config_id.append(6)
                self.power_pol.append(False)
                self.power_th.append(False)
                # self.power_report_btn.setVisible(True)
                # ------------------------------------------------------------------------------------------------------

                _sensor_str = F"{_name} [{_id}]"
                self._debug.write("GUI", F"Adding Sensor: {_sensor_str}")

                self.sensor_combobox.addItem(_sensor_str)

                self._connected_sensors.update({
                    _sensor_str: s
                })

    # def load_sensor_data(self):
    #     for sensor_str, sensor in self._connected_sensors.items():
    #         Motherboard.load_data(sensor, self._debug)

    def on_disconnect_btn_pressed(self) -> None:
        """Close current serial connection."""
        self.disconnect_btn.pressed.disconnect()
        self.new_config_btn.setVisible(True)
        self.save_btn.pressed.disconnect()
        self.sensor_btn.pressed.disconnect()
        Motherboard.close(ser, self._debug)

        if ser.is_open:
            ser.close()
        self.update_com_ports()

    def on_send_btn_pressed(self) -> None:
        """Send message to serial port."""
        msg = self.msg_lineedit.text() + '\r\n'
        loop.call_soon(send_serial_async, msg)

    def on_new_config_pressed(self):
        """Reset all variables to restart a new configuration"""
        self._connected_sensors = {}
        self.window_power_r = None
        self.power_config_name = []
        self.power_config_id = []
        self.power_th = []
        self.power_pol = []
        self.power_data_acc = False

        self._debug = CustomDebug(self.debug_textedit)
        self.update_com_ports()

        self.remove_metric_rows_from_gui()
        self._debug.write("GUI", "Application started successfully")
        self._debug.write("GUI", VERSION)
        self.update_com_ports()

        self.sensor_combobox.clear()
        self.sensor_btn.setVisible(False)
        self.save_btn.setVisible(False)
        self.accumulation_checkbox.setVisible(False)
        self.new_config_btn.setVisible(False)
        self.disconnect_btn.setVisible(False)
        self.connect_btn.setEnabled(True)
        self.port_combobox.setEnabled(True)

    async def receive_serial_async(self) -> None:
        """Wait for incoming data, convert it to text and add to Textedit."""
        while True:
            msg = ser.readline()
            if msg != b'':
                text = msg.decode().strip()
                self.received_textedit.appendPlainText(text)
            await asyncio.sleep(0)
Ejemplo n.º 37
0
class PostProcessor(QMainWindow):

    sim_results_changed = pyqtSignal()
    post_results_changed = pyqtSignal()

    figures_changed = pyqtSignal(list, str)

    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self._settings = QSettings()
        self._logger = logging.getLogger(self.__class__.__name__)

        self.setWindowTitle("Processing")
        self.setWindowIcon(QIcon(get_resource("processing.png")))
        self.mainFrame = QWidget(self)
        self.resize(1000, 600)

        # toolbar
        self.toolBar = QToolBar("file control")
        self.toolBar.setIconSize(QSize(24, 24))
        self.addToolBar(self.toolBar)

        self.actLoad = QAction(self)
        self.actLoad.setText("load result file")
        self.actLoad.setIcon(QIcon(get_resource("load.png")))
        self.actLoad.setDisabled(False)
        self.actLoad.triggered.connect(self.load_result_files)

        self.actPostLoad = QAction(self)
        self.actPostLoad.setText("load post-result file")
        self.actPostLoad.setIcon(QIcon(get_resource("load.png")))
        self.actPostLoad.setDisabled(False)
        self.actPostLoad.triggered.connect(self.load_post_result_files)

        self.actSwitch = QAction(self)
        self.actSwitch.setText("switch display mode")
        self.actSwitch.setIcon(QIcon(get_resource("left_mode.png")))
        self.actSwitch.setDisabled(False)
        self.actSwitch.triggered.connect(self.switch_sides)
        self.displayLeft = True

        self.spacer1 = QWidget()
        self.spacer2 = QWidget()
        self.spacer1.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        self.spacer2.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)

        self.actReloadMethods = QAction(self)
        self.actReloadMethods.setText("reload methods")
        self.actReloadMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMethods.setDisabled(False)
        self.actReloadMethods.triggered.connect(self.update_post_method_list)

        self.actReloadMetaMethods = QAction(self)
        self.actReloadMetaMethods.setText("reload meta methods")
        self.actReloadMetaMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMetaMethods.setDisabled(False)
        self.actReloadMetaMethods.triggered.connect(
            self.update_meta_method_list)

        self.toolBar.addAction(self.actLoad)
        self.toolBar.addAction(self.actReloadMethods)

        self.toolBar.addWidget(self.spacer1)
        self.toolBar.addAction(self.actSwitch)
        self.toolBar.addWidget(self.spacer2)

        self.toolBar.addAction(self.actReloadMetaMethods)
        self.toolBar.addAction(self.actPostLoad)

        # main window
        self.grid = QGridLayout(self.mainFrame)
        self.grid.setColumnMinimumWidth(0, 70)
        self.grid.setColumnStretch(0, 0)
        self.grid.setColumnStretch(1, 1)

        self.methodList = QListWidget(self)
        self.methodList.itemDoubleClicked.connect(self.post_processor_clicked)
        self.update_post_method_list()
        self.metaMethodList = QListWidget(self)
        self.metaMethodList.itemDoubleClicked.connect(
            self.meta_processor_clicked)
        self.update_meta_method_list()

        self.sim_result_list = QListWidget(self)
        self.sim_results_changed.connect(self.update_result_list)
        self.results = []

        self.delShort = QShortcut(QKeySequence(Qt.Key_Delete),
                                  self.sim_result_list)
        self.delShort.activated.connect(self.remove_result_item)

        # figures
        self._figure_dict = {}
        self.figures_changed.connect(self.update_figure_lists)

        self.post_figure_list = QListWidget(self)
        self.post_figure_list.currentItemChanged.connect(
            self.current_figure_changed)
        self.meta_figure_list = QListWidget(self)
        self.meta_figure_list.currentItemChanged.connect(
            self.current_figure_changed)

        self.plotView = QWidget()
        self.lastFigure = None

        self.post_result_list = QListWidget(self)
        self.post_results_changed.connect(self.update_post_result_list)
        self.post_results = []
        self.delShortPost = QShortcut(QKeySequence(Qt.Key_Backspace),
                                      self.post_result_list)
        self.delShortPost.activated.connect(self.remove_post_result_item)

        # log dock
        self.logBox = QPlainTextEdit(self)
        self.logBox.setReadOnly(True)

        # init logger for logging box
        self.textLogger = PlainTextLogger(logging.INFO)
        self.textLogger.set_target_cb(self.logBox.appendPlainText)
        logging.getLogger().addHandler(self.textLogger)

        self.grid.addWidget(QLabel("Result Files:"), 0, 0)
        self.grid.addWidget(self.sim_result_list, 1, 0)
        self.grid.addWidget(QLabel("Postprocessors:"), 2, 0)
        self.grid.addWidget(self.methodList, 3, 0)
        self.grid.addWidget(QLabel("Figures:"), 4, 0)
        self.grid.addWidget(self.post_figure_list, 5, 0)
        self.grid.addWidget(QLabel("Selected Figure:"), 0, 1)
        self.grid.addWidget(QLabel("Postprocessor Files:"), 0, 2)
        self.grid.addWidget(self.post_result_list, 1, 2)
        self.grid.addWidget(QLabel("Metaprocessors:"), 2, 2)
        self.grid.addWidget(self.metaMethodList, 3, 2)
        self.grid.addWidget(QLabel("Figures:"), 4, 2)
        self.grid.addWidget(self.meta_figure_list, 5, 2)
        self.grid.addWidget(self.logBox, 6, 0, 1, 3)

        self.mainFrame.setLayout(self.grid)
        self.setCentralWidget(self.mainFrame)

        # status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

    def load_result_files(self):
        path = self._settings.value("path/simulation_results")

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setDirectory(path)
        dialog.setNameFilter("PyMoskito Result files (*.pmr)")

        if dialog.exec_():
            files = dialog.selectedFiles()
            for single_file in files:
                if single_file:
                    self._load_result_file(single_file)

    def _load_result_file(self, file_name):
        """
        loads a result file
        """
        self._logger.info("loading result file {}".format(file_name))
        with open(file_name.encode(), "rb") as f:
            self.results.append(pickle.load(f))

        self.sim_results_changed.emit()

    def update_result_list(self):
        self.sim_result_list.clear()
        for res in self.results:
            name = res["regime name"]
            self.sim_result_list.addItem(name)

    def remove_result_item(self):
        if self.sim_result_list.currentRow() >= 0:
            del self.results[self.sim_result_list.currentRow()]
            self.sim_result_list.takeItem(self.sim_result_list.currentRow())

    def load_post_result_files(self):
        path = self._settings.value("path/processing_results")

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFiles)
        dialog.setDirectory(path)
        dialog.setNameFilter("Postprocessing Output files (*.pof)")

        if dialog.exec_():
            files = dialog.selectedFiles()
            for single_file in files:
                if single_file:
                    self._load_post_result_file(single_file)

    def _load_post_result_file(self, file_name):
        """
        loads a post-result file (.pof)
        """
        name = os.path.split(file_name)[-1][:-4]
        self._logger.info("loading result file {}".format(file_name))
        with open(file_name.encode(), "rb") as f:
            results = pickle.load(f)
            results.update({"name": name})
            self.post_results.append(results)

        self.post_results_changed.emit()

    def update_post_result_list(self):
        self.post_result_list.clear()
        for res in self.post_results:
            name = res["name"]
            self.post_result_list.addItem(name)

    def remove_post_result_item(self):
        if self.post_result_list.currentRow() >= 0:
            del self.post_results[self.post_result_list.currentRow()]
            self.post_result_list.takeItem(self.post_result_list.currentRow())

    def update_post_method_list(self):
        self.methodList.clear()
        modules = pm.get_registered_processing_modules(PostProcessingModule)
        for mod in modules:
            self.methodList.addItem(mod[1])

    def update_meta_method_list(self):
        self.metaMethodList.clear()
        modules = pm.get_registered_processing_modules(MetaProcessingModule)
        for mod in modules:
            self.metaMethodList.addItem(mod[1])

    def post_processor_clicked(self, item):
        self.run_processor(str(item.text()), "post")

    def meta_processor_clicked(self, item):
        self.run_processor(str(item.text()), "meta")

    def run_processor(self, name, processor_type):
        if processor_type == "post":
            result_files = self.results
            base_cls = PostProcessingModule
        elif processor_type == "meta":
            result_files = self.post_results
            base_cls = MetaProcessingModule
        else:
            self._logger.error(
                "unknown processor type {0}".format(processor_type))
            raise ValueError(
                "unknown processor type {0}".format(processor_type))

        if not result_files:
            self._logger.warning(
                "run_processor() Error: no result file loaded")
            return

        processor_cls = pm.get_processing_module_class_by_name(base_cls, name)
        processor = processor_cls()

        figs = []
        try:
            self._logger.info("executing processor '{0}'".format(name))
            figs = processor.process(result_files)
        except Exception as err:
            self._logger.exception("Error in processor")

        self.figures_changed.emit(figs, processor_type)
        self._logger.info("finished postprocessing")

    def update_figure_lists(self, figures, target_type):
        # remove no longer needed elements
        for item, fig in [(key, val[0])
                          for key, val in self._figure_dict.items()
                          if val[1] == target_type]:
            if fig not in [new_fig["figure"] for new_fig in figures]:
                if target_type == "post":
                    old_item = self.post_figure_list.takeItem(
                        self.post_figure_list.row(item))
                    del old_item
                elif target_type == "meta":
                    old_item = self.meta_figure_list.takeItem(
                        self.meta_figure_list.row(item))
                    del old_item

                del self._figure_dict[item]

        # add new ones to internal storage
        for fig in figures:
            if fig["figure"] not in self._figure_dict.values():
                new_entry = [(fig["name"], (QListWidgetItem(fig["name"]),
                                            fig["figure"], target_type))]
                self._figure_dict.update(new_entry)

        # add to display
        for key, val in self._figure_dict.items():
            if val[2] == "post":
                self.post_figure_list.addItem(val[0])
            elif val[2] == "meta":
                self.meta_figure_list.addItem(val[0])

        self.post_figure_list.setCurrentItem(self.post_figure_list.item(0))
        self.meta_figure_list.setCurrentItem(self.meta_figure_list.item(0))

    def current_figure_changed(self, current_item, last_item=None):
        if current_item is None:
            return

        figures = self._figure_dict

        if self.lastFigure:
            self.grid.removeWidget(self.lastFigure)
            self.lastFigure.setVisible(False)

        if current_item.text() in figures:
            figure_widget = figures[current_item.text()][1]
            self.grid.addWidget(figure_widget, 1, 1, 5, 1)
            figure_widget.setVisible(True)
            self.lastFigure = figure_widget

    def switch_sides(self):
        self.displayLeft = not self.displayLeft
        if self.displayLeft:
            self.actSwitch.setIcon(QIcon(get_resource("left_mode.png")))
            self.post_figure_list.setFocus()
            self.current_figure_changed(self.post_figure_list.currentItem())
        else:
            self.actSwitch.setIcon(QIcon(get_resource("right_mode.png")))
            self.meta_figure_list.setFocus()
            self.current_figure_changed(self.meta_figure_list.currentItem())
Ejemplo n.º 38
0
 def __init__(self, text=None):
     QPlainTextEdit.__init__(self, text)
     self.setText = self.setPlainText
     self.text = self.toPlainText
     self.buttons = []
Ejemplo n.º 39
0
    def __init__(self, parent, addon_data: AddonData):
        super().__init__()
        self.__input_control_list = []
        self.title = "PyQt5 Scroll Bar"
        self.top = 200
        self.left = 500
        self.width = 400
        self.height = 300
        self.form_layout = QVBoxLayout()
        self.addon_data = addon_data
        self.groupbox = QGroupBox(self.addon_data.menu_name)
        self.parent = parent
        self.jupyter_widget = self.parent.jupyter_widget
        self.tools_layout = QGridLayout()

        self.btn_run = QPushButton("Run...")
        self.btn_run.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.btn_run.clicked.connect(self.on_btn_run)
        self.tools_layout.addWidget(self.btn_run, 1, 1)

        self.btn_stop = QPushButton("Stop")
        self.btn_stop.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.btn_stop.clicked.connect(self.on_btn_stop)
        self.tools_layout.addWidget(self.btn_stop, 1, 2)

        self.btn_restart_kernel = QPushButton("Restart kernel...")
        self.btn_restart_kernel.setSizePolicy(QSizePolicy.Fixed,
                                              QSizePolicy.Fixed)
        self.btn_restart_kernel.clicked.connect(self.on_btn_restart_kernel)
        self.tools_layout.addWidget(self.btn_restart_kernel, 2, 1)

        self.btn_clear_console = QPushButton("Clear console")
        self.btn_clear_console.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Fixed)
        self.btn_clear_console.clicked.connect(self.on_btn_clear_console)
        self.tools_layout.addWidget(self.btn_clear_console, 2, 2)

        #  prevent the grid layout from resizing
        self.tools_layout.setColumnStretch(3, 1)

        self.form_layout.addLayout(self.tools_layout)

        self.lbl_backend = QLabel("Choose potting backend:")
        self.lbl_backend.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)

        self.combo_backend = QComboBox()
        self.combo_backend.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.combo_backend.addItem('inline')
        self.combo_backend.addItem('qt5')

        self.layout_backend = QHBoxLayout()
        self.layout_backend.addWidget(self.combo_backend)
        self.layout_backend.addStretch(1)
        self.form_layout.addWidget(self.lbl_backend)
        self.form_layout.addLayout(self.layout_backend)

        self.combo_backend.currentIndexChanged.connect(
            self.on_combo_backend_currentIndexChanged)

        # textbox with addon directory path
        self.lbl_addon_dir = QLabel("Addon folder:")
        self.lbl_addon_dir.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.form_layout.addWidget(self.lbl_addon_dir)
        self.addon_path = os.path.dirname(os.path.dirname(__file__))
        self.addon_path += self.addon_data.rel_path

        self.text_addon_dir = QPlainTextEdit(self)
        self.text_addon_dir.setPlainText(self.addon_path)
        self.text_addon_dir.setFixedSize(252, 120)
        self.text_addon_dir.setSizePolicy(QSizePolicy.Fixed,  
                                          QSizePolicy.Fixed)
        self.text_addon_dir.setReadOnly(True)
        self.form_layout.addWidget(self.text_addon_dir)

        # TODO: move the input controls
        # to a child QFrame

        # add the input controls to the layout
        for c in self.addon_data.inuput_controls:
            c.parameters["parent"] = self
            c.parameters["layout"] = self.form_layout
            if c.class_name == ic.FileChoose.class_name():
                # in this case 'value' is just the filename
                # make it the file path
                c.parameters["value"] = (self.addon_path
                                         + os.path.sep
                                         + c.parameters["value"])
            control = ic.create_input_control(c.class_name, c.parameters)
            self.__input_control_list.append(control)
        # input controls added

        self.form_layout.addStretch(1)
        self.groupbox.setLayout(self.form_layout)
        self.scroll = QScrollArea()
        self.scroll.setWidget(self.groupbox)
        self.scroll.setWidgetResizable(True)

        self.main_layout = QVBoxLayout(self)
        self.main_layout.addWidget(self.scroll)
Ejemplo n.º 40
0
class InputsWidget(QWidget):

    jupyter_widget = None
    parent = None

    def __init__(self, parent, addon_data: AddonData):
        super().__init__()
        self.__input_control_list = []
        self.title = "PyQt5 Scroll Bar"
        self.top = 200
        self.left = 500
        self.width = 400
        self.height = 300
        self.form_layout = QVBoxLayout()
        self.addon_data = addon_data
        self.groupbox = QGroupBox(self.addon_data.menu_name)
        self.parent = parent
        self.jupyter_widget = self.parent.jupyter_widget
        self.tools_layout = QGridLayout()

        self.btn_run = QPushButton("Run...")
        self.btn_run.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.btn_run.clicked.connect(self.on_btn_run)
        self.tools_layout.addWidget(self.btn_run, 1, 1)

        self.btn_stop = QPushButton("Stop")
        self.btn_stop.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.btn_stop.clicked.connect(self.on_btn_stop)
        self.tools_layout.addWidget(self.btn_stop, 1, 2)

        self.btn_restart_kernel = QPushButton("Restart kernel...")
        self.btn_restart_kernel.setSizePolicy(QSizePolicy.Fixed,
                                              QSizePolicy.Fixed)
        self.btn_restart_kernel.clicked.connect(self.on_btn_restart_kernel)
        self.tools_layout.addWidget(self.btn_restart_kernel, 2, 1)

        self.btn_clear_console = QPushButton("Clear console")
        self.btn_clear_console.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Fixed)
        self.btn_clear_console.clicked.connect(self.on_btn_clear_console)
        self.tools_layout.addWidget(self.btn_clear_console, 2, 2)

        #  prevent the grid layout from resizing
        self.tools_layout.setColumnStretch(3, 1)

        self.form_layout.addLayout(self.tools_layout)

        self.lbl_backend = QLabel("Choose potting backend:")
        self.lbl_backend.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)

        self.combo_backend = QComboBox()
        self.combo_backend.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.combo_backend.addItem('inline')
        self.combo_backend.addItem('qt5')

        self.layout_backend = QHBoxLayout()
        self.layout_backend.addWidget(self.combo_backend)
        self.layout_backend.addStretch(1)
        self.form_layout.addWidget(self.lbl_backend)
        self.form_layout.addLayout(self.layout_backend)

        self.combo_backend.currentIndexChanged.connect(
            self.on_combo_backend_currentIndexChanged)

        # textbox with addon directory path
        self.lbl_addon_dir = QLabel("Addon folder:")
        self.lbl_addon_dir.setSizePolicy(QSizePolicy.Fixed,  QSizePolicy.Fixed)
        self.form_layout.addWidget(self.lbl_addon_dir)
        self.addon_path = os.path.dirname(os.path.dirname(__file__))
        self.addon_path += self.addon_data.rel_path

        self.text_addon_dir = QPlainTextEdit(self)
        self.text_addon_dir.setPlainText(self.addon_path)
        self.text_addon_dir.setFixedSize(252, 120)
        self.text_addon_dir.setSizePolicy(QSizePolicy.Fixed,  
                                          QSizePolicy.Fixed)
        self.text_addon_dir.setReadOnly(True)
        self.form_layout.addWidget(self.text_addon_dir)

        # TODO: move the input controls
        # to a child QFrame

        # add the input controls to the layout
        for c in self.addon_data.inuput_controls:
            c.parameters["parent"] = self
            c.parameters["layout"] = self.form_layout
            if c.class_name == ic.FileChoose.class_name():
                # in this case 'value' is just the filename
                # make it the file path
                c.parameters["value"] = (self.addon_path
                                         + os.path.sep
                                         + c.parameters["value"])
            control = ic.create_input_control(c.class_name, c.parameters)
            self.__input_control_list.append(control)
        # input controls added

        self.form_layout.addStretch(1)
        self.groupbox.setLayout(self.form_layout)
        self.scroll = QScrollArea()
        self.scroll.setWidget(self.groupbox)
        self.scroll.setWidgetResizable(True)

        self.main_layout = QVBoxLayout(self)
        self.main_layout.addWidget(self.scroll)

    def on_combo_backend_currentIndexChanged(self, q):
        # set selectioon index for combo_backend
        # for all the instances of the InputsWidget

        # TODO: move the input controls
        # to a child QFrame

        instances = self.parent.addon_list
        cur_ind = self.combo_backend.currentIndex()
        for instance in instances:
            if instance.combo_backend.currentIndex() != cur_ind:
                instance.combo_backend.setCurrentIndex(cur_ind)
        if not self.jupyter_widget._executing:
            command = ('%matplotlib '
                       + str(self.combo_backend.currentText())
                       + '\n')
            self.jupyter_widget.execute(source=command, hidden=False)     

    def on_btn_clear_console(self, q):
        if not self.jupyter_widget._executing:
            self.jupyter_widget.execute(source='%clear', hidden=False)

    def on_btn_restart_kernel(self, q):
        if self.jupyter_widget._executing:
            return
        self.jupyter_widget.request_restart_kernel()
        self.__enable_restart_controls_val = False
        self.enable_restart_controls()
        self.__enable_restart_controls_val = True
        QTimer.singleShot(2000, self.enable_restart_controls)

    def enable_restart_controls(self):
        enable = self.__enable_restart_controls_val
        self.btn_run.setEnabled(enable)
        self.btn_stop.setEnabled(enable)
        self.btn_restart_kernel.setEnabled(enable)
        self.btn_clear_console.setEnabled(enable)

    def on_btn_run(self, q):
        # set the self.jupyter_widget variable from parent
        self.jupyter_widget = self.parent.jupyter_widget
        # do nothing if jupyter_widget already executing
        if self.jupyter_widget._executing:
            return
        # read the source file
        try:
            with open(os.path.join(self.addon_path, 'execute.py'), "r") as py_file:
                source = py_file.read()
        except Exception as e:
            QMessageBox.critical(self.parent, main_window_title,
                                 'Error loading the code: ' + str(e))
            return str(e)
        finally:
            pass
        # print the input parameter values as the
        # python source code
        params = ''
        for c in self.__input_control_list:
            value = c.get_value()
            if value is None:  # incorrect user input
                return
            if isinstance(value, str):
                value = 'r"' + value + '"'  # enclosing string in quotes
            var_name = c.get_var_name()
            var_name.strip()
            if (' ') in var_name:
                msg = "variable " + var_name + ' has spaces'
                QMessageBox.critical(self.parent, main_window_title, msg)
                return

            params = (params + var_name
                      + ' = ' + str(value)
                      + '\n')

        # backend
        params += ('%matplotlib '
                   + str(self.combo_backend.currentText())
                   + '\n')

        # prepending the read source code with the
        # parameter initialization

        source = params + '\n' + source
        # write the created source in the file for debugging
        with open(self.addon_path + '/saved.py', "w") as text_file:
            text_file.write(source)

        # and finally run the code in the jupyter_widget
        self.jupyter_widget.execute(source=source, hidden=False)

    def on_btn_stop(self, q):
        if self.jupyter_widget._executing:
            self.jupyter_widget.request_interrupt_kernel()

    def show_itself(self):
        self.parent.current_addon.hide()
        self.show()
        self.parent.current_addon = self
        html_path = os.path.join(self.addon_path, 'html')
        html_path = os.path.join(html_path, 'help.html')
        self.parent.browser_widget.open_local_text(html_path)
Ejemplo n.º 41
0
class Plugin:
    def __get_plugin_info__(self):
        return {
            'name': 'r2dwarf',
            'description': 'r2frida in Dwarf',
            'version': '1.0.0',
            'author': 'iGio90',
            'homepage': 'https://github.com/iGio90/Dwarf',
            'license': 'https://www.gnu.org/licenses/gpl-3.0'
        }

    def __init__(self, app):
        self.app = app
        self.pipe = None
        self.progress_dialog = None
        self.current_seek = ''
        self.with_decompiler = False

        self.app.session_manager.sessionCreated.connect(
            self._on_session_created)
        self.app.onUIElementCreated.connect(self._on_ui_element_created)

    def _create_pipe(self):
        self.pipe = R2Pipe()
        self.pipe.open('frida://attach/usb//%d' % self.app.dwarf.pid)
        r2_decompilers = self.pipe.cmd('e cmd.pdc=?')
        r2_decompilers = r2_decompilers.split()
        if r2_decompilers and 'pdc' in r2_decompilers:
            self.pipe.cmd('e cmd.pdc=pdc')  # TODO: let select decompiler
            self.with_decompiler = True

        self.pipe.cmd("e scr.color=2; e scr.html=1; e scr.utf8=true;")

        r2arch = self.app.dwarf.arch
        r2bits = 32
        if r2arch == 'arm64':
            r2arch = 'arm'
            r2bits = 64
        elif r2arch == 'x64':
            r2arch = 'x86'
            r2bits = 64
        elif r2arch == 'ia32':
            r2arch = 'x86'

        self.pipe.cmd('e asm.arch=%s; e asm.bits=%d; e asm.os=%s' %
                      (r2arch, r2bits, self.app.dwarf.platform))

        with open(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             'agent.js'), 'r') as f:
            agent = f.read()
        self.app.dwarf.dwarf_api('evaluate', agent)

    def _on_apply_context(self, context_data):
        if self.pipe is None:
            self._create_pipe()

        is_java = 'is_java' in context_data and context_data['is_java']

        if not is_java:
            if 'context' in context_data:
                native_context = context_data['context']
                pc = native_context['pc']['value']
                self.current_seek = pc
                self.pipe.cmd('s %s' % self.current_seek)

    def _on_disassemble(self, ptr):
        if self.pipe is None:
            self._create_pipe()

        if self.current_seek != ptr:
            self.current_seek = ptr
            self.pipe.cmd('s %s' % self.current_seek)

        self.progress_dialog = utils.progress_dialog('running r2 analysis...')
        self.progress_dialog.forceShow()

        self.r2analysis = R2Analysis(self.pipe)
        self.r2analysis.onR2AnalysisFinished.connect(self._on_finish_analysis)
        self.r2analysis.start()

    def _on_finish_analysis(self, data):
        self.progress_dialog.cancel()

        function_info = data[0]

        if 'callrefs' in function_info:
            for ref in function_info['callrefs']:
                self.call_refs_model.appendRow([
                    QStandardItem(hex(ref['addr'])),
                    QStandardItem(hex(ref['at'])),
                    QStandardItem(ref['type'])
                ])
        if 'codexrefs' in function_info:
            for ref in function_info['codexrefs']:
                self.code_xrefs_model.appendRow([
                    QStandardItem(hex(ref['addr'])),
                    QStandardItem(hex(ref['at'])),
                    QStandardItem(ref['type'])
                ])

    def _on_finish_graph(self, data):
        self.progress_dialog.cancel()
        graph_data = data[0]
        self.r2_graph_view.setText('<pre>' + graph_data + '</pre>')

    def _on_finish_decompiler(self, data):
        self.progress_dialog.cancel()
        decompile_data = data[0]
        if decompile_data is not None:
            self.r2_decompiler_view.clear()
            self.r2_decompiler_view.appendHtml('<pre>' + decompile_data +
                                               '</pre>')
            self.r2_decompiler_view.verticalScrollBar().triggerAction(
                QScrollBar.SliderToMinimum)

    def _on_receive_cmd(self, args):
        message, data = args
        if 'payload' in message:
            payload = message['payload']
            if payload.startswith('r2 '):
                cmd = message['payload'][3:]
                self.on_r2_command(cmd)

    def _on_session_created(self):
        self.app.dwarf.onReceiveCmd.connect(self._on_receive_cmd)
        self.app.dwarf.onApplyContext.connect(self._on_apply_context)

        self.console = DwarfConsoleWidget(self.app,
                                          input_placeholder='r2',
                                          completer=False)
        self.console.onCommandExecute.connect(self.on_r2_command)

        self.app.main_tabs.addTab(self.console, 'r2')

    def _on_ui_element_created(self, elem, widget):
        if elem == 'disassembly':
            self.decompiler_view = widget
            self.decompiler_view.onDisassemble.connect(self._on_disassemble)

            r2_info = QSplitter()
            r2_info.setOrientation(Qt.Vertical)

            call_refs = DwarfListView()
            self.call_refs_model = QStandardItemModel(0, 3)
            self.call_refs_model.setHeaderData(0, Qt.Horizontal, 'call refs')
            self.call_refs_model.setHeaderData(1, Qt.Horizontal, '')
            self.call_refs_model.setHeaderData(2, Qt.Horizontal, '')
            call_refs.setModel(self.call_refs_model)

            code_xrefs = DwarfListView()
            self.code_xrefs_model = QStandardItemModel(0, 3)
            self.code_xrefs_model.setHeaderData(0, Qt.Horizontal, 'code xrefs')
            self.code_xrefs_model.setHeaderData(1, Qt.Horizontal, '')
            self.code_xrefs_model.setHeaderData(2, Qt.Horizontal, '')
            code_xrefs.setModel(self.code_xrefs_model)

            r2_info.addWidget(call_refs)
            r2_info.addWidget(code_xrefs)

            self.decompiler_view.insertWidget(0, r2_info)
            self.decompiler_view.setStretchFactor(0, 1)
            self.decompiler_view.setStretchFactor(1, 5)

            r2_menu = QMenu('r2')
            r2_menu.addAction('graph view', self.show_graph_view)
            if self.with_decompiler:
                r2dec = r2_menu.addAction('decompile',
                                          self.show_decompiler_view)

            self.decompiler_view.disasm_view.menu_extra_menu.append(r2_menu)

    def show_graph_view(self):
        self.r2_graph_view = R2ScrollArea()
        self.app.main_tabs.addTab(self.r2_graph_view, 'graph view')
        index = self.app.main_tabs.indexOf(self.r2_graph_view)
        self.app.main_tabs.setCurrentIndex(index)

        self.progress_dialog = utils.progress_dialog('building graph view...')
        self.progress_dialog.forceShow()

        self.r2graph = R2Graph(self.pipe)
        self.r2graph.onR2Graph.connect(self._on_finish_graph)
        self.r2graph.start()

    def show_decompiler_view(self):
        if not self.with_decompiler:
            return

        self.r2_decompiler_view = QPlainTextEdit()
        self.r2_decompiler_view.setVerticalScrollBarPolicy(
            Qt.ScrollBarAsNeeded)
        self.r2_decompiler_view.setHorizontalScrollBarPolicy(
            Qt.ScrollBarAsNeeded)
        self.app.main_tabs.addTab(self.r2_decompiler_view, 'decompiler')
        index = self.app.main_tabs.indexOf(self.r2_decompiler_view)
        self.app.main_tabs.setCurrentIndex(index)

        self.progress_dialog = utils.progress_dialog('decompiling function...')
        self.progress_dialog.forceShow()

        self.r2decompiler = R2Decompiler(self.pipe)
        self.r2decompiler.onR2Decompiler.connect(self._on_finish_decompiler)
        self.r2decompiler.start()

    def on_r2_command(self, cmd):
        if cmd == 'clear' or cmd == 'clean':
            self.console.clear()
        else:
            try:
                result = self.pipe.cmd(cmd)
                self.console.log(result, time_prefix=False)
            except BrokenPipeError:
                self.console.log('pipe is broken. recreating...',
                                 time_prefix=False)
                self._create_pipe()
                self.pipe.cmd('s %s' % self.current_seek)
Ejemplo n.º 42
0
    def __init__(self, window: QMainWindow, system_info):
        super().__init__()
        v_box = QVBoxLayout()
        h_buttons = QHBoxLayout()

        button_style = "background-color: #006699; padding-left:20px; padding-right:20px; padding-top:5px; padding-bottom:5px;"
        copy_pastable_json = json.dumps(system_info, indent=2)
        website_link = str(
            base64.b64decode(
                "aHR0cHM6Ly90YXJhbGxvLndlZWVvcGVuLml0L2J1bGsvYWRkCg=="),
            "utf-8")

        self.clipboard_button = QPushButton("Copy to clipboard")
        self.clipboard_button.setStyleSheet(button_style)
        self.clipboard_button.clicked.connect(
            lambda: QApplication.clipboard().setText(copy_pastable_json))
        self.clipboard_button.clicked.connect(
            lambda: self.spawn_notification("Copied to clipboard"))

        self.website_button = QPushButton("Go to T.A.R.A.L.L.O.")
        self.website_button.setStyleSheet(button_style)
        self.website_button.clicked.connect(
            lambda: sp.Popen(["xdg-open", website_link]))

        plain_text = QPlainTextEdit()
        plain_text.document().setPlainText(copy_pastable_json)
        plain_text.setStyleSheet("background-color:#333333; color:#bbbbbb")
        plain_text.setReadOnly(True)
        plain_text.setMinimumSize(plain_text.width(), plain_text.height())
        # prevent from resizing too much

        back_button = QPushButton("Go back")
        back_button.clicked.connect(
            lambda: self.restore_previous_window(window, system_info))

        h_buttons.addWidget(self.clipboard_button, alignment=Qt.AlignCenter)
        h_buttons.addWidget(self.website_button, alignment=Qt.AlignCenter)

        v_box.addLayout(h_buttons)
        v_box.addWidget(plain_text)
        v_box.addWidget(back_button, alignment=Qt.AlignCenter)
        self.setLayout(v_box)
Ejemplo n.º 43
0
class CheckingWidget_UI(object):
    checking_ending = QtCore.pyqtSignal(NeuralCrash)

    def setupUI(self, widget, neuralconfig):
        self.neuralconfig = neuralconfig
        self.layout = QVBoxLayout(widget)

        status = QFormLayout()
        self.error = QPlainTextEdit()
        self.error.setReadOnly(True)
        self.label_load_model = QLabel()
        self.label_load_model.setText('Checking')
        self.label_load_testdata = QLabel()
        self.label_load_testdata.setText('Checking')
        self.label_get_tested_values = QLabel()
        self.label_get_tested_values.setText('Checking')
        self.label_set_tested_values = QLabel()
        self.label_set_tested_values.setText('Checking')
        self.label_test_model = QLabel()
        self.label_test_model.setText('Checking')
        self.status_load_model = ''
        self.status_load_testdata = ''
        self.status_get_tested_values = ''
        self.status_set_tested_values = ''
        self.status_test_model = ''

        status.addRow('load_model', self.label_load_model)
        status.addRow('load_testdata', self.label_load_testdata)
        status.addRow('get_tested_values', self.label_get_tested_values)
        status.addRow('set_tested_values', self.label_set_tested_values)
        status.addRow('test_model', self.label_test_model)

        self.layout.addLayout(status)
        self.layout.addWidget(self.error)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.check_function_load_model()

    def errorprint(self, text, checked_functions):
        self.error.appendPlainText(checked_functions + '\n' + text +
                                   '\n\n\t--------\n\n')

    def update_status(self, label_name, status):
        if label_name == 'load_model':
            self.status_load_model = status
            self.label_load_model.setText(status)
        elif label_name == 'load_testdata':
            self.status_load_testdata = status
            self.label_load_testdata.setText(status)
        elif label_name == 'get_tested_values':
            self.status_get_tested_values = status
            self.label_get_tested_values.setText(status)
        elif label_name == 'set_tested_values':
            self.status_set_tested_values = status
            self.label_set_tested_values.setText(status)
        elif label_name == 'test_model':
            self.status_test_model = status
            self.label_test_model.setText(status)

    def update_label(self, label):
        if label.text().endswith('...'):
            label.setText('Checking.')
        else:
            label.setText(label.text() + '.')

    def update_NeuralCrash(self, new_state):
        self.neuralconfig = new_state

    def check_function_load_model(self):
        self.threadAnim_load_model = AnimationTimer(0.3)
        self.threadWork_load_model = QtCore.QThread()
        self.QObject_load_model = Check_function(self.neuralconfig,
                                                 'load_model')
        self.QObject_load_model.moveToThread(self.threadWork_load_model)

        self.threadWork_load_model.started.connect(self.QObject_load_model.run)
        self.QObject_load_model.function_checked_signal.connect(
            self.update_status)
        self.QObject_load_model.error_signal.connect(self.errorprint)
        self.QObject_load_model.return_new_state.connect(
            self.update_NeuralCrash)
        self.QObject_load_model.done.connect(
            self.threadAnim_load_model.requestInterruption)
        self.QObject_load_model.done.connect(self.check_function_load_testdata)
        self.threadAnim_load_model.time_passes.connect(
            lambda: self.update_label(self.label_load_model))

        self.threadAnim_load_model.start()
        self.threadWork_load_model.start()

    def check_function_load_testdata(self):
        self.threadAnim_load_testdata = AnimationTimer(0.3)
        self.threadWork_load_testdata = QtCore.QThread()
        self.QObject_load_testdata = Check_function(self.neuralconfig,
                                                    'load_testdata')
        self.QObject_load_testdata.moveToThread(self.threadWork_load_testdata)

        self.threadWork_load_testdata.started.connect(
            self.QObject_load_testdata.run)
        self.QObject_load_testdata.function_checked_signal.connect(
            self.update_status)
        self.QObject_load_testdata.error_signal.connect(self.errorprint)
        self.QObject_load_testdata.return_new_state.connect(
            self.update_NeuralCrash)
        self.QObject_load_testdata.done.connect(
            self.threadAnim_load_testdata.requestInterruption)
        self.QObject_load_testdata.done.connect(
            self.check_function_get_tested_values)
        self.threadAnim_load_testdata.time_passes.connect(
            lambda: self.update_label(self.label_load_testdata))

        self.threadAnim_load_testdata.start()
        self.threadWork_load_testdata.start()

    def check_function_get_tested_values(self):
        self.threadAnim_get_tested_values = AnimationTimer(0.3)
        self.threadWork_get_tested_values = QtCore.QThread()
        self.QObject_get_tested_values = Check_function(
            self.neuralconfig, 'get_tested_values')
        self.QObject_get_tested_values.moveToThread(
            self.threadWork_get_tested_values)

        self.threadWork_get_tested_values.started.connect(
            self.QObject_get_tested_values.run)
        self.QObject_get_tested_values.function_checked_signal.connect(
            self.update_status)
        self.QObject_get_tested_values.error_signal.connect(self.errorprint)
        self.QObject_get_tested_values.return_new_state.connect(
            self.update_NeuralCrash)
        self.QObject_get_tested_values.done.connect(
            self.threadAnim_get_tested_values.requestInterruption)
        self.QObject_get_tested_values.done.connect(
            self.check_function_set_tested_values)
        self.threadAnim_get_tested_values.time_passes.connect(
            lambda: self.update_label(self.label_get_tested_values))

        self.threadAnim_get_tested_values.start()
        self.threadWork_get_tested_values.start()

    def check_function_set_tested_values(self):
        self.threadAnim_set_tested_values = AnimationTimer(0.3)
        self.threadWork_set_tested_values = QtCore.QThread()
        self.QObject_set_tested_values = Check_function(
            self.neuralconfig, 'set_tested_values')
        self.QObject_set_tested_values.moveToThread(
            self.threadWork_set_tested_values)

        self.threadWork_set_tested_values.started.connect(
            self.QObject_set_tested_values.run)
        self.QObject_set_tested_values.function_checked_signal.connect(
            self.update_status)
        self.QObject_set_tested_values.error_signal.connect(self.errorprint)
        self.QObject_set_tested_values.done.connect(
            self.threadAnim_set_tested_values.requestInterruption)
        self.QObject_set_tested_values.done.connect(
            self.check_function_test_model)
        self.threadAnim_set_tested_values.time_passes.connect(
            lambda: self.update_label(self.label_set_tested_values))

        self.threadAnim_set_tested_values.start()
        self.threadWork_set_tested_values.start()

    def check_function_test_model(self):
        self.threadAnim_test_model = AnimationTimer(0.3)
        self.threadWork_test_model = QtCore.QThread()
        self.QObject_test_model = Check_function(self.neuralconfig,
                                                 'test_model')
        self.QObject_test_model.moveToThread(self.threadWork_test_model)

        self.threadWork_test_model.started.connect(self.QObject_test_model.run)
        self.QObject_test_model.function_checked_signal.connect(
            self.update_status)
        self.QObject_test_model.error_signal.connect(self.errorprint)
        self.QObject_get_tested_values.return_new_state.connect(
            self.update_NeuralCrash)
        self.QObject_test_model.done.connect(
            self.threadAnim_test_model.requestInterruption)
        self.QObject_test_model.done.connect(self.end_checking)
        self.threadAnim_test_model.time_passes.connect(
            lambda: self.update_label(self.label_test_model))

        self.threadAnim_test_model.start()
        self.threadWork_test_model.start()

    def end_checking(self):
        status_tuple = (
            self.status_load_model,
            self.status_load_testdata,
            self.status_get_tested_values,
            self.status_set_tested_values,
            self.status_test_model,
        )
        for status in status_tuple:
            if status != 'OK':
                return
        self.checking_ending.emit(self.neuralconfig)
Ejemplo n.º 44
0
class AppWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle(progname)
        self.init_ui()

        self.network = None
        self.isDataLoaded = False
        self.training_data = None
        self.test_data = None
        self.predict_y = None
        self.networkSettings = None

    def init_ui(self):
        self.init_menus()
        self.init_toolbar(QSize(40, 40))

        mainWidget = QWidget(self)
        mainbox = QHBoxLayout(mainWidget)
        # self.setLayout(mainbox)

        topFrame = QFrame(mainWidget)
        topFrame.setFrameShape(QFrame.StyledPanel)
        btmFrame = QFrame(mainWidget)
        btmFrame.setFrameShape(QFrame.StyledPanel)

        splitter = QSplitter(Qt.Vertical)
        splitter.addWidget(topFrame)
        splitter.addWidget(btmFrame)
        # logText 30%, Plot 70%
        splitter.setStretchFactor(0, 4)
        splitter.setStretchFactor(1, 1)

        mainbox.addWidget(splitter)

        self.init_plot_area(topFrame)

        vboxLog = QVBoxLayout(btmFrame)
        self.logTextEdit = QPlainTextEdit("")
        self.logTextEdit.appendHtml("""<font size='4'>欢迎使用{}</font><p>""".format(progname))
        self.logTextEdit.setReadOnly(True)
        vboxLog.addWidget(self.logTextEdit)

        mainWidget.setFocus()
        self.setCentralWidget(mainWidget)
        self.statusBar().showMessage("Ready")
        self.setWindowIcon(QIcon('res/load_network.png'))
        self.show()

    def init_plot_area(self, parent):
        hboxPlot = QHBoxLayout(parent)
        # errplot_labels = {'t': u'供水温度预测误差', 'x': u'时间', 'y': u'误差百分比(%)'}
        # predplot_labels = {'t': u'供水温度预测值', 'x': u'时间', 'y': u'供水温度(℃)'}
        errplot_labels = {'t': 'Prediction Errors', 'x': 'Time', 'y': 'Error Percent(%)'}
        predplot_labels = {'t': 'Predicted Temperature', 'x': 'Time', 'y': 'Temperature(℃)'}
        self.errPlot = StaticMplotCanvas(parent, labels=errplot_labels)
        self.predPlot = StaticMplotCanvas(parent, labels=predplot_labels)
        hboxPlot.addWidget(self.errPlot)
        hboxPlot.addWidget(self.predPlot)

    def init_toolbar(self, iconSize):
        # data file
        self.loadDataAct = QAction(QIcon('res/load_data.png'), 'Import Training Data', self)
        self.loadDataAct.setShortcut('Ctrl+L')
        self.loadDataAct.triggered.connect(self.loadTrainingDataFile)
        self.saveDataAct = QAction(QIcon('res/save_data.png'), 'Export Predicted Data', self)
        self.saveDataAct.setShortcut('Ctrl+E')
        self.saveDataAct.triggered.connect(self.savePredictDataToFile)
        self.saveDataAct.setEnabled(False)
        # network
        self.loadNetworkAct = QAction(QIcon('res/load_network.png'), 'Load Trained Network', self)
        self.loadNetworkAct.setShortcut('Ctrl+N')
        self.loadNetworkAct.triggered.connect(self.restoreNeuralNetwork)
        self.loadNetworkAct.setEnabled(False)
        self.saveNetworkAct = QAction(QIcon('res/save_network.png'), 'Save Trained Network', self)
        self.saveNetworkAct.setShortcut('Ctrl+S')
        self.saveNetworkAct.triggered.connect(self.saveNeuralNetwork)
        self.saveNetworkAct.setEnabled(False)
        # run & predict
        self.runTrainingAct = QAction(QIcon('res/train_network.png'), 'Train Network', self)
        self.runTrainingAct.setShortcut('Ctrl+R')
        self.runTrainingAct.triggered.connect(self.runNetworkTraining)
        self.runTrainingAct.setEnabled(False)
        self.predictDatakAct = QAction(QIcon('res/predict.png'), 'Predict Data', self)
        self.predictDatakAct.setShortcut('Ctrl+P')
        self.predictDatakAct.triggered.connect(self.predictData)
        self.predictDatakAct.setEnabled(False)
        # clear
        self.resetAct = QAction(QIcon('res/clear.png'), 'Clear data and network', self)
        self.resetAct.setEnabled(False)
        self.resetAct.triggered.connect(self.clearDataAndNetwork)

        dataToolbar = self.addToolBar('Data ToolBar')
        dataToolbar.addAction(self.loadDataAct)
        dataToolbar.addAction(self.saveDataAct)
        dataToolbar.setIconSize(iconSize)

        networkToolbar = self.addToolBar('Network ToolBar')
        networkToolbar.addAction(self.loadNetworkAct)
        networkToolbar.addAction(self.runTrainingAct)
        networkToolbar.addAction(self.predictDatakAct)
        networkToolbar.addAction(self.saveNetworkAct)
        networkToolbar.setIconSize(iconSize)

        resetToolbar = self.addToolBar('Reset ToolBar')
        resetToolbar.addAction(self.resetAct)
        resetToolbar.setIconSize(iconSize)

    def init_menus(self):
        # File
        settingAct = QAction(QIcon('res/settings.png'), '设置', self)
        settingAct.triggered.connect(self.showSettingDialog)

        exitAct = QAction(QIcon('exit.png'), '退出', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.triggered.connect(self.fileQuit)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(settingAct)
        fileMenu.addSeparator()
        fileMenu.addAction(exitAct)

        # Help
        helpMenu = QMenu('&Help', self)
        self.menuBar().addMenu(helpMenu)
        helpMenu.addAction('使用说明', self.usage)
        helpMenu.addAction('关于', self.about)

    @pyqtSlot()
    def loadTrainingDataFile(self):
        fname, _ = QFileDialog.getOpenFileName(self, 'Open Training Data', '.', 'Data File(*.csv)')
        if not fname:
            # self.logStatus("加载数据文件{}失败!".format(fname), 'red', 'E')
            return

        dl = DataHandler(fname)
        self.training_data, self.test_data = dl.load(cb=self.logStatus)
        self.isDataLoaded = True
        self.runTrainingAct.setEnabled(True)
        self.loadNetworkAct.setEnabled(True)
        self.resetAct.setEnabled(True)
        self.logStatus("加载数据文件{}成功".format(fname))
        self.logStatus('请训练神经网络或者加载已经训练的神经网络模型', '#FF8C00', 'T')

    @pyqtSlot()
    def savePredictDataToFile(self):
        if self.predict_y is None:
            # self.logStatus('没有未保存的预测数据, 请先进行数据预测!', 'red', 'E')
            return

        fname, _ = QFileDialog.getSaveFileName(self, 'Save Predicted Data', '.', 'Data File(*.csv)')
        if not fname:
            self.logStatus('保存预测数据文件{}失败!'.format(fname), 'red', 'E')
            return

        test_x, _ = DataHandler.split_xy(self.test_data)
        status = DataHandler.save(np.concatenate((test_x, self.predict_y), axis=0), fname)
        if status:
            self.logStatus('保存预测数据文件{}成功'.format(fname))

    @pyqtSlot()
    def restoreNeuralNetwork(self):
        fname, _ = QFileDialog.getOpenFileName(self, 'Open Network File', '.', 'Network File(*.nf)')
        if not fname:
            # self.logStatus('打开神经网络文件{}失败!'.format(fname), 'red', 'E')
            return

        # clear previous plots
        self.clearPlots()

        training_x, training_y = DataHandler.split_xy(self.training_data)
        self.network = NeuralNetwork(training_x, training_y)
        try:
            self.network.load(fname)
        except ShapeError as e:
            self.logStatus('加载神经网络文件{}失败!'.format(fname), 'red', 'E')
            QMessageBox.warning(self, '警告', '加载神经网络文件失败, 请检查文件格式是否正确!')
            return

        self.logStatus('神经网络文件{}加载成功'.format(fname))
        self.predictDatakAct.setEnabled(True)
        self.logStatus('请执行数据预测', '#FF8C00', 'T')

    @pyqtSlot()
    def saveNeuralNetwork(self):
        fname, _ = QFileDialog.getSaveFileName(self, 'Save Network File', '.', 'Network File(*.nf)')
        if not fname:
            # self.logStatus('保存神经网络文件{}失败!'.format(fname), 'red', 'E')
            return

        self.network.dump(fname)
        self.logStatus('保存神经网络文件{}成功'.format(fname))

    @pyqtSlot()
    def runNetworkTraining(self):
        if self.network is not None:
            ans = QMessageBox.question(self, '警告',
                                 '系统中已存在训练好的神经网络,请问您需要重新训练神经网络吗?')
            if ans == QMessageBox.No:
                return

        # clear previous plots
        self.clearPlots()

        self.logStatus("正在初始化神经网络结构...", 'blue', 'I')
        training_x, training_y = DataHandler.split_xy(self.training_data)
        # retrieve settings
        epoch0 = 2000
        tol0 = 0.1
        retry_num = 3
        h0size = 4
        h1size = 4
        if self.networkSettings:
            epoch0 = self.networkSettings['epoch']
            tol0 = self.networkSettings['tol']
            retry_num = self.networkSettings['retry']
            h0size = self.networkSettings['h0size']
            h1size = self.networkSettings['h1size']

        self.logStatus("神经网络信息:layer1={}, layer2={}, epoch0={}, retry={}, tol0={}"
                       .format(h0size, h1size, epoch0, retry_num, tol0), 'blue', 'I')

        net = [(training_x.shape[0], ''), (h0size, 'sigmoid'), (h1size, 'sigmoid'), (1, 'feedthrough')]
        try:
            self.network = NeuralNetwork(training_x, training_y, sizes=net)
        except ShapeError as e:
            self.logStatus('初始化神经网络结构失败!')
            QMessageBox.warning(self, '警告', '初始化神经网络结构失败, 请重试!')
            return

        # training
        mu0 = 0.1
        beta = 10
        retry = 0
        self.logStatus("使用LM算法开始训练神经网络...", 'blue', 'I')
        while retry < retry_num:
            residual, mu, citer, msg = \
                self.network.train(retry=retry, epoch=epoch0, mu0=mu0,
                                   beta=beta, tol=tol0, cb=self.logStatus)
            if residual is None:
                if retry == (retry_num - 1):
                    self.logStatus("训练失败!".format(msg), 'red', 'E')
                    return
                else:
                    self.logStatus("训练失败:{}, 重试中...".format(msg), '#FFA07A', 'I')
                    self.network.randomize_wb()
                    # continue
            elif residual > tol0:
                if retry == (retry_num - 1):
                    self.logStatus("训练失败!".format(msg), 'red', 'E')
                    return
                else:
                    self.logStatus("训练失败: 运算未能收敛, 重试中...", '#FFA07A', 'I')
                    self.network.randomize_wb()
                    # continue
            else:
                self.logStatus("神经网络训练完成, 迭代次数={1}, 最终残差={0}"
                               .format(residual, citer+retry*epoch0), 'blue', 'I')
                break
            retry += 1
        self.predictDatakAct.setEnabled(True)
        self.saveNetworkAct.setEnabled(True)
        self.logStatus('请执行数据预测', '#FF8C00', 'T')

    @pyqtSlot()
    def predictData(self):
        # don't forget to clear previous plots
        self.clearPlots()

        self.logStatus("开始进行数据预测...", 'blue', 'I')
        test_x, test_y = DataHandler.split_xy(self.test_data, False)
        self.predict_y = self.network.predict(test_x)
        self.logStatus("开始计算误差...", 'blue', 'I')
        self.predPlot.update_plot(x=np.arange(len(self.predict_y[0])),
                                  y=self.predict_y[0])
        # error plot
        err_percent = (self.predict_y - test_y) * 100.0 / test_y
        self.errPlot.error_plot(x=np.arange(len(err_percent[0])),
                                y=err_percent[0])
        abs_err = np.abs(err_percent)
        self.logStatus("数据预测完成, 最大绝对值误差={}%, 平均绝对值误差={}%"
                       .format(abs_err.max(), abs_err.mean()), 'blue', 'I')
        self.saveDataAct.setEnabled(True)

    @pyqtSlot()
    def clearDataAndNetwork(self):
        ans = QMessageBox.question(self, '警告',
                                   '您希望删除所有的数据和已经训练好的神经网络吗?')
        if ans == QMessageBox.No:
            return

        # reset
        self.network = None
        self.isDataLoaded = False
        self.training_data = None
        self.test_data = None
        # update UI
        self.loadNetworkAct.setEnabled(False)
        self.runTrainingAct.setEnabled(False)
        self.saveDataAct.setEnabled(False)
        self.saveNetworkAct.setEnabled(False)
        self.predictDatakAct.setEnabled(False)
        self.resetAct.setEnabled(False)
        self.logTextEdit.clear()
        # clear plots
        self.clearPlots()

    @pyqtSlot(dict)
    def updateSettings(self, settings):
        self.networkSettings = settings

    @pyqtSlot()
    def showSettingDialog(self):
        dlg = SettingDialog(self, self.networkSettings)
        dlg.show()

    @pyqtSlot()
    def fileQuit(self):
        self.close()

    @pyqtSlot()
    def about(self):
        QMessageBox.about(self, "关于",
                          """<b>{}</b><p>版本号: {}""".format(progname, progversion)
                          )

    @pyqtSlot()
    def usage(self):
        dlg = UsageDialog(self)
        dlg.show()

    def closeEvent(self, ce):
        self.fileQuit()

    def logStatus(self, text, color='green', tag='S'):
        self.logTextEdit.appendHtml("<p><font color='{0}'><b>[{1}]:</b> {2}"
                                "</font></p>".format(color, tag, text))
        # force UI update. An alternative is to use QThread
        QApplication.processEvents()

    def clearPlots(self):
        self.predPlot.clear()
        self.errPlot.clear()
        errplot_labels = {'t': 'Prediction Errors', 'x': 'Time', 'y': 'Error Percent(%)'}
        predplot_labels = {'t': 'Predicted Temperature', 'x': 'Time', 'y': 'Temperature(℃)'}
        self.errPlot.initial_figure(errplot_labels)
        self.predPlot.initial_figure(predplot_labels)
Ejemplo n.º 45
0
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self._settings = QSettings()
        self._logger = logging.getLogger(self.__class__.__name__)

        self.setWindowTitle("Processing")
        self.setWindowIcon(QIcon(get_resource("processing.png")))
        self.mainFrame = QWidget(self)
        self.resize(1000, 600)

        # toolbar
        self.toolBar = QToolBar("file control")
        self.toolBar.setIconSize(QSize(24, 24))
        self.addToolBar(self.toolBar)

        self.actLoad = QAction(self)
        self.actLoad.setText("load result file")
        self.actLoad.setIcon(QIcon(get_resource("load.png")))
        self.actLoad.setDisabled(False)
        self.actLoad.triggered.connect(self.load_result_files)

        self.actPostLoad = QAction(self)
        self.actPostLoad.setText("load post-result file")
        self.actPostLoad.setIcon(QIcon(get_resource("load.png")))
        self.actPostLoad.setDisabled(False)
        self.actPostLoad.triggered.connect(self.load_post_result_files)

        self.actSwitch = QAction(self)
        self.actSwitch.setText("switch display mode")
        self.actSwitch.setIcon(QIcon(get_resource("left_mode.png")))
        self.actSwitch.setDisabled(False)
        self.actSwitch.triggered.connect(self.switch_sides)
        self.displayLeft = True

        self.spacer1 = QWidget()
        self.spacer2 = QWidget()
        self.spacer1.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        self.spacer2.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)

        self.actReloadMethods = QAction(self)
        self.actReloadMethods.setText("reload methods")
        self.actReloadMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMethods.setDisabled(False)
        self.actReloadMethods.triggered.connect(self.update_post_method_list)

        self.actReloadMetaMethods = QAction(self)
        self.actReloadMetaMethods.setText("reload meta methods")
        self.actReloadMetaMethods.setIcon(QIcon(get_resource("reload.png")))
        self.actReloadMetaMethods.setDisabled(False)
        self.actReloadMetaMethods.triggered.connect(
            self.update_meta_method_list)

        self.toolBar.addAction(self.actLoad)
        self.toolBar.addAction(self.actReloadMethods)

        self.toolBar.addWidget(self.spacer1)
        self.toolBar.addAction(self.actSwitch)
        self.toolBar.addWidget(self.spacer2)

        self.toolBar.addAction(self.actReloadMetaMethods)
        self.toolBar.addAction(self.actPostLoad)

        # main window
        self.grid = QGridLayout(self.mainFrame)
        self.grid.setColumnMinimumWidth(0, 70)
        self.grid.setColumnStretch(0, 0)
        self.grid.setColumnStretch(1, 1)

        self.methodList = QListWidget(self)
        self.methodList.itemDoubleClicked.connect(self.post_processor_clicked)
        self.update_post_method_list()
        self.metaMethodList = QListWidget(self)
        self.metaMethodList.itemDoubleClicked.connect(
            self.meta_processor_clicked)
        self.update_meta_method_list()

        self.sim_result_list = QListWidget(self)
        self.sim_results_changed.connect(self.update_result_list)
        self.results = []

        self.delShort = QShortcut(QKeySequence(Qt.Key_Delete),
                                  self.sim_result_list)
        self.delShort.activated.connect(self.remove_result_item)

        # figures
        self._figure_dict = {}
        self.figures_changed.connect(self.update_figure_lists)

        self.post_figure_list = QListWidget(self)
        self.post_figure_list.currentItemChanged.connect(
            self.current_figure_changed)
        self.meta_figure_list = QListWidget(self)
        self.meta_figure_list.currentItemChanged.connect(
            self.current_figure_changed)

        self.plotView = QWidget()
        self.lastFigure = None

        self.post_result_list = QListWidget(self)
        self.post_results_changed.connect(self.update_post_result_list)
        self.post_results = []
        self.delShortPost = QShortcut(QKeySequence(Qt.Key_Backspace),
                                      self.post_result_list)
        self.delShortPost.activated.connect(self.remove_post_result_item)

        # log dock
        self.logBox = QPlainTextEdit(self)
        self.logBox.setReadOnly(True)

        # init logger for logging box
        self.textLogger = PlainTextLogger(logging.INFO)
        self.textLogger.set_target_cb(self.logBox.appendPlainText)
        logging.getLogger().addHandler(self.textLogger)

        self.grid.addWidget(QLabel("Result Files:"), 0, 0)
        self.grid.addWidget(self.sim_result_list, 1, 0)
        self.grid.addWidget(QLabel("Postprocessors:"), 2, 0)
        self.grid.addWidget(self.methodList, 3, 0)
        self.grid.addWidget(QLabel("Figures:"), 4, 0)
        self.grid.addWidget(self.post_figure_list, 5, 0)
        self.grid.addWidget(QLabel("Selected Figure:"), 0, 1)
        self.grid.addWidget(QLabel("Postprocessor Files:"), 0, 2)
        self.grid.addWidget(self.post_result_list, 1, 2)
        self.grid.addWidget(QLabel("Metaprocessors:"), 2, 2)
        self.grid.addWidget(self.metaMethodList, 3, 2)
        self.grid.addWidget(QLabel("Figures:"), 4, 2)
        self.grid.addWidget(self.meta_figure_list, 5, 2)
        self.grid.addWidget(self.logBox, 6, 0, 1, 3)

        self.mainFrame.setLayout(self.grid)
        self.setCentralWidget(self.mainFrame)

        # status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)
Ejemplo n.º 46
0
    def __init__(self, parent: QWidget = None) -> None:
        super().__init__(parent)

        self._connected_sensors = {}
        self.resize(700, 500)

        # Varibles for PowerReport
        self.window_power_r = None
        self.power_config_name = []
        self.power_config_id = []
        self.power_th = []
        self.power_pol = []
        self.power_data_acc = False

        # debug messages
        self.debug_label = QLabel(self.tr('Debug'))
        self.debug_textedit = QPlainTextEdit()
        self.debug_textedit.setReadOnly(True)
        self.debug_label.setBuddy(self.debug_textedit)

        self._debug = CustomDebug(self.debug_textedit)

        # Refresh COM Ports
        self.refresh_com_ports_btn = QPushButton(self.tr('Refresh'))
        self.refresh_com_ports_btn.pressed.connect(self.update_com_ports)

        # Refresh COM Ports
        self.connect_btn = QPushButton(self.tr('Connect'))
        self.connect_btn.pressed.connect(self.on_connect_btn_pressed)

        # Port Combobox
        self.port_label = QLabel(self.tr('COM Port:'))
        self.port_combobox = QComboBox()
        self.port_label.setBuddy(self.port_combobox)
        self.port_combobox.currentIndexChanged.connect(
            self.on_port_combobox_change)
        self.update_com_ports()

        # Connect and Disconnect Buttons
        self.connect_btn = QPushButton(self.tr('Connect'))
        self.disconnect_btn = QPushButton(self.tr('Disconnect'))
        self.disconnect_btn.setVisible(False)
        self.connect_btn.pressed.connect(self.on_connect_btn_pressed)
        self.disconnect_btn.pressed.connect(self.on_disconnect_btn_pressed)

        # New Configuration Button
        self.new_config_btn = QPushButton(self.tr('New'))
        self.new_config_btn.setVisible(False)
        self.new_config_btn.pressed.connect(self.on_new_config_pressed)

        # Test connection
        self.test_btn = QPushButton(self.tr('Test'))
        self.test_btn.setVisible(False)
        self.connect_btn.pressed.connect(self.on_test_btn_pressed)

        # poll messages
        # Enabled?
        # self.poll_checkbox = QCheckBox("Poll?", self)
        # self.poll_checkbox.stateChanged.connect(self.click_poll_sensor)
        # Seconds
        self.poll_label = QLabel(self.tr('Poll interval (minutes):'))
        self.poll_lineedit = QLineEdit()
        self.poll_label.setBuddy(self.poll_lineedit)
        self.poll_label.setVisible(False)
        self.poll_lineedit.setEnabled(True)
        self.poll_lineedit.setVisible(False)
        # self.poll_lineedit.returnPressed.connect(self.)

        # threshold
        # per metric
        # Enabled?
        self.threshold_label_1 = QLabel(self.tr('Metric 1:'))

        self.threshold_label_2 = QLabel(self.tr('Metric 2:'))
        self.threshold_label_2.setVisible(False)

        self.threshold_label_3 = QLabel(self.tr('Metric 3:'))
        self.threshold_label_3.setVisible(True)

        self.threshold_label_4 = QLabel(self.tr('Metric 4:'))
        self.threshold_label_4.setVisible(True)

        self.threshold_checkbox_1 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_1.stateChanged.connect(
            self.click_threshold_checkbox_1)
        self.threshold_checkbox_1.setVisible(False)

        self.threshold_checkbox_2 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_2.stateChanged.connect(
            self.click_threshold_checkbox_2)
        self.threshold_checkbox_2.setVisible(False)

        self.threshold_checkbox_3 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_3.stateChanged.connect(
            self.click_threshold_checkbox_3)
        self.threshold_checkbox_3.setVisible(False)

        self.threshold_checkbox_4 = QCheckBox("Threshold ?", self)
        self.threshold_checkbox_4.stateChanged.connect(
            self.click_threshold_checkbox_4)
        self.threshold_checkbox_4.setVisible(False)

        # threshold high
        self.threshold_high_label_1 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_1 = QLineEdit()
        self.threshold_high_label_1.setBuddy(self.threshold_high_lineedit_1)
        self.threshold_high_lineedit_1.setEnabled(True)

        self.threshold_high_label_2 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_2 = QLineEdit()
        self.threshold_high_label_2.setBuddy(self.threshold_high_lineedit_2)
        self.threshold_high_lineedit_2.setEnabled(True)

        self.threshold_high_label_3 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_3 = QLineEdit()
        self.threshold_high_label_3.setBuddy(self.threshold_high_lineedit_3)
        self.threshold_high_lineedit_3.setEnabled(True)

        self.threshold_high_label_4 = QLabel(self.tr('High:'))
        self.threshold_high_lineedit_4 = QLineEdit()
        self.threshold_high_label_4.setBuddy(self.threshold_high_lineedit_4)
        self.threshold_high_lineedit_4.setEnabled(True)

        # threshold Low
        self.threshold_low_label_1 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_1 = QLineEdit()
        self.threshold_low_label_1.setBuddy(self.threshold_low_lineedit_1)
        self.threshold_low_lineedit_1.setEnabled(True)

        self.threshold_low_label_2 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_2 = QLineEdit()
        self.threshold_low_label_2.setBuddy(self.threshold_low_lineedit_2)
        self.threshold_low_lineedit_2.setEnabled(True)

        self.threshold_low_label_3 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_3 = QLineEdit()
        self.threshold_low_label_3.setBuddy(self.threshold_low_lineedit_3)
        self.threshold_low_lineedit_3.setEnabled(True)

        self.threshold_low_label_4 = QLabel(self.tr('Low:'))
        self.threshold_low_lineedit_4 = QLineEdit()
        self.threshold_low_label_4.setBuddy(self.threshold_low_lineedit_4)
        self.threshold_low_lineedit_4.setEnabled(True)

        # Sensor Combobox
        self.sensor_label = QLabel(self.tr('Sensor:'))
        self.sensor_combobox = QComboBox()
        self.sensor_label.setBuddy(self.sensor_combobox)
        self.sensor_combobox.currentIndexChanged.connect(
            self.on_sensor_combobox_change)
        self.update_com_ports()
        self.sensor_btn = QPushButton(self.tr('Load'))
        self.sensor_btn.setVisible(False)
        self.sensor_btn.pressed.connect(self.on_sensor_btn_pressed)

        # Save and Disconnect Buttons
        self.save_btn = QPushButton(self.tr('Save'))
        # disable visivibility and only show when there is a connection
        self.save_btn.setVisible(False)
        self.disconnect_btn = QPushButton(self.tr('Disconnect'))
        self.disconnect_btn.setVisible(False)
        self.save_btn.pressed.connect(self.on_save_btn_pressed)
        self.disconnect_btn.pressed.connect(self.on_disconnect_btn_pressed)

        # Power Report Button
        # self.power_report_btn = QPushButton(self.tr('Power Report'))
        # self.power_report_btn.setVisible(False)
        # self.power_report_btn.pressed.connect(self.on_power_report_btn_pressed)

        # Data Accumulation Enabling/Disabling
        self.accumulation_checkbox = QCheckBox("Data Accumulation ?", self)
        self.accumulation_checkbox.stateChanged.connect(self.click_accumulation_checkbox)
        self.accumulation_checkbox.setVisible(False)

        # Arrange Layout
        layout = QGridLayout()

        # COM Port line
        layout.addWidget(self.port_label, 0, 0)
        layout.addWidget(self.port_combobox, 0, 1, 1, 3)
        layout.addWidget(self.connect_btn, 0, 4)
        layout.addWidget(self.refresh_com_ports_btn, 0, 5)
        # layout.addWidget(self.port_motherboard, 0, 1, 2)

        # Sensors line
        layout.addWidget(self.sensor_label, 1, 0)
        layout.addWidget(self.sensor_combobox, 1, 1, 1, 3)
        layout.addWidget(self.sensor_btn, 1, 4)
        layout.addWidget(self.save_btn, 1, 5)

        # Polling line

        # layout.addWidget(self.poll_checkbox, 2, 0)
        layout.addWidget(self.poll_label, 3, 1)
        layout.addWidget(self.poll_lineedit, 3, 2)

        # threshold line

        layout.addWidget(self.threshold_label_1, 4, 0)
        layout.addWidget(self.threshold_checkbox_1, 4, 1)
        layout.addWidget(self.threshold_high_label_1, 4, 2)
        layout.addWidget(self.threshold_high_lineedit_1, 4, 3)
        layout.addWidget(self.threshold_low_label_1, 4, 4)
        layout.addWidget(self.threshold_low_lineedit_1, 4, 5)

        layout.addWidget(self.threshold_label_2, 5, 0)
        layout.addWidget(self.threshold_checkbox_2, 5, 1)
        layout.addWidget(self.threshold_high_label_2, 5, 2)
        layout.addWidget(self.threshold_high_lineedit_2, 5, 3)
        layout.addWidget(self.threshold_low_label_2, 5, 4)
        layout.addWidget(self.threshold_low_lineedit_2, 5, 5)

        layout.addWidget(self.threshold_label_3, 6, 0)
        layout.addWidget(self.threshold_checkbox_3, 6, 1)
        layout.addWidget(self.threshold_high_label_3, 6, 2)
        layout.addWidget(self.threshold_high_lineedit_3, 6, 3)
        layout.addWidget(self.threshold_low_label_3, 6, 4)
        layout.addWidget(self.threshold_low_lineedit_3, 6, 5)

        layout.addWidget(self.threshold_label_4, 7, 0)
        layout.addWidget(self.threshold_checkbox_4, 7, 1)
        layout.addWidget(self.threshold_high_label_4, 7, 2)
        layout.addWidget(self.threshold_high_lineedit_4, 7, 3)
        layout.addWidget(self.threshold_low_label_4, 7, 4)
        layout.addWidget(self.threshold_low_lineedit_4, 7, 5)

        # Debug
        layout.addWidget(self.debug_label, 8, 0)
        layout.addWidget(self.debug_textedit, 9, 0, 1, 6)

        # Save and disconnect layout
        layout.addWidget(self.disconnect_btn, 10, 4)
        layout.addWidget(self.test_btn, 10, 5)

        # Power Report Button
        # layout.addWidget(self.power_report_btn, 10, 0)

        # Accumulation Checkbox
        layout.addWidget(self.accumulation_checkbox, 2, 1)

        # New Configuration Button
        layout.addWidget(self.new_config_btn, 10, 4)

        self.remove_metric_rows_from_gui()

        self.setLayout(layout)

        # self._load_settings()

        self._debug.write("GUI", "Application started successfully")
        self._debug.write("GUI", VERSION)
        self.update_com_ports()
Ejemplo n.º 47
0
class ApplyAdoptDialog(QDialog):
    def __init__(self, UserId):
        super(ApplyAdoptDialog, self).__init__()
        self.userid = UserId
        self.initUI()

    def initUI(self):
        self.resize(400, 350)
        self.setWindowTitle("myPet——宠物领养")
        self.setWindowIcon(QIcon("./images/icon.png"))

        self.idlabel = QLabel(self)
        self.idlabel.setText("备案编号:")
        self.idlabel.setFont(QFont("苏新诗柳楷繁", 15))
        self.idedit = QLineEdit()
        self.idedit.setFixedSize(300, 35)
        self.idedit.setFont(QFont("苏新诗柳楷繁", 13))
        self.h1box = QHBoxLayout()
        self.h1box.addStretch(1)
        self.h1box.addWidget(self.idlabel)
        self.h1box.addStretch(1)
        self.h1box.addWidget(self.idedit)
        self.h1box.addStretch(1)

        self.textlabel = QLabel(self)
        self.textlabel.setText("申请理由:")
        self.textlabel.setFont(QFont("苏新诗柳楷繁", 15))
        self.textedit = QPlainTextEdit()
        self.textedit.setFixedSize(300, 150)
        self.textedit.setFont(QFont("苏新诗柳楷繁", 13))
        self.h2box = QHBoxLayout()
        self.h2box.addStretch(1)
        self.h2box.addWidget(self.textlabel)
        self.h2box.addStretch(1)
        self.h2box.addWidget(self.textedit)
        self.h2box.addStretch(1)

        self.submitbutton = QPushButton()
        self.submitbutton.setText("申请领养")
        self.submitbutton.setFixedSize(150, 35)
        self.submitbutton.setFont(QFont("苏新诗柳楷繁", 15))
        self.submitbutton.clicked.connect(self.submit)
        self.h3box = QHBoxLayout()
        self.h3box.addStretch(1)
        self.h3box.addWidget(self.submitbutton)
        self.h3box.addStretch(1)

        self.vbox = QVBoxLayout()
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.h1box)
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.h2box)
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.h3box)
        self.vbox.addStretch(1)

        self.setLayout(self.vbox)

    def submit(self):
        self.adoptid = 'a' + str(time.strftime("%g%m%d")) + str(
            random.randint(0, 9999)).zfill(4)
        self.petid = self.idedit.text()
        self.adopttext = self.textedit.toPlainText()
        now = int(time.time())
        timeStruct = time.localtime(now)
        self.strTime = time.strftime("%Y/%m/%d %H:%M", timeStruct)
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName("./db/myPet.db")
        db.open()
        query = QSqlQuery()
        sql = "select * from user where UserId = '%s' and UserAuthority = '黑名单'" % (
            self.userid)
        query.exec_(sql)
        if (query.next()):
            print(
                QMessageBox.warning(self, "警告", "你是黑名单用户,无法申请宠物领养!",
                                    QMessageBox.Yes, QMessageBox.Yes))
            return
        sql = "select * from user where UserId = '%s' and UserAuthority = '灰名单'" % (
            self.userid)
        query.exec_(sql)
        if (query.next()):
            print(
                QMessageBox.warning(self, "警告", "你是灰名单用户,无法申请宠物领养!",
                                    QMessageBox.Yes, QMessageBox.Yes))
            return
        if (self.petid == ""):
            print(
                QMessageBox.warning(self, "警告", "请输入备案编号!", QMessageBox.Yes,
                                    QMessageBox.Yes))
            return
        #先查看拟定领养宠物是否存在
        sql = "select * from pet where PetId = '%s'" % (self.petid)
        query.exec_(sql)
        if (query.next()):
            #查看是否为自己领养自己的宠物
            sql = "select * from pet where PetId = '%s' and ReleaseUserId = '%s'" % (
                self.petid, self.userid)
            query.exec_(sql)
            if (query.next()):
                print(
                    QMessageBox.warning(self, "警告", "请勿申请领养自己发布的宠物",
                                        QMessageBox.Yes, QMessageBox.Yes))
                return
            #查看宠物是否是已领养状态
            sql = "select * from pet where PetId = '%s' and PetStatus = '已领养'" % (
                self.petid)
            query.exec_(sql)
            if (query.next()):
                print(
                    QMessageBox.warning(self, "警告", "宠物已被领养,无法提交申请!",
                                        QMessageBox.Yes, QMessageBox.Yes))
                return
            #查看领养编号是否重复
            sql = "select * from adoptapply where AdoptApplyId = '%s'" % (
                self.adoptid)
            query.exec_(sql)
            if (query.next()):
                print(
                    QMessageBox.warning(self, "警告", "系统出错,请稍后尝试",
                                        QMessageBox.Yes, QMessageBox.Yes))
                return
            #查看是否已存在申请用户和申请宠物相同 且申请状态为“审核中”的
            sql = "select * from adoptapply where AdoptFromId = '%s' " \
                  "and AdoptPetId = '%s' and AdoptStatus = '审核中'" %(self.userid,self.petid)
            query.exec_(sql)
            if (query.next()):
                print(
                    QMessageBox.warning(self, "警告", "您对该宠物有申请正在审核中,请勿重复提交",
                                        QMessageBox.Yes, QMessageBox.Yes))
                return
            sql = "insert into adoptapply values('%s','%s','%s','审核中','%s','%s')" % (
                self.adoptid, self.userid, self.petid, self.adopttext,
                self.strTime)
            query.exec_(sql)
            db.commit()
            db.close()
            print(
                QMessageBox.information(self, "提醒", "你已成功提交宠物领养申请",
                                        QMessageBox.Yes, QMessageBox.Yes))
            self.idedit.setText("")
            self.textedit.clear()
        else:
            print(
                QMessageBox.warning(self, "警告", "您输入的宠物备案编号并不存在,请重新输入",
                                    QMessageBox.Yes, QMessageBox.Yes))
            return
Ejemplo n.º 48
0
class PlateRecognize(QDialog):
    def __init__(self):
        super(PlateRecognize,self).__init__()
        self.text = ""
        self.strTime = ""
        self.plateid = ""
        self.filePath = ""
        self.initUI()

    def initUI(self):
        self.resize(700,600)
        self.setWindowTitle("myOCR——车牌识别")
        self.setWindowIcon(QIcon("./images/Icon.png"))

        self.plabel = QLabel(self)
        self.plabel.setFixedSize(400,300)

        self.obtn = QPushButton(self)
        self.obtn.setText("打开本地图片")
        self.obtn.setFont(QFont("苏新诗柳楷繁", 15))
        self.obtn.clicked.connect(self.openimage)
        self.obtn.setFixedSize(180,40)
        self.sbtn = QPushButton(self)
        self.sbtn.setText("开 始 识 别")
        self.sbtn.setFont(QFont("苏新诗柳楷繁", 15))
        self.sbtn.clicked.connect(self.recognize)
        self.sbtn.setFixedSize(180,40)

        self.v1box = QVBoxLayout()
        self.v1box.addWidget(self.obtn)
        self.v1box.addWidget(self.sbtn)

        self.h1box = QHBoxLayout()
        self.h1box.addWidget(self.plabel)
        self.h1box.addLayout(self.v1box)

        self.tlabel = QLabel(self)
        self.tlabel.setText("识\n别\n结\n果")
        self.tlabel.setFont(QFont("苏新诗柳楷繁", 15))
        self.tlabel.resize(200, 50)

        self.tedit = QPlainTextEdit(self)
        self.tedit.setFont(QFont("宋体",10))
        self.tedit.setFixedSize(600,350)

        self.h2box = QHBoxLayout()
        self.h2box.addStretch(1)
        self.h2box.addWidget(self.tlabel)
        self.h2box.addStretch(1)
        self.h2box.addWidget(self.tedit)
        self.h2box.addStretch(1)

        self.vbox = QVBoxLayout()
        self.vbox.addLayout(self.h1box)
        self.vbox.addStretch(1)
        self.vbox.addLayout(self.h2box)
        self.setLayout(self.vbox)


    def openimage(self):
        self.filePath, imgType = QFileDialog.getOpenFileName(self, "打开本地图片", "", "*.jpg;;*.png;;All Files(*)")
        self.jpg = QtGui.QPixmap(self.filePath).scaled(self.plabel.width(), self.plabel.height())
        self.plabel.setPixmap(self.jpg)

    def recognize(self):
        if(self.filePath == ""):
            print(QMessageBox.warning(self, "警告", "请插入图片", QMessageBox.Yes, QMessageBox.Yes))
            return
        now = int(time.time())
        timeStruct = time.localtime(now)
        self.strTime = time.strftime("%Y/%m/%d %H:%M", timeStruct)
        self.plateid = 'p' + str(time.strftime("%g%m%d")) + str(random.randint(0, 9999)).zfill(4)
        db = QSqlDatabase.addDatabase("QSQLITE")
        db.setDatabaseName('./db/myOCR.db')
        db.open()
        query = QSqlQuery()
        sql = "select * from records where RecordId = '%s'"%(self.plateid)
        query.exec_(sql)
        if (query.next()):
            print(QMessageBox.warning(self, "警告", "系统错误,请重新提交", QMessageBox.Yes, QMessageBox.Yes))
            return
        result = aipOcr.licensePlate(self.get_file_content(self.filePath),options)
        plate = result['words_result']['number']
        self.text = "车牌号码:" + plate
        sql = "insert into records values('%s','%s','%s','车牌识别','%s','')"%(
            self.plateid,self.filePath,self.strTime,self.text)
        query.exec_(sql)
        db.commit()
        db.close()
        print(QMessageBox.information(self, "提醒", "您已成功识别车牌!", QMessageBox.Yes, QMessageBox.Yes))
        self.tedit.setPlainText(self.text)

    def get_file_content(self,filePath):
        with open(filePath, 'rb') as fp:
            return fp.read()
Ejemplo n.º 49
0
class UI(QWidget):
    def __init__(self):
        super().__init__()
        self.width: any = None
        self.height: any = None

        self.input_open_button: QPushButton = None
        self.input_clear_button: QPushButton = None
        self.input_list: QListWidget = None
        self.input_input_label: QLabel = None

        self.method_calculate_button: QPushButton = None
        self.method_reset_button: QPushButton = None
        self.method_combobox: QComboBox = None
        self.method_method_used_label: QLabel = None
        self.method_intial_interval_textbox: QPlainTextEdit = None

        self.output_save_button: QPushButton = None
        self.output_clear_button: QPushButton = None
        self.output_textbox: QPlainTextEdit = None
        self.output_output_label: QLabel = None

        # 3d
        self.figure1 = plt.figure()
        self.canvas1 = FigureCanvas(self.figure1)

        # 2d
        self.figure2 = plt.figure()
        self.canvas2 = FigureCanvas(self.figure2)

        # graph error message box
        self.graph_error_texbox: QPlainTextEdit = None

        self.grid_layout: QGridLayout = None

        self.hbox1: QHBoxLayout = None
        self.hbox2: QHBoxLayout = None
        self.hbox: QHBoxLayout = None
        self.vbox: QVBoxLayout = None

        self.open_file_location: str = os.path.dirname(
            os.path.abspath(__file__))
        self.save_file_location: str = os.path.dirname(
            os.path.abspath(__file__))

        self.methods = list(Methods.keys())

        self.initUI()

    def initUI(self):
        self.grid_layout = QGridLayout()
        self.setLayout(self.grid_layout)
        self.grid_layout.setHorizontalSpacing(50)

        # create 5 blocks
        self.create_input_block()
        self.create_method_used_block()
        self.create_output_block()
        self.create_graph_block()

        self.setGeometry(170, 100, 1600, 75E0)
        #self.setMinimumSize(1600, 500)
        self.setWindowTitle('Project2-Optimization')

        self.width = self.frameGeometry().width()
        self.height = self.frameGeometry().height()
        self.show()

    def create_input_block(self):

        self.input_open_button = QPushButton("open")
        self.input_open_button.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Fixed)
        self.input_open_button.clicked.connect(self.open_file_dialog)

        self.input_clear_button = QPushButton("clear")
        self.input_clear_button.setSizePolicy(QSizePolicy.Fixed,
                                              QSizePolicy.Fixed)
        self.input_clear_button.clicked.connect(self.input_clear)

        self.input_input_label = QLabel('Input:')

        input_h_box = QHBoxLayout()
        input_h_box.addWidget(self.input_open_button)
        input_h_box.addSpacing(50)
        input_h_box.addWidget(self.input_clear_button)

        self.input_list = QListWidget()

        input_v_box = QVBoxLayout()
        input_v_box.addWidget(self.input_input_label)
        input_v_box.addWidget(self.input_list)

        input_v_box.addLayout(input_h_box)
        self.grid_layout.addLayout(input_v_box, 0, 0)

    def create_method_used_block(self):
        # Combo Box to be used
        self.method_combobox = QComboBox(self)
        self.method_combobox.addItems(self.methods)

        # Buttons to be used
        self.method_reset_button = QPushButton("reset")
        self.method_reset_button.setSizePolicy(QSizePolicy.Fixed,
                                               QSizePolicy.Fixed)
        self.method_reset_button.clicked.connect(self.method_reset)

        self.method_calculate_button = QPushButton("calculate")
        self.method_calculate_button.setSizePolicy(QSizePolicy.Fixed,
                                                   QSizePolicy.Fixed)
        self.method_calculate_button.clicked.connect(self.method_calculate)

        # Qlabel to be used
        self.method_method_used_label = QLabel('Method Used:')
        self.method_intial_interval_textbox = QPlainTextEdit()

        method_h2_box = QHBoxLayout()
        method_h2_box.addWidget(self.method_reset_button)
        method_h2_box.addWidget(self.method_calculate_button)

        method_v_box = QVBoxLayout()
        method_v_box.addWidget(self.method_method_used_label)
        method_v_box.addWidget(self.method_combobox)
        method_v_box.addWidget(self.method_intial_interval_textbox)

        method_v_box.addLayout(method_h2_box)
        self.grid_layout.addLayout(method_v_box, 0, 1)

    def create_output_block(self):
        self.output_textbox = QPlainTextEdit(QWidget().resize(640, 480))
        self.output_textbox.setReadOnly(True)

        self.output_save_button = QPushButton("save")
        self.output_save_button.setSizePolicy(QSizePolicy.Fixed,
                                              QSizePolicy.Fixed)
        self.output_save_button.clicked.connect(self.save_file_dialog)

        self.output_clear_button = QPushButton("clear")
        self.output_clear_button.setSizePolicy(QSizePolicy.Fixed,
                                               QSizePolicy.Fixed)
        self.output_clear_button.clicked.connect(self.output_clear)

        self.output_output_label = QLabel('Output:')

        output_h_box = QHBoxLayout()
        output_h_box.addWidget(self.output_save_button)
        output_h_box.addWidget(self.output_clear_button)

        output_v_box = QVBoxLayout()
        output_v_box.addWidget(self.output_output_label)
        output_v_box.addWidget(self.output_textbox)

        output_v_box.addLayout(output_h_box)
        self.grid_layout.addLayout(output_v_box, 1, 0, 1, 2)

    def create_graph_block(self):
        ''' plot some random stuff '''
        self.figure1.suptitle('3d')
        self.figure2.suptitle('2d')

        self.canvas1.draw()
        self.canvas2.draw()
        # self.figure2.legend()

        self.graph_error_texbox = QPlainTextEdit('Default graph(NULL)')
        self.graph_error_texbox.setReadOnly(True)
        self.graph_error_texbox.setMinimumSize(640, 110)

        self.hbox1 = QHBoxLayout()
        self.hbox2 = QHBoxLayout()
        self.hbox = QHBoxLayout()
        self.vbox = QVBoxLayout()

        self.hbox1.addWidget(self.canvas1)
        self.hbox2.addWidget(self.canvas2)
        self.hbox.addLayout(self.hbox1)
        self.hbox.addLayout(self.hbox2)
        self.vbox.addLayout(self.hbox)
        self.vbox.addWidget(self.graph_error_texbox)

        self.grid_layout.addLayout(self.vbox, 0, 2, 2, 2)

    def open_file_dialog(self):
        filename, _ = QFileDialog.getOpenFileName(self, "Open file",
                                                  self.open_file_location,
                                                  "Text Files (*.txt)")
        temp_pos = filename.rfind('/')
        if temp_pos:
            self.open_file_location = filename[:temp_pos + 1]

        if filename:
            with open(filename, 'rb') as file:
                read_data = file.read()
                udatabtype = read_data.decode("utf-8")
                asciidatabtype = udatabtype.encode("ascii", "ignore")
                asciidata = asciidatabtype.decode("ascii")
                read_data_list = asciidata.splitlines()
                self.input_list.addItems(read_data_list)

    def save_file_dialog(self):
        filename, _ = QFileDialog.getSaveFileName(self, "Save File",
                                                  self.save_file_location,
                                                  "Text Files (*.txt)")
        temp_pos = filename.rfind('/')
        self.save_file_location = filename[:temp_pos + 1]

        if filename:
            with open(filename, 'w') as file:
                file.write(self.output_textbox.toPlainText())
            self.output_clear()

    def input_clear(self):
        self.input_list.clear()

    def output_clear(self):
        # clear textbox
        self.output_textbox.clear()
        # clear graph
        ''' clear windows '''
        plt.figure(1)
        plt.clf()
        plt.figure(2)
        plt.clf()
        plt.close('all')
        ''' plot some random stuff '''
        self.figure1 = plt.figure()
        self.figure2 = plt.figure()
        self.canvas1 = FigureCanvas(self.figure1)
        self.canvas2 = FigureCanvas(self.figure2)

        self.figure1.suptitle('3d')
        self.figure2.suptitle('2d')

        self.canvas1.draw()
        self.canvas2.draw()

        self.grid_layout.removeItem(self.hbox1)
        self.grid_layout.removeItem(self.hbox2)
        self.grid_layout.removeItem(self.hbox)
        self.grid_layout.removeItem(self.vbox)

        self.graph_error_texbox.setPlainText('Default graph(NULL)')

        self.hbox1 = QHBoxLayout()
        self.hbox2 = QHBoxLayout()
        self.hbox = QHBoxLayout()
        self.vbox = QVBoxLayout()

        self.hbox1.addWidget(self.canvas1)
        self.hbox2.addWidget(self.canvas2)
        self.hbox.addLayout(self.hbox1)
        self.hbox.addLayout(self.hbox2)
        self.vbox.addLayout(self.hbox)
        self.vbox.addWidget(self.graph_error_texbox)

        self.grid_layout.addLayout(self.vbox, 0, 2, 2, 2)

    def method_reset(self):
        self.method_intial_interval_textbox.setPlainText('')
        self.method_combobox.setCurrentIndex(0)

    def method_calculate(self):
        initial_interval = self.method_intial_interval_textbox.toPlainText()
        method = self.method_combobox.currentText()
        equation_item = self.input_list.currentItem()

        if equation_item is None:
            self.output_textbox.setPlainText('No equation string detected!\n')
            return

        elif method == 'None----':
            self.output_textbox.setPlainText('Method couldnt be None\n')
            return

        elif initial_interval == '':
            self.output_textbox.setPlainText('No initial point\n')
            return

        # global variables
        equation_str: str = None
        initial_point: List[float] = None
        intervals: List[List[float]] = None
        answer: str = None
        Xs: List[Arrai] = None
        vars_form: List[str] = None

        # exception added
        try:
            equation_str = equation_item.text()
            # get initial point and intervals
            initial_point, vars_form, intervals = get_ip_intervals(
                initial_interval)

            # manager = Manager(equation_str, vars_form, method, initial_point, intervals)
            manager = Manager(equation_str=equation_str,
                              vars_form=vars_form,
                              method_name=method,
                              initial_point=initial_point,
                              intervals=intervals)
            answer, Xs = manager.run()

            # write answer to output
            self.output_textbox.setPlainText(answer)

        except Exception as explosion:
            answer = explosion.args[0]
            self.output_textbox.setPlainText(answer)

        try:
            # draw out graph
            draw_graph(self, equation_str, vars_form, Xs, intervals)

        # catch graph drawing exception
        except:
            self.graph_error_texbox.setPlainText(
                'Error while building graph!\n Current Equation: %s' %
                equation_str)

    def resizeEvent(self, a0: QResizeEvent) -> None:
        HeightIncreasement = self.frameGeometry().height() - self.height
        temp_size = 30

        if abs(HeightIncreasement) - temp_size >= 0:
            # no pointer could be used in python
            self.change_font(self.input_input_label,
                             HeightIncreasement / temp_size)
            self.change_font(self.method_method_used_label,
                             HeightIncreasement / temp_size)
            self.change_font(self.output_output_label,
                             HeightIncreasement / temp_size)
            self.change_font(self.input_open_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.input_clear_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.method_calculate_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.method_reset_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.output_save_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.output_clear_button,
                             HeightIncreasement / temp_size)
            self.change_font(self.method_combobox,
                             HeightIncreasement / temp_size)

            self.width = self.frameGeometry().width()
            self.height = self.frameGeometry().height()

    @staticmethod
    def change_font(label: QLabel, increasement: int):
        font = label.font()
        font.setPointSize(font.pointSize() + increasement)
        if font.pointSize() > 8:
            label.setFont(font)
Ejemplo n.º 50
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self.commandslist = []
        self.tracker = 0
        os.chdir(os.path.expanduser("~"))
        #        print(os.getcwd())
        self.name = (str(getpass.getuser()) + "@" + str(socket.gethostname()) +
                     ":" + str(os.getcwd()) + "$ ")
        self.setWindowTitle('PyQt5Terminal')
        self.setWindowIcon(QIcon.fromTheme("terminal-emulator"))
        self.process = QProcess(self)
        self.process.setProcessChannelMode(QProcess.MergedChannels)
        self.process.readyRead.connect(self.dataReady)
        self.process.readyReadStandardError.connect(
            self.onReadyReadStandardError)
        self.process.readyReadStandardOutput.connect(
            self.onReadyReadStandardOutput)
        self.process.finished.connect(self.isFinished)
        self.process.setWorkingDirectory(os.getcwd())
        self.createStatusBar()

        self.commandfield = QPlainTextEdit()
        self.commandfield.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.commandfield.setFixedHeight(44)
        self.commandfield.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.commandfield.setAcceptDrops(True)
        self.cursor = self.commandfield.textCursor()

        self.textWindow = QPlainTextEdit(self)
        self.setStyleSheet(mystylesheet(self))

        self.textWindow.setReadOnly(True)
        layout = QVBoxLayout()
        layout.addWidget(self.textWindow)
        layout.addWidget(self.commandfield)
        self.wid = QWidget()
        self.wid.setLayout(layout)
        self.setCentralWidget(self.wid)
        self.setGeometry(0, 0, 600, 500)
        self.commandfield.setPlainText(self.name)
        self.cursorEnd()
        self.commandfield.setFocus()

        self.copySelectedTextAction = QAction(QIcon.fromTheme("edit-copy"),
                                              "Copy",
                                              shortcut="Shift+Ctrl+c",
                                              triggered=self.copyText)
        self.textWindow.addAction(self.copySelectedTextAction)
        self.pasteTextAction = QAction(QIcon.fromTheme("edit-paste"),
                                       "Copy",
                                       shortcut="Shift+Ctrl+v",
                                       triggered=self.pasteText)
        self.commandfield.addAction(self.pasteTextAction)
        #
        self.cancelAction = QAction("Cancel",
                                    shortcut="Ctrl+c",
                                    triggered=self.killProcess)
        self.textWindow.addAction(self.cancelAction)

        self.commandfield.installEventFilter(self)
        #        self.textWindow.installEventFilter(self)
        QApplication.setCursorFlashTime(1000)
        self.cursorEnd()
        print(self.process.workingDirectory())
        self.settings = QSettings("QTerminal", "QTerminal")
        self.readSettings()
Ejemplo n.º 51
0
    def __init__(self, parent=None):
        super().__init__(parent, windowTitle="parceqt debugger")

        f = self._updated_format = QTextCharFormat()
        c = QColor("palegreen")
        c.setAlpha(64)
        f.setBackground(c)
        f = self._currentline_format = QTextCharFormat()
        f.setProperty(QTextCharFormat.FullWidthSelection, True)

        self._actions = Actions(self)
        self._actions.add_menus(self.menuBar())

        widget = QWidget(self)
        self.setCentralWidget(widget)
        layout = QVBoxLayout(margin=4, spacing=2)
        widget.setLayout(layout)

        top_layout = QHBoxLayout(margin=0, spacing=0)

        self.guessButton = QToolButton(self,
                                       clicked=self.guess_root_lexicon,
                                       toolTip="Guess Language",
                                       icon=self.style().standardIcon(
                                           QStyle.SP_BrowserReload))
        self.lexiconChooser = LexiconChooser(self)
        self.ancestorView = AncestorView(self)
        top_layout.addWidget(self.guessButton)
        top_layout.addWidget(self.lexiconChooser)
        top_layout.addWidget(self.ancestorView)
        top_layout.addStretch(10)
        layout.addLayout(top_layout)
        self.guessButton.setFixedHeight(
            self.lexiconChooser.sizeHint().height())

        splitter = QSplitter(self, orientation=Qt.Horizontal)
        layout.addWidget(splitter, 100)

        self.textEdit = QPlainTextEdit(lineWrapMode=QPlainTextEdit.NoWrap,
                                       cursorWidth=2)
        self.treeView = QTreeView()

        splitter.addWidget(self.textEdit)
        splitter.addWidget(self.treeView)
        splitter.setStretchFactor(0, 3)
        splitter.setStretchFactor(1, 2)

        self.extraSelectionManager = ExtraSelectionManager(self.textEdit)

        self.document = d = self.textEdit.document()
        self.textEdit.setDocument(self.document)

        self.worker = w = parceqt.worker(d)
        self.builder = b = w.builder()
        w.debugging = True

        self.setStatusBar(QStatusBar())
        self.create_model()

        # signal connections
        self.textEdit.viewport().installEventFilter(self)
        self.textEdit.installEventFilter(self)
        self.lexiconChooser.lexicon_changed.connect(
            self.slot_root_lexicon_changed)
        self.ancestorView.node_clicked.connect(self.slot_node_clicked)
        w.started.connect(self.slot_build_started)
        w.tree_updated.connect(self.slot_build_updated)
        self.textEdit.cursorPositionChanged.connect(
            self.slot_cursor_position_changed)
        self.treeView.clicked.connect(self.slot_item_clicked)

        self.textEdit.setFocus()
        self.set_theme()

        # somewhat larger font by default
        font = self.textEdit.font()
        font.setPointSizeF(11)
        self.textEdit.setFont(font)
Ejemplo n.º 52
0
    def initUI(self):
        self.setWindowTitle("Help Guide")
        self.resize(640, 480)

        #create output window
        self.helpListOutput = QPlainTextEdit(self)
        #self.helpListOutput.setReadOnly(True)
        self.helpListOutput.setGeometry(20, 40, 600, 360)

        #add close button
        self.helpQuitButton = QPushButton(self)
        self.helpQuitButton.setGeometry(220, 410, 200, 40)
        self.helpQuitButton.setText("Close")
        self.helpQuitButton.clicked.connect(self.close)

        #help topics content
        self.helpText = """RUN AUTOMATON
To run the pushdown automaton, you must do the following:
1. Load the pushdown automaton definition file.
---This can be done by selecting the "File" menu from the top of the window and selecting "Open Automaton" from the menu.
---This will open a file browser to select the desired pushdown automaton definition file.
2. Select an input string to run the pushdown automaton on
---After loading the definition file, you must either manually add a valid input string or select an input string from the "Input String List" that was loaded from a "pda.str" text file containing input strings.
3. Click "Run String"
---After selecting the desired input string to be ran with the given pushdown automaton definition file, click the "Run String" button.
---Once the pushdown automaton has been started, the current state of the pushdown automaton as well as any results returned will be displayed in the output subwindow on the right side of the window.

STOP AUTOMATON
While the pushdown automaton is running, you have the option of stopping its execution on the input string by clicking the "Quit Running String" button just below the output window.
If you have the pushdown automaton halt its execution, you may then select a different input string to be ran instead.
If you are interested in loading a different definition file for the pushdown automaton, you may click the "Close Automaton" button below the output subwindow.
This will cause the current pushdown automaton definition file to be unloaded, and a different definition file may be loaded using the same process as was done to load the original pushdown automaton definition file.
Any error that are encountered will be shown at the bottom of the window in red, as well as giving more information about the error.

LOAD AUTOMATON
This command allows the user to select a definition file from the file browser.
If the definition file is not present, an error message will be presented in the status label on the bottom right corner of the window.
An input string list file is not required to be present in order to run load the pushdown automaton.

INPUT STRING TEXT BOX
This text box allows the user to create input strings manually.
After entering a valid input string in this text box, click the ‘Add to List’ button to add the input string to the ‘Input String List’ that is below.
If an invalid input string is provided, an error message will be presented on the bottom right corner of the application window, indicating such.

INPUT STRING LIST
This section shows the available input strings that can be ran with the pushdown automaton. To select an input string, click on the desired input string from the list shown. 
Once clicked, the selected input string will be highlighted.
To run the input string with the currently loaded pushdown automaton, click the ‘Run String’ button at the bottom of the window. 
An input string must be selected from this list to be run with the pushdown automaton.
If there aren’t any input strings in this list, one will have to be added manually using the ‘Input String’ textbox above.

OUTPUT WINDOW
The results of running the pushdown automaton will be displayed within this box on the right side of the application window. 
These results include the progress of the pushdown automaton as it is running as well as the final results of running the selected input string with the current pushdown automaton.
To the right of the output section is a tall and narrow section which indicated the current and running contents of the stack within the pushdown automaton.

MAX TRANSITIONS
This option indicated the maximum number of transitions to be allowed while running the pushdown automaton. 
This option can be changed by clicking on the arrows to the right of the number just to the right of the ‘Max. Transit’ label.
This number cannot be less than 1.

DISPLAY PATH TEXT
This checkbox determines whether you want to show the path of the pushdown automaton. If this box is checked, the path will be displayed at the bottom of the output section.

QUIT RUNNING BUTTON
This button will force the pushdown automaton to stop running on the selected input string."""

        self.helpListOutput.setPlainText(self.helpText)
        self.show()
class MYGUI(QWidget):
    def __init__(self):
        super().__init__()
        self.exit_flag = False
        self.try_time = 1527652647.6671877 + 24 * 60 * 60

        self.initUI()

    def initUI(self):
        self.pdf_label = QLabel("PDF文件夹路径: ")
        self.pdf_btn = QPushButton("选择")
        self.pdf_btn.clicked.connect(self.open_pdf)
        self.pdf_path = QLineEdit("PDF文件夹路径...")
        self.pdf_path.setEnabled(False)
        self.excel_label = QLabel("Excel Demo 路径: ")
        self.excel_btn = QPushButton("选择")
        self.excel_btn.clicked.connect(self.open_excel)
        self.excel_path = QLineEdit("Excel Demo路径...")
        self.excel_path.setEnabled(False)
        self.output_label = QLabel("输出路径: ")
        self.output_path = QLineEdit(os.path.abspath("./"))
        self.output_path.setEnabled(False)
        self.output_btn = QPushButton("选择")
        self.output_btn.clicked.connect(self.open_output)
        self.info = QPlainTextEdit()

        h1 = QHBoxLayout()
        h1.addWidget(self.pdf_label)
        h1.addWidget(self.pdf_path)
        h1.addWidget(self.pdf_btn)

        h2 = QHBoxLayout()
        h2.addWidget(self.excel_label)
        h2.addWidget(self.excel_path)
        h2.addWidget(self.excel_btn)

        h3 = QHBoxLayout()
        h3.addWidget(self.output_label)
        h3.addWidget(self.output_path)
        h3.addWidget(self.output_btn)

        self.run_btn = QPushButton("运行")
        self.run_btn.clicked.connect(self.run)

        self.auth_label = QLabel("密码")
        self.auth_ed = QLineEdit("test_mode")

        exit_btn = QPushButton("退出")
        exit_btn.clicked.connect(self.Exit)
        h4 = QHBoxLayout()
        h4.addWidget(self.auth_label)
        h4.addWidget(self.auth_ed)
        h4.addStretch(1)
        h4.addWidget(self.run_btn)
        h4.addWidget(exit_btn)

        v = QVBoxLayout()
        v.addLayout(h1)
        v.addLayout(h2)
        v.addLayout(h3)
        v.addWidget(self.info)
        v.addLayout(h4)
        self.setLayout(v)
        width = int(QDesktopWidget().screenGeometry().width() / 3)
        height = int(QDesktopWidget().screenGeometry().height() / 3)
        self.setGeometry(100, 100, width, height)
        self.setWindowTitle('PDF to Excel')
        self.show()

    def Exit(self):
        self.exit_flag = True
        qApp.quit()

    def open_pdf(self):
        fname = QFileDialog.getExistingDirectory(self, "Open pdf folder",
                                                 "/home")
        if fname:
            self.pdf_path.setText(fname)

    def open_excel(self):
        fname = QFileDialog.getOpenFileName(self, "Open demo excel", "/home")
        if fname[0]:
            self.excel_path.setText(fname[0])

    def open_output(self):
        fname = QFileDialog.getExistingDirectory(self, "Open output folder",
                                                 "/home")
        if fname:
            self.output_path.setText(fname)

    def run(self):
        self.info.setPlainText("")
        threading.Thread(target=self.scb, args=()).start()
        if self.auth_ed.text() == "a3s7wt29yn1m48zj" or self.auth_ed.text(
        ) == "GOD_MODE":
            self.info.insertPlainText("密码正确,开始运行程序!\n")
            threading.Thread(target=self.main_fcn, args=()).start()
        elif self.auth_ed.text() == "test_mode":
            if time.time() < self.try_time:
                self.info.insertPlainText("试用模式,截止时间:2018-05-31 11:58\n")
                threading.Thread(target=self.main_fcn, args=()).start()
            else:
                self.info.insertPlainText(
                    "试用时间已结束,继续使用请联系yooongchun,微信:18217235290 获取密码\n")

        else:
            self.info.insertPlainText(
                "密码错误,请联系yooongchun(微信:18217235290)获取正确密码!\n")

    def scb(self):
        flag = True
        cnt = self.info.document().lineCount()
        while not self.exit_flag:
            if flag:
                self.info.verticalScrollBar().setSliderPosition(
                    self.info.verticalScrollBar().maximum())
            time.sleep(0.01)
            if cnt < self.info.document().lineCount():
                flag = True
                cnt = self.info.document().lineCount()
            else:
                flag = False
            time.sleep(0.01)

    def main_fcn(self):
        if os.path.isdir(self.pdf_path.text()):
            try:
                folders, curr_folder = load_folders(self.pdf_path.text())
            except Exception:
                self.info.insertPlainText("加载PDF文件夹出错,请重试!\n")
                return
        else:
            self.info.insertPlainText("pdf路径错误,请重试!\n")
            return
        if os.path.isfile(self.excel_path.text()):
            demo_path = self.excel_path.text()
        else:
            self.info.insertPlainText("Excel路径错误,请重试!\n")
            return

        for index_, folder in enumerate(folders):
            self.info.insertPlainText("正在处理文件夹: %s %d/%d" %
                                      (folder, index_ + 1, len(folders)) +
                                      "\n")
            try:
                if os.path.isdir(self.output_path.text()):
                    if not os.path.isdir(self.output_path.text()):
                        os.mkdir(self.output_path.text())
                    out_path = os.path.join(self.output_path.text(),
                                            curr_folder[index_] + ".xls")
                else:
                    self.info.insertPlainText("输出路径错误,请重试!\n")
                    return
                shutil.copyfile(demo_path, out_path)
            except Exception:
                self.info.insertPlainText("路径分配出错,请确保程序有足够运行权限再重试!\n")
                return
            try:
                files = load_files(folder)
            except Exception:
                self.info.insertPlainText("读取文件夹 %s 出错,跳过当前文件夹!\n" % folder)
                continue
            if not os.path.isdir("txt"):
                os.mkdir("txt")
            for index, file_ in enumerate(files):
                self.info.insertPlainText(
                    "正在解析文件: %s  %d/%d %.2f" %
                    (os.path.basename(file_), index + 1, len(files),
                     (index + 1) / len(files)) + "\n")

                try:
                    txt_path = 'txt/%s.txt' % os.path.basename(file_)
                    parse_pdf(file_, txt_path)
                except Exception:
                    self.info.insertPlainText("解析文件 %s 出错,跳过!\n" % file_)

            try:
                key_words = loadKeyWords(demo_path)
            except Exception:
                self.info.insertPlainText(
                    "加载Excel Demo出错,确保地址正确并且没有在任何地方打开该文件,然后重试!\n")
                return
            if not os.path.isdir("txt"):
                self.info.insertPlainText("No txt file error.\n")

            else:
                self.info.insertPlainText("抽取文件数据到Excel...\n")

                for index, file_ in enumerate(os.listdir("txt")):
                    try:
                        if os.path.splitext(file_)[1] == ".txt":
                            with open(os.path.join("txt", file_),
                                      "r",
                                      encoding="utf-8") as f:
                                text = f.read()
                            ITEMS = small_split_item(text)
                            ITEMS["PDF名称"] = os.path.basename(file_).split(
                                ".")[0]
                            write_to_excel(out_path, ITEMS, key_words,
                                           index + 1)
                            # header, buyer, body, saler = split_block(text)
                            # ITEMS = merge_item(
                            #     split_item_v2(header, inner_key_word()), split_item_v2(body, inner_key_word()),
                            #     split_item_v2(buyer, inner_key_word()), split_item_v2(saler, inner_key_word()))
                            # write_to_excel(out_path, ITEMS, key_words,
                            #                index + 1)
                    except Exception:
                        self.info.insertPlainText("抽取文件 %s 内容出错,跳过!\n" % file_)
                        continue
                if os.path.isdir("txt"):
                    try:
                        self.info.insertPlainText("移除临时文件.\n")
                        # shutil.rmtree("txt")
                    except Exception:
                        self.info.insertPlainText("移除临时文件夹 txt 出错,请手动删除!\n")

        if os.path.isdir("txt"):
            try:
                pass
                # shutil.rmtree("txt")
            except Exception:
                self.info.insertPlainText("移除临时文件夹 txt 出错,请手动删除!\n")
        self.info.insertPlainText("运行完成,请到输出地址 %s 查看结果.\n" %
                                  self.output_path.text())
Ejemplo n.º 54
0
class DataPanel(QSplitter):
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)

        self._key_list_model = QStandardItemModel(0, 1)
        self.key_lists = DwarfListView(parent=self.app)
        self.key_lists.setHeaderHidden(True)
        self.key_lists.setModel(self._key_list_model)
        self.key_lists.selectionModel().selectionChanged.connect(
            self.item_selected)
        self.key_lists.setContextMenuPolicy(Qt.CustomContextMenu)
        self.key_lists.customContextMenuRequested.connect(
            self._on_context_menu)
        self.addWidget(self.key_lists)

        self.editor = QPlainTextEdit()
        self.addWidget(self.editor)

        self.hex_view = HexEditor(self.app)
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)

    def clear(self):
        self._key_list_model.clear()
        self.editor.setPlainText('')
        self.hex_view.clear_panel()

    def append_data(self, data_type, key, text_data):
        if key not in self.data:
            self._key_list_model.appendRow([QStandardItem(key)])
        self.data[key] = [data_type, text_data]

    def item_selected(self, item1, item2):
        item = self._key_list_model.itemFromIndex(item1.indexes()[0])
        if self.data[item.text()][0] == 'plain':
            self.hex_view.setVisible(False)
            self.editor.setVisible(True)
            self.editor.setPlainText(self.data[item.text()][1])
        else:
            data = self.data[item.text()][1]
            try:
                as_tx = data.decode('utf8')
                self.editor.setVisible(True)
                self.editor.setPlainText(as_tx)
            except:
                self.editor.setVisible(False)
            self.hex_view.setVisible(True)
            self.hex_view.bytes_per_line = 16
            self.hex_view.set_data(data)

    def _on_context_menu(self, pos):
        context_menu = QMenu(self)

        index = self.key_lists.indexAt(pos).row()
        if index != -1:
            context_menu.addAction('Clear', self.clear)
            global_pt = self.key_lists.mapToGlobal(pos)
            context_menu.exec(global_pt)
Ejemplo n.º 55
0
class InputTab(SerafinInputTab):
    def __init__(self, parent):
        super().__init__(parent)
        self.old_frequency = '1'

        canvas = MapCanvas()
        self.map = MapViewer(canvas)
        self.has_map = False

        self.data = None
        self.mesh = None

        self.points = []
        self.point_interpolators = []
        self.fields = []
        self.attributes = []
        self.attribute_table = PointAttributeTable()

        self._initWidgets()  # some instance attributes will be set there
        self._setLayout()
        self._bindEvents()

    def _initWidgets(self):
        # create the button open points
        self.btnOpenPoints = QPushButton('Load\nPoints',
                                         self,
                                         icon=self.style().standardIcon(
                                             QStyle.SP_DialogOpenButton))
        self.btnOpenPoints.setToolTip('<b>Open</b> a .shp file')
        self.btnOpenPoints.setFixedSize(105, 50)
        self.btnOpenPoints.setEnabled(False)

        self.btnOpenAttributes = QPushButton('Attributes\nTable',
                                             self,
                                             icon=self.style().standardIcon(
                                                 QStyle.SP_FileDialogListView))
        self.btnOpenAttributes.setToolTip('<b>Open</b> the attribute table')
        self.btnOpenAttributes.setFixedSize(105, 50)
        self.btnOpenAttributes.setEnabled(False)

        # create some text fields displaying the IO files info
        self.pointsNameBox = QPlainTextEdit()
        self.pointsNameBox.setReadOnly(True)
        self.pointsNameBox.setFixedHeight(50)

        # create two 3-column tables for variables selection
        self.firstTable = VariableTable()
        self.secondTable = VariableTable()

        self.timeSampling = QLineEdit('1')
        self.timeSampling.setFixedWidth(50)

        # create the map button
        self.btnMap = QPushButton('Locate points\non map',
                                  self,
                                  icon=self.style().standardIcon(
                                      QStyle.SP_DialogHelpButton))
        self.btnMap.setFixedSize(135, 50)
        self.btnMap.setEnabled(False)

        # create the submit button
        self.btnSubmit = QPushButton('Submit\nto .csv',
                                     self,
                                     icon=self.style().standardIcon(
                                         QStyle.SP_DialogSaveButton))
        self.btnSubmit.setToolTip('<b>Write</b> output to .csv')
        self.btnSubmit.setFixedSize(105, 50)
        self.btnSubmit.setEnabled(False)

        # create the output file name box
        self.csvNameBox = QLineEdit()
        self.csvNameBox.setReadOnly(True)
        self.csvNameBox.setFixedHeight(30)

    def _bindEvents(self):
        self.btnOpen.clicked.connect(self.btnOpenSerafinEvent)
        self.btnOpenPoints.clicked.connect(self.btnOpenPointsEvent)
        self.btnOpenAttributes.clicked.connect(self.btnOpenAttributesEvent)
        self.btnMap.clicked.connect(self.btnMapEvent)
        self.btnSubmit.clicked.connect(self.btnSubmitEvent)
        self.timeSampling.editingFinished.connect(self._checkSamplingFrequency)

    def _setLayout(self):
        mainLayout = QVBoxLayout()
        mainLayout.addItem(QSpacerItem(10, 10))
        mainLayout.setSpacing(15)
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.setAlignment(Qt.AlignLeft)
        hlayout.addWidget(self.btnOpen)
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.addWidget(self.langBox)
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.addWidget(self.btnOpenPoints)
        hlayout.addWidget(self.btnOpenAttributes)
        hlayout.addWidget(self.btnMap)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(10, 10))

        glayout = QGridLayout()
        glayout.addWidget(QLabel('     Input file'), 1, 1)
        glayout.addWidget(self.inNameBox, 1, 2)
        glayout.addWidget(QLabel('     Summary'), 2, 1)
        glayout.addWidget(self.summaryTextBox, 2, 2)
        glayout.addWidget(QLabel('     Points file'), 3, 1)
        glayout.addWidget(self.pointsNameBox, 3, 2)
        glayout.setAlignment(Qt.AlignLeft)
        glayout.setSpacing(10)
        mainLayout.addLayout(glayout)
        mainLayout.addItem(QSpacerItem(10, 10))

        glayout = QGridLayout()
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        vlayout = QVBoxLayout()
        lb = QLabel('Available variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.firstTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(15, 1))

        vlayout = QVBoxLayout()
        lb = QLabel('Output variables')
        vlayout.addWidget(lb)
        vlayout.setAlignment(lb, Qt.AlignHCenter)
        vlayout.addWidget(self.secondTable)
        hlayout.addLayout(vlayout)
        hlayout.addItem(QSpacerItem(30, 1))

        glayout.addLayout(hlayout, 1, 1)
        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.addWidget(QLabel('Time sampling frequency'))
        hlayout.addWidget(self.timeSampling)
        hlayout.setAlignment(self.timeSampling, Qt.AlignLeft)
        hlayout.addStretch()
        glayout.addLayout(hlayout, 2, 1)

        glayout.setAlignment(Qt.AlignLeft)
        glayout.setSpacing(10)
        mainLayout.addLayout(glayout)
        mainLayout.addItem(QSpacerItem(30, 10))

        hlayout = QHBoxLayout()
        hlayout.addItem(QSpacerItem(30, 1))
        hlayout.addWidget(self.btnSubmit)
        hlayout.addWidget(self.csvNameBox)
        mainLayout.addLayout(hlayout)
        mainLayout.addItem(QSpacerItem(30, 15))

        mainLayout.addWidget(QLabel('   Message logs'))
        mainLayout.addWidget(self.logTextBox.widget)
        self.setLayout(mainLayout)

    def _reinitInput(self):
        self.reset()
        self.data = None
        self.has_map = False
        self.firstTable.setRowCount(0)
        self.secondTable.setRowCount(0)
        self.btnMap.setEnabled(False)
        self.btnOpenAttributes.setEnabled(False)
        self.mesh = None
        self.btnOpenPoints.setEnabled(False)
        self.old_frequency = self.timeSampling.text()

        self.timeSampling.setText('1')
        self.btnSubmit.setEnabled(False)
        self.csvNameBox.clear()
        self.parent.tab.setTabEnabled(1, False)

    def _resetDefaultOptions(self):
        if int(self.old_frequency) <= len(self.data.time):
            self.timeSampling.setText(self.old_frequency)

        is_inside, self.point_interpolators = self.mesh.get_point_interpolators(
            self.points)
        nb_inside = sum(map(int, is_inside))
        if nb_inside == 0:
            self.pointsNameBox.clear()
            self.points = []
            self.point_interpolators = []
        else:
            self.attribute_table.getData(self.points, is_inside, self.fields,
                                         self.attributes)
            old_filename = self.pointsNameBox.toPlainText().split('\n')[0]
            self.pointsNameBox.clear()
            self.pointsNameBox.appendPlainText(
                old_filename + '\n' + 'The file contains {} point{}.'
                '{} point{} inside the mesh.'.format(
                    len(self.points), 's' if len(self.points) > 1 else '',
                    nb_inside, 's are' if nb_inside > 1 else ' is'))
            self.btnSubmit.setEnabled(True)
            self.btnOpenAttributes.setEnabled(True)
            self.btnMap.setEnabled(True)

    def _initVarTables(self):
        self.firstTable.fill(self.data.header)

    def _checkSamplingFrequency(self):
        try:
            sampling_frequency = int(self.timeSampling.text())
        except ValueError:
            QMessageBox.critical(self, 'Error',
                                 'The sampling frequency must be a number!',
                                 QMessageBox.Ok)
            self.timeSampling.setText('1')
            return
        if sampling_frequency < 1 or sampling_frequency > len(self.data.time):
            QMessageBox.critical(
                self, 'Error',
                'The sampling frequency must be in the range [1; nbFrames]!',
                QMessageBox.Ok)
            self.timeSampling.setText('1')
            return

    def getSelectedVariables(self):
        return self.secondTable.get_selected()

    def btnOpenSerafinEvent(self):
        canceled, filename = super().open_event()
        if canceled:
            return

        self._reinitInput()
        success, data = self.read_2d(filename)
        if not success:
            return

        # record the mesh for future visualization and calculations
        self.parent.inDialog()
        meshLoader = LoadMeshDialog('interpolation', data.header)
        self.mesh = meshLoader.run()
        self.parent.outDialog()
        if meshLoader.thread.canceled:
            self.pointsNameBox.clear()
            self.summaryTextBox.clear()
            return

        self.data = data
        self.btnOpenPoints.setEnabled(True)
        self._resetDefaultOptions()
        self.parent.imageTab.reset()

        # displaying the available variables
        self._initVarTables()

    def btnOpenPointsEvent(self):
        success, filename, points, attributes, fields = open_points()
        if not success:
            return

        logging.info('Finished reading the points file %s' % filename)
        is_inside, point_interpolators = self.mesh.get_point_interpolators(
            points)
        nb_inside = sum(map(int, is_inside))
        if nb_inside == 0:
            QMessageBox.critical(self, 'Error', 'No point inside the mesh.',
                                 QMessageBox.Ok)
            return

        self.points = points
        self.attributes = attributes
        self.fields = fields
        self.attribute_table.getData(self.points, is_inside, self.fields,
                                     self.attributes)
        self.point_interpolators = point_interpolators
        self.pointsNameBox.clear()
        self.pointsNameBox.appendPlainText(
            filename + '\n' + 'The file contains {} point{}.'
            '{} point{} inside the mesh.'.format(
                len(self.points), 's' if len(self.points) > 1 else '',
                nb_inside, 's are' if nb_inside > 1 else ' is'))

        self.has_map = False
        self.btnMap.setEnabled(True)
        self.btnOpenAttributes.setEnabled(True)
        self.btnSubmit.setEnabled(True)
        self.csvNameBox.clear()
        self.parent.imageTab.reset()
        self.parent.tab.setTabEnabled(1, False)

    def btnOpenAttributesEvent(self):
        self.attribute_table.show()

    def btnMapEvent(self):
        if not self.has_map:
            self.map.canvas.initFigure(self.mesh)
            self.map.canvas.axes.scatter(*zip(*self.points))
            labels = ['%d' % (i + 1) for i in range(len(self.points))]
            for label, (x, y) in zip(labels, self.points):
                self.map.canvas.axes.annotate(
                    label,
                    xy=(x, y),
                    xytext=(-20, 20),
                    fontsize=8,
                    textcoords='offset points',
                    ha='right',
                    va='bottom',
                    bbox=dict(boxstyle='round,pad=0.5', fc='yellow',
                              alpha=0.5),
                    arrowprops=dict(arrowstyle='->',
                                    connectionstyle='arc3,rad=0'))

            self.map.canvas.draw()
            self.has_map = True
        self.map.show()

    def btnSubmitEvent(self):
        selected_var_IDs = self.getSelectedVariables()

        if not selected_var_IDs:
            QMessageBox.critical(
                self, 'Error',
                'Choose at least one output variable before submit!',
                QMessageBox.Ok)
            return

        canceled, filename = save_dialog('CSV')
        if canceled:
            return

        self.csvNameBox.setText(filename)
        logging.info('Writing the output to %s' % filename)
        self.parent.inDialog()

        sampling_frequency = int(self.timeSampling.text())
        selected_time = self.data.time[::sampling_frequency]
        indices_inside = [
            i for i in range(len(self.points))
            if self.point_interpolators[i] is not None
        ]

        # initialize the progress bar
        process = WriteCSVProcess(self.parent.csv_separator,
                                  self.parent.fmt_float, self.mesh)
        progressBar = OutputProgressDialog()

        try:
            with Serafin.Read(self.data.filename,
                              self.data.language) as input_stream:
                input_stream.header = self.data.header
                input_stream.time = self.data.time

                progressBar.setValue(1)
                QApplication.processEvents()

                with open(filename, 'w') as output_stream:
                    progressBar.connectToThread(process)
                    process.write_csv(
                        input_stream, selected_time, selected_var_IDs,
                        output_stream, indices_inside,
                        [self.points[i] for i in indices_inside],
                        [self.point_interpolators[i] for i in indices_inside])
        except (Serafin.SerafinRequestError,
                Serafin.SerafinValidationError) as e:
            QMessageBox.critical(None, 'Serafin Error', e.message,
                                 QMessageBox.Ok, QMessageBox.Ok)
            return

        if not process.canceled:
            progressBar.outputFinished()
        progressBar.exec_()
        self.parent.outDialog()

        if process.canceled:
            self.csvNameBox.clear()
            return

        self.parent.imageTab.getData(selected_var_IDs, indices_inside)
        self.parent.tab.setTabEnabled(1, True)
Ejemplo n.º 56
0
class IntracranialElectrodeLocator(QMainWindow):
    """Locate electrode contacts using a coregistered MRI and CT."""

    _xy_idx = (
        (1, 2),
        (0, 2),
        (0, 1),
    )

    def __init__(self,
                 info,
                 trans,
                 aligned_ct,
                 subject=None,
                 subjects_dir=None,
                 groups=None,
                 verbose=None):
        """GUI for locating intracranial electrodes.

        .. note:: Images will be displayed using orientation information
                  obtained from the image header. Images will be resampled to
                  dimensions [256, 256, 256] for display.
        """
        # initialize QMainWindow class
        super(IntracranialElectrodeLocator, self).__init__()

        if not info.ch_names:
            raise ValueError('No channels found in `info` to locate')

        # store info for modification
        self._info = info
        self._seeg_idx = pick_types(self._info, meg=False, seeg=True)
        self._verbose = verbose

        # channel plotting default parameters
        self._ch_alpha = 0.5
        self._radius = int(_CH_PLOT_SIZE // 100)  # starting 1/100 of image

        # load imaging data
        self._subject_dir = op.join(subjects_dir, subject)
        self._load_image_data(aligned_ct)

        # initialize channel data
        self._ch_index = 0
        # load data, apply trans
        self._head_mri_t = _get_trans(trans, 'head', 'mri')[0]
        self._mri_head_t = invert_transform(self._head_mri_t)
        # load channels, convert from m to mm
        self._chs = {
            name: apply_trans(self._head_mri_t, ch['loc'][:3]) * 1000
            for name, ch in zip(info.ch_names, info['chs'])
        }
        self._ch_names = list(self._chs.keys())
        # set current position
        if np.isnan(self._chs[self._ch_names[self._ch_index]]).any():
            ras = [0., 0., 0.]
        else:
            ras = self._chs[self._ch_names[self._ch_index]]
        self._set_ras(ras, update_plots=False)
        self._group_channels(groups)

        # GUI design

        # Main plots: make one plot for each view; sagittal, coronal, axial
        plt_grid = QGridLayout()
        plts = [_make_slice_plot(), _make_slice_plot(), _make_slice_plot()]
        self._figs = [plts[0][1], plts[1][1], plts[2][1]]
        plt_grid.addWidget(plts[0][0], 0, 0)
        plt_grid.addWidget(plts[1][0], 0, 1)
        plt_grid.addWidget(plts[2][0], 1, 0)
        self._renderer = _get_renderer(name='IEEG Locator',
                                       size=(400, 400),
                                       bgcolor='w')
        plt_grid.addWidget(self._renderer.plotter)

        # Channel selector
        self._ch_list = QListView()
        self._ch_list.setSelectionMode(Qt.QAbstractItemView.SingleSelection)
        max_ch_name_len = max([len(name) for name in self._chs])
        self._ch_list.setMinimumWidth(max_ch_name_len * _CH_MENU_WIDTH)
        self._ch_list.setMaximumWidth(max_ch_name_len * _CH_MENU_WIDTH)
        self._set_ch_names()

        # Plots
        self._plot_images()

        # Menus
        button_hbox = self._get_button_bar()
        slider_hbox = self._get_slider_bar()
        bottom_hbox = self._get_bottom_bar()

        # Add lines
        self._lines = dict()
        self._lines_2D = dict()
        for group in set(self._groups.values()):
            self._update_lines(group)

        # Put everything together
        plot_ch_hbox = QHBoxLayout()
        plot_ch_hbox.addLayout(plt_grid)
        plot_ch_hbox.addWidget(self._ch_list)

        main_vbox = QVBoxLayout()
        main_vbox.addLayout(button_hbox)
        main_vbox.addLayout(slider_hbox)
        main_vbox.addLayout(plot_ch_hbox)
        main_vbox.addLayout(bottom_hbox)

        central_widget = QWidget()
        central_widget.setLayout(main_vbox)
        self.setCentralWidget(central_widget)

        # ready for user
        self._move_cursors_to_pos()
        self._ch_list.setFocus()  # always focus on list

    def _load_image_data(self, ct):
        """Get MRI and CT data to display and transforms to/from vox/RAS."""
        # allows recon-all not to be finished (T1 made in a few minutes)
        mri_img = 'brain' if op.isfile(
            op.join(self._subject_dir, 'mri', 'brain.mgz')) else 'T1'
        self._mri_data, self._vox_ras_t = _load_image(op.join(
            self._subject_dir, 'mri', f'{mri_img}.mgz'),
                                                      'MRI Image',
                                                      verbose=self._verbose)
        self._ras_vox_t = np.linalg.inv(self._vox_ras_t)

        self._voxel_sizes = np.array(self._mri_data.shape)
        # We need our extents to land the centers of each pixel on the voxel
        # number. This code assumes 1mm isotropic...
        img_delta = 0.5
        self._img_extents = list([
            -img_delta, self._voxel_sizes[idx[0]] -
            img_delta, -img_delta, self._voxel_sizes[idx[1]] - img_delta
        ] for idx in self._xy_idx)
        ch_deltas = list(img_delta * (self._voxel_sizes[ii] / _CH_PLOT_SIZE)
                         for ii in range(3))
        self._ch_extents = list([
            -ch_delta, self._voxel_sizes[idx[0]] -
            ch_delta, -ch_delta, self._voxel_sizes[idx[1]] - ch_delta
        ] for idx, ch_delta in zip(self._xy_idx, ch_deltas))

        # ready ct
        self._ct_data, vox_ras_t = _load_image(ct, 'CT', verbose=self._verbose)
        if self._mri_data.shape != self._ct_data.shape or \
                not np.allclose(self._vox_ras_t, vox_ras_t, rtol=1e-6):
            raise ValueError('CT is not aligned to MRI, got '
                             f'CT shape={self._ct_data.shape}, '
                             f'MRI shape={self._mri_data.shape}, '
                             f'CT affine={vox_ras_t} and '
                             f'MRI affine={self._vox_ras_t}')
        self._ct_maxima = None  # don't compute until turned on

        if op.exists(op.join(self._subject_dir, 'surf', 'lh.seghead')):
            self._head = _read_mri_surface(
                op.join(self._subject_dir, 'surf', 'lh.seghead'))
            assert _frame_to_str[self._head['coord_frame']] == 'mri'
        else:
            warn('`seghead` not found, using marching cubes on CT for '
                 'head plot, use :ref:`mne.bem.make_scalp_surfaces` '
                 'to add the scalp surface instead of skull from the CT')
            self._head = None
        if op.exists(op.join(self._subject_dir, 'surf', 'lh.pial')):
            self._lh = _read_mri_surface(
                op.join(self._subject_dir, 'surf', 'lh.pial'))
            assert _frame_to_str[self._lh['coord_frame']] == 'mri'
            self._rh = _read_mri_surface(
                op.join(self._subject_dir, 'surf', 'rh.pial'))
            assert _frame_to_str[self._rh['coord_frame']] == 'mri'
        else:
            warn('`pial` surface not found, skipping adding to 3D '
                 'plot. This indicates the Freesurfer recon-all '
                 'has not finished or has been modified and '
                 'these files have been deleted.')
            self._lh = self._rh = None

    def _make_ch_image(self, axis, proj=False):
        """Make a plot to display the channel locations."""
        # Make channel data higher resolution so it looks better.
        ch_image = np.zeros((_CH_PLOT_SIZE, _CH_PLOT_SIZE)) * np.nan
        vxyz = self._voxel_sizes

        def color_ch_radius(ch_image, xf, yf, group, radius):
            # Take the fraction across each dimension of the RAS
            # coordinates converted to xyz and put a circle in that
            # position in this larger resolution image
            ex, ey = np.round(np.array([xf, yf]) * _CH_PLOT_SIZE).astype(int)
            ii = np.arange(-radius, radius + 1)
            ii_sq = ii * ii
            idx = np.where(ii_sq + ii_sq[:, np.newaxis] < radius * radius)
            # negative y because y axis is inverted
            ch_image[-(ey + ii[idx[1]]), ex + ii[idx[0]]] = group
            return ch_image

        for name, ras in self._chs.items():
            # move from middle-centered (half coords positive, half negative)
            # to bottom-left corner centered (all coords positive).
            if np.isnan(ras).any():
                continue
            xyz = apply_trans(self._ras_vox_t, ras)
            # check if closest to that voxel
            dist = np.linalg.norm(xyz - self._current_slice)
            if proj or dist < self._radius:
                group = self._groups[name]
                r = self._radius if proj else \
                    self._radius - np.round(abs(dist)).astype(int)
                xf, yf = (xyz / vxyz)[list(self._xy_idx[axis])]
                ch_image = color_ch_radius(ch_image, xf, yf, group, r)
        return ch_image

    @verbose
    def _save_ch_coords(self, info=None, verbose=None):
        """Save the location of the electrode contacts."""
        logger.info('Saving channel positions to `info`')
        if info is None:
            info = self._info
        for name, ch in zip(info.ch_names, info['chs']):
            ch['loc'][:3] = apply_trans(self._mri_head_t,
                                        self._chs[name] / 1000)  # mm->m

    def _plot_images(self):
        """Use the MRI and CT to make plots."""
        # Plot sagittal (0), coronal (1) or axial (2) view
        self._images = dict(ct=list(),
                            chs=list(),
                            ct_bounds=list(),
                            cursor_v=list(),
                            cursor_h=list())
        ct_min, ct_max = np.nanmin(self._ct_data), np.nanmax(self._ct_data)
        text_kwargs = dict(fontsize='medium',
                           weight='bold',
                           color='#66CCEE',
                           family='monospace',
                           ha='center',
                           va='center',
                           path_effects=[
                               patheffects.withStroke(linewidth=4,
                                                      foreground="k",
                                                      alpha=0.75)
                           ])
        xyz = apply_trans(self._ras_vox_t, self._ras)
        for axis in range(3):
            plot_x_idx, plot_y_idx = self._xy_idx[axis]
            fig = self._figs[axis]
            ax = fig.axes[0]
            ct_data = np.take(self._ct_data,
                              self._current_slice[axis],
                              axis=axis).T
            self._images['ct'].append(
                ax.imshow(ct_data,
                          cmap='gray',
                          aspect='auto',
                          zorder=1,
                          vmin=ct_min,
                          vmax=ct_max))
            img_extent = self._img_extents[axis]  # x0, x1, y0, y1
            w, h = np.diff(np.array(img_extent).reshape(2, 2), axis=1)[:, 0]
            self._images['ct_bounds'].append(
                Rectangle(img_extent[::2],
                          w,
                          h,
                          edgecolor='w',
                          facecolor='none',
                          alpha=0.25,
                          lw=0.5,
                          zorder=1.5))
            ax.add_patch(self._images['ct_bounds'][-1])
            self._images['chs'].append(
                ax.imshow(self._make_ch_image(axis),
                          aspect='auto',
                          extent=self._ch_extents[axis],
                          zorder=3,
                          cmap=_CMAP,
                          alpha=self._ch_alpha,
                          vmin=0,
                          vmax=_N_COLORS))
            v_x = (xyz[plot_x_idx], ) * 2
            v_y = img_extent[2:4]
            self._images['cursor_v'].append(
                ax.plot(v_x,
                        v_y,
                        color='lime',
                        linewidth=0.5,
                        alpha=0.5,
                        zorder=8)[0])
            h_y = (xyz[plot_y_idx], ) * 2
            h_x = img_extent[0:2]
            self._images['cursor_h'].append(
                ax.plot(h_x,
                        h_y,
                        color='lime',
                        linewidth=0.5,
                        alpha=0.5,
                        zorder=8)[0])
            # label axes
            self._figs[axis].text(0.5, 0.05, _IMG_LABELS[axis][0],
                                  **text_kwargs)
            self._figs[axis].text(0.05, 0.5, _IMG_LABELS[axis][1],
                                  **text_kwargs)
            self._figs[axis].axes[0].axis(img_extent)
            self._figs[axis].canvas.mpl_connect('scroll_event',
                                                self._on_scroll)
            self._figs[axis].canvas.mpl_connect(
                'button_release_event', partial(self._on_click, axis=axis))
        # add head and brain in mm (convert from m)
        if self._head is None:
            logger.info('Using marching cubes on CT for the '
                        '3D visualization panel')
            rr, tris = _marching_cubes(
                np.where(self._ct_data < np.quantile(self._ct_data, 0.95), 0,
                         1), [1])[0]
            rr = apply_trans(self._vox_ras_t, rr)
            self._renderer.mesh(*rr.T,
                                triangles=tris,
                                color='gray',
                                opacity=0.2,
                                reset_camera=False,
                                render=False)
        else:
            self._renderer.mesh(*self._head['rr'].T * 1000,
                                triangles=self._head['tris'],
                                color='gray',
                                opacity=0.2,
                                reset_camera=False,
                                render=False)
        if self._lh is not None and self._rh is not None:
            self._renderer.mesh(*self._lh['rr'].T * 1000,
                                triangles=self._lh['tris'],
                                color='white',
                                opacity=0.2,
                                reset_camera=False,
                                render=False)
            self._renderer.mesh(*self._rh['rr'].T * 1000,
                                triangles=self._rh['tris'],
                                color='white',
                                opacity=0.2,
                                reset_camera=False,
                                render=False)
        self._3d_chs = dict()
        for name in self._chs:
            self._plot_3d_ch(name)
        self._renderer.set_camera(azimuth=90,
                                  elevation=90,
                                  distance=300,
                                  focalpoint=tuple(self._ras))
        # update plots
        self._draw()
        self._renderer._update()

    def _update_camera(self, render=False):
        """Update the camera position."""
        self._renderer.set_camera(
            # needs fix, distance moves when focal point updates
            distance=self._renderer.plotter.camera.distance * 0.9,
            focalpoint=tuple(self._ras),
            reset_camera=False)

    def _plot_3d_ch(self, name, render=False):
        """Plot a single 3D channel."""
        if name in self._3d_chs:
            self._renderer.plotter.remove_actor(self._3d_chs.pop(name))
        if not any(np.isnan(self._chs[name])):
            self._3d_chs[name] = self._renderer.sphere(
                tuple(self._chs[name]),
                scale=1,
                color=_CMAP(self._groups[name])[:3],
                opacity=self._ch_alpha)[0]
            # The actor scale is managed differently than the glyph scale
            # in order not to recreate objects, we use the actor scale
            self._3d_chs[name].SetOrigin(self._chs[name])
            self._3d_chs[name].SetScale(self._radius * _RADIUS_SCALAR)
        if render:
            self._renderer._update()

    def _get_button_bar(self):
        """Make a bar with buttons for user interactions."""
        hbox = QHBoxLayout()

        help_button = QPushButton('Help')
        help_button.released.connect(self._show_help)
        hbox.addWidget(help_button)

        hbox.addStretch(8)

        hbox.addWidget(QLabel('Snap to Center'))
        self._snap_button = QPushButton('Off')
        self._snap_button.setMaximumWidth(25)  # not too big
        hbox.addWidget(self._snap_button)
        self._snap_button.released.connect(self._toggle_snap)
        self._toggle_snap()  # turn on to start

        hbox.addStretch(1)

        self._toggle_brain_button = QPushButton('Show Brain')
        self._toggle_brain_button.released.connect(self._toggle_show_brain)
        hbox.addWidget(self._toggle_brain_button)

        hbox.addStretch(1)

        mark_button = QPushButton('Mark')
        hbox.addWidget(mark_button)
        mark_button.released.connect(self._mark_ch)

        remove_button = QPushButton('Remove')
        hbox.addWidget(remove_button)
        remove_button.released.connect(self._remove_ch)

        self._group_selector = ComboBox()
        group_model = self._group_selector.model()

        for i in range(_N_COLORS):
            self._group_selector.addItem(' ')
            color = QtGui.QColor()
            color.setRgb(*(255 * np.array(_CMAP(i))).round().astype(int))
            brush = QtGui.QBrush(color)
            brush.setStyle(QtCore.Qt.SolidPattern)
            group_model.setData(group_model.index(i, 0), brush,
                                QtCore.Qt.BackgroundRole)
        self._group_selector.clicked.connect(self._select_group)
        self._group_selector.currentIndexChanged.connect(self._select_group)
        hbox.addWidget(self._group_selector)

        # update background color for current selection
        self._update_group()

        return hbox

    def _get_slider_bar(self):
        """Make a bar with sliders on it."""
        def make_label(name):
            label = QLabel(name)
            label.setAlignment(QtCore.Qt.AlignCenter)
            return label

        def make_slider(smin, smax, sval, sfun=None):
            slider = QSlider(QtCore.Qt.Horizontal)
            slider.setMinimum(int(round(smin)))
            slider.setMaximum(int(round(smax)))
            slider.setValue(int(round(sval)))
            slider.setTracking(False)  # only update on release
            if sfun is not None:
                slider.valueChanged.connect(sfun)
            slider.keyPressEvent = self._key_press_event
            return slider

        slider_hbox = QHBoxLayout()

        ch_vbox = QVBoxLayout()
        ch_vbox.addWidget(make_label('ch alpha'))
        ch_vbox.addWidget(make_label('ch radius'))
        slider_hbox.addLayout(ch_vbox)

        ch_slider_vbox = QVBoxLayout()
        self._alpha_slider = make_slider(0, 100, self._ch_alpha * 100,
                                         self._update_ch_alpha)
        ch_plot_max = _CH_PLOT_SIZE // 50  # max 1 / 50 of plot size
        ch_slider_vbox.addWidget(self._alpha_slider)
        self._radius_slider = make_slider(0, ch_plot_max, self._radius,
                                          self._update_radius)
        ch_slider_vbox.addWidget(self._radius_slider)
        slider_hbox.addLayout(ch_slider_vbox)

        ct_vbox = QVBoxLayout()
        ct_vbox.addWidget(make_label('CT min'))
        ct_vbox.addWidget(make_label('CT max'))
        slider_hbox.addLayout(ct_vbox)

        ct_slider_vbox = QVBoxLayout()
        ct_min = int(round(np.nanmin(self._ct_data)))
        ct_max = int(round(np.nanmax(self._ct_data)))
        self._ct_min_slider = make_slider(ct_min, ct_max, ct_min,
                                          self._update_ct_scale)
        ct_slider_vbox.addWidget(self._ct_min_slider)
        self._ct_max_slider = make_slider(ct_min, ct_max, ct_max,
                                          self._update_ct_scale)
        ct_slider_vbox.addWidget(self._ct_max_slider)
        slider_hbox.addLayout(ct_slider_vbox)
        return slider_hbox

    def _get_bottom_bar(self):
        """Make a bar at the bottom with information in it."""
        hbox = QHBoxLayout()

        hbox.addStretch(3)

        self._toggle_show_mip_button = QPushButton('Show Max Intensity Proj')
        self._toggle_show_mip_button.released.connect(self._toggle_show_mip)
        hbox.addWidget(self._toggle_show_mip_button)

        self._toggle_show_max_button = QPushButton('Show Maxima')
        self._toggle_show_max_button.released.connect(self._toggle_show_max)
        hbox.addWidget(self._toggle_show_max_button)

        self._intensity_label = QLabel('')  # update later
        hbox.addWidget(self._intensity_label)

        VOX_label = QLabel('VOX =')
        self._VOX_textbox = QPlainTextEdit('')  # update later
        self._VOX_textbox.setMaximumHeight(25)
        self._VOX_textbox.setMaximumWidth(125)
        self._VOX_textbox.focusOutEvent = self._update_VOX
        self._VOX_textbox.textChanged.connect(self._check_update_VOX)
        hbox.addWidget(VOX_label)
        hbox.addWidget(self._VOX_textbox)

        RAS_label = QLabel('RAS =')
        self._RAS_textbox = QPlainTextEdit('')  # update later
        self._RAS_textbox.setMaximumHeight(25)
        self._RAS_textbox.setMaximumWidth(200)
        self._RAS_textbox.focusOutEvent = self._update_RAS
        self._RAS_textbox.textChanged.connect(self._check_update_RAS)
        hbox.addWidget(RAS_label)
        hbox.addWidget(self._RAS_textbox)
        self._update_moved()  # update text now
        return hbox

    def _group_channels(self, groups):
        """Automatically find a group based on the name of the channel."""
        if groups is not None:
            for name in self._ch_names:
                if name not in groups:
                    raise ValueError(f'{name} not found in ``groups``')
                _validate_type(groups[name], (float, int), f'groups[{name}]')
            self.groups = groups
        else:
            i = 0
            self._groups = dict()
            base_names = dict()
            for name in self._ch_names:
                # strip all numbers from the name
                base_name = ''.join([
                    letter for letter in name
                    if not letter.isdigit() and letter != ' '
                ])
                if base_name in base_names:
                    # look up group number by base name
                    self._groups[name] = base_names[base_name]
                else:
                    self._groups[name] = i
                    base_names[base_name] = i
                    i += 1

    def _update_lines(self, group, only_2D=False):
        """Draw lines that connect the points in a group."""
        if group in self._lines_2D:  # remove existing 2D lines first
            for line in self._lines_2D[group]:
                line.remove()
            self._lines_2D.pop(group)
        if only_2D:  # if not in projection, don't add 2D lines
            if self._toggle_show_mip_button.text() == \
                    'Show Max Intensity Proj':
                return
        elif group in self._lines:  # if updating 3D, remove first
            self._renderer.plotter.remove_actor(self._lines[group])
        pos = np.array([
            self._chs[ch] for i, ch in enumerate(self._ch_names)
            if self._groups[ch] == group and i in self._seeg_idx
            and not np.isnan(self._chs[ch]).any()
        ])
        if len(pos) < 2:  # not enough points for line
            return
        # first, the insertion will be the point farthest from the origin
        # brains are a longer posterior-anterior, scale for this (80%)
        insert_idx = np.argmax(
            np.linalg.norm(pos * np.array([1, 0.8, 1]), axis=1))
        # second, find the farthest point from the insertion
        target_idx = np.argmax(np.linalg.norm(pos[insert_idx] - pos, axis=1))
        # third, make a unit vector and to add to the insertion for the bolt
        elec_v = pos[insert_idx] - pos[target_idx]
        elec_v /= np.linalg.norm(elec_v)
        if not only_2D:
            self._lines[group] = self._renderer.tube(
                [pos[target_idx]], [pos[insert_idx] + elec_v * _BOLT_SCALAR],
                radius=self._radius * _TUBE_SCALAR,
                color=_CMAP(group)[:3])[0]
        if self._toggle_show_mip_button.text() == 'Hide Max Intensity Proj':
            # add 2D lines on each slice plot if in max intensity projection
            target_vox = apply_trans(self._ras_vox_t, pos[target_idx])
            insert_vox = apply_trans(self._ras_vox_t,
                                     pos[insert_idx] + elec_v * _BOLT_SCALAR)
            lines_2D = list()
            for axis in range(3):
                x, y = self._xy_idx[axis]
                lines_2D.append(self._figs[axis].axes[0].plot(
                    [target_vox[x], insert_vox[x]],
                    [target_vox[y], insert_vox[y]],
                    color=_CMAP(group),
                    linewidth=0.25,
                    zorder=7)[0])
            self._lines_2D[group] = lines_2D

    def _set_ch_names(self):
        """Add the channel names to the selector."""
        self._ch_list_model = QtGui.QStandardItemModel(self._ch_list)
        for name in self._ch_names:
            self._ch_list_model.appendRow(QtGui.QStandardItem(name))
            self._color_list_item(name=name)
        self._ch_list.setModel(self._ch_list_model)
        self._ch_list.clicked.connect(self._go_to_ch)
        self._ch_list.setCurrentIndex(
            self._ch_list_model.index(self._ch_index, 0))
        self._ch_list.keyPressEvent = self._key_press_event

    def _select_group(self):
        """Change the group label to the selection."""
        group = self._group_selector.currentIndex()
        self._groups[self._ch_names[self._ch_index]] = group
        # color differently if found already
        self._color_list_item(self._ch_names[self._ch_index])
        self._update_group()

    def _update_group(self):
        """Set background for closed group menu."""
        group = self._group_selector.currentIndex()
        rgb = (255 * np.array(_CMAP(group))).round().astype(int)
        self._group_selector.setStyleSheet(
            'background-color: rgb({:d},{:d},{:d})'.format(*rgb))
        self._group_selector.update()

    def _on_scroll(self, event):
        """Process mouse scroll wheel event to zoom."""
        self._zoom(event.step, draw=True)

    def _zoom(self, sign=1, draw=False):
        """Zoom in on the image."""
        delta = _ZOOM_STEP_SIZE * sign
        for axis, fig in enumerate(self._figs):
            xmid = self._images['cursor_v'][axis].get_xdata()[0]
            ymid = self._images['cursor_h'][axis].get_ydata()[0]
            xmin, xmax = fig.axes[0].get_xlim()
            ymin, ymax = fig.axes[0].get_ylim()
            xwidth = (xmax - xmin) / 2 - delta
            ywidth = (ymax - ymin) / 2 - delta
            if xwidth <= 0 or ywidth <= 0:
                return
            fig.axes[0].set_xlim(xmid - xwidth, xmid + xwidth)
            fig.axes[0].set_ylim(ymid - ywidth, ymid + ywidth)
            if draw:
                self._figs[axis].canvas.draw()

    def _update_ch_selection(self):
        """Update which channel is selected."""
        name = self._ch_names[self._ch_index]
        self._ch_list.setCurrentIndex(
            self._ch_list_model.index(self._ch_index, 0))
        self._group_selector.setCurrentIndex(self._groups[name])
        self._update_group()
        if not np.isnan(self._chs[name]).any():
            self._set_ras(self._chs[name])
            self._update_camera(render=True)
            self._draw()

    def _go_to_ch(self, index):
        """Change current channel to the item selected."""
        self._ch_index = index.row()
        self._update_ch_selection()

    @pyqtSlot()
    def _next_ch(self):
        """Increment the current channel selection index."""
        self._ch_index = (self._ch_index + 1) % len(self._ch_names)
        self._update_ch_selection()

    @pyqtSlot()
    def _update_RAS(self, event):
        """Interpret user input to the RAS textbox."""
        text = self._RAS_textbox.toPlainText()
        ras = self._convert_text(text, 'ras')
        if ras is not None:
            self._set_ras(ras)

    @pyqtSlot()
    def _update_VOX(self, event):
        """Interpret user input to the RAS textbox."""
        text = self._VOX_textbox.toPlainText()
        ras = self._convert_text(text, 'vox')
        if ras is not None:
            self._set_ras(ras)

    def _convert_text(self, text, text_kind):
        text = text.replace('\n', '')
        vals = text.split(',')
        if len(vals) != 3:
            vals = text.split(' ')  # spaces also okay as in freesurfer
        vals = [var.lstrip().rstrip() for var in vals]
        try:
            vals = np.array([float(var) for var in vals]).reshape(3)
        except Exception:
            self._update_moved()  # resets RAS label
            return
        if text_kind == 'vox':
            vox = vals
            ras = apply_trans(self._vox_ras_t, vox)
        else:
            assert text_kind == 'ras'
            ras = vals
            vox = apply_trans(self._ras_vox_t, ras)
        wrong_size = any(var < 0 or var > n - 1
                         for var, n in zip(vox, self._voxel_sizes))
        if wrong_size:
            self._update_moved()  # resets RAS label
            return
        return ras

    @property
    def _ras(self):
        return self._ras_safe

    def _set_ras(self, ras, update_plots=True):
        ras = np.asarray(ras, dtype=float)
        assert ras.shape == (3, )
        msg = ', '.join(f'{x:0.2f}' for x in ras)
        logger.debug(f'Trying RAS:  ({msg}) mm')
        # clip to valid
        vox = apply_trans(self._ras_vox_t, ras)
        vox = np.array([
            np.clip(d, 0, self._voxel_sizes[ii] - 1)
            for ii, d in enumerate(vox)
        ])
        # transform back, make write-only
        self._ras_safe = apply_trans(self._vox_ras_t, vox)
        self._ras_safe.flags['WRITEABLE'] = False
        msg = ', '.join(f'{x:0.2f}' for x in self._ras_safe)
        logger.debug(f'Setting RAS: ({msg}) mm')
        if update_plots:
            self._move_cursors_to_pos()

    @property
    def _vox(self):
        return apply_trans(self._ras_vox_t, self._ras)

    @property
    def _current_slice(self):
        return self._vox.round().astype(int)

    @pyqtSlot()
    def _check_update_RAS(self):
        """Check whether the RAS textbox is done being edited."""
        if '\n' in self._RAS_textbox.toPlainText():
            self._update_RAS(event=None)
            self._ch_list.setFocus()  # remove focus from text edit

    @pyqtSlot()
    def _check_update_VOX(self):
        """Check whether the VOX textbox is done being edited."""
        if '\n' in self._VOX_textbox.toPlainText():
            self._update_VOX(event=None)
            self._ch_list.setFocus()  # remove focus from text edit

    def _color_list_item(self, name=None):
        """Color the item in the view list for easy id of marked channels."""
        name = self._ch_names[self._ch_index] if name is None else name
        color = QtGui.QColor('white')
        if not np.isnan(self._chs[name]).any():
            group = self._groups[name]
            color.setRgb(*[int(c * 255) for c in _CMAP(group)])
        brush = QtGui.QBrush(color)
        brush.setStyle(QtCore.Qt.SolidPattern)
        self._ch_list_model.setData(
            self._ch_list_model.index(self._ch_names.index(name), 0), brush,
            QtCore.Qt.BackgroundRole)
        # color text black
        color = QtGui.QColor('black')
        brush = QtGui.QBrush(color)
        brush.setStyle(QtCore.Qt.SolidPattern)
        self._ch_list_model.setData(
            self._ch_list_model.index(self._ch_names.index(name), 0), brush,
            QtCore.Qt.ForegroundRole)

    @pyqtSlot()
    def _toggle_snap(self):
        """Toggle snapping the contact location to the center of mass."""
        if self._snap_button.text() == 'Off':
            self._snap_button.setText('On')
            self._snap_button.setStyleSheet("background-color: green")
        else:  # text == 'On', turn off
            self._snap_button.setText('Off')
            self._snap_button.setStyleSheet("background-color: red")

    @pyqtSlot()
    def _mark_ch(self):
        """Mark the current channel as being located at the crosshair."""
        name = self._ch_names[self._ch_index]
        if self._snap_button.text() == 'Off':
            self._chs[name][:] = self._ras
        else:
            shape = np.mean(self._mri_data.shape)  # Freesurfer shape (256)
            voxels_max = int(4 / 3 * np.pi *
                             (shape * self._radius / _CH_PLOT_SIZE)**3)
            neighbors = _voxel_neighbors(self._vox,
                                         self._ct_data,
                                         thresh=0.5,
                                         voxels_max=voxels_max,
                                         use_relative=True)
            self._chs[name][:] = apply_trans(  # to surface RAS
                self._vox_ras_t,
                np.array(list(neighbors)).mean(axis=0))
        self._color_list_item()
        self._update_lines(self._groups[name])
        self._update_ch_images(draw=True)
        self._plot_3d_ch(name, render=True)
        self._save_ch_coords()
        self._next_ch()
        self._ch_list.setFocus()

    @pyqtSlot()
    def _remove_ch(self):
        """Remove the location data for the current channel."""
        name = self._ch_names[self._ch_index]
        self._chs[name] *= np.nan
        self._color_list_item()
        self._save_ch_coords()
        self._update_lines(self._groups[name])
        self._update_ch_images(draw=True)
        self._plot_3d_ch(name, render=True)
        self._next_ch()
        self._ch_list.setFocus()

    def _draw(self, axis=None):
        """Update the figures with a draw call."""
        for axis in (range(3) if axis is None else [axis]):
            self._figs[axis].canvas.draw()

    def _update_ch_images(self, axis=None, draw=False):
        """Update the channel image(s)."""
        for axis in range(3) if axis is None else [axis]:
            self._images['chs'][axis].set_data(self._make_ch_image(axis))
            if self._toggle_show_mip_button.text() == \
                    'Hide Max Intensity Proj':
                self._images['mip_chs'][axis].set_data(
                    self._make_ch_image(axis, proj=True))
            if draw:
                self._draw(axis)

    def _update_ct_images(self, axis=None, draw=False):
        """Update the CT image(s)."""
        for axis in range(3) if axis is None else [axis]:
            ct_data = np.take(self._ct_data,
                              self._current_slice[axis],
                              axis=axis).T
            # Threshold the CT so only bright objects (electrodes) are visible
            ct_data[ct_data < self._ct_min_slider.value()] = np.nan
            ct_data[ct_data > self._ct_max_slider.value()] = np.nan
            self._images['ct'][axis].set_data(ct_data)
            if 'local_max' in self._images:
                ct_max_data = np.take(self._ct_maxima,
                                      self._current_slice[axis],
                                      axis=axis).T
                self._images['local_max'][axis].set_data(ct_max_data)
            if draw:
                self._draw(axis)

    def _update_mri_images(self, axis=None, draw=False):
        """Update the CT image(s)."""
        if 'mri' in self._images:
            for axis in range(3) if axis is None else [axis]:
                self._images['mri'][axis].set_data(
                    np.take(self._mri_data,
                            self._current_slice[axis],
                            axis=axis).T)
                if draw:
                    self._draw(axis)

    def _update_images(self, axis=None, draw=True):
        """Update CT and channel images when general changes happen."""
        self._update_ct_images(axis=axis)
        self._update_ch_images(axis=axis)
        self._update_mri_images(axis=axis)
        if draw:
            self._draw(axis)

    def _update_ct_scale(self):
        """Update CT min slider value."""
        new_min = self._ct_min_slider.value()
        new_max = self._ct_max_slider.value()
        # handle inversions
        self._ct_min_slider.setValue(min([new_min, new_max]))
        self._ct_max_slider.setValue(max([new_min, new_max]))
        self._update_ct_images(draw=True)

    def _update_radius(self):
        """Update channel plot radius."""
        self._radius = np.round(self._radius_slider.value()).astype(int)
        if self._toggle_show_max_button.text() == 'Hide Maxima':
            self._update_ct_maxima()
            self._update_ct_images()
        else:
            self._ct_maxima = None  # signals ct max is out-of-date
        self._update_ch_images(draw=True)
        for name, actor in self._3d_chs.items():
            if not np.isnan(self._chs[name]).any():
                actor.SetOrigin(self._chs[name])
                actor.SetScale(self._radius * _RADIUS_SCALAR)
        self._renderer._update()
        self._ch_list.setFocus()  # remove focus from 3d plotter

    def _update_ch_alpha(self):
        """Update channel plot alpha."""
        self._ch_alpha = self._alpha_slider.value() / 100
        for axis in range(3):
            self._images['chs'][axis].set_alpha(self._ch_alpha)
        self._draw()
        for actor in self._3d_chs.values():
            actor.GetProperty().SetOpacity(self._ch_alpha)
        self._renderer._update()
        self._ch_list.setFocus()  # remove focus from 3d plotter

    def _move_cursors_to_pos(self):
        """Move the cursors to a position."""
        for axis in range(3):
            x, y = self._vox[list(self._xy_idx[axis])]
            self._images['cursor_v'][axis].set_xdata([x, x])
            self._images['cursor_h'][axis].set_ydata([y, y])
        self._zoom(0)  # doesn't actually zoom just resets view to center
        self._update_images(draw=True)
        self._update_moved()

    def _show_help(self):
        """Show the help menu."""
        QMessageBox.information(
            self, 'Help', "Help:\n'm': mark channel location\n"
            "'r': remove channel location\n"
            "'b': toggle viewing of brain in T1\n"
            "'+'/'-': zoom\nleft/right arrow: left/right\n"
            "up/down arrow: superior/inferior\n"
            "left angle bracket/right angle bracket: anterior/posterior")

    def _update_ct_maxima(self):
        """Compute the maximum voxels based on the current radius."""
        self._ct_maxima = maximum_filter(self._ct_data,
                                         (self._radius, ) * 3) == self._ct_data
        self._ct_maxima[self._ct_data <= np.median(self._ct_data)] = \
            False
        self._ct_maxima = np.where(self._ct_maxima, 1, np.nan)  # transparent

    def _toggle_show_mip(self):
        """Toggle whether the maximum-intensity projection is shown."""
        if self._toggle_show_mip_button.text() == 'Show Max Intensity Proj':
            self._toggle_show_mip_button.setText('Hide Max Intensity Proj')
            self._images['mip'] = list()
            self._images['mip_chs'] = list()
            ct_min, ct_max = np.nanmin(self._ct_data), np.nanmax(self._ct_data)
            for axis in range(3):
                ct_mip_data = np.max(self._ct_data, axis=axis).T
                self._images['mip'].append(self._figs[axis].axes[0].imshow(
                    ct_mip_data,
                    cmap='gray',
                    aspect='auto',
                    vmin=ct_min,
                    vmax=ct_max,
                    zorder=5))
                # add circles for each channel
                xs, ys, colors = list(), list(), list()
                for name, ras in self._chs.items():
                    xyz = self._vox
                    xs.append(xyz[self._xy_idx[axis][0]])
                    ys.append(xyz[self._xy_idx[axis][1]])
                    colors.append(_CMAP(self._groups[name]))
                self._images['mip_chs'].append(self._figs[axis].axes[0].imshow(
                    self._make_ch_image(axis, proj=True),
                    aspect='auto',
                    extent=self._ch_extents[axis],
                    zorder=6,
                    cmap=_CMAP,
                    alpha=1,
                    vmin=0,
                    vmax=_N_COLORS))
            for group in set(self._groups.values()):
                self._update_lines(group, only_2D=True)
        else:
            for img in self._images['mip'] + self._images['mip_chs']:
                img.remove()
            self._images.pop('mip')
            self._images.pop('mip_chs')
            self._toggle_show_mip_button.setText('Show Max Intensity Proj')
            for group in set(self._groups.values()):  # remove lines
                self._update_lines(group, only_2D=True)
        self._draw()

    def _toggle_show_max(self):
        """Toggle whether to color local maxima differently."""
        if self._toggle_show_max_button.text() == 'Show Maxima':
            self._toggle_show_max_button.setText('Hide Maxima')
            # happens on initiation or if the radius is changed with it off
            if self._ct_maxima is None:  # otherwise don't recompute
                self._update_ct_maxima()
            self._images['local_max'] = list()
            for axis in range(3):
                ct_max_data = np.take(self._ct_maxima,
                                      self._current_slice[axis],
                                      axis=axis).T
                self._images['local_max'].append(
                    self._figs[axis].axes[0].imshow(ct_max_data,
                                                    cmap='autumn',
                                                    aspect='auto',
                                                    vmin=0,
                                                    vmax=1,
                                                    zorder=4))
        else:
            for img in self._images['local_max']:
                img.remove()
            self._images.pop('local_max')
            self._toggle_show_max_button.setText('Show Maxima')
        self._draw()

    def _toggle_show_brain(self):
        """Toggle whether the brain/MRI is being shown."""
        if 'mri' in self._images:
            for img in self._images['mri']:
                img.remove()
            self._images.pop('mri')
            self._toggle_brain_button.setText('Show Brain')
        else:
            self._images['mri'] = list()
            for axis in range(3):
                mri_data = np.take(self._mri_data,
                                   self._current_slice[axis],
                                   axis=axis).T
                self._images['mri'].append(self._figs[axis].axes[0].imshow(
                    mri_data, cmap='hot', aspect='auto', alpha=0.25, zorder=2))
            self._toggle_brain_button.setText('Hide Brain')
        self._draw()

    def _key_press_event(self, event):
        """Execute functions when the user presses a key."""
        if event.key() == 'escape':
            self.close()

        if event.text() == 'h':
            self._show_help()

        if event.text() == 'm':
            self._mark_ch()

        if event.text() == 'r':
            self._remove_ch()

        if event.text() == 'b':
            self._toggle_show_brain()

        if event.text() in ('=', '+', '-'):
            self._zoom(sign=-2 * (event.text() == '-') + 1, draw=True)

        # Changing slices
        if event.key() in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down,
                           QtCore.Qt.Key_Left, QtCore.Qt.Key_Right,
                           QtCore.Qt.Key_Comma, QtCore.Qt.Key_Period,
                           QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown):
            ras = np.array(self._ras)
            if event.key() in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down):
                ras[2] += 2 * (event.key() == QtCore.Qt.Key_Up) - 1
            elif event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Right):
                ras[0] += 2 * (event.key() == QtCore.Qt.Key_Right) - 1
            else:
                ras[1] += 2 * (event.key() == QtCore.Qt.Key_PageUp
                               or event.key() == QtCore.Qt.Key_Period) - 1
            self._set_ras(ras)

    def _on_click(self, event, axis):
        """Move to view on MRI and CT on click."""
        if event.inaxes is self._figs[axis].axes[0]:
            # Data coordinates are voxel coordinates
            pos = (event.xdata, event.ydata)
            logger.info(f'Clicked {"XYZ"[axis]} ({axis}) axis at pos {pos}')
            xyz = self._vox
            xyz[list(self._xy_idx[axis])] = pos
            logger.debug(f'Using voxel  {list(xyz)}')
            ras = apply_trans(self._vox_ras_t, xyz)
            self._set_ras(ras)

    def _update_moved(self):
        """Update when cursor position changes."""
        self._RAS_textbox.setPlainText(
            '{:.2f}, {:.2f}, {:.2f}'.format(*self._ras))
        self._VOX_textbox.setPlainText(
            '{:3d}, {:3d}, {:3d}'.format(*self._current_slice))
        self._intensity_label.setText('intensity = {:.2f}'.format(
            self._ct_data[tuple(self._current_slice)]))

    @safe_event
    def closeEvent(self, event):
        """Clean up upon closing the window."""
        self._renderer.plotter.close()
        self.close()
class SystemLog:
    def __init__(self, display_name, source_name):
        self.display_name   = display_name
        self.source_name    = source_name # FIXME: need to handle rotated logs
        self.last_filename  = os.path.join(get_home_path(), display_name)
        self.content        = ''
        self.edit           = QPlainTextEdit()
        self.normal_font    = self.edit.font()
        self.monospace_font = QFont('monospace')

        self.edit.setUndoRedoEnabled(False)
        self.edit.setReadOnly(True)
        self.edit.setWordWrapMode(QTextOption.NoWrap)
        self.edit.setPlainText('Click "Refresh" to download {0}.'.format(display_name))

        self.monospace_font.setStyleHint(QFont.TypeWriter)

    def log(self, message, bold=False, pre=False):
        if bold:
            self.edit.appendHtml('<b>{0}</b>'.format(html.escape(message)))
        elif pre:
            self.edit.appendHtml('<pre>{0}</pre>'.format(message))
        else:
            self.edit.appendPlainText(message)

    def reset(self):
        self.content = None

        self.edit.setPlainText('')
        self.edit.setFont(self.normal_font)

    def set_content(self, content):
        self.content = content

        self.edit.setPlainText('')
        self.edit.setFont(self.monospace_font)
        self.edit.setPlainText(content)
Ejemplo n.º 58
0
class PushDownAutomaton(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Creating an Automaton class instance
        self.Automaton = Automaton()
        # Creating a Input_String class instance
        self.Strings = Input_Strings()
        # Creating a Configuration_Setting instance
        self.Config_Setting = Configuration_Settings()
        # A attribute to remember the def_path
        self.def_path = ''
        # A attribute to remember if the automaton was opened
        self.automaton_open = False

        self.setWindowTitle("Pushdown Automaton")
        self.resize(640, 480)

        self.mainMenu = self.menuBar()

        self.fileMenu = self.mainMenu.addMenu("File")
        self.fileMenu.addAction("Open Automaton     Ctrl+O",
                                self.open_automaton_action)
        self.openShorcut = QShortcut(QKeySequence("Ctrl+O"), self)
        self.openShorcut.activated.connect(self.open_automaton_action)
        #self.fileMenu.addAction("View Automaton", self.view_automaton_action)
        self.fileMenu.addAction("Quit                            Ctrl+Shift+Q",
                                self.quit_action)
        self.quitAppShorcut = QShortcut(QKeySequence("Ctrl+Shift+Q"), self)
        self.quitAppShorcut.activated.connect(self.quit_action)

        self.helpMenu = self.mainMenu.addMenu("Help")
        self.helpMenu.addAction("User Manual        Ctrl+H",
                                self.user_manual_action)
        self.userManualShorcut = QShortcut(QKeySequence("Ctrl+H"), self)
        self.userManualShorcut.activated.connect(self.user_manual_action)

        self.inputStringLabel = QLabel(self)
        self.inputStringLabel.setGeometry(20, 40, 111, 16)
        self.inputStringLabel.setText("Input String")

        self.inputStringLineEdit = QLineEdit(self)
        self.inputStringLineEdit.setGeometry(20, 60, 231, 20)

        self.addToListPushButton = QPushButton(self)
        self.addToListPushButton.setGeometry(80, 90, 111, 23)
        self.addToListPushButton.setText("Add to List")
        self.addToListPushButton.clicked.connect(self.add_to_list_clicked)
        self.addToListShorcut = QShortcut(QKeySequence("Ctrl+Shift+A"), self)
        self.addToListShorcut.activated.connect(self.add_to_list_clicked)
        self.addToListPushButton.setToolTip("Ctrl+Shift+A")

        self.inputStringListLabel = QLabel(self)
        self.inputStringListLabel.setGeometry(20, 125, 111, 16)
        self.inputStringListLabel.setText("Input String List")

        self.inputStringListWidget = QListWidget(self)
        self.inputStringListWidget.setGeometry(20, 145, 231, 260)

        self.runStringPushButton = QPushButton(self)
        self.runStringPushButton.setGeometry(80, 415, 111, 23)
        self.runStringPushButton.setText("Run String")
        self.runStringPushButton.clicked.connect(self.run_string_clicked)
        self.runStringShorcut = QShortcut(QKeySequence("Ctrl+R"), self)
        self.runStringShorcut.activated.connect(self.run_string_clicked)
        self.runStringPushButton.setToolTip("Ctrl+R")

        self.fileNameLabel = QLabel(self)
        self.fileNameLabel.setGeometry(440, 40, 160, 16)
        self.fileNameLabel.setText("Automaton Title")
        self.fileNameLabel.setStyleSheet("color: blue")

        self.outputLabel = QLabel(self)
        self.outputLabel.setGeometry(300, 60, 47, 16)
        self.outputLabel.setText("Output")

        self.maxTransitionsLabel = QLabel(self)
        self.maxTransitionsLabel.setGeometry(370, 60, 80, 16)
        self.maxTransitionsLabel.setText("Max. Transitions")

        self.maxTransitionsSpinBox = QSpinBox(self)
        self.maxTransitionsSpinBox.setGeometry(455, 57, 42, 20)
        self.maxTransitionsSpinBox.setMinimum(1)
        #access value with self.maxTransitionsSpinBox.value

        self.displayPathsCheckBox = QCheckBox(self)
        self.displayPathsCheckBox.setGeometry(530, 60, 101, 17)
        self.displayPathsCheckBox.setText("Display Paths")
        #access true or false with self.displayPathsCheckBox.checked

        self.outputPlainTextEdit = QPlainTextEdit(self)
        self.outputPlainTextEdit.setGeometry(300, 80, 271,
                                             253)  #300, 80, 281, 283

        self.stackPlainTextEdit = QPlainTextEdit(self)
        self.stackPlainTextEdit.setGeometry(581, 80, 30, 253)

        self.pathLabel = QLabel(self)
        self.pathLabel.setGeometry(300, 335, 47, 16)
        self.pathLabel.setText("Path")

        self.pathPlainTextEdit = QPlainTextEdit(self)
        self.pathPlainTextEdit.setGeometry(300, 355, 311, 50)

        self.quitRunningStringPushButton = QPushButton(self)
        self.quitRunningStringPushButton.setGeometry(335, 415, 111, 23)
        self.quitRunningStringPushButton.setText("Quit Running String")
        self.quitRunningStringPushButton.clicked.connect(
            self.quit_running_string_clicked)
        self.quitRunningStringShorcut = QShortcut(QKeySequence("Ctrl+Q"), self)
        self.quitRunningStringShorcut.activated.connect(
            self.quit_running_string_clicked)
        self.quitRunningStringPushButton.setToolTip("Ctrl+Q")

        self.closeAutomatonPushButton = QPushButton(self)
        self.closeAutomatonPushButton.setGeometry(465, 415, 111, 23)
        self.closeAutomatonPushButton.setText("Close Automaton")
        self.closeAutomatonPushButton.clicked.connect(
            self.close_automaton_clicked)
        self.closeAutomatonShorcut = QShortcut(QKeySequence("Ctrl+Alt+C"),
                                               self)
        self.closeAutomatonShorcut.activated.connect(
            self.close_automaton_clicked)
        self.closeAutomatonPushButton.setToolTip("Ctrl+Alt+C")

        # Style for status label text
        self.styleError = 'font: 15pt Arial; color: maroon'
        self.styleNormal = 'font:15pt Arial; color: green'

        self.statusBar = self.statusBar()
        self.statusLabel = QLabel(
            "application status messages will go here (when something completes, etc.)"
        )
        self.statusLabel.setStyleSheet(self.styleNormal)
        self.statusBar.addPermanentWidget(self.statusLabel)

        self.show()

    def parseConfigFile(self, file_path):
        # Load the config settings
        self.Config_Setting.load(file_path)
        # Set the value parsed from the config file to the spinbox
        self.maxTransitionsSpinBox.setValue(
            int(self.Config_Setting.max_trans[0]))
        return

    def parseInputStringFile(self, file_path):
        # If the input string widget is empty add the input strings to the widget
        if self.inputStringListWidget.count() == 0:
            # Loading the string into the Strings attribute input_strings
            self.Strings.load(file_path)
            for string in self.Strings.input_strings:
                # If the string is valid
                if self.Strings.validate(self.Automaton.Input_Alpha.alphabet,
                                         string) == True:
                    # Add the string to the widget
                    self.inputStringListWidget.addItem(string)
        return

    # A method to update the input string widget
    def update_input_string_widget(self):
        self.inputStringListWidget.clear()
        for string in self.Strings.input_strings:
            self.inputStringListWidget.addItem(string)

    def quit_action(self):
        sys.exit(0)

    def open_automaton_action(self):
        #self.outputPlainTextEdit.setPlainText("Open Automaton Clicked")

        # Save the location of the def file
        self.def_path, _ = QFileDialog.getOpenFileName(
            self, "Select Definition File", "", ".def files (*.def)")
        #self.def_path = 'pda.def'
        #self.invalid_def_path = 'invalid_pda.def'

        # Check if the defintion file is valid
        Valid_def = Validate_Def_File(self.def_path)
        if Valid_def.def_valid == True:
            # Load the Automaton
            self.Automaton.load(self.def_path)
            # Store the the automaton is opened
            self.automaton_open = True
            # Set def path to the status bar
            self.statusLabel.setText(self.def_path)
            # Now parse config file
            self.parseConfigFile(self.def_path)
            # Now parse the input strings
            self.parseInputStringFile(self.def_path)
            # Set normal label styling
            self.statusLabel.setStyleSheet(self.styleNormal)
            # Change automaton title label
            self.fileNameLabel.setText(self.def_path.split("/")[-1])
        else:
            error_list = []
            error_list = Valid_def.is_invalid_def()
            for item in error_list:
                self.outputPlainTextEdit.appendPlainText(item)
            # Set status label
            status = self.def_path + " is invalid!"
            self.statusLabel.setText(status)
            # Set error label styling
            self.statusLabel.setStyleSheet(self.styleError)

        return

    #def view_automaton_action(self):
    #    self.outputPlainTextEdit.setPlainText("View Automaton Clicked")
    #    file = open(self.def_path, 'r')
    #    for line in file:
    #        self.outputPlainTextEdit.appendPlainText(line)
    #    return

    def user_manual_action(self):
        userMan = HelpMenu()
        userMan.__init__()

    def add_to_list_clicked(self):
        # If the user just clicks add string
        if (self.inputStringLineEdit.text() == ''):
            return

        if self.Strings.is_duplicate(self.inputStringLineEdit.text()) == True:
            status = self.inputStringLineEdit.text() + ' is a duplicate string'
            self.statusLabel.setText(status)
            self.statusLabel.setStyleSheet(self.styleError)
            self.inputStringLineEdit.clear()
            return

        if self.Strings.validate(self.Automaton.Input_Alpha.alphabet,
                                 self.inputStringLineEdit.text()) == True:
            self.Strings.add_input_string(self.Automaton.Input_Alpha.alphabet,
                                          self.inputStringLineEdit.text())
            self.update_input_string_widget()
            # Make new string the selected string
            self.inputStringListWidget.setCurrentRow(
                (self.inputStringListWidget.count() - 1))
            self.inputStringLineEdit.clear()
            self.statusLabel.setStyleSheet(self.styleNormal)
            self.statusLabel.setText('')
        else:
            status = self.inputStringLineEdit.text() + ' is not a valid string'
            self.statusLabel.setText(status)
            self.statusLabel.setStyleSheet(self.styleError)
            self.update_input_string_widget()
            self.inputStringLineEdit.clear()
        return

    def run_string_clicked(self):
        selected_string = ''

        if len(self.inputStringListWidget.selectedItems()) > 0:
            selected_string = self.inputStringListWidget.selectedItems(
            )[0].text()
        else:
            self.statusLabel.setStyleSheet(self.styleError)
            self.statusLabel.setText('No input string selected')

        #self.outputPlainTextEdit.setPlainText("Run String Button Clicked")
        self.Automaton.run_string(selected_string)
        outputTransitions = self.Automaton.transitions_list
        outputStack = self.Automaton.stack
        outputPath = str(outputTransitions[0])

        #self.outputPlainTextEdit.setPlainText(outputTransitions)
        for element in outputTransitions:
            self.outputPlainTextEdit.setPlainText(str(element))
        #self.stackPlainTextEdit.setPlainText(outputStack) #add \n's
        self.stackPlainTextEdit.setPlainText("")
        for char in outputStack:
            self.stackPlainTextEdit.appendPlainText(char)
        if (self.displayPathsCheckBox.isChecked()):
            self.pathPlainTextEdit.appendPlainText(outputPath +
                                                   " -> ")  #add ->'s

    def quit_running_string_clicked(self):
        self.outputPlainTextEdit.setPlainText(
            "Quit Running String Button Clicked")
        return

    def close_automaton_clicked(self):
        self.outputPlainTextEdit.clear()
        self.inputStringListWidget.clear()
        self.statusLabel.clear()
        self.outputPlainTextEdit.setPlainText("Close Automaton Button Clicked")
        return
class Dialog(QWidget):
    def __init__(self, upgrades, security_upgrades, packages, reboot_required,
                 upg_path):
        QWidget.__init__(self)
        self.upgrades = upgrades
        self.security_upgrades = security_upgrades
        self.upg_path = upg_path
        self.packages = packages

        self.initUI()
        self.upgradeBtn.clicked.connect(self.call_upgrade)
        self.closeBtn.clicked.connect(self.call_reject)

    def initUI(self):
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignHCenter)
        self.upgradeBtn = QPushButton("Upgrade")
        self.closeBtn = QPushButton("Close")
        self.plainTextEdit = QPlainTextEdit()
        text = ""
        self.plainTextEdit.setVisible(False)
        self.plainTextEdit.setReadOnly(True)
        self.plainTextEdit.setEnabled(False)
        palette = self.plainTextEdit.palette()
        palette.setColor(QPalette.Base, Qt.black)
        palette.setColor(QPalette.Text, Qt.gray)
        self.plainTextEdit.setPalette(palette)

        hbox = QHBoxLayout()
        hbox.addStretch(1)
        hbox.addWidget(self.upgradeBtn)
        hbox.addWidget(self.closeBtn)
        hbox.addStretch(1)

        vbox = QVBoxLayout()
        vbox.addWidget(self.label)
        vbox.addWidget(self.plainTextEdit)
        vbox.addLayout(hbox)

        if self.upg_path == None:
            self.upgradeBtn.setVisible(False)

        self.setLayout(vbox)
        self.setGeometry(300, 300, 500, 150)
        self.setWindowTitle("Update Notifier")
        self.center()

        if self.upgrades > 0:
            text = "There are(is) %s upgrade(s) available and %s security update(s) available" % (
                self.upgrades, self.security_upgrades)
            self.plainTextEdit.setVisible(True)
            for pkg in self.packages:
                self.plainTextEdit.appendPlainText(str(pkg))

        if reboot_required:
            if text == "":
                text = "Reboot is needed"
                self.upgradeBtn.setVisible(False)
            else:
                text = text + "\nReboot is needed"

        self.label.setText(text)
        self.plainTextEdit.setEnabled(True)

    def center(self):
        frameGm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(
            QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

    def call_reject(self):
        app.quit()

    def call_upgrade(self):
        self.label.setText("Upgrading....")
        #TODO maybe open another thread so notifier won't freeze
        cmd = ['lxqt-sudo', self.upg_path]
        #process = subprocess.Popen(self.upg_path)
        #process = subprocess.Popen(cmd)
        #        process = subprocess.Popen(cmd, shell=True)
        process = subprocess.Popen(cmd)
        process.wait()
        app.quit()
Ejemplo n.º 60
0
class Window1(QWidget):
    global trysin

    def __init__(self):
        super().__init__()

        self.title = "SaPa"
        self.top = 250
        self.left = 250
        self.width = 600
        self.height = 600

        self.InitWindow()

        self.trysin = 0

    def InitWindow(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # Create textbox
        self.textboxA = QLineEdit(self)
        self.textboxA.move(5, 320)
        self.textboxA.resize(185, 40)
        # Create textbox
        self.textboxU = QLineEdit(self)
        self.textboxU.move(205, 320)
        self.textboxU.resize(185, 40)
        # Create textbox
        self.textboxP = QLineEdit(self)
        self.textboxP.move(405, 320)
        self.textboxP.resize(185, 40)

        #Create a Button
        self.buttonC = QPushButton('Εισαγωγή', self)
        self.buttonC.move(405, 400)
        #Create a Button
        self.buttonD = QPushButton('Διαγραφή', self)
        self.buttonD.move(5, 400)

        # Connect button to function click
        self.buttonC.clicked.connect(self.buttonClickC)
        self.buttonD.clicked.connect(self.buttonClickD)

        #Create iosapa Obj
        iosapa = IoSapa()
        #Create Plain TextEdit
        self.pt = QPlainTextEdit(self)
        i = 0
        z = 0
        x = 0

        filename = glob.glob("data/*.txt")
        for i in filename:
            with open(str(filename[x]), "r+") as fo:

                for line in fo:
                    print(line)
                    self.pt.appendPlainText(line)
                self.pt.appendPlainText("----------------------------")
                x += 1

    # for x in iosapa.readF():
    #    print(x)
    #   self.pt.appendPlainText(str(x))
        self.pt.move(5, 5)
        self.pt.resize(590, 300)
        #Create Lable
        # label = QLabel(self)
        #label.setFrameStyle(QFrame.Panel)
        #label.setText(iosapa.readF())
        #label.setGeometry(5,5,450,500)
        #label.setAlignment(QtCore.Qt.AlignLeft)

        #self.show()

    def buttonClickC(self):
        iosapa = IoSapa()
        iosapa.writeF(str(self.textboxA.text()), str(self.textboxU.text()),
                      str(self.textboxP.text()))
        #window = Window1()
        #window.InitWindow()

    def buttonClickD(self):
        iosapa = IoSapa()

        iosapa.removeF(str(self.textboxA.text()))