예제 #1
0
    def setup_ui(self):
        layout = QGridLayout()

        table = QTreeWidget()
        table.setHeaderLabels(['name', 'width', 'height', 'ratio'])
        table.setSortingEnabled(True)
        items = []
        for size in self.manager.project.sizes:
            i = ComparingTreeWidgetItem(None, [
                f'{size.width}x{size.height}',
                str(size.width),
                str(size.height),
                str(size.ratio())
            ])
            i.__data__ = size
            items.append(i)
        table.addTopLevelItems(items)

        @table.currentItemChanged.connect
        def _(item, prev):
            del_btn.setEnabled(item is not None)

        layout.addWidget(table, 0, 0, 1, 2)

        add_btn = QPushButton('add new')

        @add_btn.clicked.connect
        def _(*args):
            diag = SizeInput(self.manager.project.sizes, self)
            if diag.exec_() != QDialog.Accepted:
                return
            size = diag.value
            self.manager.add_size(size)
            item = ComparingTreeWidgetItem(None, [
                f'{size.width}x{size.height}',
                str(size.width),
                str(size.height),
                str(size.ratio())
            ])
            table.addTopLevelItem(item)

        layout.addWidget(add_btn, 1, 0)

        del_btn = QPushButton('delete')
        del_btn.setEnabled(False)

        @del_btn.clicked.connect
        def _(*args):
            item = table.currentItem()
            size = item.__data__
            self.manager.del_size(size)
            shiboken2.delete(item)

        layout.addWidget(del_btn, 1, 1)

        self.setLayout(layout)
예제 #2
0
class SelectTiVoWidget(QDialog):
    """Displays the list of TiVos that were discovered on the network."""

    # Signals
    connect_to_tivo = Signal(str, str)

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

        self.tivos_found = []

        self.label = QLabel(self)

        self.label.setText('Below is a listing of all TiVos discovered on your'
                           ' network, which will refresh every 5 seconds. If y'
                           'ou do not see your TiVo, '
                           '<a href="#specify_ip">click here to specify an IP'
                           ' address.</a>')

        self.label.linkActivated.connect(self.specify_ip_address)

        self.tivo_listings = QTreeWidget(self)
        self.tivo_listings.itemDoubleClicked.connect(self.tivo_selected)
        self.tivo_listings.setHeaderLabels(["Name", "IP Address"])

        self.layout = QVBoxLayout(self)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.tivo_listings)

        self.setWindowTitle("Select TiVo")
        self.resize(512, 384)

        self.setModal(True)

    def add_tivo(self, name, ip_address):
        item = QTreeWidgetItem()
        item.setText(0, name)
        item.setText(1, ip_address)

        self.tivo_listings.addTopLevelItem(item)
        self.tivos_found.append(item)

    def tivo_selected(self, item, column):
        self.connect_to_tivo.emit(item.text(0), item.text(1))

    def specify_ip_address(self, link):
        text, ok = QInputDialog().getText(self, "Specify TiVO IP address",
                                          "IP address:", QLineEdit.Normal)

        if ok:
            self.connect_to_tivo.emit("unknown", text)
예제 #3
0
    def add_tree_with_header(self, parent):
        tw = QTreeWidget()
        parent.addWidget(tw)
        tw.setHeaderLabels(['Type', 'Legs', 'Has Hair/Fur'])
        tw.setSortingEnabled(True)
        tw.setAlternatingRowColors(True)
        i1 = QTreeWidgetItem(tw, ['Mammal'])
        i2 = QTreeWidgetItem(i1, ['Rodent'])
        i3 = QTreeWidgetItem(i2, ['Rat', '4', 'True'])
        i3 = QTreeWidgetItem(i2, ['Beaver', '2', 'True'])
        i2 = QTreeWidgetItem(i1, ['Primate'])
        i3 = QTreeWidgetItem(i2, ['Baboon', '2', 'True'])
        i3 = QTreeWidgetItem(i2, ['Human', '2', 'True'])
        i1 = QTreeWidgetItem(tw, ['Reptile'])
        i2 = QTreeWidgetItem(i1, ['Snake', '0', 'False'])
        i3 = QTreeWidgetItem(i1, ['Crocodile', '4', 'False'])

        self.add_expand_collapse_buttons(parent, tw)
예제 #4
0
    def setup_ui(self):
        layout = QGridLayout()

        table = QTreeWidget()
        table.setHeaderLabels(['name', 'type', 'width', 'height'])
        table.setSortingEnabled(True)
        items = []
        for photo in self.manager.project.photos:
            if not photo.is_available():
                w = h = 'N/A!'
            else:
                w, h = photo.raw_size()
            i = ComparingTreeWidgetItem(
                None,
                [str(photo), type(photo).__name__,
                 str(w), str(h)])
            i.__data__ = photo
            items.append(i)
        table.addTopLevelItems(items)

        @table.currentItemChanged.connect
        def _(item, prev):
            del_btn.setEnabled(item is not None)

        layout.addWidget(table, 0, 0)

        del_btn = QPushButton('delete')
        del_btn.setEnabled(False)

        @del_btn.clicked.connect
        def _(*args):
            item = table.currentItem()
            size = item.__data__
            self.manager.del_photo(size)
            shiboken2.delete(item)

        layout.addWidget(del_btn, 1, 0)

        self.setLayout(layout)
