示例#1
0
class HelpWidget(QDockWidget):
    def __init__(self):
        super(HelpWidget, self).__init__()
        # TODO: ovo treba da bude kao neki widget u koji moze da se unese instrukcija ili registar ili direktiva
        # TODO: pa mu se onda ispise neki uredjeni HTML kao onaj tekst iz praktikuma sta ta kljucna rec znaci
        # TODO: mozda da se ispisu i neki odabrani algoritmi npr. sabiranje u dvostrukoj preciznosti sa ilustracijama
        # TODO: ili iteriranje kroz niz
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.setMinimumWidth(200)
        self.setStyleSheet("background-color: #2D2D30; color: white;")
        self.searchLabel = QLineEdit()
        self.searchLabel.setPlaceholderText("Search for an instruction...")
        self.completer = QCompleter(list(InstructionsInfo.INFO.keys()), self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.popup().setStyleSheet(
            "background-color: #2D2D30; color: white")
        self.searchLabel.setCompleter(self.completer)
        self.searchLabel.setStyleSheet(
            "margin-bottom: 10px; margin-top: 10px;")
        self.setTitleBarWidget(self.searchLabel)
        self.setFeatures(QDockWidget.DockWidgetMovable
                         | QDockWidget.DockWidgetClosable)
        self.setWindowTitle("Instructions help")
        self.resultBox = QTextEdit()
        self.resultBox.setReadOnly(True)
        self.setWidget(self.resultBox)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Return and self.searchLabel.hasFocus():
            seachWord = self.searchLabel.text().strip()
            if seachWord in InstructionsInfo.INFO:
                self.resultBox.setHtml(InstructionsInfo.INFO[seachWord])
        super(HelpWidget, self).keyPressEvent(event)
示例#2
0
 def on_search_suggestions(self):
     logging.info('Received search suggestions for keywords: "{}"'.format(
         self.keywords))
     self.searchbar.setEnabled(True)
     self.searchbar.setFocus()
     if self.suggestions:
         suggestions = [
             suggestion['label'] for suggestion in self.suggestions
         ]
         completer = QCompleter(suggestions)
         completer.setCaseSensitivity(Qt.CaseInsensitive)
         self.searchbar.setCompleter(completer)
         self.searchbar.completer().complete()
         self.searchbar.completer().popup().setStyleSheet(
             css(
                 """
             QListView {
                 border: 1px solid {{borderColor}};
                 padding: 10px;
                 background: {{backgroundColor}};
             }
             QItemSelection {
                 padding: 10px;
             }
             """,
                 borderColor=colors.SECONDARY_COLOR,
                 backgroundColor=colors.PLACEHOLDER_COLOR,
             ))
示例#3
0
    def __init__(self):
        WizardPage.__init__(self)
        self.fetch_config = None
        self.app_model = QStringListModel(
            REGISTRY.names(
                lambda klass: not getattr(klass, "disable_in_gui", None)))
        self.ui.app_combo.setModel(self.app_model)
        if mozinfo.bits == 64:
            if mozinfo.os == "mac":
                self.bits_model = QStringListModel(["64"])
                bits_index = 0
            else:
                self.bits_model = QStringListModel(["32", "64"])
                bits_index = 1
        elif mozinfo.bits == 32:
            self.bits_model = QStringListModel(["32"])
            bits_index = 0
        self.ui.bits_combo.setModel(self.bits_model)
        self.ui.bits_combo.setCurrentIndex(bits_index)
        self.build_type_model = QStringListModel()

        self.ui.app_combo.currentIndexChanged.connect(self._set_fetch_config)
        self.ui.bits_combo.currentIndexChanged.connect(self._set_fetch_config)
        self.ui.app_combo.setCurrentIndex(
            self.ui.app_combo.findText("firefox"))

        self.ui.repository.textChanged.connect(self._on_repo_changed)

        completer = QCompleter(sorted(get_branches()), self)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.ui.repository.setCompleter(completer)
        QApplication.instance().focusChanged.connect(self._on_focus_changed)
示例#4
0
 def _completerSetupFunction(self, editor, index):
     completer = QCompleter(getHeadersData(), editor)
     completer.setCompletionColumn(0)
     completer.setCompletionRole(Qt.EditRole)
     completer.setCaseSensitivity(Qt.CaseInsensitive)
     try:
         editor.setCompleter(completer)
     except:
         pass
示例#5
0
    def __init__(self, lookup_names: List[str], on_entered: CallbackType) -> None:
        widget = QLineEdit("")
        completer = QCompleter(lookup_names)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setFilterMode(Qt.MatchFlag.MatchContains)
        completer.setMaxVisibleItems(50)
        widget.setCompleter(completer)

        super().__init__("Название рецепта:", widget)

        self._on_recipe_name_entered = on_entered
        self._connect_slots()
示例#6
0
    def __init__(self, food_names: List[str],
                 on_ingredient_entered: CallbackType,
                 on_ingredient_finalized: CallbackType) -> None:
        super().__init__()

        self._food_names = food_names
        self._on_ingredient_entered = on_ingredient_entered
        self._on_ingredient_finalized = on_ingredient_finalized

        # ingredient
        ingredient_label = QLabel("Продукт:")
        ingredient_line_edit = QLineEdit()

        # Completer for the ingredient line edit
        completer = QCompleter(self._food_names)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        ingredient_line_edit.setCompleter(completer)

        # ingredient mass line edit
        ingredient_mass_line_edit = QLineEdit()
        ingredient_mass_line_edit.setPlaceholderText("Масса (гр.)")
        ingredient_mass_line_edit.setFixedWidth(100)
        ingredient_mass_line_edit.setValidator(QIntValidator())
        ingredient_mass_line_edit.setMaxLength(4)

        # Button to add ingredient to the recipe

        ingredient_add_button = QPushButton("+")

        # Layout for ingredient_label / ingredient_line_edit
        ingredient_layout = QHBoxLayout()
        ingredient_layout.addWidget(ingredient_label)
        ingredient_layout.addWidget(ingredient_line_edit)
        ingredient_layout.addWidget(ingredient_mass_line_edit)
        ingredient_layout.addWidget(ingredient_add_button)

        self.setLayout(ingredient_layout)

        self._ingredient_line_edit = ingredient_line_edit
        self._ingredient_mass_line_edit = ingredient_mass_line_edit
        self._ingredient_add_button = ingredient_add_button

        self._connect_slots()
示例#7
0
    def __init__(self, lookup_names: List,
                 on_item_added: CallbackType) -> None:
        super().__init__()

        recipe_search_label = QLabel("Блюдо:")

        recipe_search_line_edit = QLineEdit("")
        completer = QCompleter(lookup_names)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setFilterMode(Qt.MatchFlag.MatchContains)
        completer.setMaxVisibleItems(50)
        recipe_search_line_edit.setCompleter(completer)

        serves_amount_label = QLabel("Порций:")

        serves_amount_line_edit = QLineEdit(str(self.DEFAULT_SERVES_AMOUNT))
        serves_amount_line_edit.setFixedWidth(30)
        serves_amount_line_edit.setValidator(QIntValidator())
        serves_amount_line_edit.setMaxLength(2)

        add_push_button = QPushButton("+")

        # Widget layout
        layout = QHBoxLayout()
        layout.addWidget(recipe_search_label)
        layout.addWidget(recipe_search_line_edit)
        layout.addWidget(serves_amount_label)
        layout.addWidget(serves_amount_line_edit)
        layout.addWidget(add_push_button)
        layout.addStretch()

        self.setLayout(layout)

        # Init self data
        self._on_item_added = on_item_added
        self._recipe_search_line_edit = recipe_search_line_edit
        self._serves_amount_line_edit = serves_amount_line_edit
        self._add_push_button = add_push_button

        # Connect slots
        self._connect_slots()
示例#8
0
    def more_trans_complete(self):
        curr_text = self.view.method_of_trans.currentText()
        helping = []
        if curr_text == "Salary":
            for value in (
                    "Bash Imam",
                    "Ass. Imam",
                    "Muazzin",
                    "Ass. Muazzin",
                    "Sibithi",
                    "Akshah",
                    "Sadarth",
            ):
                helping.append(value)
        elif curr_text == "Till Box":
            for value in ("1", "2"):
                helping.append(value)
        elif curr_text == "Maintenance":
            for value in ("Labourer charge", "Material charge", "Cleaning"):
                helping.append(value)

        completer = QCompleter(helping)
        completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
        self.view.more_trans_detail.setCompleter(completer)
示例#9
0
class AbstractReferenceSelector(ABC, QWidget, metaclass=SelectorMeta):
    changed = Signal()

    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.completer = None
        self.p_selected_id = 0

        self.layout = QHBoxLayout()
        self.layout.setMargin(0)
        self.name = QLineEdit()
        self.name.setText("")
        self.layout.addWidget(self.name)
        self.details = QLabel()
        self.details.setText("")
        self.details.setVisible(False)
        self.layout.addWidget(self.details)
        self.button = QPushButton("...")
        self.button.setFixedWidth(self.button.fontMetrics().width("XXXX"))
        self.layout.addWidget(self.button)
        self.setLayout(self.layout)

        self.setFocusProxy(self.name)

        self.button.clicked.connect(self.on_button_clicked)

        if self.details_field:
            self.name.setFixedWidth(self.name.fontMetrics().width("X") * 15)
            self.details.setVisible(True)
        self.completer = QCompleter(self.dialog.model.completion_model)
        self.completer.setCompletionColumn(
            self.dialog.model.completion_model.fieldIndex(self.selector_field))
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.name.setCompleter(self.completer)
        self.completer.activated[QModelIndex].connect(self.on_completion)

    def getId(self):
        return self.p_selected_id

    def setId(self, selected_id):
        if self.p_selected_id == selected_id:
            return
        self.p_selected_id = selected_id
        self.name.setText(
            self.dialog.model.getFieldValue(selected_id, self.selector_field))
        if self.details_field:
            self.details.setText(
                self.dialog.model.getFieldValue(selected_id,
                                                self.details_field))

    selected_id = Property(int, getId, setId, notify=changed, user=True)

    def on_button_clicked(self):
        ref_point = self.mapToGlobal(self.name.geometry().bottomLeft())
        self.dialog.setGeometry(ref_point.x(), ref_point.y(),
                                self.dialog.width(), self.dialog.height())
        res = self.dialog.exec_(enable_selection=True,
                                selected=self.selected_id)
        if res:
            self.selected_id = self.dialog.selected_id
            self.changed.emit()

    @Slot(QModelIndex)
    def on_completion(self, index):
        model = index.model()
        self.selected_id = model.data(model.index(index.row(), 0),
                                      Qt.DisplayRole)
        self.changed.emit()

    def isCustom(self):
        return True
示例#10
0
class SearchEdit(QLineEdit):
    def __init__(self, parent: QWidget):
        QLineEdit.__init__(self, parent)
        self.completer = None

    def init_completer(self, words: Iterable[str]) -> None:
        assert self.completer is None

        self.completer = QCompleter(list(words), self)
        self.completer.setWidget(self)
        self.completer.setCompletionMode(QCompleter.PopupCompletion)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.activated.connect(self.on_insert_completion)

    def completer(self) -> QCompleter:
        return self.completer

    def on_insert_completion(self, completion):
        if self.completer.widget() != self:
            return
        prefix = self.completer.completionPrefix()
        extra_text = completion[len(prefix):] + ', '
        self.insert(extra_text)

    def text_under_cursor(self) -> str:
        text = self.text()
        cursor_pos = self.cursorPosition()

        start_index = None
        comma_index1 = text[:cursor_pos].rfind(',')
        if comma_index1 >= 0:
            start_index = comma_index1 + 1

        end_index = None
        comma_index2 = text[cursor_pos:].find(',')
        if comma_index2 >= 0:
            end_index = cursor_pos + comma_index2

        return text[start_index:end_index].strip()

    def focus_in_event(self, event: QFocusEvent) -> None:
        if self.completer:
            self.completer.setWidget(self)
        QLineEdit.focusInEvent(self, event)

    def keyPressEvent(self, key_event: QKeyEvent) -> None:
        if self.completer and self.completer.popup().isVisible():
            # The following keys are forwarded by the completer to the widget
            key = key_event.key()
            if key in (Qt.Key_Enter, Qt.Key_Return, Qt.Key_Escape, Qt.Key_Tab,
                       Qt.Key_Backtab):
                key_event.ignore()
                return  # let the completer do default behavior

        is_ctrl_modifier = (key_event.modifiers() & Qt.ControlModifier) != 0
        is_shift_modifier = (key_event.modifiers() & Qt.ShiftModifier) != 0
        ctrl_or_shift = is_ctrl_modifier or is_shift_modifier

        is_shortcut = is_ctrl_modifier and key_event.key(
        ) == Qt.Key_E  # CTRL+E
        if not self.completer or not is_shortcut:  # do not process the shortcut when we have a completer
            QLineEdit.keyPressEvent(self, key_event)

        if not self.completer or ctrl_or_shift and key_event.text() == '':
            return

        eow = "~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="  # end of word
        has_modifier = (key_event.modifiers() !=
                        Qt.NoModifier) and not ctrl_or_shift
        completion_prefix = self.text_under_cursor()

        if not is_shortcut:
            event_text = key_event.text()
            if has_modifier or not event_text or len(
                    completion_prefix) < 1 or event_text[-1] in eow:
                self.completer.popup().hide()
                return

        if completion_prefix != self.completer.completionPrefix():
            self.completer.setCompletionPrefix(completion_prefix)
            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)  # popup it up!