예제 #5
0
class ObjectTreeDialog(QDialog):
    def __init__(self, parent=None, root_object=None):
        super(ObjectTreeDialog, self).__init__(parent)
        self.setWindowTitle("Object Tree")

        layout = QtWidgets.QVBoxLayout()

        # Tree widget for displaying our object hierarchy
        self.tree_widget = QTreeWidget()
        self.tree_widget_columns = [
            "TYPE", "OBJECT NAME", "TEXT", "ICONTEXT", "TITLE", "WINDOW_TITLE",
            "CLASSES", "POINTER_ADDRESS", "GEOMETRY"
        ]
        self.tree_widget.setColumnCount(len(self.tree_widget_columns))
        self.tree_widget.setHeaderLabels(self.tree_widget_columns)

        # Only show our type and object name columns.  The others we only use to store data so that
        # we can use the built-in QTreeWidget.findItems to query.
        for column_name in self.tree_widget_columns:
            if column_name == "TYPE" or column_name == "OBJECT NAME":
                continue

            column_index = self.tree_widget_columns.index(column_name)
            self.tree_widget.setColumnHidden(column_index, True)

        header = self.tree_widget.header()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)

        # Populate our object tree widget
        # If a root object wasn't specified, then use the Editor main window
        if not root_object:
            params = azlmbr.qt.QtForPythonRequestBus(
                azlmbr.bus.Broadcast, "GetQtBootstrapParameters")
            editor_id = QtWidgets.QWidget.find(params.mainWindowId)
            editor_main_window = wrapInstance(int(getCppPointer(editor_id)[0]),
                                              QtWidgets.QMainWindow)
            root_object = editor_main_window
        self.build_tree(root_object, self.tree_widget)

        # Listen for when the tree widget selection changes so we can update
        # selected item properties
        self.tree_widget.itemSelectionChanged.connect(
            self.on_tree_widget_selection_changed)

        # Split our tree widget with a properties view for showing more information about
        # a selected item. We also use a stacked layout for the properties view so that
        # when nothing has been selected yet, we can show a message informing the user
        # that something needs to be selected.
        splitter = QSplitter()
        splitter.addWidget(self.tree_widget)
        self.widget_properties = QWidget(self)
        self.stacked_layout = QtWidgets.QStackedLayout()
        self.widget_info = QWidget()
        form_layout = QtWidgets.QFormLayout()
        self.name_value = QLineEdit("")
        self.name_value.setReadOnly(True)
        self.type_value = QLabel("")
        self.geometry_value = QLabel("")
        self.text_value = QLabel("")
        self.icon_text_value = QLabel("")
        self.title_value = QLabel("")
        self.window_title_value = QLabel("")
        self.classes_value = QLabel("")
        form_layout.addRow("Name:", self.name_value)
        form_layout.addRow("Type:", self.type_value)
        form_layout.addRow("Geometry:", self.geometry_value)
        form_layout.addRow("Text:", self.text_value)
        form_layout.addRow("Icon Text:", self.icon_text_value)
        form_layout.addRow("Title:", self.title_value)
        form_layout.addRow("Window Title:", self.window_title_value)
        form_layout.addRow("Classes:", self.classes_value)
        self.widget_info.setLayout(form_layout)

        self.widget_properties.setLayout(self.stacked_layout)
        self.stacked_layout.addWidget(
            QLabel("Select an object to view its properties"))
        self.stacked_layout.addWidget(self.widget_info)
        splitter.addWidget(self.widget_properties)

        # Give our splitter stretch factor of 1 so it will expand to take more room over
        # the footer
        layout.addWidget(splitter, 1)

        # Create our popup widget for showing information when hovering over widgets
        self.hovered_widget = None
        self.inspect_mode = False
        self.inspect_popup = InspectPopup()
        self.inspect_popup.resize(100, 50)
        self.inspect_popup.hide()

        # Add a footer with a button to switch to widget inspect mode
        self.footer = QWidget()
        footer_layout = QtWidgets.QHBoxLayout()
        self.inspect_button = QPushButton("Pick widget to inspect")
        self.inspect_button.clicked.connect(self.on_inspect_clicked)
        footer_layout.addStretch(1)
        footer_layout.addWidget(self.inspect_button)
        self.footer.setLayout(footer_layout)
        layout.addWidget(self.footer)

        self.setLayout(layout)

        # Delete ourselves when the dialog is closed, so that we don't stay living in the background
        # since we install an event filter on the application
        self.setAttribute(Qt.WA_DeleteOnClose, True)

        # Listen to events at the application level so we can know when the mouse is moving
        app = QtWidgets.QApplication.instance()
        app.installEventFilter(self)

    def eventFilter(self, obj, event):
        # Look for mouse movement events so we can see what widget the mouse is hovered over
        event_type = event.type()
        if event_type == QEvent.MouseMove:
            global_pos = event.globalPos()

            # Make our popup follow the mouse, but we need to offset it by 1, 1 otherwise
            # the QApplication.widgetAt will always return our popup instead of the Editor
            # widget since it is on top
            self.inspect_popup.move(global_pos + QtCore.QPoint(1, 1))

            # Find out which widget is under our current mouse position
            hovered_widget = QtWidgets.QApplication.widgetAt(global_pos)
            if self.hovered_widget:
                # Bail out, this is the same widget we are already hovered on
                if self.hovered_widget is hovered_widget:
                    return False

            # Update our hovered widget and label
            self.hovered_widget = hovered_widget
            self.update_hovered_widget_popup()
        elif event_type == QEvent.KeyRelease:
            if event.key() == Qt.Key_Escape:
                # Cancel the inspect mode if the Escape key is pressed
                # We don't need to actually hide the inspect popup here because
                # it will be hidden already by the Escape action
                self.inspect_mode = False
        elif event_type == QEvent.MouseButtonPress or event_type == QEvent.MouseButtonRelease:
            # Trigger inspecting the currently hovered widget when the left mouse button is clicked
            # Don't continue processing this event
            if self.inspect_mode and event.button() == Qt.LeftButton:
                # Only trigger the inspect on the click release, but we want to also eat the press
                # event so that the widget we clicked on isn't stuck in a weird state (e.g. thinks its being dragged)
                # Also hide the inspect popup since it won't be hidden automatically by the mouse click since we are
                # consuming the event
                if event_type == event_type == QEvent.MouseButtonRelease:
                    self.inspect_popup.hide()
                    self.inspect_widget()
                return True

        # Pass every event through
        return False

    def build_tree(self, obj, parent_tree):
        if len(obj.children()) == 0:
            return
        for child in obj.children():
            object_type = type(child).__name__
            object_name = child.objectName()
            text = icon_text = title = window_title = geometry_str = classes = "(N/A)"
            if isinstance(child, QtGui.QWindow):
                title = child.title()
            if isinstance(child, QAction):
                text = child.text()
                icon_text = child.iconText()
            if isinstance(child, QWidget):
                window_title = child.windowTitle()
                if not (child.property("class") == ""):
                    classes = child.property("class")
            if isinstance(child, QAbstractButton):
                text = child.text()

            # Keep track of the pointer address for this object so we can search for it later
            pointer_address = str(int(getCppPointer(child)[0]))

            # Some objects might not have a geometry (e.g. actions, generic qobjects)
            if hasattr(child, 'geometry'):
                geometry_rect = child.geometry()
                geometry_str = "x: {x}, y: {y}, width: {width}, height: {height}".format(
                    x=geometry_rect.x(),
                    y=geometry_rect.y(),
                    width=geometry_rect.width(),
                    height=geometry_rect.height())

            child_tree = QTreeWidgetItem([
                object_type, object_name, text, icon_text, title, window_title,
                classes, pointer_address, geometry_str
            ])
            if isinstance(parent_tree, QTreeWidget):
                parent_tree.addTopLevelItem(child_tree)
            else:
                parent_tree.addChild(child_tree)
            self.build_tree(child, child_tree)

    def update_hovered_widget_popup(self):
        if self.inspect_mode and self.hovered_widget:
            if not self.inspect_popup.isVisible():
                self.inspect_popup.show()

            self.inspect_popup.update_widget(self.hovered_widget)
        else:
            self.inspect_popup.hide()

    def on_inspect_clicked(self):
        self.inspect_mode = True
        self.update_hovered_widget_popup()

    def on_tree_widget_selection_changed(self):
        selected_items = self.tree_widget.selectedItems()

        # If nothing is selected, then switch the stacked layout back to 0
        # to show the message
        if not selected_items:
            self.stacked_layout.setCurrentIndex(0)
            return

        # Update the selected widget properties and switch to the 1 index in
        # the stacked layout so that all the rows will be visible
        item = selected_items[0]
        self.name_value.setText(
            item.text(self.tree_widget_columns.index("OBJECT NAME")))
        self.type_value.setText(
            item.text(self.tree_widget_columns.index("TYPE")))
        self.geometry_value.setText(
            item.text(self.tree_widget_columns.index("GEOMETRY")))
        self.text_value.setText(
            item.text(self.tree_widget_columns.index("TEXT")))
        self.icon_text_value.setText(
            item.text(self.tree_widget_columns.index("ICONTEXT")))
        self.title_value.setText(
            item.text(self.tree_widget_columns.index("TITLE")))
        self.window_title_value.setText(
            item.text(self.tree_widget_columns.index("WINDOW_TITLE")))
        self.classes_value.setText(
            item.text(self.tree_widget_columns.index("CLASSES")))
        self.stacked_layout.setCurrentIndex(1)

    def inspect_widget(self):
        self.inspect_mode = False

        # Find the tree widget item that matches our hovered widget, and then set it as the current item
        # so that the tree widget will scroll to it, expand it, and select it
        widget_pointer_address = str(int(
            getCppPointer(self.hovered_widget)[0]))
        pointer_address_column = self.tree_widget_columns.index(
            "POINTER_ADDRESS")
        items = self.tree_widget.findItems(
            widget_pointer_address, Qt.MatchFixedString | Qt.MatchRecursive,
            pointer_address_column)
        if items:
            item = items[0]
            self.tree_widget.clearSelection()
            self.tree_widget.setCurrentItem(item)
        else:
            print("Unable to find widget")
예제 #6
0
# ---------------------------
# Treeにitemに子itemを追加する
# ---------------------------
import sys
from PySide2.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem

app = QApplication(sys.argv)

qw_tree = QTreeWidget()
qw_tree.setHeaderLabels(["name", "tel", "mail"])
qw_tree_parent_item = QTreeWidgetItem(['family'])
qw_tree_parent_item.addChild(
    QTreeWidgetItem(['A', '111-111-111', '*****@*****.**']))  # Itemに子Itemを追加
qw_tree.addTopLevelItem(qw_tree_parent_item)
qw_tree.expandAll()  # TreeのItemを全て開く
qw_tree.show()

sys.exit(app.exec_())
예제 #7
0
# ---------------------------
# TreeをクリックしてTextEditを切り替える
# ---------------------------
import sys
from PySide2.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem, QTextEdit, QStackedWidget, QSplitter

app = QApplication(sys.argv)

qw_stack = QStackedWidget()

qw_tree = QTreeWidget()
qw_tree.setHeaderLabels(["test"])


def tree_item_clicked(item, column):
    print(item, column, item.type())
    # TreeがクリックされたときにTextEditを切り替える
    qw_stack.setCurrentIndex(item.type())


for i in range(3):
    text = 'page No.' + str(i + 1)
    qw_tree_item = QTreeWidgetItem([text], type=i)
    qw_tree.addTopLevelItem(qw_tree_item)

    qw_text_edit = QTextEdit()
    qw_text_edit.append(text)

    stack_idx = qw_stack.addWidget(qw_text_edit)
    # print(stack_idx)