示例#11
0
class ConsoleDialog(QDialog):
    def __init__(self, title: str,
                 program: str,
                 args: List[str],
                 commands: List[str]):
        super().__init__()

        self.setWindowTitle(title)
        self.program = program
        self.args = args

        self.layout = QGridLayout()

        self.output = QTextEdit()
        self.output.acceptRichText = True

        self.input = QLineEdit()
        self.completer = QCompleter(commands, self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.input.setCompleter(self.completer)
        self.input.setFocus()

        self.layout.addWidget(self.output)
        self.layout.addWidget(self.input)
        self.setLayout(self.layout)

        self.connect(self.input, SIGNAL("returnPressed(void)"),
                     self.execute_user_command)

        self.connect(self.completer, SIGNAL("activated(const QString&)"),
                     self.input.clear, Qt.QueuedConnection)

    def execute_user_command(self):
        cmd = str(self.input.text())
        self.run_command(cmd)

    def run_command(self, cmd: str):
        log.info(
            'run_command',
            program=self.program,
            args=self.args,
            cmd=cmd
        )
        self.output.append(f'> {cmd}\n')
        self.input.clear()

        process = QProcess()
        process.setProgram(self.program)
        process.setCurrentReadChannel(0)

        # noinspection PyUnresolvedReferences
        process.readyReadStandardError.connect(
            lambda: self.handle_error(process)
        )
        # noinspection PyUnresolvedReferences
        process.readyReadStandardOutput.connect(
            lambda: self.handle_output(process)
        )

        connect_args = list(self.args)

        args = cmd.split(' ')
        if args[0] == self.program.split('/')[-1]:
            args.pop(0)
        process.setArguments(connect_args + args)
        process.start()

    def handle_error(self, process: QProcess):
        output: QByteArray = process.readAllStandardError()
        message = output.data().decode('utf-8').strip()
        self.output.append(message)

    def handle_output(self, process: QProcess):
        output: QByteArray = process.readAllStandardOutput()
        message = output.data().decode('utf-8').strip()
        if message.startswith('{') or message.startswith('['):
            formatter = HtmlFormatter()
            formatter.noclasses = True
            formatter.linenos = False
            formatter.nobackground = True
            message = highlight(message, JsonLexer(), formatter)
            self.output.insertHtml(message)
        else:
            self.output.append(message)

        # This is just for generating the command lists in constants
        # commands = None
        # if '== Blockchain ==' in message:
        #     commands = self.parse_litecoin_cli_commands(message)
        # elif 'lncli [global options] command [command options]' in message:
        #     commands = self.parse_lncli_commands(message)
        # if commands is not None:
        #     log.debug('commands', commands=commands)

        max_scroll = self.output.verticalScrollBar().maximum()
        self.output.verticalScrollBar().setValue(max_scroll)

    @staticmethod
    def parse_litecoin_cli_commands(message: str):
        log.debug('parse_litecoin_cli_commands')
        commands = []
        for line in message.split(sep='\n'):
            line = line.strip()
            if not line or line.startswith('=='):
                continue
            command = line.split()[0]
            command = command.strip()
            commands.append(command)
        return commands

    @staticmethod
    def parse_lncli_commands(message: str):
        log.debug('parse_lncli_commands')
        at_commands = False
        commands = []
        for line in message.split(sep='\n'):
            line = line.strip()
            if not at_commands:
                if 'COMMANDS:' in line:
                    at_commands = True
                    log.debug('commands line',
                              line=line)
                continue
            elif 'GLOBAL OPTIONS' in line:
                return commands
            elif line.endswith(':') or not line:
                continue

            command = line.split()[0]
            command = command.strip().replace(',', '')
            commands.append(command)
        return commands

    def show(self):
        self.showMaximized()
        self.raise_()
        self.setWindowState(self.windowState() & ~Qt.WindowMinimized | Qt.WindowActive)
        self.activateWindow()

        self.input.setFocus()
        self.run_command('help')
示例#12
0
class LibraryItems(QObject):
    item_selected = Signal(object)
    item_activated = Signal(object)

    def __init__(self, app, window, lib_tree):
        QObject.__init__(self)
        self.app = app
        self.lib_tree = lib_tree
        self.library = app.library
        self.input = window.search_query_input
        self.view = window.lib_items
        self.tree_conditions = []
        self.items = []
        self.items_incomplete = False
        self.model = ItemModel(self.app)
        self.model.setColumnCount(1)
        self.compl_model = QStandardItemModel()
        self.compl_model.setColumnCount(1)
        self.completer = QCompleter(self.compl_model)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setModelSorting(QCompleter.CaseSensitivelySortedModel)
        self.input.setCompleter(self.completer)
        self.view.setHeaderHidden(True)
        self.view.setIndentation(0)
        self.view.setModel(self.model)
        self.view.sortByColumn(0, Qt.AscendingOrder)
        self.view.setDragEnabled(True)
        self.view.setAcceptDrops(True)
        self.view.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        selection_model = self.view.selectionModel()
        selection_model.selectionChanged.connect(self.selection_changed)
        tree_selection_model = window.lib_tree.selectionModel()
        tree_selection_model.selectionChanged.connect(
            self.tree_selection_changed)
        self.input.editingFinished.connect(self.query_entered)
        self.input.textChanged.connect(self.query_changed)
        self.view.doubleClicked.connect(self.double_clicked)
        self.run_query()

    def reload(self):
        self.model.clear()
        self.item_selected.emit(None)
        icon = QIcon.fromTheme("audio-x-generic")
        for item in self.items:
            s_item = QStandardItem(icon, item.name)
            s_item.setDragEnabled(True)
            s_item.setDropEnabled(False)
            s_item.setData(item)
            self.model.appendRow([s_item])
        if self.items_incomplete:
            s_item = QStandardItem("…and more")
            s_item.setDragEnabled(False)
            s_item.setDropEnabled(False)
            self.model.appendRow([s_item])

    @Slot(QItemSelection)
    def selection_changed(self, selection):
        logger.debug("selection changed")
        indexes = selection.indexes()
        if indexes:
            index = selection.indexes()[0]
            s_item = self.model.itemFromIndex(index)
            metadata = s_item.data()
        else:
            metadata = None
        self.item_selected.emit(metadata)

    @Slot(QModelIndex)
    def double_clicked(self, index):
        s_item = self.model.itemFromIndex(index)
        metadata = s_item.data()
        self.item_activated.emit(metadata)

    @Slot(QItemSelection)
    def tree_selection_changed(self, selection):
        logger.debug("tree selection changed")
        self.tree_conditions = self.lib_tree.get_current_conditions()
        self.run_query()

    def run_query(self):
        text_query = self.input.text()
        query = SearchQuery.from_string(text_query)
        query.add_conditions(self.tree_conditions)
        items = self.library.get_items(query, limit=ITEM_LIMIT + 1)
        if len(items) > ITEM_LIMIT:
            self.items_incomplete = True
            self.items = items[:ITEM_LIMIT]
        else:
            self.items_incomplete = False
            self.items = items
        self.reload()

    @Slot()
    def query_entered(self):
        self.run_query()

    @Slot()
    def query_changed(self, text):
        compl_query = CompletionQuery.from_string(text)
        if compl_query:
            columns = ["offsets(compl_fts.fts)", "compl_fts.content"]
            compl_query.add_conditions(self.tree_conditions)
            sql_query, params = compl_query.as_sql(columns=columns)
            logger.debug("completing %r with query %r %r", compl_query.prefix,
                         sql_query, params)
            matches = self.library.get_completions(compl_query,
                                                   limit=COMPLETION_LIMIT)
            self.compl_model.clear()
            for match in sorted(matches):
                match = text[:compl_query.start_index] + match
                logger.debug("Adding match: %r", match)
                s_item = QStandardItem(match)
                self.compl_model.appendRow([s_item])
        else:
            self.model.clear()
示例#13
0
class ConsoleDialog(QDialog):
    def __init__(self, node):
        super().__init__()

        self.node = node

        self.show_help = True

        self.layout = QGridLayout()
        self.setLayout(self.layout)

        self.output_area = QTextEdit()
        self.output_area.setReadOnly(True)
        self.output_area.acceptRichText = True
        self.output_area.document().setMaximumBlockCount(5000)
        self.layout.addWidget(self.output_area)

        self.input_area = QLineEdit()
        self.completer = QCompleter()
        # noinspection PyUnresolvedReferences
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.input_area.setCompleter(self.completer)
        self.input_area.setFocus()
        self.layout.addWidget(self.input_area)

        self.connect(self.input_area, SIGNAL("returnPressed(void)"),
                     self.execute_user_command)

    @property
    def cli(self):
        try:
            return self.node.software.cli
        except AttributeError:
            return None

    @property
    def cli_args(self):
        try:
            return self.node.configuration.cli_args
        except AttributeError:
            return None

    def showEvent(self, event):
        super().showEvent(event)

        if self.show_help:
            success = self.run_command('help')
            if success:
                self.show_help = False

    def execute_user_command(self):
        cmd = str(self.input_area.text())
        self.input_area.clear()
        self.run_command(cmd)

    def run_command(self, command):
        try:
            if self.cli is None or self.cli_args is None:
                self.output_area.append(
                    'Node starting up, please try again later...')
                return False

            self.output_area.append(f'> {command}\n')

            process = QProcess()
            process.setProgram(self.cli)
            process.setCurrentReadChannel(0)

            # noinspection PyUnresolvedReferences
            process.readyReadStandardError.connect(
                lambda: self.handle_cli_error_output(process))

            # noinspection PyUnresolvedReferences
            process.readyReadStandardOutput.connect(
                lambda: self.handle_cli_output(process))

            args = command.split(' ')
            if args[0] == self.cli.split('/')[-1]:
                args.pop(0)
            process.setArguments(self.cli_args + args)
            process.start()

            log.info('run_command',
                     program=self.cli,
                     args=self.cli_args,
                     cmd=command)

            return True
        except Exception:
            self.output_area.append(
                'Node starting up, please try again later...')
            return False

    def handle_cli_error_output(self, cli_process: QProcess):
        output: QByteArray = cli_process.readAllStandardError()
        message = output.data().decode('utf-8').strip()
        self.output_area.append(message)

    def handle_cli_output(self, cli_process: QProcess):
        output: QByteArray = cli_process.readAllStandardOutput()
        message = output.data().decode('utf-8').strip()

        if message.startswith('{') or message.startswith('['):
            formatter = HtmlFormatter()
            formatter.noclasses = True
            formatter.linenos = False
            formatter.nobackground = True
            message = highlight(message, JsonLexer(), formatter)
            self.output_area.insertHtml(message)
        else:
            self.output_area.append(message)
示例#14
0
class TraceWindow(QMainWindow):
    def __init__(self, qmp):

        QMainWindow.__init__(self)

        self.qmp = qmp

        os.system('rm /tmp/errors.log 2>/dev/null')

        self.trace_events = self.qmp.hmp_command('info trace-events')
        self.qmp.hmp_command('logfile /tmp/errors.log')

        self.trace_events = sorted(
            self.trace_events['return'].split('\r\n'))[1:]
        self.activated = []

        self.length = 100

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.disp_output)
        self.timer.start(100)

        self.init_ui()

    def init_ui(self):

        self.setWindowTitle('Trace Event Window')
        self.setGeometry(100, 100, 800, 600)

        bar = self.menuBar()

        file_ = bar.addMenu('File')
        export_log = QAction('Save to File',
                             self,
                             triggered=lambda: self.save_log())

        options = bar.addMenu('Options')
        auto_refresh = QAction(
            'Auto Refresh',
            self,
            checkable=True,
            triggered=lambda: self.timer.start(100)
            if auto_refresh.isChecked() else self.timer.stop())
        auto_refresh.setChecked(True)

        options.addAction(auto_refresh)
        file_.addAction(export_log)

        vgrid = QVBoxLayout()
        grid = QHBoxLayout()

        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(['Name'])

        self.top = []
        self.lst = []

        for n, event in enumerate(self.trace_events):
            word = event.split('_')[0]
            if word not in self.top:
                self.top.append(word)
                item = QTreeWidgetItem(self.tree)
                self.lst.append(item)
                item.setText(0, word)
            subitem = QTreeWidgetItem(item)
            subitem.setText(0, '    ' + event.split(' : ')[0])
            # subitem.setCheckState(0, Qt.Unchecked)
            cbox = QCheckBox()
            cbox.stateChanged.connect(lambda state, text=subitem.text(0): self.
                                      handle_checked(state, text))
            self.tree.setItemWidget(subitem, 0, cbox)

        # self.tree.setColumnWidth(0, 25)

        self.tracelist = QLabel()
        self.disp_output()

        self.traceview = QScrollArea()
        self.traceview.setWidget(self.tracelist)
        self.traceview.setWidgetResizable(True)

        search = QHBoxLayout()

        self.search_bar = QLineEdit(self)

        self.completer = QCompleter(self.top, self)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)

        self.search_bar.setCompleter(self.completer)

        search_button = QPushButton('Search')
        search_button.clicked.connect(lambda: self.tree.setCurrentItem(
            self.lst[self.top.index(self.search_bar.text())]))

        expand = QPushButton('▼')
        expand.setFixedSize(QSize(25, 25))
        expand.clicked.connect(lambda: self.tree.expandAll())

        collapse = QPushButton('▲')
        collapse.setFixedSize(QSize(25, 25))
        collapse.clicked.connect(lambda: self.tree.collapseAll())

        self.search_bar.returnPressed.connect(lambda: search_button.click())

        search.addWidget(self.search_bar)
        search.addWidget(search_button)
        search.addWidget(expand)
        search.addWidget(collapse)

        self.digest = QLabel()

        vgrid.addLayout(search)
        vgrid.addWidget(self.tree)

        vgridwid = QWidget()
        vgridwid.setLayout(vgrid)

        split = QSplitter(Qt.Horizontal)

        split.addWidget(vgridwid)
        split.addWidget(self.traceview)

        split.setStretchFactor(1, 1)

        # grid.addLayout(vgrid)
        grid.addWidget(split)
        # grid.addWidget(self.tracelist)

        self.disp_output()

        center = QWidget()
        center.setLayout(grid)
        self.setCentralWidget(center)
        self.show()

    def disp_output(self):

        self.shorten_file()

        with open('/tmp/errors.log', 'r') as errors:

            self.digest = []
            lines = 0

            for line in errors:
                if re.match(r"\d+@\d+\.\d+:.*", line):
                    self.digest.append(line)
                    lines += 1

            if not self.digest:
                self.digest = ['<font color="grey">Empty...</font>']

            self.digest = ''.join(self.digest[-self.length:])

            self.tracelist.setText(self.digest)
            self.tracelist.setFont(QFont('Monospace', 10))
            self.tracelist.setTextInteractionFlags(Qt.TextSelectableByMouse)

    def shorten_file(self):

        with open('/tmp/errors.log', 'r+') as tracefile:

            content = ''.join(tracefile.readlines()[-(self.length * 3):])

            tracefile.seek(0)
            tracefile.truncate()

            tracefile.write(content)

    def save_log(self):

        name = QFileDialog.getSaveFileName(self, 'Save File', '',
                                           'Text files (*.txt)')

        log_file = open(name[0], 'w')
        log_file.write(self.digest)
        log_file.close()

    def handle_checked(self, state, text):

        if state:
            self.qmp.hmp_command('trace-event %s on' % text.strip())
            self.activated.append(text)
        else:
            self.qmp.hmp_command('trace-event %s off' % text.strip())
            self.activated.remove(text)

    def closeEvent(self, event):

        self.timer.stop()

        for e in self.activated:
            self.qmp.hmp_command('trace-event %s off' % e.strip())

        os.system('rm /tmp/errors.log')

        event.accept()