예제 #8
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.attach_event()
        self.setAcceptDrops(True)
        
    def init_ui(self):
        # Define & Configure Components
        normal_button_size = QSize(80, 24)
        icon_button_size = QSize(24, 24)
        icon_size = QSize(18, 18)
        
        self.central_widget = QWidget()
        self.central_layout = QGridLayout()
        self.central_widget.setLayout(self.central_layout)

        self.tab_group_widget = QTabWidget()
        self.tab_group_widget.setMinimumSize(400, 0)
        self.tab_group_widget.setFixedHeight(150)
        self.tab1_name = '스폰서 변환'
        self.tab2_name = '싱크 조절(초)'
        self.tab3_name = '싱크 조절(%)'

        self.tab_page_1 = QWidget()
        self.tab_grid_1 = QGridLayout()
        self.tab1_search_label = QLabel('검색 텍스트')
        self.tab1_search = QLineEdit()
        self.tab1_sponsor = QWidget()
        self.tab1_sponsor_layout = QHBoxLayout()
        self.tab1_sponsor_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_sponsor_label = QLabel('스폰서 영상 길이')
        self.tab1_sponsor_value = QDoubleSpinBox()
        self.tab1_sponsor_value.setFixedWidth(60)
        self.tab1_sponsor_value.setMinimum(-1000000000)
        self.tab1_sponsor_value.setValue(10)
        self.tab1_offset = QWidget()
        self.tab1_offset_layout = QHBoxLayout()
        self.tab1_offset_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_offset_label = QLabel('라인 오프셋')
        self.tab1_offset_value = QSpinBox()
        self.tab1_offset_value.setMinimum(-1000000000)
        self.tab1_offset_value.setValue(2)
        self.tab1_offset_value.setFixedWidth(50)
        self.tab1_ignore = QWidget()
        self.tab1_ignore_layout = QHBoxLayout()
        self.tab1_ignore_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_ignore_label1 = QLabel('시작부터')
        self.tab1_ignore_value = QSpinBox()
        self.tab1_ignore_value.setFixedWidth(50)
        self.tab1_ignore_value.setValue(5)
        self.tab1_ignore_label2 = QLabel('줄 ')
        self.tab1_ignore_sec = QSpinBox()
        self.tab1_ignore_sec.setFixedWidth(60)
        self.tab1_ignore_sec.setMaximum(1000)
        self.tab1_ignore_sec.setValue(90)
        self.tab1_ignore_label3 = QLabel('초 무시하기')
        self.tab1_add_button = QPushButton('추가하기')

        self.tab_page_2 = QWidget()
        self.tab_grid_2 = QGridLayout()
        self.tab2_shift = QWidget()
        self.tab2_shift_layout = QHBoxLayout()
        self.tab2_shift_layout.setContentsMargins(0, 0, 0, 0)
        self.tab2_shift_label1 = QLabel('자막 싱크')
        self.tab2_shift_value = QDoubleSpinBox()
        self.tab2_shift_value.setFixedWidth(60)
        self.tab2_shift_label2 = QLabel('초 ')
        self.tab2_slow_radio = QRadioButton('느리게')
        self.tab2_slow_radio.setChecked(True)
        self.tab2_fast_radio = QRadioButton('빠르게')
        self.tab2_add_button = QPushButton('추가하기')

        self.tab_page_3 = QWidget()
        self.tab_grid_3 = QGridLayout()
        self.tab3_speed_label1 = QLabel('자막 싱크')
        self.tab3_speed_value = QSpinBox()
        self.tab3_speed_value.setFixedWidth(70)
        self.tab3_speed_value.setRange(1, 1000)
        self.tab3_speed_value.setValue(100)
        self.tab3_speed_label2 = QLabel('%')
        self.tab3_add_button = QPushButton('추가하기')

        self.que_label = QLabel('작업 목록')
        self.que_label.setFixedHeight(24)
        self.que_widget = QWidget()
        self.que_widget.setFixedHeight(114)
        self.que_layout = QGridLayout()
        self.que_layout.setContentsMargins(0, 0, 0, 0)
        self.que_list = QTreeWidget()
        self.que_list.setHeaderLabels(['작업', '옵션'])
        self.que_delete_button = QPushButton(QIcon(':/remove.png'), '')
        self.que_delete_button.setFixedSize(icon_button_size)
        self.que_delete_button.setIconSize(icon_size)
        self.que_delete_button.setToolTip('목록 삭제')
        self.que_up_button = QPushButton(QIcon(':/up.png'), '')
        self.que_up_button.setIconSize(icon_size)
        self.que_up_button.setFixedSize(icon_button_size)
        self.que_up_button.setToolTip('위로')
        self.que_down_button = QPushButton(QIcon(':/down.png'), '')
        self.que_down_button.setIconSize(icon_size)
        self.que_down_button.setFixedSize(icon_button_size)
        self.que_down_button.setToolTip('아래로')
        self.que_clear_button = QPushButton(QIcon(':/clear.png'), '')
        self.que_clear_button.setIconSize(icon_size)
        self.que_clear_button.setFixedSize(icon_button_size)
        self.que_clear_button.setToolTip('비우기')

        self.file_label = QLabel('파일 목록')
        self.file_label.setFixedHeight(24)
        self.file_widget = QWidget()
        self.file_layout = QGridLayout()
        self.file_layout.setContentsMargins(0, 0, 0, 0)
        self.file_list = QTreeWidget()
        self.file_list.setAcceptDrops(True)
        self.file_list.setHeaderLabels(['이름', '경로'])
        self.file_file_open = QPushButton(QIcon(':/file.png'), '')
        self.file_file_open.setFixedSize(icon_button_size)
        self.file_file_open.setIconSize(icon_size)
        self.file_file_open.setToolTip('파일 열기')
        self.file_dir_open = QPushButton(QIcon(':/folder.png'), '')
        self.file_dir_open.setFixedSize(icon_button_size)
        self.file_dir_open.setIconSize(icon_size)
        self.file_dir_open.setToolTip('폴더 열기')
        self.file_delete = QPushButton(QIcon(':/remove.png'), '')
        self.file_delete.setFixedSize(icon_button_size)
        self.file_delete.setIconSize(icon_size)
        self.file_delete.setToolTip('목록 삭제')
        self.file_clear = QPushButton(QIcon(':/clear.png'), '')
        self.file_clear.setFixedSize(icon_button_size)
        self.file_clear.setIconSize(icon_size)
        self.file_clear.setToolTip('비우기')
        self.file_encode = QPushButton(QIcon(':/encode.png'), '')
        self.file_encode.setFixedSize(icon_button_size)
        self.file_encode.setIconSize(icon_size)
        self.file_encode.setToolTip('인코딩 설정')

        self.save_widget = QGroupBox('저장 옵션')
        self.save_widget.setMinimumSize(400, 0)
        self.save_widget.setFixedHeight(82)
        self.save_layout = QGridLayout()
        self.save_orig_radio = QRadioButton('원본 위치에 저장')
        self.save_orig_radio.setChecked(True)
        self.save_strip = QCheckBox('싱크 꼬임 무시')
        self.save_strip.setToolTip('싱크 꼬임을 무시하고 모든 자막을 보존합니다.')
        self.save_dir_radio = QRadioButton('다른 위치에 저장')
        self.save_dir_line = QLineEdit()
        self.save_dir_find = QPushButton('...')
        self.save_dir_find.setFixedWidth(40)

        self.ok_button = QPushButton('적용')
        self.ok_button.setFixedSize(normal_button_size)
        self.cancel_button = QPushButton('취소')
        self.cancel_button.setFixedSize(normal_button_size)

        # Display GUI Components
        self.central_layout.addWidget(self.tab_group_widget, 0, 0, 1, 3)
        self.central_layout.addWidget(self.que_label, 1, 0, 1, 3)
        self.central_layout.addWidget(self.que_widget, 2, 0, 1, 3)
        self.central_layout.addWidget(self.file_label, 3, 0, 1, 3)
        self.central_layout.addWidget(self.file_widget, 4, 0, 1, 3)
        self.central_layout.addWidget(self.save_widget, 5, 0, 1, 3)
        self.central_layout.addWidget(self.ok_button, 6, 1, 1, 1)
        self.central_layout.addWidget(self.cancel_button, 6, 2, 1, 1)

        self.tab_group_widget.addTab(self.tab_page_1, QIcon(), self.tab1_name)
        self.tab_group_widget.addTab(self.tab_page_2, QIcon(), self.tab2_name)
        self.tab_group_widget.addTab(self.tab_page_3, QIcon(), self.tab3_name)

        self.tab_page_1.setLayout(self.tab_grid_1)
        self.tab_grid_1.addWidget(self.tab1_search_label, 0, 0, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_search, 0, 1, 1, 2)
        self.tab_grid_1.addWidget(self.tab1_sponsor, 1, 1, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_offset, 1, 2, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_ignore, 2, 1, 1, 2)
        self.tab_grid_1.addWidget(self.tab1_add_button, 3, 0, 1, 3)
        self.tab1_sponsor.setLayout(self.tab1_sponsor_layout)
        self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_label)
        self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_value)
        self.tab1_sponsor_layout.addStretch(1)
        self.tab1_offset.setLayout(self.tab1_offset_layout)
        self.tab1_offset_layout.addWidget(self.tab1_offset_label)
        self.tab1_offset_layout.addWidget(self.tab1_offset_value)
        self.tab1_offset_layout.addStretch(1)
        self.tab1_ignore.setLayout(self.tab1_ignore_layout)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label1)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_value)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label2)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_sec)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label3)
        self.tab1_ignore_layout.addStretch(1)

        self.tab_page_2.setLayout(self.tab_grid_2)
        self.tab_grid_2.setRowStretch(0, 1)
        self.tab_grid_2.addWidget(self.tab2_shift, 1, 0, 2, 1)
        self.tab_grid_2.addWidget(self.tab2_slow_radio, 1, 1, 1, 1)
        self.tab_grid_2.addWidget(self.tab2_fast_radio, 2, 1, 1, 1)
        self.tab_grid_2.setColumnStretch(2, 1)
        self.tab_grid_2.setRowStretch(3, 1)
        self.tab_grid_2.addWidget(self.tab2_add_button, 4, 0, 1, 3)
        self.tab2_shift.setLayout(self.tab2_shift_layout)
        self.tab2_shift_layout.addWidget(self.tab2_shift_label1)
        self.tab2_shift_layout.addWidget(self.tab2_shift_value)
        self.tab2_shift_layout.addWidget(self.tab2_shift_label2)

        self.tab_page_3.setLayout(self.tab_grid_3)
        self.tab_grid_3.setRowStretch(0, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_label1, 1, 0, 1, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_value, 1, 1, 1, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_label2, 1, 2, 1, 1)
        self.tab_grid_3.setColumnStretch(3, 1)
        self.tab_grid_3.setRowStretch(2, 1)
        self.tab_grid_3.addWidget(self.tab3_add_button, 3, 0, 1, 4)

        self.que_widget.setLayout(self.que_layout)
        self.que_layout.addWidget(self.que_list, 0, 0, 4, 1)
        self.que_layout.addWidget(self.que_delete_button, 0, 1, 1, 1)
        self.que_layout.addWidget(self.que_up_button, 1, 1, 1, 1)
        self.que_layout.addWidget(self.que_down_button, 2, 1, 1, 1)
        self.que_layout.addWidget(self.que_clear_button, 3, 1, 1, 1)

        self.file_widget.setLayout(self.file_layout)
        self.file_layout.addWidget(self.file_list, 0, 0, 6, 1)
        self.file_layout.addWidget(self.file_file_open, 0, 1, 1, 1)
        self.file_layout.addWidget(self.file_dir_open, 1, 1, 1, 1)
        self.file_layout.addWidget(self.file_delete, 2, 1, 1, 1)
        self.file_layout.addWidget(self.file_clear, 3, 1, 1, 1)
        self.file_layout.addWidget(self.file_encode, 5, 1, 1, 1)

        self.save_widget.setLayout(self.save_layout)
        self.save_layout.addWidget(self.save_orig_radio, 0, 0, 1, 1)
        self.save_layout.setColumnStretch(1, 1)
        self.save_layout.addWidget(self.save_strip, 0, 2, 1, 2)
        self.save_layout.addWidget(self.save_dir_radio, 1, 0, 1, 1)
        self.save_layout.addWidget(self.save_dir_line, 1, 1, 1, 2)
        self.save_layout.addWidget(self.save_dir_find, 1, 3, 1, 1)

        self.setWindowTitle('Batch SAMI Sync v0.2')
        self.setCentralWidget(self.central_widget)
        self.adjustSize()

    def attach_event(self):
        # Default encoding hack
        self.encoding = '자동'

        # Define and Connect event handlers
        def tab1_add():
            sponsor_text = self.tab1_search.text()
            sponsor_time = self.tab1_sponsor_value.value()
            line_offset = self.tab1_offset_value.value()
            line_ignore = self.tab1_ignore_value.value()
            time_ignore = self.tab1_ignore_sec.value()
            data = [1, sponsor_time, sponsor_text, line_offset, line_ignore, time_ignore]
            item = QTreeWidgetItem(self.que_list, [self.tab1_name, '스폰서 영상 시간 : ' + str(sponsor_time) + '초, 오프셋 : ' + str(line_offset) + '줄, 시작부터 ' + str(line_ignore) + '번째 줄, ' + str(time_ignore) + '초 무시 - 검색어 : ' + sponsor_text])
            item.setData(2, 2, data)

        def tab2_add():
            shift_time = self.tab2_shift_value.value()
            shift_direction = self.tab2_fast_radio.isChecked()
            direction_text = '빠르게' if shift_direction else '느리게'
            data = [2, shift_time, shift_direction]
            item = QTreeWidgetItem(self.que_list, [self.tab2_name, '자막 싱크 ' + str(shift_time) + '초 ' + direction_text])
            item.setData(2, 2, data)

        def tab3_add():
            speed_rate = self.tab3_speed_value.value()
            data = [3, speed_rate]
            item = QTreeWidgetItem(self.que_list, [self.tab3_name, '자막 속도 ' + str(speed_rate) + '%'])
            item.setData(2, 2, data)

        def file_open():
            selected = QFileDialog.getOpenFileNames(self, "자막 파일 선택", "", "SAMI Files (*.smi);;All Files (*)")
            for file in selected[0]:
                name = ntpath.basename(file)
                Utils.insert_list(self.file_list, name, file)

        def dir_open():
            selected = QFileDialog.getExistingDirectory(self, "자막 폴더 선택")
            for paths, subdirs, files in os.walk(selected):
                for file in files:
                    if fnmatch(file, '*.smi'):
                        name = ntpath.basename(file)
                        Utils.insert_list(self.file_list, name, file)

        def open_encode_dialog():
            self.dialog = QInputDialog(self)
            self.dialog.setWindowTitle('인코딩 설정')
            self.dialog.setLabelText('텍스트 인코딩 설정')
            self.dialog.setComboBoxItems(['자동', 'EUC-KR', 'UTF-8', 'UTF-16LE', 'UTF-16BE', '직접 입력'])
            self.dialog.show()

            self.dialog.textValueChanged.connect(type_encode)
            self.dialog.textValueSelected.connect(set_encode)

        def type_encode(text):
            if text == '직접 입력':
                self.dialog.setComboBoxItems([])
                self.dialog.setComboBoxEditable(True)

        def set_encode(text):
            self.encoding = text

        def save_dir():
            selected = QFileDialog.getExistingDirectory(self, "저장 위치 선택")
            self.save_dir_line.setText(selected)

        def apply():
            self.ok_button.setEnabled(False)
            ques = Utils.read_list(self.que_list, False)
            files = Utils.read_list(self.file_list, False)
            strip = False if self.save_strip.isChecked() else True
            log = []
            for file in files:
                try:
                    text = Utils.launch_que(file[1], ques, self.encoding, strip)
                    if len(text):
                        if self.save_orig_radio.isChecked():
                            savepath = file[1]
                        else:
                            savepath = self.save_dir_line.text() + '/' + file[0]
                        Utils.save_file(savepath, text)
                except Exception as e:
                    log.append(file[0] + ' 처리 오류 : ' + str(e))
            if log:
                ScrollMessageBox(QMessageBox.Warning, 'Batch SAMI Sync', "\n".join(log))

            else:
                QMessageBox.information(self, 'Batch SAMI Sync', '변환 완료!')
            self.ok_button.setEnabled(True)

        self.tab1_add_button.clicked.connect(tab1_add)
        self.tab2_add_button.clicked.connect(tab2_add)
        self.tab3_add_button.clicked.connect(tab3_add)
        self.que_delete_button.clicked.connect(lambda: Utils.delete_list(self.que_list))
        self.que_clear_button.clicked.connect(lambda: Utils.clear_list(self.que_list))
        self.que_up_button.clicked.connect(lambda: Utils.up_list(self.que_list))
        self.que_down_button.clicked.connect(lambda: Utils.down_list(self.que_list))
        self.file_file_open.clicked.connect(file_open)
        self.file_dir_open.clicked.connect(dir_open)
        self.file_delete.clicked.connect(lambda: Utils.delete_list(self.file_list))
        self.file_clear.clicked.connect(lambda: Utils.clear_list(self.file_list))
        self.file_encode.clicked.connect(open_encode_dialog)
        self.save_dir_find.clicked.connect(save_dir)
        self.ok_button.clicked.connect(apply)
        self.cancel_button.clicked.connect(sys.exit)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            for url in event.mimeData().urls():
                if url.isLocalFile():
                    file = str(url.toLocalFile())
                    if fnmatch(file, '*.smi'):
                        name = ntpath.basename(file)
                        Utils.insert_list(self.file_list, name, file)
                    elif not fnmatch(file, '*.*'):
                        for paths, subdirs, files in os.walk(file):
                            for file in files:
                                if fnmatch(file, '*.smi'):
                                    name = ntpath.basename(file)
                                    Utils.insert_list(self.file_list, name, file)

        else:
            event.ignore()
예제 #9
0
    def _initUI(self):
        def _init_tool_buttons():

            # First logic buttons
            logic_buttons_layout = QHBoxLayout()

            logic_buttons = [('NO', QPushButton('NO')),
                             ('AND', QPushButton('AND')),
                             ('OR', QPushButton('OR')),
                             ('implies', QPushButton('→')),
                             ('equivalence', QPushButton('↔')),
                             ('forall', QPushButton('∀')),
                             ('exists', QPushButton('∃'))]

            for name, button in logic_buttons:
                if name in self.tool_buttons:
                    logic_buttons_layout.addWidget(button)

            # Then proof buttons
            proof_buttons_layout = QHBoxLayout()
            proof_buttons = [\
                    ('p_contraposition', QPushButton('Proof by contraposition')),
                    ('p_absurd', QPushButton('Proof by contradicton')),
                    ('p_cases', QPushButton('Cases disjunction')),
                    ('p_induction', QPushButton('Proof by induction'))]

            for name, button in proof_buttons:
                if name in self.tool_buttons:
                    proof_buttons_layout.addWidget(button)

            # Put it all together
            buttons_layout = QVBoxLayout()
            buttons_layout.addLayout(logic_buttons_layout)
            buttons_layout.addLayout(proof_buttons_layout)

            return buttons_layout

        # Create widgets
        objects = PropobjList()
        objects.addItem('X : ensemble')
        objects.addItem('Y : ensemble')
        objects.addItem('f : X → Y')
        objects.addItem('x ∈ X')
        objects.addItem('A : partie de X')
        icon_item = QListWidgetItem('B partie de X')
        icon_item.setIcon(QIcon('icon_blue.png'))
        objects.addItem(icon_item)

        properties = PropobjList()
        properties.addItem('f est une fonction de remplissage')
        properties.addItem("transitivité de l'union")

        statements = QTreeWidget()
        statements.setAlternatingRowColors(True)
        statements.setHeaderLabels(['Énoncé', 'Identifiant'])
        anneaux_ideaux = StatementNode(statements, 'Anneaux et idéaux')
        Statement(anneaux_ideaux, ['Définition anneau', 'Définition 1.1'])
        Statement(anneaux_ideaux, ['Définition idéal', 'Définition 1.7'])
        Statement(anneaux_ideaux, ["Existence d'un idéal maximal", 'Théorème'])
        noetherianite = StatementNode(statements, 'Noetherianité')
        Statement(noetherianite, ['Transfert de Noethérianité', ''])
        Statement(noetherianite,
                  ['Principal implique noethérien', 'Proposition 2.3'])
        statements.resizeColumnToContents(0)

        goal = Goal(GOAL)

        # Create layouts
        goal_layout = QHBoxLayout()
        logic_buttons = _init_tool_buttons()  # already contains buttons
        main_layout = QVBoxLayout()
        workspace_layout = QHBoxLayout()
        propobj_layout = QVBoxLayout()
        tools_layout = QVBoxLayout()

        # Create QGroupBox to have titles
        propobj_gb = QGroupBox('Properties and objects')
        tools_gb = QGroupBox('Tools (affect goal, prop. and obj.)')

        # Put widgets in layouts and group boxes
        goal_layout.addStretch()
        goal_layout.addWidget(goal)
        goal_layout.addStretch()
        # Add space below goal
        goal_layout.setContentsMargins(0, 10, 0, 30)  #LTRB
        propobj_layout.addWidget(objects)
        propobj_layout.addWidget(properties)
        tools_layout.addLayout(logic_buttons)
        tools_layout.addWidget(statements)
        propobj_gb.setLayout(propobj_layout)
        tools_gb.setLayout(tools_layout)
        workspace_layout.addWidget(propobj_gb)
        workspace_layout.addWidget(tools_gb)

        # Don't forget me
        main_layout.addLayout(goal_layout)
        main_layout.addLayout(workspace_layout)
        self.setWindowTitle("L'union des images réciproque est l'image "\
                "réciproque de l'union — d∃∀duction")
        self.setLayout(main_layout)
        self.show()
예제 #10
0
# ---------------------------
# Treeにヘッダーを表示する
# ---------------------------
import sys
from PySide2.QtWidgets import QApplication, QTreeWidget

app = QApplication(sys.argv)

qw_tree = QTreeWidget()
qw_tree.setHeaderLabels(["name", "tel", "mail"])  # Headerをつける
qw_tree.show()

sys.exit(app.exec_())
예제 #11
0
class CourseTreeWidget(QWidget, ABookCore):
    def __init__(self, path, settings, session):
        QWidget.__init__(self)
        ABookCore.__init__(self, path, settings, session)

        self.signal = CourseTreeWidgetSignals()
        self.selectedList = []

        self.treeWidget = QTreeWidget()
        self.treeWidget.setHeaderLabels(['Name', "Course ID", "Chapter ID"])
        self.treeWidget.itemChanged.connect(self.checkbox_toggled)
        self.treeWidget.clicked.connect(self.loadResourceList)

        self.addDownloadTaskButton = QPushButton("Add to Downloader")
        self.addDownloadTaskButton.clicked.connect(self.addDownloadTask)

        self.importCourseButton = QPushButton("Import Courses")
        self.importCourseButton.clicked.connect(self.startImportCourseWidget)

        main_layout = QGridLayout()
        main_layout.addWidget(self.treeWidget, 0, 0, 1, 2)
        main_layout.addWidget(self.importCourseButton, 1, 0)
        main_layout.addWidget(self.addDownloadTaskButton, 1, 1)
        main_layout.setMargin(0)
        self.setLayout(main_layout)

        if settings['first_launch'] is True:
            settings['first_launch'] = False
            self.importCourseButton.click()
        else:
            self.createTreeRoot()

    def createTreeRoot(self):
        courseList = self.getCourseList()
        for course in courseList:
            courseId = course['courseInfoId']
            currentChapterList = self.getChapterList(courseId)
            self.createTree(self.treeWidget, 'course', course,
                            currentChapterList, courseId)

    def createTree(self, parentItem, itemType, itemData, chapterList,
                   courseId):
        if itemType == 'course':
            courseName = itemData['courseTitle']
            courseId = itemData['courseInfoId']
            courseItem = self.createCourseTreeItem(courseName, courseId,
                                                   'None', True)
            parentItem.addTopLevelItem(courseItem)
            childChapterList = self.getChildChapterList(chapterList, {'id': 0})
            self.createTree(courseItem, 'chapter', childChapterList,
                            chapterList, courseId)
        elif itemType == 'chapter':
            for chapter in itemData:
                childChapterList = self.getChildChapterList(
                    chapterList, chapter)
                chapterName = chapter['name']
                chapterId = chapter['id']
                hasChild = len(childChapterList) > 0
                chapterItem = self.createCourseTreeItem(
                    chapterName, courseId, chapterId, hasChild)
                parentItem.addChild(chapterItem)
                if hasChild:
                    self.createTree(chapterItem, 'chapter', childChapterList,
                                    chapterList, courseId)
        else:
            raise KeyError('Wrong TODO')

    def checkbox_toggled(self, node: QTreeWidgetItem, column: int):
        if node.checkState(column) == Qt.Checked:
            self.selectedList.append(
                [node.text(0), node.text(1),
                 node.text(2)])
        elif node.checkState(column) == Qt.Unchecked:
            if len(self.selectedList) > 1:
                self.selectedList.remove(
                    [node.text(0), node.text(1),
                     node.text(2)])
            else:
                self.selectedList = []

    def createCourseTreeItem(self, name: str, courseId: str, chapterId: str,
                             hasChild: bool):
        item = QTreeWidgetItem()
        item.setText(0, str(name))
        item.setText(1, str(courseId))
        item.setText(2, str(chapterId))
        if hasChild is True:
            item.setFlags(item.flags() | Qt.ItemIsTristate
                          | Qt.ItemIsUserCheckable)
        else:
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(0, Qt.Unchecked)
        return item

    def addDownloadTask(self):
        for item in self.selectedList:
            if item[1] != "None" and item[2] != "None":
                courseId = item[1]
                chapterId = item[2]
                downloadList = self.getResourceList(courseId, chapterId)
                if downloadList is not None:
                    for resource in downloadList:
                        fileDir, filePath, fileName, coursePath = self.getResourcePath(
                            courseId, chapterId, resource["resourceInfoId"])
                        self.signal.addDownloadTask.emit(
                            fileName, filePath,
                            "http://abook.hep.com.cn/ICourseFiles/" +
                            resource["resFileUrl"])

    def startImportCourseWidget(self):
        wizard = ImportCourseWizard(self)
        wizard.show()

    def loadResourceList(self):
        # When triggered on click, first adjust the width of the column
        self.treeWidget.resizeColumnToContents(0)
        self.treeWidget.resizeColumnToContents(1)
        self.treeWidget.resizeColumnToContents(2)

        # Get the course_id and chapter_id
        courseId = self.sender().currentItem().text(1)
        chapterId = self.sender().currentItem().text(2)

        # Ignore the root nodes
        if courseId != "None" and chapterId != "None":

            # Get the resource list
            # resource_list = self.get_resource_info(courseId, chapterId)
            resourceList = self.getResourceList(courseId, chapterId)
            # Clear the FileListWidget
            self.signal.clearFileListWidget.emit()
            # If resource list is not empty
            if isinstance(resourceList, list):
                # Each resource item is a QStandardItem
                # data role -1 stores the url of the resource
                # data role -2 stores the url of the preview image of the resource
                # data role Qt.TooltipRole stores the url of the resource
                # data role Qt.DecorationRole stores the preview image of the resource
                # We need to lazy load and cache the preview image so that the main thread will not be blocked
                # 1. create items without the Qt.DecorationRole and add it to resourceItemList
                # 2. pass the resource_item_list to LoadPicWorker to cache and load
                resourceItemList = []
                for resource in resourceList:
                    resName = resource["resTitle"]
                    urlBase = "http://abook.hep.com.cn/ICourseFiles/"
                    resFileUrl = urlBase + resource["resFileUrl"]
                    resourceItem = QStandardItem(resName)
                    resourceItem.setData(resFileUrl, Qt.ToolTipRole)
                    resourceItem.setData(resFileUrl, -1)
                    resourceItem.setData(resource['picUrl'], -2)
                    self.signal.appendRowFileListWidget.emit(resourceItem)
                    resourceItemList.append(resourceItem)
                loadPicWorker = LoadPicWorker(resourceItemList, self)
                loadPicWorker.start()
예제 #12
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()
예제 #13
0
class MemTree(QWidget):
    def __init__(self, qmp, parent):
        super().__init__()
        self.qmp = qmp
        self.qmp.memoryMap.connect(self.update_tree)

        self.parent = parent

        self.tree_sem = QSemaphore(1)
        self.sending_sem = QSemaphore(
            1)  # used to prevent sending too many requests at once

        self.init_ui()
        self.get_map()

    def init_ui(self):

        self.vbox = QVBoxLayout()

        self.refresh = QPushButton('Refresh')
        self.refresh.clicked.connect(lambda: self.get_map())
        self.vbox.addWidget(self.refresh)

        self.tree = QTreeWidget()
        self.tree.itemDoubleClicked.connect(self.open_region)
        self.tree.setColumnCount(3)
        self.tree.header().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.tree.setHeaderLabels(
            ['Memory Region', 'Start Address', 'End Address'])
        self.vbox.addWidget(self.tree)

        self.setLayout(self.vbox)
        self.setGeometry(100, 100, 500, 300)
        self.setWindowTitle("Memory Tree")
        self.show()

    def get_map(self):
        self.tree.clear()
        self.qmp.command('mtree')

    # finds item with name 'name' in self.tree
    # self.tree_sem must be acquired before use
    def find(self, name, node):
        if node.text(0) == name:
            return node
        else:
            for i in range(node.childCount()):
                result = self.find(name, node.child(i))
                if result:
                    return result
            return None

    def update_tree(self, value):
        if value != None:
            self.tree_sem.acquire()
            current_addr_space = ''

            for region in value:
                parent_node = self.tree
                parent = region['parent']

                if parent != '':
                    root = self.tree.invisibleRootItem()
                    for i in range(root.childCount()):
                        if root.child(i).text(0) == current_addr_space:
                            root = root.child(i)
                            break
                    parent_node = self.find(parent, root)
                else:
                    current_addr_space = region['name']

                node = QTreeWidgetItem(parent_node)
                node.setText(0, region['name'])
                start = region['start']
                end = region['end']
                if start < 0:
                    start = start + (1 << constants['bits'])
                if end < 0:
                    end = end + (1 << constants['bits'])
                node.setText(1, f'{start:016x}')
                node.setText(2, f'{end:016x}')
                node.setFont(0, QFont('Courier New'))
                node.setFont(1, QFont('Courier New'))
                node.setFont(2, QFont('Courier New'))

            self.tree_sem.release()

    def open_region(self, node, col):
        self.parent.open_new_window(
            MemDumpWindow(self.qmp,
                          base=int(node.text(1), 16),
                          max=int(node.text(2), 16)))
예제 #14
0
class DiscoverUi(QWidget):
    
    def __init__(self):
        super().__init__()
        
        self.discover = Discover()
        self.devices = self.discover.devices
        self.listWidget = None
        self.treeWidget = None
        self.initUI()
        self.mac_addr = None

    def initDevices(self):
        for device in self.devices:
            newItem = QListWidgetItem()
            newItem.setText(device.name + " (" + device.address + ")")
            self.listWidget.addItem(newItem)

    def initUI(self):
        self.listWidget = QListWidget()
        self.initDevices()

        self.treeWidget = QTreeWidget()
        self.treeWidget.itemPressed.connect(self.onItemPressed)
        self.treeWidget.setColumnCount(4)
        self.treeWidget.setColumnWidth(0, 250)
        self.treeWidget.setColumnWidth(1, 300)
        self.treeWidget.setColumnWidth(2, 300)
        self.treeWidget.setColumnWidth(3, 150)
        self.treeWidget.setHeaderLabels(["Service", "Service UUID", "Characteristic UUID", "Characteristic Property"])

        btn = QPushButton("Read Services")
        btn.clicked.connect(self.onPushButton)

        groupDevices = QGroupBox("Devices")
        groupDevices.setMaximumWidth(300)

        vbox = QVBoxLayout()
        vbox.addWidget(self.listWidget)
        vbox.addWidget(btn)
        groupDevices.setLayout(vbox)

        self.btnR = QPushButton("Read")
        self.btnR.clicked.connect(self.onReadButton)
        self.btnW = QPushButton("Write")
        self.btnW.clicked.connect(self.onWriteButton)
        self.lneI = QLineEdit()
        self.chkN = QCheckBox("Notify")
        self.chkN.toggled.connect(self.onNotifyCheck)
        hbox = QHBoxLayout()
        hbox.addWidget(self.btnR)
        hbox.addWidget(self.btnW)
        hbox.addWidget(self.lneI)
        hbox.addWidget(self.chkN)

        groupProperty = QGroupBox("Property")
        #groupProperty.setLayout(vbox)
        groupProperty.setLayout(hbox)

        groupServices = QGroupBox("Services")

        vbox = QVBoxLayout()
        vbox.addWidget(self.treeWidget)
        vbox.addWidget(groupProperty)
        groupServices.setLayout(vbox)

        hbox = QHBoxLayout()
        hbox.addWidget(groupDevices)
        hbox.addWidget(groupServices)
        self.setLayout(hbox)
        
        self.setGeometry(300, 300, 800, 600)
        self.setWindowTitle('BLE Discover')
        self.show()

    def onPushButton(self):
        try:
            self.mac_addr = self.devices[self.listWidget.currentRow()].address
            self.discover.getServices(self.mac_addr)
        except:
            print("Could not get GATT services.")
        else:
            svcs = self.discover.svcs
            for serviceKey, serviceValue in svcs.services.items():
                item = QTreeWidgetItem(None, [serviceValue.description, serviceValue.uuid])
                
                for characteristic in serviceValue.characteristics:
                    for property in characteristic.properties:
                        child = QTreeWidgetItem(["", "", characteristic.uuid, property])
                        item.addChild(child)

                self.treeWidget.addTopLevelItem(item)


    def onReadButton(self):
        byteArray = self.discover.readGattChar(self.mac_addr, self.chosenUuid)
        text = ''.join('{:02x}'.format(x) for x in byteArray)
        self.lneI.setText(text)

    def onWriteButton(self):
        text = self.lneI.text()
        print("onWriteButton")
        self.discover.writeGattChar(self.mac_addr, self.chosenUuid, bytes.fromhex(text))

    def notifyCallback(self, sender, data):
        text = ''.join('{:02x}'.format(x) for x in data)
        self.lneI.textChanged.emit(text)

    def onNotifyCheck(self, checked):
        if checked:
            print("onNotifyCheck")
            self.discover.startNotify(self.mac_addr, self.chosenUuid, self.notifyCallback)
        else:
            print("onNotifyCheck else")
            

    def onItemPressed(self, item, column):
        if item.child(0) is None:
            print(item)
            print(item.text(2))
            print(item.text(3))
            self.chosenUuid = item.text(2)
            property = item.text(3)

            if property == "read":
                self.btnR.setEnabled(True)
                self.btnW.setEnabled(False)
                self.lneI.setEnabled(False)
                self.chkN.setEnabled(False)
            elif property == "write":
                self.btnR.setEnabled(True)
                self.btnW.setEnabled(True)
                self.lneI.setEnabled(True)
                self.chkN.setEnabled(False)
            elif property == "notify":
                self.btnR.setEnabled(False)
                self.btnW.setEnabled(False)
                self.lneI.setEnabled(False)
                self.chkN.setEnabled(True)