Beispiel #1
0
 def show_log(self, key, log):
     d = WindowModalDialog(self, _("Payment log"))
     vbox = QVBoxLayout(d)
     log_w = QTreeWidget()
     log_w.setHeaderLabels(
         [_('Route'),
          _('Channel ID'),
          _('Message'),
          _('Blacklist')])
     for i, (route, success, failure_log) in enumerate(log):
         route_str = '%d' % len(route)
         if not success:
             sender_idx, failure_msg, blacklist = failure_log
             short_channel_id = route[sender_idx + 1].short_channel_id
             data = failure_msg.data
             message = repr(failure_msg.code)
         else:
             short_channel_id = route[-1].short_channel_id
             message = _('Success')
             blacklist = False
         chan_str = format_short_channel_id(short_channel_id)
         x = QTreeWidgetItem(
             [route_str, chan_str, message,
              repr(blacklist)])
         log_w.addTopLevelItem(x)
     vbox.addWidget(log_w)
     vbox.addLayout(Buttons(CloseButton(d)))
     d.exec_()
Beispiel #2
0
class CBPAttrWidget(QWidget):
    def __init__(self, bpID, parent=None):
        super(CBPAttrWidget, self).__init__(parent)
        self.m_TreeWidget = None
        self.m_BPID = bpID
        self._InitUI()
        self._InitAttrUI()

    def _InitUI(self):
        self.m_TreeWidget = QTreeWidget(self)
        self.m_TreeWidget.setHeaderHidden(True)
        vBox = QVBoxLayout(self)
        vBox.addWidget(self.m_TreeWidget)
        self.setLayout(vBox)
        self.m_TreeWidget.setIndentation(0)

    def _InitAttrUI(self):
        for (sType, cls) in [
            (define.BP_ATTR_GRAPHIC, graphictree.CGraphicAttrTree),
            (define.BP_ATTR_VARIABLE, variabletree.CVariableAttrTree),
        ]:
            item = QTreeWidgetItem()
            self.m_TreeWidget.addTopLevelItem(item)
            oHeadWidget = basetree.CExpandWidget(item, sType, self.m_BPID)
            self.m_TreeWidget.setItemWidget(item, 0, oHeadWidget)

            section = QTreeWidgetItem(item)
            section.setDisabled(True)
            oWidget = cls(self.m_BPID, self)
            self.m_TreeWidget.setItemWidget(section, 0, oWidget)
            item.addChild(section)
Beispiel #3
0
    def on_tensor_data_update(self, tensor_data):
        #for x in range(self.tw.topLevelItemCount()):
        #    pass
        if self.tw: self.tw.deleteLater()

        tw = QTreeWidget(self)
        self.layout.addWidget(tw)
        tw.setColumnCount(2)
        tw.setHeaderLabels(["where", "rank", "size"])

        for x in range(tensor_data.partitions[0]):
            x_child = QTreeWidgetItem(["x:{}".format(x)])
            #x_child.setText(0, "Hello")
            for y in range(tensor_data.partitions[1]):
                y_child = QTreeWidgetItem(["y:{}".format(y)])
                for z in range(tensor_data.partitions[2]):
                    sub_x, sub_y, sub_z = tensor_data.sub_size(x, y, z)
                    z_child = QTreeWidgetItem(["z:{}".format(z)
                        , "{}".format(tensor_data.rank(x, y, z))
                        , "{}x{}x{}".format(sub_x, sub_y, sub_z)
                        ])
                    y_child.addChild(z_child)
                x_child.addChild(y_child)
            tw.addTopLevelItem(x_child)

        self.tw = tw
        self.is_expanded = False
Beispiel #4
0
class PlotItemMenu(QWidget):

    messageKeyRole = Qt.UserRole + 1
    plotDataSignal = pyqtSignal(object, int)

    def __init__(self, parent = None):
        super().__init__(parent)
        self.setLayout(QVBoxLayout())
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        self.tree.setColumnCount(1)
        self.tree.itemChanged.connect(self.__toggleDataPlot)
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().addWidget(self.tree)
        self.rootItems = []

    def addMAVLinkMessage(self, msg):
        tp = msg.get_type()
        if tp not in self.rootItems:
            self.rootItems.append(tp)
            rt = QTreeWidgetItem(self.tree)
            rt.setText(0, tp)
            for attr in msg.get_fieldnames():
                if attr not in PlotterPanel.IGNORED_ATTRIBUTES:
                    chld = QTreeWidgetItem()
                    chld.setText(0, attr)
                    chld.setFlags(chld.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable)
                    chld.setCheckState(0, Qt.Unchecked)
                    chld.setData(0, PlotItemMenu.messageKeyRole, QVariant('{}.{}'.format(tp, attr)))
                    rt.addChild(chld)
            self.tree.addTopLevelItem(rt)

    def __toggleDataPlot(self, item, col):
        self.plotDataSignal.emit(item.data(col, PlotItemMenu.messageKeyRole), item.checkState(col))
Beispiel #5
0
    def show_table_context_menu(self, position):
        col = self.dataWidget.columnAt(position.x())
        dialog = QDialog(self, Qt.Popup)
        schema_view = QTreeWidget(dialog)
        schema_view.headerItem().setText(0, "Field")
        schema_view.headerItem().setText(1, "Type")
        root = type_parser.parse(self.data_schema[col])
        schema_tree = self.type_tree(
            self.dataWidget.horizontalHeaderItem(col).text(), root)
        schema_view.addTopLevelItem(schema_tree)
        schema_view.expandToDepth(2)
        schema_view.header().setStretchLastSection(False)
        schema_view.setSizeAdjustPolicy(
            QAbstractScrollArea.AdjustToContentsOnFirstShow)
        schema_view.header().setSectionResizeMode(QHeaderView.ResizeToContents)
        schema_view.setMinimumHeight(30)
        schema_view.setMaximumHeight(400)
        schema_view.adjustSize()
        schema_view.setHeaderHidden(True)

        dialog.move(
            self.dataWidget.mapToGlobal(position) +
            QPoint(dialog.width() / 5 * 2,
                   dialog.height() + 5))
        dialog.adjustSize()
        dialog.show()
Beispiel #6
0
class List(QWidget):

    def __init__(self, rt, article_list):
        super().__init__()
        self.rt = rt
        self.layout = QVBoxLayout(self)
        self.tool_bar = ToolBar(self)
        self.list_widget = QTreeWidget()
        self.article_list = article_list
        for article in article_list:
            if 'id' in article:
                item = Item(article['title'], id=article['id'])
            elif 'children' in article:
                item = Item(article['title'], children=article['children'])
            self.list_widget.addTopLevelItem(item)
        self.list_widget.itemClicked.connect(self.select)
        self.layout.addWidget(self.list_widget)
        self.layout.addWidget(self.tool_bar)

    def select(self, item):
        if not hasattr(item, 'id'):
            return
        self.rt.ui.view.set_article(*self.rt.article.item(item.id))

    def add(self, title):
        id, self.article_list = self.rt.article.add(title)
        item = Item(title, id=id)
        self.list_widget.addTopLevelItem(item)

    def edit(self):
        pass

    def remove(self):
        pass
Beispiel #7
0
 def show_log(self, key, log: Sequence[PaymentAttemptLog]):
     d = WindowModalDialog(self, _("Payment log"))
     d.setMinimumWidth(800)
     vbox = QVBoxLayout(d)
     log_w = QTreeWidget()
     log_w.setHeaderLabels([_('Route'), _('Channel ID'), _('Message'), _('Blacklist')])
     for payment_attempt_log in log:
         if not payment_attempt_log.exception:
             route = payment_attempt_log.route
             route_str = '%d'%len(route)
             if not payment_attempt_log.success:
                 sender_idx = payment_attempt_log.failure_details.sender_idx
                 failure_msg = payment_attempt_log.failure_details.failure_msg
                 blacklist_msg = str(payment_attempt_log.failure_details.is_blacklisted)
                 short_channel_id = route[sender_idx+1].short_channel_id
                 data = failure_msg.data
                 message = repr(failure_msg.code)
             else:
                 short_channel_id = route[-1].short_channel_id
                 message = _('Success')
                 blacklist_msg = str(False)
             chan_str = str(short_channel_id)
         else:
             route_str = 'None'
             chan_str = 'N/A'
             message = str(payment_attempt_log.exception)
             blacklist_msg = 'N/A'
         x = QTreeWidgetItem([route_str, chan_str, message, blacklist_msg])
         log_w.addTopLevelItem(x)
     vbox.addWidget(log_w)
     vbox.addLayout(Buttons(CloseButton(d)))
     d.exec_()
Beispiel #8
0
class CollapsibleDialog(QDialog):
    """a dialog to which collapsible sections can be added;
    subclass and reimplement define_sections() to define sections and
        add them as (title, widget) tuples to self.sections
    """
    def __init__(self):
        super().__init__()
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        self.setLayout(layout)
        self.tree.setIndentation(0)

        self.sections = []
        self.define_sections()
        self.add_sections()

    def add_sections(self):
        """adds a collapsible sections for every 
        (title, widget) tuple in self.sections
        """
        for (title, widget) in self.sections:
            button1 = self.add_button(title)
            section1 = self.add_widget(button1, widget)
            button1.addChild(section1)

    def define_sections(self):
        """reimplement this to define all your sections
        and add them as (title, widget) tuples to self.sections
        """
        widget = QFrame(self.tree)
        layout = QHBoxLayout(widget)
        layout.addWidget(QLabel("Bla"))
        layout.addWidget(QLabel("Blubb"))
        title = "Section 1"
        self.sections.append((title, widget))

    def add_button(self, title):
        """creates a QTreeWidgetItem containing a button 
        to expand or collapse its section
        """
        item = QTreeWidgetItem()
        self.tree.addTopLevelItem(item)
        self.tree.setItemWidget(item, 0, SectionExpandButton(item, text=title))
        return item

    def add_widget(self, button, widget):
        """creates a QWidgetItem containing the widget,
        as child of the button-QWidgetItem
        """
        section = QTreeWidgetItem(button)
        section.setDisabled(True)
        self.tree.setItemWidget(section, 0, widget)
        return section
class MyApp(object):    
    def __init__(self):
        super(MyApp, self).__init__()                
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)

        self.hLayout = QHBoxLayout()
        self.mainLayout.insertLayout(0, self.hLayout)


        self.listA = QTreeWidget()
        self.listA.setColumnCount(3)
        self.listA.setHeaderLabels(['Checkbox','Name','Data'])

        for i in range(3):
            item = QTreeWidgetItem()
            item.setCheckState(0,QtCore.Qt.Checked)
            item.setText(1, 'Item '+str(i))
            item.setData(2, QtCore.Qt.UserRole, id(item) )
            item.setText(2, str(id(item) ) )
            self.listA.addTopLevelItem(item)

        self.hLayout.addWidget(self.listA)

        self.buttonGroupbox = QGroupBox()
        self.buttonlayout = QVBoxLayout()
        self.buttonGroupbox.setLayout(self.buttonlayout)

        okButton = QPushButton('Remove Selected')
        okButton.clicked.connect(self.removeSel)
        self.buttonlayout.addWidget(okButton)

        getDataButton = QPushButton('Get Items Data')
        getDataButton.clicked.connect(self.getItemsData)
        self.buttonlayout.addWidget(getDataButton)

        self.mainLayout.addWidget(self.buttonGroupbox)
        self.mainWidget.show()
        sys.exit(app.exec_())

    def removeSel(self):
        listItems=self.listA.selectedItems()
        if not listItems: return   
        for item in listItems:
            itemIndex=self.listA.indexOfTopLevelItem(item)
            self.listA.takeTopLevelItem(itemIndex)
        print('\n\t Number of items remaining', self.listA.topLevelItemCount())

    def getItemsData(self):
        for i in range(self.listA.topLevelItemCount()):
            item=self.listA.topLevelItem(i)
            itmData=item.data(2, QtCore.Qt.UserRole)
            itemId=itmData.toPyObject()
            print('\n\t Item Id Stored as Item Data:', itemId, 'Item Checkbox State:', item.checkState(0))
Beispiel #10
0
class Editor(QDialog):
    """Basic scene editor."""
    def __init__(self, parent: MainWindow, renderers: List[Renderer]) -> None:
        """Initialize the Editor."""
        super().__init__(parent=parent)
        self.renderers = renderers

        self.tree_widget = QTreeWidget()
        self.tree_widget.setHeaderHidden(True)
        self.stacked_widget = QStackedWidget()
        self.layout = QHBoxLayout()
        self.layout.addWidget(self.tree_widget)
        self.layout.addWidget(self.stacked_widget)

        def _selection_callback() -> None:
            for item in self.tree_widget.selectedItems():
                widget_idx = item.data(0, Qt.ItemDataRole.UserRole)
                self.stacked_widget.setCurrentIndex(widget_idx)

        self.tree_widget.itemSelectionChanged.connect(_selection_callback)

        self.setLayout(self.layout)
        self.setWindowTitle("Editor")
        self.setModal(True)

        self.update()

    def update(self) -> None:
        """Update the internal widget list."""
        self.tree_widget.clear()
        for idx, renderer in enumerate(self.renderers):
            actors = renderer._actors  # pylint: disable=protected-access
            widget_idx = self.stacked_widget.addWidget(
                _get_renderer_widget(renderer))
            top_item = QTreeWidgetItem(self.tree_widget,
                                       ["Renderer {}".format(idx)])
            top_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx)
            self.tree_widget.addTopLevelItem(top_item)
            for name, actor in actors.items():
                if actor is not None:
                    widget_idx = self.stacked_widget.addWidget(
                        _get_actor_widget(actor))
                    child_item = QTreeWidgetItem(top_item, [name])
                    child_item.setData(0, Qt.ItemDataRole.UserRole, widget_idx)
                    top_item.addChild(child_item)
        self.tree_widget.expandAll()

    def toggle(self) -> None:
        """Toggle the editor visibility."""
        self.update()
        if self.isVisible():
            self.hide()
        else:
            self.show()
Beispiel #11
0
def build_conflict_tree_widget(container: QTreeWidget,
                               archive_instance: ArchiveInstance):
    for root, conflicts in archive_instance.conflicts():
        root_widget = QTreeWidgetItem()
        root_widget.setText(0, root)
        root_widget.setText(1, "")
        for item in conflicts:
            if isinstance(item, FileMetadata):
                content = [item.path, item.origin]
            else:
                content = [item, "Archive"]
            _create_treewidget(content, root_widget)
        container.addTopLevelItem(root_widget)
Beispiel #12
0
class PropertyWindow(QDockWidget):
    def __init__(self, info):
        """Property Window

        Args:
            info ([type]): [description]
        """
        super().__init__()
        self.setWindowTitle('Info')

        self.treeview = QTreeWidget()
        self.treeview.setHeaderLabels(["Property", "Value"])
        name_item = QTreeWidgetItem(["Name", info.file_name])
        hash_item = QTreeWidgetItem(["Hash", info.file_hash])
        location_item = QTreeWidgetItem(["Location", info.file_path])
        tag_item = QTreeWidgetItem(["Tags", info.tags])
        created_item = QTreeWidgetItem(['Created', str(info.created)])

        self.treeview.addTopLevelItem(name_item)
        self.treeview.addTopLevelItem(hash_item)
        self.treeview.addTopLevelItem(location_item)
        self.treeview.addTopLevelItem(tag_item)
        self.treeview.addTopLevelItem(created_item)

        self.setWidget(self.treeview)
 def show_log(self, key, log: Sequence[HtlcLog]):
     d = WindowModalDialog(self, _("Payment log"))
     d.setMinimumWidth(600)
     vbox = QVBoxLayout(d)
     log_w = QTreeWidget()
     log_w.setHeaderLabels([_('Hops'), _('Channel ID'), _('Message')])
     log_w.header().setSectionResizeMode(2, QHeaderView.Stretch)
     log_w.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
     for payment_attempt_log in log:
         route_str, chan_str, message = payment_attempt_log.formatted_tuple()
         x = QTreeWidgetItem([route_str, chan_str, message])
         log_w.addTopLevelItem(x)
     vbox.addWidget(log_w)
     vbox.addLayout(Buttons(CloseButton(d)))
     d.exec_()
Beispiel #14
0
    def init_ui(self):
        vbox = QVBoxLayout()
        treewidget = QTreeWidget()
        vbox.addWidget(treewidget)

        self.setLayout(vbox)

        treewidget.setColumnCount(3)

        item1 = QTreeWidgetItem(['1', '2', '3'])
        treewidget.addTopLevelItem(item1)

        item2 = QTreeWidgetItem(['1', '2', '3'])
        item1.addChild(item2)

        treewidget.setStyle(YqStyle())
Beispiel #15
0
def populate_tree_view(root: Node, tree: QTreeWidget, basis=None) -> None:
    """
    Populates a given tree view with a tree and optionally a basis
    :param root: root of a tree
    :param tree: tree view to populate
    :param basis: basis of the
    """
    root_item = QTreeWidgetItem(root.to_list())
    for i in range(2):
        root_item.setTextAlignment(i + 1, Qt.AlignCenter)
    stack: list[Tuple[Node, QTreeWidgetItem]] = [(root, root_item)]

    # Initializing brushes
    success = QBrush()
    fail = QBrush()
    success.setColor(QColor(Qt.green))
    fail.setColor(QColor(Qt.red))

    while len(stack) > 0:
        cur, cur_item = stack.pop()
        for child in cur.children:
            item = QTreeWidgetItem(child.to_list())
            for i in range(2):
                item.setTextAlignment(i + 1, Qt.AlignCenter)
            cur_item.addChild(item)
            stack.append((child, item))
        if cur.terminal == "SUCCESS":
            cur_item.setBackground(0, success)
        elif cur.terminal == "FAIL":
            cur_item.setBackground(0, fail)

    tree.clear()
    tree.addTopLevelItem(root_item)

    if basis:
        basis_root = QTreeWidgetItem(["Basis"])
        for i in range(2):
            basis_root.setTextAlignment(i + 1, Qt.AlignCenter)
        for num, (first, second) in enumerate(basis):
            child = QTreeWidgetItem([
                '#' + str(num), '(' + ", ".join(first) + ')',
                '(' + ", ".join(second) + ')', 'BASIS'
            ])
            for i in range(2):
                child.setTextAlignment(i + 1, Qt.AlignCenter)
            basis_root.addChild(child)
        tree.addTopLevelItem(basis_root)
Beispiel #16
0
class Example(QWidget):
    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):
        self.tree = QTreeWidget(self)
        self.tree.setColumnCount(2)
        self.tree.setHeaderLabels(["key","values"])

        root = QTreeWidgetItem()
        root.setText(0,"root")
        root.setCheckState(0, Qt.Checked)
        child1 = QTreeWidgetItem(root)
        child1.setText(0, 'child1')
        child1.setText(1, 'ios')
        child1.setCheckState(0, Qt.Checked)
        # root.addChild(child1)

        child2 = QTreeWidgetItem(root)
        child2.setText(0, 'child2')
        child2.setText(1, '')
        child2.setCheckState(0, Qt.Checked)


        child3 = QTreeWidgetItem(child2)
        child3.setText(0, 'child3')
        child3.setText(1, 'android')


        self.tree.addTopLevelItem(root)
        self.tree.expandAll()
        # self.setCentralWidget(self.tree)

        self.tree.clicked.connect(self.onClicked)


        self.setGeometry(300, 300, 280, 170)
        self.setWindowTitle('QTreeWidget')
        self.show()



    def onClicked(self, qmodeLindex):
        item = self.tree.currentItem()
        print('Key=%s,value=%s,parent=%s,index=%s' % (item.text(0), item.text(1),item.parent().text(0),item.parent().indexOfChild(item)))
Beispiel #17
0
    def article_list_layout(self):

        lst = QTreeWidget()
        header_lst = ["Location", "Title", "id", "Status", "Tags"]
        header = QTreeWidgetItem(header_lst)
        lst.setHeaderItem(header)
        lst.setSelectionMode(QAbstractItemView.ExtendedSelection)

        for article in self.selection_article_list:
            lst.addTopLevelItem(article)

        for column in range(len(header_lst)):
            lst.resizeColumnToContents(column)

        self.article_tree = lst

        return self.article_tree
Beispiel #18
0
class MyWin(QtWidgets.QMainWindow):
    def __init__(self, parent= None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)


    def init_ui(self):
        # Creating the required widgets
        self.vboxLayout = QVBoxLayout()
        self.treeWidget = QTreeWidget()
        self.label = QLabel("I'm going to inform you about the buttons")
        # Adding the widgets
        self.vboxLayout.addWidget(self.treeWidget)
        self.vboxLayout.addWidget(self.label)

        self.topLevelItem = QTreeWidgetItem()

        # Creating top level and child widgets
        self.topLevelButton= QComboBox()

        self.childButton_1 = QPushButton("Child 1")
        self.childButton_2 = QPushButton("Child 2")
        self.childButton_3 = QPushButton("Child 3")
        self.childLineEdit = QLineEdit()
        self.childLineEdit.setPlaceholderText("Add Text Here")

        # Adding the child to the top level item
        self.childItems = []
        for i in range(4):
            self.childItems.append(QTreeWidgetItem())
            self.topLevelItem.addChild(self.childItems[i])

        self.treeWidget.addTopLevelItem(self.topLevelItem)
        self.treeWidget.setItemWidget(self.topLevelItem, 0, self.topLevelButton)

        # Replacing the child items with widgets
        self.treeWidget.setItemWidget(self.childItems[0], 0, self.childButton_1)
        self.treeWidget.setItemWidget(self.childItems[1], 0, self.childButton_2)
        self.treeWidget.setItemWidget(self.childItems[2], 0, self.childButton_3)
        self.treeWidget.setItemWidget(self.childItems[3], 0, self.childLineEdit)


        # Setting the layout

        self.setLayout(self.vboxLayout)
class InfoDialog(QDialog):
    def __init__(self, parent, info, title):
        super().__init__(parent)

        self.setWindowTitle(
            translate('MediaInfo', 'Media Info') + ' - ' + title)
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMinimumSize(550, 300)
        self.resize(550, 500)

        self.vLayout = QVBoxLayout(self)

        self.infoTree = QTreeWidget(self)
        self.infoTree.setColumnCount(2)
        self.infoTree.setHeaderLabels(
            [translate('MediaInfo', 'Info'),
             translate('MediaInfo', 'Value')])
        self.infoTree.setAlternatingRowColors(True)
        self.infoTree.setSelectionMode(QAbstractItemView.NoSelection)
        self.infoTree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.infoTree.header().setStretchLastSection(False)
        self.infoTree.header().setSectionResizeMode(
            QHeaderView.ResizeToContents)
        self.vLayout.addWidget(self.infoTree)

        self.__generate_items(info)
        self.infoTree.expandAll()

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
        self.vLayout.addWidget(self.buttonBox)

        self.buttonBox.rejected.connect(self.close)

    def __generate_items(self, info, parent=None):
        for key in sorted(info.keys()):
            if isinstance(info[key], dict):
                widget = QTreeWidgetItem([key])
                self.__generate_items(info[key], widget)
            else:
                widget = QTreeWidgetItem([key, info[key]])

            if parent is not None:
                parent.addChild(widget)
            else:
                self.infoTree.addTopLevelItem(widget)
Beispiel #20
0
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)

        tree_widget = QTreeWidget()
        self.tree_widget = tree_widget
        tree_widget.setAlternatingRowColors(True)

        branch1 = QTreeWidgetItem()
        branch1.setText(0, "branch1")

        branch2 = QTreeWidgetItem()
        branch2.setText(0, "branch2")

        def addItem(branch, name, num, num2):
            item = QTreeWidgetItem(branch)
            item.setFlags(item.flags() | Qt.ItemIsEditable)
            item.setText(0, name)
            item.setText(1, str(num))
            item.setText(2, str(num2))

        addItem(branch1, "apple", 1, 100)
        addItem(branch1, "banana", 2, 200)
        addItem(branch2, "lemon", 3, 300)
        addItem(branch2, "orange", 4, 400)

        tree_widget.addTopLevelItem(branch1)
        tree_widget.addTopLevelItem(branch2)

        tree_widget.setColumnCount(3)
        tree_widget.setHeaderLabels(["ID:Serial", "B", "C"])

        branch1.setExpanded(True)
        branch2.setExpanded(True)

        button = QPushButton("Check")
        button.clicked.connect(self.buttonClicked)

        layout = QVBoxLayout()
        layout.addWidget(tree_widget)
        layout.addWidget(button)

        self.setLayout(layout)

        self.setWindowTitle("tree")
        self.show()
Beispiel #21
0
class TreeWidgetDemo(QWidget):
    """主窗口"""
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setWindowTitle("QTreeWidget 使用")

        # 实例化
        self.tree_widget = QTreeWidget()
        # 设置列数
        self.tree_widget.setColumnCount(2)
        # 设置树形控件头部标题
        self.tree_widget.setHeaderLabels(["键", "值"])

        # 根节点
        root = QTreeWidgetItem()
        root.setText(0, "根")
        root.setText(1, "---")

        # 设置子节点 1
        child_1 = QTreeWidgetItem(root)
        child_1.setText(0, "子 1 键")  # 第1列
        child_1.setText(1, "子 1 值")  # 第2列
        child_1.setIcon(
            0, QIcon("03_高级界面控件/示例内容/sources/python-96.png"))  # 为第1列添加图标

        # 设置子节点 2
        child_2 = QTreeWidgetItem(root)
        child_2.setText(0, "子 2 键")  # 第1列
        child_2.setText(1, "子 2 值")  # 第2列
        child_2.setIcon(
            0, QIcon("03_高级界面控件/示例内容/sources/golang-96.png"))  # 为第2列添加图标

        self.tree_widget.addTopLevelItem(root)
        self.tree_widget.clicked.connect(self.tree_click)

        h_layout = QHBoxLayout()
        h_layout.addWidget(self.tree_widget)
        self.setLayout(h_layout)

    def tree_click(self, qmodelindex):
        print("信号传入值", qmodelindex)
        item = self.tree_widget.currentItem()
        print("键 = %s, 值 = %s" % (item.text(0), item.text(1)))
Beispiel #22
0
    def createTree(self):
        tree = QTreeWidget()
        tree.setColumnCount(1)
        root = QTreeWidgetItem(tree)
        root.setText(0, 'root')

        child1 = QTreeWidgetItem(root)
        child1.setText(0, 'child1')
        child1.setText(1, 'name1')
        child2 = QTreeWidgetItem(root)
        child2.setText(0, 'child2')
        child2.setText(1, 'name2')
        child3 = QTreeWidgetItem(root)
        child3.setText(0, 'child3')
        child4 = QTreeWidgetItem(child3)
        child4.setText(0, 'child4')
        child4.setText(1, 'name4')
        tree.addTopLevelItem(root)
        return tree
Beispiel #23
0
class QCollapsibleWidget(QWidget):
    """a dialog to which collapsible sections can be added;
    subclass and reimplement define_sections() to define sections and
        add them as (title, widget) tuples to self.sections
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        self.tree.setVerticalScrollMode(QTreeWidget.ScrollPerPixel)
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self.tree)
        self.setLayout(layout)
        self.tree.setIndentation(0)

    def addSection(self, title, widget):
        """adds a collapsible sections for every 
        (title, widget) tuple in self.sections
        """
        button1 = self.addButton(title)
        section1 = self.addWidget(button1, widget)
        button1.addChild(section1)

    def addButton(self, title):
        """creates a QTreeWidgetItem containing a button 
        to expand or collapse its section
        """
        item = QTreeWidgetItem()
        self.tree.addTopLevelItem(item)
        self.tree.setItemWidget(item, 0, SectionExpandButton(item, text=title))
        return item

    def addWidget(self, button, widget):
        """creates a QWidgetItem containing the widget,
        as child of the button-QWidgetItem
        """
        section = QTreeWidgetItem(button)
        section.setDisabled(True)
        self.tree.setItemWidget(section, 0, widget)
        return section
Beispiel #24
0
class ErrorsTree(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        IDE.register_service("errors_tree", self)
        box = QVBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)
        self._tree = QTreeWidget()
        self._tree.header().setHidden(True)
        self._tree.setAnimated(True)
        box.addWidget(self._tree)

    def refresh(self, errors, path):
        self._tree.clear()
        parent = QTreeWidgetItem(self._tree, [path])
        for lineno, msg in errors.items():
            item = QTreeWidgetItem(parent, [msg])
            self._tree.addTopLevelItem(item)

    def display_name(self):
        return 'Errors'
Beispiel #25
0
class InfoDialog(QDialog):

    def __init__(self, parent, info, title):
        super().__init__(parent)

        self.setWindowTitle('Media Info - ' + title)
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setMinimumSize(500, 250)
        self.resize(500, 250)

        self.vLayout = QVBoxLayout(self)

        self.infoTree = QTreeWidget(self)
        self.infoTree.setColumnCount(2)
        self.infoTree.setHeaderLabels(['Scope', 'Value'])
        self.infoTree.setAlternatingRowColors(True)
        self.infoTree.setSelectionMode(QAbstractItemView.NoSelection)
        self.infoTree.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.vLayout.addWidget(self.infoTree)

        self.__generate_widgets(info)
        self.infoTree.setColumnWidth(0, 150)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
        self.vLayout.addWidget(self.buttonBox)

        self.buttonBox.rejected.connect(self.close)

    def __generate_widgets(self, info, parent=None):
        for key in sorted(info.keys()):
            if(isinstance(info[key], dict)):
                widget = QTreeWidgetItem([key])
                self.__generate_widgets(info[key], widget)
            else:
                widget = QTreeWidgetItem([key, info[key]])

            if(parent):
                parent.addChild(widget)
            else:
                self.infoTree.addTopLevelItem(widget)
Beispiel #26
0
class ErrorsTree(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        IDE.register_service("errors_tree", self)
        box = QVBoxLayout(self)
        box.setContentsMargins(0, 0, 0, 0)
        self._tree = QTreeWidget()
        self._tree.header().setHidden(True)
        self._tree.setAnimated(True)
        box.addWidget(self._tree)

    def refresh(self, errors, path):
        self._tree.clear()
        parent = QTreeWidgetItem(self._tree, [path])
        for lineno, msg in errors.items():
            item = QTreeWidgetItem(parent, [msg])
            self._tree.addTopLevelItem(item)

    def display_name(self):
        return 'Errors'
Beispiel #27
0
 def setTreeWidgetJsonData(treeWidget: QTreeWidget, data={}, isExpand=True):
     """
     给TreeWidget设置数据
     :param treeWidget: TreeWidget
     :param data: json数据
     :param isExpand: isExpand是否全部展开
     """
     treeWidget.clear()
     root = None
     if DataTypeUtil.isDict(data):
         root = WidgetUtil.createTreeWidgetItem("{}")
     elif DataTypeUtil.isList(data):
         root = WidgetUtil.createTreeWidgetItem("[]")
     else:
         print("data is not json data")
         return
     items = WidgetUtil.createTreeWidgetItems(data)
     root.addChildren(items)
     treeWidget.addTopLevelItem(root)
     if isExpand:
         treeWidget.expandAll()
     pass
Beispiel #28
0
    def __init__(self, parent=None):
        super().__init__(parent)

        data_len_per_dim = 5
        layout = QBoxLayout(QBoxLayout.TopToBottom, self)

        label_container = QWidget(self)
        layout.addWidget(label_container)
        label_container_layout = QHBoxLayout(label_container)
        label = QLabel('Tensor Rank', self)
        label.setAlignment(Qt.AlignHCenter)
        label_container_layout.addWidget(label)
        show_all_button = QPushButton('Expand/Collapse', self)
        label_container_layout.addWidget(show_all_button)

        tw = QTreeWidget(self)
        layout.addWidget(tw)
        tw.setColumnCount(2)
        tw.setHeaderLabels(["where", "rank", "size"])

        for x in range(data_len_per_dim):
            x_child = QTreeWidgetItem(["x:{}".format(x)])
            for y in range(data_len_per_dim):
                y_child = QTreeWidgetItem(["y:{}".format(y)])
                for z in range(data_len_per_dim):
                    z_child = QTreeWidgetItem(["z:{}".format(z), "({},{},{})".format(1, 1, 1), "{}x{}x{}".format(10, 10, 10)])
                    y_child.addChild(z_child)
                x_child.addChild(y_child)
            tw.addTopLevelItem(x_child)

        self.is_expanded = False
        def toggle_expand():
            tw.collapseAll() if self.is_expanded else tw.expandAll()
            self.is_expanded = not self.is_expanded

        show_all_button.clicked.connect(toggle_expand)
class OtherExtensionModulesPage(QWidget):
    """ The GUI for the other extension modules page of a project. """

    # The page's label.
    label = "Other Extension Modules"

    @property
    def project(self):
        """ The project property getter. """

        return self._project

    @project.setter
    def project(self, value):
        """ The project property setter. """

        if self._project != value:
            self._project = value
            self._extension_modules_delegate.set_project(value)
            self._update_page()

    def __init__(self):
        """ Initialise the page. """

        super().__init__()

        self._project = None

        # Create the page's GUI.
        layout = QVBoxLayout()

        self._extension_modules_edit = QTreeWidget(
                whatsThis="This shows a list of additional compiled "
                        "extension modules to be linked with the application. "
                        "<b>Name</b> should be the full (dot separated) "
                        "package name of the extension module. <b>LIBS</b> "
                        "should be the value of the corresponding "
                        "<tt>qmake</tt> variable needed to link the extension "
                        "module. Double-click on an entry to edit or remove "
                        "it. Double-click below the last entry in order to "
                        "add a new one. Values may be prefixed by a platform "
                        "specific <tt>qmake</tt> scope.")
        self._extension_modules_edit.setHeaderLabels(["Name", "LIBS"])
        self._extension_modules_edit.setEditTriggers(
                QTreeWidget.DoubleClicked|QTreeWidget.SelectedClicked|
                QTreeWidget.EditKeyPressed)
        self._extension_modules_edit.setRootIsDecorated(False)
        self._extension_modules_edit.itemChanged.connect(
                self._extension_module_changed)

        self._extension_modules_delegate = FilenameEditorDelegate(
                "Extension Module Directory", directory=True)

        self._extension_modules_edit.setItemDelegateForColumn(1,
                self._extension_modules_delegate)

        layout.addWidget(self._extension_modules_edit)

        self.setLayout(layout)

    def _update_page(self):
        """ Update the page using the current project. """

        project = self.project

        # Set the extension modules.
        self._extension_modules_edit.clear()

        for extension_module in project.other_extension_modules:
            self._add_extension_module_item(extension_module)

        # Add one to be edited to create a new entry.
        self._add_extension_module_item()

    def _add_extension_module_item(self, extension_module=None):
        """ Add a QTreeWidgetItem that holds an exclusion. """

        if extension_module is not None:
            name = extension_module.name
            libs = extension_module.libs
        else:
            name = libs = ''

        itm = QTreeWidgetItem([name, libs])

        itm.setFlags(
                Qt.ItemIsSelectable|Qt.ItemIsEditable|Qt.ItemIsEnabled|
                        Qt.ItemNeverHasChildren)

        self._extension_modules_edit.addTopLevelItem(itm)

    def _extension_module_changed(self, itm, value):
        """ Invoked when an extension module has changed. """

        project = self.project
        em_edit = self._extension_modules_edit

        new_name = itm.data(0, Qt.DisplayRole).strip()
        new_libs = itm.data(1, Qt.DisplayRole).strip()
        itm_index = em_edit.indexOfTopLevelItem(itm)

        if new_name != '' or new_libs != '':
            # See if we have added a new one.
            if itm_index == em_edit.topLevelItemCount() - 1:
                self._add_extension_module_item()
        else:
            # It is empty so remove it.
            em_edit.takeTopLevelItem(itm_index)

        # Save the new extension modules.
        project.other_extension_modules = [
                ExtensionModule(
                        em_edit.topLevelItem(i).data(0, Qt.DisplayRole).strip(),
                        em_edit.topLevelItem(i).data(1, Qt.DisplayRole).strip())
                        for i in range(em_edit.topLevelItemCount() - 1)]

        project.modified = True
Beispiel #30
0
class ChangedDocumentsListDialog(widgets.dialog.Dialog):
    def __init__(self):
        super(ChangedDocumentsListDialog, self).__init__(buttons=('close',))
        self.setWindowModality(Qt.NonModal)
        self.setAttribute(Qt.WA_QuitOnClose, False)
        
        layout = QGridLayout(margin=0)
        self.mainWidget().setLayout(layout)
        self.tree = QTreeWidget(headerHidden=True, rootIsDecorated=False,
                                columnCount=2, itemsExpandable=False)
        self.tree.setSelectionMode(QTreeWidget.ExtendedSelection)
        
        self.buttonReload = QPushButton()
        self.buttonReloadAll = QPushButton()
        self.buttonSave = QPushButton()
        self.buttonSaveAll = QPushButton()
        self.buttonShowDiff = QPushButton()
        self.checkWatchingEnabled = QCheckBox(checked=enabled())
        
        layout.addWidget(self.tree, 0, 0, 6, 1)
        layout.addWidget(self.buttonReload, 0, 1)
        layout.addWidget(self.buttonReloadAll, 1, 1)
        layout.addWidget(self.buttonSave, 2, 1)
        layout.addWidget(self.buttonSaveAll, 3, 1)
        layout.addWidget(self.buttonShowDiff, 4, 1)
        layout.addWidget(self.checkWatchingEnabled, 6, 0, 1, 2)
        layout.setRowStretch(5, 10)
        
        app.documentClosed.connect(self.removeDocument)
        app.documentSaved.connect(self.removeDocument)
        app.documentUrlChanged.connect(self.removeDocument)
        app.documentLoaded.connect(self.removeDocument)
        self.tree.itemSelectionChanged.connect(self.updateButtons)
        self.buttonReload.clicked.connect(self.slotButtonReload)
        self.buttonReloadAll.clicked.connect(self.slotButtonReloadAll)
        self.buttonSave.clicked.connect(self.slotButtonSave)
        self.buttonSaveAll.clicked.connect(self.slotButtonSaveAll)
        self.buttonShowDiff.clicked.connect(self.slotButtonShowDiff)
        self.checkWatchingEnabled.toggled.connect(setEnabled)
    
        app.translateUI(self)
        qutil.saveDialogSize(self, 'externalchanges/dialog/size', QSize(400, 200))
        userguide.addButton(self.buttonBox(), "externalchanges")
        self.button('close').setFocus()
    
    def translateUI(self):
        self.setWindowTitle(app.caption(_("Modified Files")))
        self.setMessage(_(
            "The following files were modified or deleted by other "
            "applications:"))
        self.buttonReload.setText(_("Reload"))
        self.buttonReload.setToolTip(_(
            "Reloads the selected documents from disk. "
            "(You can still reach the previous state of the document "
            "using the Undo command.)"))
        self.buttonReloadAll.setText(_("Reload All"))
        self.buttonReloadAll.setToolTip(_(
            "Reloads all externally modified documents from disk. "
            "(You can still reach the previous state of the document "
            "using the Undo command.)"))
        self.buttonSave.setText(_("Save"))
        self.buttonSave.setToolTip(_(
            "Saves the selected documents to disk, overwriting the "
            "modifications by another program."))
        self.buttonSaveAll.setText(_("Save All"))
        self.buttonSaveAll.setToolTip(_(
            "Saves all documents to disk, overwriting the modifications by "
            "another program."))
        self.buttonShowDiff.setText(_("Show Difference..."))
        self.buttonShowDiff.setToolTip(_(
            "Shows the differences between the current document "
            "and the file on disk."))
        self.checkWatchingEnabled.setText(_(
            "Enable watching documents for external changes"))
        self.checkWatchingEnabled.setToolTip(_(
            "If checked, Frescobaldi will warn you when opened files are "
            "modified or deleted by other applications."))
    
    def setDocuments(self, documents):
        """Display the specified documents in the list."""
        # clear the treewidget
        for d in self.tree.invisibleRootItem().takeChildren():
            for i in d.takeChildren():
                i.doc = None
        # group the documents by directory
        dirs = {}
        for d in documents:
            path = d.url().toLocalFile()
            if path:
                dirname, filename = os.path.split(path)
                dirs.setdefault(dirname, []).append((filename, d))
        for dirname in sorted(dirs, key=util.naturalsort):
            diritem = QTreeWidgetItem()
            diritem.setText(0, util.homify(dirname))
            self.tree.addTopLevelItem(diritem)
            diritem.setExpanded(True)
            diritem.setFlags(Qt.ItemIsEnabled)
            diritem.setIcon(0, icons.get('folder-open'))
            for filename, document in sorted(dirs[dirname],
                                              key=lambda item: util.naturalsort(item[0])):
                fileitem = QTreeWidgetItem()
                diritem.addChild(fileitem)
                if documentwatcher.DocumentWatcher.instance(document).isdeleted():
                    itemtext = _("[deleted]") 
                    icon = "dialog-error"
                else:
                    itemtext = _("[modified]")
                    icon = "document-edit"
                fileitem.setIcon(0, icons.get(icon))
                fileitem.setText(0, filename)
                fileitem.setText(1, itemtext)
                fileitem.doc = document
        # select the item if there is only one
        if len(dirs) == 1 and len(list(dirs.values())[0]) == 1:
            fileitem.setSelected(True)
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
        self.updateButtons()
        
    def removeDocument(self, document):
        """Remove the specified document from our list."""
        for d in range(self.tree.topLevelItemCount()):
            diritem = self.tree.topLevelItem(d)
            for f in range(diritem.childCount()):
                if diritem.child(f).doc is document:
                    i = diritem.takeChild(f)
                    i.doc = None
                    if diritem.childCount() == 0:
                        self.tree.takeTopLevelItem(d)
                    break
            else:
                continue
            break
        self.updateButtons()
        # hide if no documents are left
        if self.tree.topLevelItemCount() == 0:
            self.hide()
    
    def selectedDocuments(self):
        """Return the selected documents."""
        return [i.doc for i in self.tree.selectedItems()]
    
    def allDocuments(self):
        """Return all shown documents."""
        return [self.tree.topLevelItem(d).child(f).doc
                for d in range(self.tree.topLevelItemCount())
                for f in range(self.tree.topLevelItem(d).childCount())]
    
    def updateButtons(self):
        """Updates the buttons regarding the selection."""
        docs_sel = self.selectedDocuments()
        docs_all = self.allDocuments()
        all_deleted_sel = all(documentwatcher.DocumentWatcher.instance(d).isdeleted()
                              for d in docs_sel)
        all_deleted_all = all(documentwatcher.DocumentWatcher.instance(d).isdeleted()
                              for d in docs_all)
        self.buttonSave.setEnabled(len(docs_sel) > 0)
        self.buttonSaveAll.setEnabled(len(docs_all) > 0)
        self.buttonReload.setEnabled(not all_deleted_sel)
        self.buttonReloadAll.setEnabled(not all_deleted_all)
        self.buttonShowDiff.setEnabled(len(docs_sel) == 1 and not all_deleted_sel)
    
    def slotButtonReload(self):
        """Called when the user clicks Reload."""
        self.reloadDocuments(self.selectedDocuments())
        
    def slotButtonReloadAll(self):
        """Called when the user clicks Reload All."""
        self.reloadDocuments(self.allDocuments())
    
    def slotButtonSave(self):
        """Called when the user clicks Save."""
        self.saveDocuments(self.selectedDocuments())
    
    def slotButtonSaveAll(self):
        """Called when the user clicks Save All."""
        self.saveDocuments(self.allDocuments())
    
    def reloadDocuments(self, documents):
        """Used by slotButtonReload and slotButtonReloadAll."""
        failures = []
        for d in documents:
            try:
                d.load(keepUndo=True)
            except IOError as e:
                failures.append((d, e))
        if failures:
            msg = _("Could not reload:") + "\n\n" + "\n".join(
                "{url}: {strerror} ({errno})".format(
                    url = d.url().toLocalFile(),
                    strerror = e.strerror,
                    errno = e.errno) for d, e in failures)
            QMessageBox.critical(self, app.caption(_("Error")), msg)

    def saveDocuments(self, documents):
        """Used by slotButtonSave and slotButtonSaveAll."""
        failures = []
        for d in documents:
            try:
                d.save()
            except IOError as e:
                failures.append((d, e))
        if failures:
            msg = _("Could not save:") + "\n\n" + "\n".join(
                "{url}: {strerror} ({errno})".format(
                    url = d.url().toLocalFile(),
                    strerror = e.strerror,
                    errno = e.errno) for d, e in failures) + "\n\n" + \
            _("Please save the document using the \"Save As...\" dialog.",
              "Please save the documents using the \"Save As...\" dialog.",
              len(failures))
            QMessageBox.critical(self, app.caption(_("Error")), msg)
        
    def slotButtonShowDiff(self):
        """Called when the user clicks Show Difference."""
        docs = self.selectedDocuments() or self.allDocuments()
        if not docs:
            return
        d = docs[0]
        if documentwatcher.DocumentWatcher.instance(d).isdeleted():
            return
        
        filename = d.url().toLocalFile()
        try:
            with open(filename, 'rb') as f:
                disktext = util.decode(f.read())
        except (IOError, OSError):
            return
        
        currenttext = d.toPlainText()
        
        html = htmldiff.htmldiff(
            currenttext, disktext, 
            _("Current Document"), _("Document on Disk"), numlines=5)
        dlg = widgets.dialog.Dialog(self, buttons=('close',))
        view = QTextBrowser(lineWrapMode=QTextBrowser.NoWrap)
        view.setHtml(html)
        dlg.setMainWidget(view)
        dlg.setWindowTitle(app.caption("Differences"))
        dlg.setMessage(_(
            "Document: {url}\n"
            "Difference between the current document and the file on disk:").format(
                url=filename))
        dlg.setWindowModality(Qt.NonModal)
        dlg.setAttribute(Qt.WA_QuitOnClose, False)
        dlg.setAttribute(Qt.WA_DeleteOnClose)
        qutil.saveDialogSize(dlg, "externalchanges/diff/dialog/size", QSize(600, 300))
        dlg.show()
Beispiel #31
0
class JackConnectionsDialog(QDialog):
    def __init__(self, jack_client, parent=None, **kwargs):
        super().__init__(parent)

        self.resize(600, 400)

        self.setLayout(QGridLayout())
        # self.layout().setContentsMargins(0, 0, 0, 0)

        self.output_widget = QTreeWidget(self)
        self.output_widget.setHeaderLabels(['Output ports'])

        self.input_widget = QTreeWidget(self)
        self.input_widget.setHeaderLabels(['Input ports'])

        self.connections_widget = ConnectionsWidget(self.output_widget,
                                                    self.input_widget,
                                                    parent=self)
        self.output_widget.itemExpanded.connect(self.connections_widget.update)
        self.output_widget.itemCollapsed.connect(self.connections_widget.update)
        self.input_widget.itemExpanded.connect(self.connections_widget.update)
        self.input_widget.itemCollapsed.connect(self.connections_widget.update)

        self.input_widget.itemSelectionChanged.connect(
            self.__input_selection_changed)
        self.output_widget.itemSelectionChanged.connect(
            self.__output_selection_changed)

        self.layout().addWidget(self.output_widget, 0, 0)
        self.layout().addWidget(self.connections_widget, 0, 1)
        self.layout().addWidget(self.input_widget, 0, 2)

        self.layout().setColumnStretch(0, 2)
        self.layout().setColumnStretch(1, 1)
        self.layout().setColumnStretch(2, 2)

        self.connectButton = QPushButton('Connect', self)
        self.connectButton.clicked.connect(self.__disconnect_selected)
        self.connectButton.setEnabled(False)
        self.layout().addWidget(self.connectButton, 1, 1)

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

        self.__jack_client = jack_client
        self.__selected_in = None
        self.__selected_out = None

        self.connections = []
        self.update_graph()

    def set_connections(self, connections):
        self.connections = connections
        self.connections_widget.connections = self.connections
        self.connections_widget.update()

    def update_graph(self):
        input_ports = self.__jack_client.get_ports(is_audio=True, is_input=True)

        self.output_widget.clear()
        for port in range(8):
            self.output_widget.addTopLevelItem(
                QTreeWidgetItem(['output_' + str(port)]))

        self.input_widget.clear()
        clients = {}
        for port in input_ports:
            client_name = port.name[:port.name.index(':')]

            if client_name not in clients:
                clients[client_name] = ClientItem(client_name)
                self.input_widget.addTopLevelItem(clients[client_name])

            clients[client_name].add_port(port.name)

    def __input_selection_changed(self):
        if self.input_widget.selectedItems():
            self.__selected_in = self.input_widget.selectedItems()[0]
        else:
            self.__selected_in = None

        self.__check_selection()

    def __output_selection_changed(self):
        if self.output_widget.selectedItems():
            self.__selected_out = self.output_widget.selectedItems()[0]
        else:
            self.__selected_out = None

        self.__check_selection()

    def __check_selection(self):
        if self.__selected_in is not None and self.__selected_out is not None:
            output = self.output_widget.indexOfTopLevelItem(self.__selected_out)

            self.connectButton.clicked.disconnect()
            self.connectButton.setEnabled(True)

            if self.__selected_in.name in self.connections[output]:
                self.connectButton.setText('Disconnect')
                self.connectButton.clicked.connect(self.__disconnect_selected)
            else:
                self.connectButton.setText('Connect')
                self.connectButton.clicked.connect(self.__connect_selected)
        else:
            self.connectButton.setEnabled(False)

    def __connect_selected(self):
        output = self.output_widget.indexOfTopLevelItem(self.__selected_out)
        self.connections[output].append(self.__selected_in.name)
        self.connections_widget.update()
        self.__check_selection()

    def __disconnect_selected(self):
        output = self.output_widget.indexOfTopLevelItem(self.__selected_out)
        self.connections[output].remove(self.__selected_in.name)
        self.connections_widget.update()
        self.__check_selection()
Beispiel #32
0
class FontsColors(preferences.Page):
    def __init__(self, dialog):
        super(FontsColors, self).__init__(dialog)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        
        self.scheme = SchemeSelector(self)
        layout.addWidget(self.scheme)
        
        self.printScheme = QCheckBox()
        layout.addWidget(self.printScheme)
        
        hbox = QHBoxLayout()
        self.tree = QTreeWidget(self)
        self.tree.setHeaderHidden(True)
        self.tree.setAnimated(True)
        self.stack = QStackedWidget(self)
        hbox.addWidget(self.tree)
        hbox.addWidget(self.stack)
        layout.addLayout(hbox)
        
        hbox = QHBoxLayout()
        self.fontLabel = QLabel()
        self.fontChooser = QFontComboBox()
        self.fontSize = QDoubleSpinBox()
        self.fontSize.setRange(6.0, 32.0)
        self.fontSize.setSingleStep(0.5)
        self.fontSize.setDecimals(1)
        hbox.addWidget(self.fontLabel)
        hbox.addWidget(self.fontChooser, 1)
        hbox.addWidget(self.fontSize)
        layout.addLayout(hbox)
        
        # add the items to our list
        self.baseColorsItem = i = QTreeWidgetItem()
        self.tree.addTopLevelItem(i)
        self.defaultStylesItem = i = QTreeWidgetItem()
        self.tree.addTopLevelItem(i)
        
        self.defaultStyles = {}
        for name in textformats.defaultStyles:
            self.defaultStyles[name] = i = QTreeWidgetItem()
            self.defaultStylesItem.addChild(i)
            i.name = name
        self.defaultStylesItem.setExpanded(True)
        
        self.allStyles = {}
        for group, styles in ly.colorize.default_mapping():
            i = QTreeWidgetItem()
            children = {}
            self.allStyles[group] = (i, children)
            self.tree.addTopLevelItem(i)
            i.group = group
            for name, base, clss in styles:
                j = QTreeWidgetItem()
                j.name = name
                j.base = base
                i.addChild(j)
                children[name] = j
        
        self.baseColorsWidget = BaseColors(self)
        self.customAttributesWidget = CustomAttributes(self)
        self.emptyWidget = QWidget(self)
        self.stack.addWidget(self.baseColorsWidget)
        self.stack.addWidget(self.customAttributesWidget)
        self.stack.addWidget(self.emptyWidget)
        
        self.tree.currentItemChanged.connect(self.currentItemChanged)
        self.tree.setCurrentItem(self.baseColorsItem)
        self.scheme.currentChanged.connect(self.currentSchemeChanged)
        self.scheme.changed.connect(self.changed)
        self.baseColorsWidget.changed.connect(self.baseColorsChanged)
        self.customAttributesWidget.changed.connect(self.customAttributesChanged)
        self.fontChooser.currentFontChanged.connect(self.fontChanged)
        self.fontSize.valueChanged.connect(self.fontChanged)
        self.printScheme.clicked.connect(self.printSchemeChanged)
        
        app.translateUI(self)
        
    def translateUI(self):
        self.printScheme.setText(_("Use this scheme for printing"))
        self.fontLabel.setText(_("Font:"))
        self.baseColorsItem.setText(0, _("Base Colors"))
        self.defaultStylesItem.setText(0, _("Default Styles"))
        
        self.defaultStyleNames = defaultStyleNames()
        self.allStyleNames = allStyleNames()
        
        for name in textformats.defaultStyles:
            self.defaultStyles[name].setText(0, self.defaultStyleNames[name])
        for group, styles in ly.colorize.default_mapping():
            try:
                n = self.allStyleNames[group][0]
            except KeyError:
                n = group
            self.allStyles[group][0].setText(0, n)
            for name, base, clss in styles:
                try:
                    n = self.allStyleNames[group][1][name]
                except KeyError:
                    n = name
                self.allStyles[group][1][name].setText(0, n)
            
    def currentItemChanged(self, item, previous):
        if item is self.baseColorsItem:
            self.stack.setCurrentWidget(self.baseColorsWidget)
        elif not item.parent():
            self.stack.setCurrentWidget(self.emptyWidget)
        else:
            data = self.data[self.scheme.currentScheme()]
            w = self.customAttributesWidget
            self.stack.setCurrentWidget(w)
            toptext = None
            if item.parent() is self.defaultStylesItem:
                # default style
                w.setTitle(item.text(0))
                w.setTristate(False)
                w.setTextFormat(data.defaultStyles[item.name])
            else:
                # specific style of specific group
                group, name = item.parent().group, item.name
                w.setTitle("{0}: {1}".format(item.parent().text(0), item.text(0)))
                inherit = item.base
                if inherit:
                    toptext = _("(Inherits: {name})").format(name=self.defaultStyleNames[inherit])
                w.setTristate(bool(inherit))
                w.setTextFormat(data.allStyles[group][name])
            w.setTopText(toptext)
    
    def currentSchemeChanged(self):
        scheme = self.scheme.currentScheme()
        if scheme not in self.data:
            self.data[scheme] = textformats.TextFormatData(scheme)
        self.updateDisplay()
        if self.tree.currentItem():
            self.currentItemChanged(self.tree.currentItem(), None)
        with qutil.signalsBlocked(self.printScheme):
            self.printScheme.setChecked(scheme == self._printScheme)
    
    def fontChanged(self):
        data = self.data[self.scheme.currentScheme()]
        data.font = self.fontChooser.currentFont()
        data.font.setPointSizeF(self.fontSize.value())
        self.updateDisplay()
        self.changed.emit()
    
    def printSchemeChanged(self):
        if self.printScheme.isChecked():
            self._printScheme = self.scheme.currentScheme()
        else:
            self._printScheme = None
        self.changed.emit()
    
    def addSchemeData(self, scheme, tfd):
        self.data[scheme] = tfd
        
    def currentSchemeData(self):
        return self.data[self.scheme.currentScheme()]
        
    def updateDisplay(self):
        data = self.data[self.scheme.currentScheme()]
        
        with qutil.signalsBlocked(self.fontChooser, self.fontSize):
            self.fontChooser.setCurrentFont(data.font)
            self.fontSize.setValue(data.font.pointSizeF())
        
        with qutil.signalsBlocked(self):
            # update base colors
            for name in textformats.baseColors:
                self.baseColorsWidget.color[name].setColor(data.baseColors[name])
        
        # update base colors for whole treewidget
        p = QApplication.palette()
        p.setColor(QPalette.Base, data.baseColors['background'])
        p.setColor(QPalette.Text, data.baseColors['text'])
        p.setColor(QPalette.Highlight, data.baseColors['selectionbackground'])
        p.setColor(QPalette.HighlightedText, data.baseColors['selectiontext'])
        self.tree.setPalette(p)
        
        def setItemTextFormat(item, f):
            font = QFont(data.font)
            if f.hasProperty(QTextFormat.ForegroundBrush):
                item.setForeground(0, f.foreground().color())
            else:
                item.setForeground(0, data.baseColors['text'])
            if f.hasProperty(QTextFormat.BackgroundBrush):
                item.setBackground(0, f.background().color())
            else:
                item.setBackground(0, QBrush())
            font.setWeight(f.fontWeight())
            font.setItalic(f.fontItalic())
            font.setUnderline(f.fontUnderline())
            item.setFont(0, font)
            
        # update looks of default styles
        for name in textformats.defaultStyles:
            setItemTextFormat(self.defaultStyles[name], data.defaultStyles[name])
        
        # update looks of all the specific styles
        for group, styles in ly.colorize.default_mapping():
            children = self.allStyles[group][1]
            for name, inherit, clss in styles:
                f = QTextCharFormat(data.defaultStyles[inherit]) if inherit else QTextCharFormat()
                f.merge(data.allStyles[group][name])
                setItemTextFormat(children[name], f)
        
    def baseColorsChanged(self, name):
        # keep data up to date with base colors
        data = self.data[self.scheme.currentScheme()]
        data.baseColors[name] = self.baseColorsWidget.color[name].color()
        self.updateDisplay()
        self.changed.emit()
    
    def customAttributesChanged(self):
        item = self.tree.currentItem()
        if not item or not item.parent():
            return
        data = self.data[self.scheme.currentScheme()]
        if item.parent() is self.defaultStylesItem:
            # a default style has been changed
            data.defaultStyles[item.name] = self.customAttributesWidget.textFormat()
        else:
            # a specific style has been changed
            group, name = item.parent().group, item.name
            data.allStyles[group][name] = self.customAttributesWidget.textFormat()
        self.updateDisplay()
        self.changed.emit()
        
    def import_(self, filename):
        from . import import_export
        import_export.importTheme(filename, self, self.scheme)
        
    def export(self, name, filename):
        from . import import_export
        try:
            import_export.exportTheme(self, name, filename)
        except (IOError, OSError) as e:
            QMessageBox.critical(self, _("Error"), _(
                "Can't write to destination:\n\n{url}\n\n{error}").format(
                url=filename, error=e.strerror))
    
    def loadSettings(self):
        self.data = {} # holds all data with scheme as key
        self._printScheme = QSettings().value("printer_scheme", "default", str)
        self.scheme.loadSettings("editor_scheme", "editor_schemes")
        
    def saveSettings(self):
        self.scheme.saveSettings("editor_scheme", "editor_schemes", "fontscolors")
        for scheme in self.scheme.schemes():
            if scheme in self.data:
                self.data[scheme].save(scheme)
        if self._printScheme:
            QSettings().setValue("printer_scheme", self._printScheme)
        else:
            QSettings().remove("printer_scheme")
Beispiel #33
0
class NodeSelector(QDialog):
    """ Popup window for creating new nodes """
    def __init__(self, moduleManager, modfilter={}):
        super().__init__()

        self.modMan = moduleManager
        self.modfilter = modfilter

        self.gridLayout = QGridLayout(self)

        self.lineEdit = QLineEdit()
        self.lineEdit.textChanged.connect(self.textChanged)
        self.gridLayout.addWidget(self.lineEdit, 0, 0, 1, 1)

        self.treeWidget = QTreeWidget()
        self.treeWidget.itemActivated.connect(self.itemActivated)
        self.gridLayout.addWidget(self.treeWidget, 1, 0, 1, 1)

        self.data = {"node": None, "pin": None}

        self.rebuildTree()



    def rebuildTree(self):
        # Fill Tree with items
        ## Find all available Categories
        self.treeWidget.clear()
        self.categories = []
        for key in self.modMan.availableNodes:
            if self.modMan.availableNodes[key].placable and self.filterModule(self.modMan.availableNodes[key]):
                self.categories.append(self.modMan.availableNodes[key].category)
        self.categories = list(set(self.categories))  # Make list unique

        self.categoryTreeitems = {}
        for category in self.categories:
            newTreeitem = QTreeWidgetItem()
            newTreeitem.setText(0, category)
            self.treeWidget.addTopLevelItem(newTreeitem)

            self.categoryTreeitems[category] = newTreeitem

        self.moduleDict = {}
        for key in self.modMan.availableNodes:
            if self.modMan.availableNodes[key].placable and self.filterModule(self.modMan.availableNodes[key]): # Todo: Could reuse previous results if performance becomes critical
                newTreeitem = QTreeWidgetItem()
                newTreeitem.setText(0, self.modMan.availableNodes[key].name)
                newTreeitem.setToolTip(0, self.modMan.availableNodes[key].desc)
                self.categoryTreeitems[self.modMan.availableNodes[key].category].addChild(newTreeitem)

                self.moduleDict[key] = newTreeitem

        for key in self.categoryTreeitems:
            self.categoryTreeitems[key].setExpanded(True)


    def filterModule(self, module):
        ratio = 0
        compatibleType = False
        if "type" in self.modfilter:
            if self.modfilter["type"]["dir"] == "input":
                for input in module.inputDefs:
                    if input.pintype == self.modfilter["type"]["type"]:
                        compatibleType = True
                        break
            elif self.modfilter["type"]["dir"] == "output":
                for output in module.outputDefs:
                    if output.pintype == self.modfilter["type"]["type"]:
                        compatibleType = True
                        break

            if not compatibleType:
                return False

        if "text" in self.modfilter:    # Filter by text input
            if self.modfilter["text"] in module.name:
                return True
            if not self.modfilter["text"]:  # Text entry is empty
                return True
            ratio = fuzz.ratio(self.modfilter["text"], module.name)
            ratio = max(ratio, fuzz.partial_ratio(self.modfilter["text"], module.desc))
        else:
            return True     # Don't filter by text? Return all remaining

        if ratio > 40:
            return True
        else:
            return False

    def textChanged(self, newText):
        self.modfilter["text"] = newText
        self.rebuildTree()

    def itemActivated(self, item, column):
        for key in self.moduleDict:
            if self.moduleDict[key] == item:

                if "type" in self.modfilter:
                    if self.modfilter["type"]["dir"] == "input":
                        for input in self.modMan.availableNodes[key].inputDefs:
                            if input.pintype == self.modfilter["type"]["type"]:
                                self.data["pin"] = self.modMan.availableNodes[key].inputDefs.index(input)
                                break
                    elif self.modfilter["type"]["dir"] == "output":
                        for output in self.modMan.availableNodes[key].outputDefs:
                            if output.pintype == self.modfilter["type"]["type"]:
                                self.data["pin"] = self.modMan.availableNodes[key].outputDefs.index(output)
                                break

                self.data["node"] = self.modMan.availableNodes[key]
                self.done(1)
Beispiel #34
0
class Shortcuts(preferences.Page):
    def __init__(self, dialog):
        super(Shortcuts, self).__init__(dialog)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.scheme = SchemeSelector(self)
        layout.addWidget(self.scheme)
        self.searchEntry = LineEdit()
        self.searchEntry.setPlaceholderText(_("Search..."))
        layout.addWidget(self.searchEntry)
        self.tree = QTreeWidget(self)
        self.tree.setHeaderLabels([_("Command"), _("Shortcut")])
        self.tree.setRootIsDecorated(False)
        self.tree.setColumnCount(2)
        self.tree.setAllColumnsShowFocus(True)
        self.tree.setAnimated(True)
        layout.addWidget(self.tree)

        self.edit = QPushButton(icons.get("preferences-desktop-keyboard-shortcuts"), '')
        layout.addWidget(self.edit)

        # signals
        self.searchEntry.textChanged.connect(self.updateFilter)
        self.scheme.currentChanged.connect(self.slotSchemeChanged)
        self.scheme.changed.connect(self.changed)
        self.tree.currentItemChanged.connect(self.slotCurrentItemChanged)
        self.tree.itemDoubleClicked.connect(self.editCurrentItem)
        self.edit.clicked.connect(self.editCurrentItem)

        # make a dict of all actions with the actions as key and the names as
        # value, with the collection prepended (for loading/saving)
        win = dialog.parent()
        allactions = {}
        for collection in actioncollectionmanager.manager(win).actionCollections():
            for name, action in collection.actions().items():
                allactions[action] = (collection, name)

        # keep a list of actions not in the menu structure
        left = list(allactions.keys())

        def add_actions(menuitem, actions):
            """Add actions to a QTreeWidgetItem."""
            for a in actions:
                if a.menu():
                    item = build_menu_item(a)
                    if item.childCount():
                        menuitem.addChild(item)
                elif a in left:
                    left.remove(a)
                    menuitem.addChild(ShortcutItem(a, *allactions[a]))
            menuitem.setFlags(Qt.ItemIsEnabled) # disable selection

        def build_menu_item(action):
            """Return a QTreeWidgetItem with children for all the actions in the submenu."""
            menuitem = QTreeWidgetItem()
            text = qutil.removeAccelerator(action.text())
            menuitem.setText(0, _("Menu {name}").format(name=text))
            add_actions(menuitem, action.menu().actions())
            return menuitem

        # present the actions nicely ordered as in the menus
        for a in win.menuBar().actions():
            menuitem = build_menu_item(a)
            if menuitem.childCount():
                self.tree.addTopLevelItem(menuitem)

        # sort leftover actions
        left.sort(key=lambda i: i.text())

        # show actions that are left, grouped by collection
        titlegroups = {}
        for a in left[:]: # copy
            collection, name = allactions[a]
            if collection.title():
                titlegroups.setdefault(collection.title(), []).append(a)
                left.remove(a)
        for title in sorted(titlegroups):
            item = QTreeWidgetItem(["{0}:".format(title)])
            for a in titlegroups[title]:
                item.addChild(ShortcutItem(a, *allactions[a]))
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled) # disable selection

        # show other actions that were not in the menus
        item = QTreeWidgetItem([_("Other commands:")])
        for a in left:
            if a.text() and not a.menu():
                item.addChild(ShortcutItem(a, *allactions[a]))
        if item.childCount():
            self.tree.addTopLevelItem(item)
            item.setFlags(Qt.ItemIsEnabled) # disable selection

        self.tree.expandAll()

        item = self.tree.topLevelItem(0).child(0)
        if _lastaction:
            # find the previously selected item
            for i in self.items():
                if i.name == _lastaction:
                    item = i
                    break
        self.tree.setCurrentItem(item)
        self.tree.resizeColumnToContents(0)

    def items(self):
        """Yield all the items in the actions tree."""
        def children(item):
            for i in range(item.childCount()):
                c = item.child(i)
                if c.childCount():
                    for c1 in children(c):
                        yield c1
                else:
                    yield c
        for c in children(self.tree.invisibleRootItem()):
            yield c

    def item(self, collection, name):
        for item in self.items():
            if item.collection.name == collection and item.name == name:
                return item

    def saveSettings(self):
        self.scheme.saveSettings("shortcut_scheme", "shortcut_schemes", "shortcuts")
        for item in self.items():
            for scheme in self.scheme.schemes():
                item.save(scheme)
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())

    def loadSettings(self):
        self.scheme.loadSettings("shortcut_scheme", "shortcut_schemes")
        # clear the settings in all the items
        for item in self.items():
            item.clearSettings()
            item.switchScheme(self.scheme.currentScheme())

    def slotSchemeChanged(self):
        """Called when the Scheme combobox is changed by the user."""
        for item in self.items():
            item.switchScheme(self.scheme.currentScheme())

    def slotCurrentItemChanged(self, item):
        if isinstance(item, ShortcutItem):
            self.edit.setText(
                _("&Edit Shortcut for \"{name}\"").format(name=item.text(0)))
            self.edit.setEnabled(True)
            global _lastaction
            _lastaction = item.name
        else:
            self.edit.setText(_("(no shortcut)"))
            self.edit.setEnabled(False)

    def import_(self, filename):
        from . import import_export
        import_export.importShortcut(filename, self, self.scheme)

    def export(self, name, filename):
        from . import import_export
        try:
            import_export.exportShortcut(self, self.scheme.currentScheme(), name, filename)
        except (IOError, OSError) as e:
            QMessageBox.critical(self, _("Error"), _(
                "Can't write to destination:\n\n{url}\n\n{error}").format(
                url=filename, error=e.strerror))

    def findShortcutConflict(self, shortcut):
        """Find the possible shortcut conflict and return the conflict name."""
        if shortcut:
            item = self.tree.currentItem()
            if not isinstance(item, ShortcutItem):
                return None
            scheme = self.scheme.currentScheme()
            for i in self.items():
                a = i.action(scheme)
                if i != item and a.shortcuts():
                    for s1 in a.shortcuts():
                        if s1.matches(shortcut) or shortcut.matches(s1):
                            return qutil.removeAccelerator(a.text())
        return None

    def editCurrentItem(self):
        item = self.tree.currentItem()
        if not isinstance(item, ShortcutItem):
            return

        dlg = ShortcutEditDialog(self, self.findShortcutConflict)
        scheme = self.scheme.currentScheme()
        action = item.action(scheme)
        default = item.defaultShortcuts() or None
        if dlg.editAction(action, default):
            shortcuts = action.shortcuts()
            # check for conflicts
            conflicting = []
            for i in self.items():
                if i is not item:
                    for s1, s2 in itertools.product(i.shortcuts(scheme), shortcuts):
                        if s1.matches(s2) or s2.matches(s1):
                            conflicting.append(i)
            if conflicting:
                for i in conflicting:
                    l = i.shortcuts(scheme)
                    for s1 in list(l): # copy
                        for s2 in shortcuts:
                            if s1.matches(s2) or s2.matches(s1):
                                l.remove(s1)
                    i.setShortcuts(l, scheme)

            # store the shortcut
            item.setShortcuts(shortcuts, scheme)
            self.changed.emit()

    def updateFilter(self):
        """Called when the search text changes."""
        search = self.searchEntry.text()
        scheme = self.scheme.currentScheme()
        def hidechildren(item):
            hideparent = True
            for n in range(item.childCount()):
                c = item.child(n)
                if c.childCount():
                    # submenu item
                    if hidechildren(c):
                        c.setHidden(True)
                    else:
                        c.setHidden(False)
                        c.setExpanded(True)
                        hideparent = False
                elif isinstance(c, ShortcutItem):
                    # shortcut item, should be the case
                    if c.matches(scheme, search):
                        c.setHidden(False)
                        hideparent = False
                    else:
                        c.setHidden(True)
            return hideparent
        hidechildren(self.tree.invisibleRootItem())
class TorrentPreferencesDialog(QDialog):
    dataReady = pyqtSignal(dict)

    def __init__(self, parent, torrent_info):
        super().__init__(parent)
        self.torrentInfo = torrent_info

        self.setUp()

    def setUp(self):
        self.setWindowTitle("Torrent settings")

        parentRect = self.parentWidget().geometry()
        self.resize(parentRect.width() * 0.75, parentRect.height() * 0.9)
        self.setMinimumSize(self.size())

        # Create the dialog layout
        self.layout = QVBoxLayout(self)

        # Set up the destination folder selector
        self.setUpDialogHeader()
        # Set up the file lister for the torrent file
        self.setUpFileLister()
        # Set up the whole torrent priority combo box and buttons
        self.setUpDialogFooter()

    def setUpDialogHeader(self):
        headerLayout = QGridLayout()
        self.destinationFolder = paths.writableLocation(paths.DownloadLocation)
        torrentName = self.torrentInfo.name()

        # Show the torrent name row
        nameLabel = QLabel("Torrent name:", self)
        headerLayout.addWidget(nameLabel, 0, 0)

        nameEdit = QLineEdit(torrentName, self)
        nameEdit.setReadOnly(True)
        headerLayout.addWidget(nameEdit, 0, 1)

        # Show the destination folder row
        dirLabel = QLabel("Destination folder:", self)
        headerLayout.addWidget(dirLabel, 1, 0)

        self.textField = QLineEdit(self.destinationFolder, self)
        self.textField.setReadOnly(True)
        headerLayout.addWidget(self.textField, 1, 1)

        button = QPushButton("Browse", self)
        button.clicked.connect(self.selectFolder)
        headerLayout.addWidget(button, 1, 2)

        self.layout.addLayout(headerLayout)

    def selectFolder(self):
        newDir = str(QFileDialog.getExistingDirectory(self,
                                                      "Select Directory"))
        if newDir:
            self.textField.setText(newDir)
            self.destinationFolder = newDir

    def setUpFileLister(self):
        self.files = [(f.path, f.size) for f in self.torrentInfo.files()]
        self.treeView = QTreeWidget(self)
        self.treeView.setColumnCount(3)
        self.treeView.setColumnWidth(0, 350)
        self.treeView.setColumnWidth(1, 80)
        self.treeView.setHeaderLabels(["Name", "size", "Priority"])
        self.treeView.setExpandsOnDoubleClick(False)

        if len(self.files) == 1:
            tree = file_tree.FileTree(self.files[0][0], self.files[0][1])
        else:
            tree = file_tree.FileTree(self.files[0][0].split('/')[0], 0)
            for f in self.files:
                tree.add_file(f[0], f[1])

        rootItem = TreeNodeItem(tree.get_root(), self.treeView)
        self.treeView.addTopLevelItem(rootItem)
        self.treeView.expandAll()
        self.treeView.itemClicked.connect(self.rowClicked)
        self.layout.addWidget(self.treeView)

    def rowClicked(self, item, column):
        if item.checkState(0) == Qt.PartiallyChecked:
            item.setCheckState(0, Qt.Checked)

        if column == 2:
            priorityChanges = {'Normal': 'High',
                               'High': 'Low',
                               'Low': 'Normal',
                               'Mixed': 'Normal'}
            newPriority = priorityChanges[item.text(2)]
            self.changeTextOfAllChildren(item, 2, newPriority)

            self.reprioritize(item)

    def changeTextOfAllChildren(self, item, column, text):
        item.setText(column, text)
        for i in range(0, item.childCount()):
            self.changeTextOfAllChildren(item.child(i), column, text)

    def reprioritize(self, start_node):
        parent = start_node.parent()
        if parent:
            if self.allChildrenHaveSamePriority(parent):
                parent.setText(2, start_node.text(2))
            else:
                parent.setText(2, "Mixed")

            self.reprioritize(parent)

    def allChildrenHaveSamePriority(self, node):
        for i in range(1, node.childCount()):
            if node.child(i - 1).text(2) != node.child(i).text(2):
                return False

        return True

    def setUpDialogFooter(self):
        footerLayout = QGridLayout()
        footerLayout.setColumnStretch(0, 4)

        footerLayout.addWidget(QLabel("Torrent priority"), 0, 1)
        self.priorityComboBox = QComboBox(self)
        self.priorityComboBox.addItems(["High", "Normal", "Low"])
        self.priorityComboBox.setCurrentIndex(1)
        footerLayout.addWidget(self.priorityComboBox, 0, 2)

        secondRowLayout = QHBoxLayout()

        OKButton = QPushButton("Open", self)
        OKButton.setFocus()
        OKButton.clicked.connect(self.accept)
        cancelButton = QPushButton("Cancel", self)
        cancelButton.clicked.connect(self.reject)
        secondRowLayout.addWidget(OKButton)
        secondRowLayout.addWidget(cancelButton)
        footerLayout.addLayout(secondRowLayout, 1, 2)

        self.layout.addLayout(footerLayout)

    def accept(self):
        torrentPriorities = {"Low": 0, "Normal": 127, "High": 255}
        filePriorities = {"Low": 1, "Normal": 4, "High": 7}

        it = QTreeWidgetItemIterator(self.treeView,
                                     QTreeWidgetItemIterator.NoChildren)

        itemsInfo = {}
        while it.value():
            currentItem = it.value()
            if currentItem.checkState(0) == Qt.Unchecked:
                priority = 0
            else:
                priority = filePriorities[currentItem.text(2)]

            itemsInfo[self.getFullPath(currentItem)] = priority
            it += 1

        paths = [f.path for f in self.torrentInfo.files()]
        self.prioritiesList = [itemsInfo[p] for p in paths]

        comboBoxIndex = self.priorityComboBox.currentIndex()
        self.priority = torrentPriorities[self.priorityComboBox.itemText(
                                                                comboBoxIndex)]

        self.hide()
        self.dataReady.emit(self.getData())
        super().accept()

    def getFullPath(self, treeItem):
        items = [treeItem.text(0)]
        parent = treeItem.parent()

        while parent:
            items.append(parent.text(0))
            parent = parent.parent()

        return '/'.join(reversed(items))

    def getData(self):
        return {'info': self.torrentInfo,
                'destination_folder': self.destinationFolder,
                'torrent_priority': self.priority,
                'file_priorities': self.prioritiesList}
Beispiel #36
0
class Preferences(QDialog):

    configuration = {}
    weight = 0
    # Signals
    savePreferences = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent, Qt.Dialog)
        self.setWindowTitle(translations.TR_PREFERENCES_TITLE)
        self.setMinimumSize(900, 650)
        box = QVBoxLayout(self)
        box.setContentsMargins(3, 3, 3, 3)
        self.setAutoFillBackground(True)
        # Header
        self._header_label = QLabel("")
        header_font = self._header_label.font()
        header_font.setBold(True)
        header_font.setPointSize(header_font.pointSize() + 4)
        self._header_label.setFont(header_font)

        hbox = QHBoxLayout()
        hbox.setContentsMargins(0, 0, 0, 0)

        self.tree = QTreeWidget()
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(QTreeWidget.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.tree.setFixedWidth(200)
        hbox.addWidget(self.tree)

        self.stacked = QStackedLayout()
        header_layout = QVBoxLayout()
        header_layout.setContentsMargins(0, 0, 0, 0)
        header_layout.addWidget(self._header_label)
        header_layout.addLayout(self.stacked)
        hbox.addLayout(header_layout)
        box.addLayout(hbox)

        # Footer buttons
        button_box = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        box.addWidget(button_box)

        # Connections
        button_box.rejected.connect(self.close)
        button_box.accepted.connect(self._save_preferences)
        self.tree.selectionModel().currentRowChanged.connect(
            self._change_current)

        self.load_ui()

    @pyqtSlot()
    def _save_preferences(self):
        self.savePreferences.emit()
        self.close()

    def load_ui(self):
        sections = sorted(
            Preferences.configuration.keys(),
            key=lambda item: Preferences.configuration[item]['weight'])
        for section in sections:
            text = Preferences.configuration[section]['text']
            Widget = Preferences.configuration[section]['widget']
            widget = Widget(self)
            area = QScrollArea()
            area.setWidgetResizable(True)
            area.setWidget(widget)
            self.stacked.addWidget(area)
            index = self.stacked.indexOf(area)
            item = QTreeWidgetItem([text])
            item.setData(0, Qt.UserRole, index)
            self.tree.addTopLevelItem(item)

            # Sort Item Children
            subcontent = Preferences.configuration[section].get(
                'subsections', {})
            subsections = sorted(
                subcontent.keys(), key=lambda item: subcontent[item]['weight'])
            for sub in subsections:
                text = subcontent[sub]['text']
                Widget = subcontent[sub]['widget']
                widget = Widget(self)
                area = QScrollArea()
                area.setWidgetResizable(True)
                area.setWidget(widget)
                self.stacked.addWidget(area)
                index = self.stacked.indexOf(area)
                subitem = QTreeWidgetItem([text])
                subitem.setData(0, Qt.UserRole, index)
                item.addChild(subitem)

        self.tree.expandAll()
        self.tree.setCurrentIndex(self.tree.model().index(0, 0))

    def _change_current(self):
        item = self.tree.currentItem()
        index = item.data(0, Qt.UserRole)
        self.stacked.setCurrentIndex(index)
        self._header_label.setText(item.text(0))

    @classmethod
    def register_configuration(cls, section, widget, text,
                               weight=None, subsection=None):
        if weight is None:
            Preferences.weight += 1
            weight = Preferences.weight
        if subsection is None:
            Preferences.configuration[section] = {
                'widget': widget,
                'weight': weight,
                'text': text
            }
        else:
            config = Preferences.configuration.get(section, {})
            if not config:
                config[section] = {
                    'widget': None,
                    'weight': 100
                }
            subconfig = config.get('subsections', {})
            subconfig[subsection] = {
                'widget': widget,
                'weight': weight,
                'text': text
            }
            config['subsections'] = subconfig
            Preferences.configuration[section] = config
Beispiel #37
0
class SessionsManager(QDialog):
    """Session Manager, to load different configurations of ninja."""

    def __init__(self, parent=None):
        super(SessionsManager, self).__init__(parent, Qt.Dialog)
        self._ninja = parent
        self.setModal(True)
        self.setWindowTitle(translations.TR_SESSIONS_TITLE)
        self.setMinimumWidth(550)
        self.setMinimumHeight(450)
        self._manager = _SessionManager(parent)
        self._load_ui()

    def install(self):
        self._manager.load_sessions()

    def _load_ui(self):
        main_layout = QVBoxLayout(self)
        main_layout.addWidget(QLabel(translations.TR_SESSIONS_DIALOG_BODY))
        main_hbox = QHBoxLayout()
        # Session list
        session_layout = QVBoxLayout()
        self._session_list = QTreeWidget()
        self._session_list.setHeaderLabels(["Session", "Last Modified"])
        session_layout.addWidget(self._session_list)
        # Content frame
        content_frame = QFrame()
        content_frame.hide()
        frame_layout = QVBoxLayout(content_frame)
        content_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        session_layout.addWidget(content_frame)
        frame_layout.setContentsMargins(0, 0, 0, 0)
        self._content_list = QTreeWidget()
        self._content_list.setHeaderHidden(True)
        frame_layout.addWidget(self._content_list)
        # Separator line
        line_frame = QFrame()
        line_frame.setFrameStyle(QFrame.VLine | QFrame.Sunken)
        # Buttons
        btn_layout = QVBoxLayout()
        btn_create = QPushButton(translations.TR_SESSIONS_BTN_CREATE)
        btn_activate = QPushButton(translations.TR_SESSIONS_BTN_ACTIVATE)
        btn_update = QPushButton(translations.TR_SESSIONS_BTN_UPDATE)
        btn_delete = QPushButton(translations.TR_SESSIONS_BTN_DELETE)
        btn_details = QPushButton(translations.TR_SESSIONS_BTN_DETAILS)
        btn_details.setCheckable(True)
        # Add buttons to layout
        btn_layout.addWidget(btn_create)
        btn_layout.addWidget(btn_activate)
        btn_layout.addWidget(btn_update)
        btn_layout.addWidget(btn_delete)
        btn_layout.addStretch()
        btn_layout.addWidget(btn_details)
        # Add widgets and layouts to the main layout
        main_layout.addLayout(main_hbox)
        main_hbox.addLayout(session_layout)
        main_hbox.addWidget(line_frame)
        main_hbox.addLayout(btn_layout)
        main_hbox.setSizeConstraint(QLayout.SetFixedSize)
        btn_details.toggled[bool].connect(content_frame.setVisible)
        # Connections
        self._session_list.itemSelectionChanged.connect(
            self.load_session_content)
        btn_activate.clicked.connect(self.open_session)
        btn_update.clicked.connect(self.save_session)
        btn_create.clicked.connect(self.create_session)
        btn_delete.clicked.connect(self.delete_session)

    def __load_sessions(self):
        for session_name in self._manager.sessions:
            item = QTreeWidgetItem()
            item.setText(0, session_name)
            item.setText(1, "FIXME: manage this!")
            self._session_list.addTopLevelItem(item)
        self._session_list.setCurrentItem(
            self._session_list.topLevelItem(0))

    def load_session_content(self):
        """Load the selected session, replacing the current session."""
        item = self._session_list.currentItem()
        self._content_list.clear()
        if item is not None:
            key = item.text(0)
            files, projects = self._manager.get_session(key)
            files_parent = QTreeWidgetItem(
                self._content_list, [translations.TR_FILES])
            for ffile in files:
                QTreeWidgetItem(files_parent, [ffile[0]])
            projects_parent = QTreeWidgetItem(
                self._content_list, [translations.TR_PROJECT])
            for project in projects:
                QTreeWidgetItem(projects_parent, [project])

            files_parent.setExpanded(True)
            projects_parent.setExpanded(True)

    def create_session(self):
        """Create a new Session."""
        session_info = QInputDialog.getText(
            None, translations.TR_SESSIONS_CREATE_TITLE,
            translations.TR_SESSIONS_CREATE_BODY)
        if session_info[1]:
            session_name = session_info[0]
            if not session_name or session_name in settings.SESSIONS:
                QMessageBox.information(
                    self,
                    translations.TR_SESSIONS_MESSAGE_TITLE,
                    translations.TR_SESSIONS_MESSAGE_BODY)
                return
            self._manager.save_session_data(session_name)
        self.close()

    def save_session(self):
        """Save current session"""
        if self._session_list.currentItem():
            session_name = self._session_list.currentItem().text(0)
            self._manager.save_session_data(session_name)
            self._ninja.show_message(
                translations.TR_SESSIONS_UPDATED_NOTIF.format(session_name))
            self.load_session_content()

    def open_session(self):
        """Open a saved session"""
        if self._session_list.currentItem():
            session_name = self._session_list.currentItem().text(0)
            self._manager.load_session(session_name)
            self._manager.set_current_session(session_name)
            self.close()

    def delete_session(self):
        """Delete a session"""
        if self._session_list.currentItem():
            key = self._session_list.currentItem().text(0)
            self._manager.delete_session(key)
            self._session_list.takeTopLevelItem(
                self._session_list.currentIndex().row())

    @property
    def current_session(self):
        return self._manager.current_session()

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

    def hideEvent(self, event):
        super().hideEvent(event)
        self._session_list.clear()
Beispiel #38
0
def load(filename, widget):
    """Loads snippets from a file, displaying them in a list.

    The user can then choose:
    - overwrite builtin snippets or not
    - overwrite own snippets with same title or not
    - select and view snippets contents.

    """
    try:
        d = ET.parse(filename)
        elements = list(d.findall('snippet'))
        if not elements:
            raise ValueError(_("No snippets found."))
    except Exception as e:
        QMessageBox.critical(widget, app.caption(_("Error")),
        _("Can't read from source:\n\n{url}\n\n{error}").format(
            url=filename, error=e))
        return


    dlg = widgets.dialog.Dialog(widget)
    dlg.setWindowModality(Qt.WindowModal)
    dlg.setWindowTitle(app.caption(_("dialog title", "Import Snippets")))
    tree = QTreeWidget(headerHidden=True, rootIsDecorated=False)
    dlg.setMainWidget(tree)
    userguide.addButton(dlg.buttonBox(), "snippet_import_export")

    allnames = frozenset(snippets.names())
    builtins = frozenset(builtin.builtin_snippets)
    titles = dict((snippets.title(n), n) for n in allnames if n not in builtins)

    new = QTreeWidgetItem(tree, [_("New Snippets")])
    updated = QTreeWidgetItem(tree, [_("Updated Snippets")])
    unchanged = QTreeWidgetItem(tree, [_("Unchanged Snippets")])

    new.setFlags(Qt.ItemIsEnabled)
    updated.setFlags(Qt.ItemIsEnabled)
    unchanged.setFlags(Qt.ItemIsEnabled)

    new.setExpanded(True)
    updated.setExpanded(True)

    items = []
    for snip in elements:
        item = QTreeWidgetItem()

        item.body = snip.find('body').text
        item.title = snip.find('title').text
        item.shortcuts = list(e.text for e in snip.findall('shortcuts/shortcut'))

        title = item.title or snippets.maketitle(snippets.parse(item.body).text)
        item.setText(0, title)

        name = snip.get('id')
        name = name if name in builtins else None


        # determine if new, updated or unchanged
        if not name:
            name = titles.get(title)
        item.name = name

        if not name or name not in allnames:
            new.addChild(item)
            items.append(item)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
            item.setCheckState(0, Qt.Checked)
        elif name:
            if (item.body != snippets.text(name)
                or title != snippets.title(name)
                or (item.shortcuts and item.shortcuts !=
                    [s.toString() for s in model.shortcuts(name) or ()])):
                updated.addChild(item)
                items.append(item)
                item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                item.setCheckState(0, Qt.Checked)
            else:
                unchanged.addChild(item)
                item.setFlags(Qt.ItemIsEnabled)
    # count:
    for i in new, updated, unchanged:
        i.setText(0, i.text(0) + " ({0})".format(i.childCount()))
    for i in new, updated:
        if i.childCount():
            i.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
            i.setCheckState(0, Qt.Checked)

    def changed(item):
        if item in (new, updated):
            for i in range(item.childCount()):
                c = item.child(i)
                c.setCheckState(0, item.checkState(0))

    tree.itemChanged.connect(changed)

    importShortcuts = QTreeWidgetItem([_("Import Keyboard Shortcuts")])
    if items:
        tree.addTopLevelItem(importShortcuts)
        importShortcuts.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
        importShortcuts.setCheckState(0, Qt.Checked)
        dlg.setMessage(_("Choose which snippets you want to import:"))
    else:
        dlg.setMessage(_("There are no new or updated snippets in the file."))
        unchanged.setExpanded(True)

    tree.setWhatsThis(_(
        "<p>Here the snippets from {filename} are displayed.</p>\n"
        "<p>If there are new or updated snippets, you can select or deselect "
        "them one by one, or all at once, using the checkbox of the group. "
        "Then click OK to import all the selected snippets.</p>\n"
        "<p>Existing, unchanged snippets can't be imported.</p>\n"
        ).format(filename=os.path.basename(filename)))

    qutil.saveDialogSize(dlg, "snippettool/import/size", QSize(400, 300))
    if not dlg.exec_() or not items:
        return
    ac = model.collection()
    m = model.model()
    with qutil.busyCursor():
        for i in items:
            if i.checkState(0) == Qt.Checked:
                index = m.saveSnippet(i.name, i.body, i.title)
                if i.shortcuts and importShortcuts.checkState(0):
                    shortcuts = list(map(QKeySequence.fromString, i.shortcuts))
                    ac.setShortcuts(m.name(index), shortcuts)
        widget.updateColumnSizes()
Beispiel #39
0
class QrcPackageEditor(QGridLayout):
    """ A resource file system package editor.  Note that this is a QLayout and
    not a QWidget.
    """

    # Emitted when the package has changed.
    package_changed = pyqtSignal()

    def __init__(self, show_root=False, scan="Scan", scan_whats_this='', whats_this=''):
        """ Initialise the editor. """

        super().__init__()

        self.package = None
        self.project = None

        self._show_root = show_root

        self._package_edit = QTreeWidget(whatsThis=whats_this)
        self._package_edit.header().hide()
        self._package_edit.itemChanged.connect(self._package_changed)
        self.addWidget(self._package_edit, 0, 0, 3, 1)

        self._scan_button = QPushButton(scan, whatsThis=scan_whats_this,
                clicked=self._scan, enabled=False)
        self.addWidget(self._scan_button, 0, 1)

        self._remove_button = QPushButton("Remove all",
                whatsThis="Remove all of the scanned directories and files.",
                clicked=self._remove_all, enabled=False)
        self.addWidget(self._remove_button, 0, 2)

        self._include_button = QPushButton("Include all",
                whatsThis="Select all of the scanned directories and files.",
                clicked=self._include_all, enabled=False)
        self.addWidget(self._include_button, 1, 1)

        self._exclude_button = QPushButton("Exclude all",
                whatsThis="Deselect all of the scanned directories and files.",
                clicked=self._exclude_all, enabled=False)
        self.addWidget(self._exclude_button, 1, 2)

        self._exclusions_edit = QTreeWidget(
                whatsThis="Any directory or file that matches any of the "
                        "these patterns will be automatically ignored when "
                        "scanning. Double-click on a pattern to edit or remove "
                        "it. Double-click below the last pattern in order to "
                        "add a new one.")
        self._exclusions_edit.setHeaderLabel("Exclusions")
        self._exclusions_edit.setEditTriggers(
                QTreeWidget.DoubleClicked|QTreeWidget.SelectedClicked|
                        QTreeWidget.EditKeyPressed)
        self._exclusions_edit.setRootIsDecorated(False)
        self._exclusions_edit.itemChanged.connect(self._exclusion_changed)

        self.addWidget(self._exclusions_edit, 2, 1, 1, 2)

    def configure(self, package, project):
        """ Configure the editor with the contents of the given package and
        project.
        """

        # Save the configuration.
        self.package = package
        self.project = project

        # Set the package itself.
        self._visualise()

        # Set the exclusions.
        self._exclusions_edit.clear()

        for exclude in package.exclusions:
            self._add_exclusion_item(exclude)

        # Add one to be edited to create a new entry.
        self._add_exclusion_item()

        self._scan_button.setEnabled(package is not None)

    def get_root_dir(self):
        """ Return the root directory to scan, or '' if there was an error or
        the user cancelled.
        """

        raise NotImplementedError

    def filter(self, name):
        """ See if a scanned name should be discarded. """

        # Include everything by default.
        return False

    def required(self, name):
        """ See if a scanned name is required. """

        # Nothing is required by default.
        return False

    def _add_exclusion_item(self, exclude=''):
        """ Add a QTreeWidgetItem that holds an exclusion. """

        itm = QTreeWidgetItem([exclude])

        itm.setFlags(
                Qt.ItemIsSelectable|Qt.ItemIsEditable|Qt.ItemIsEnabled|
                        Qt.ItemNeverHasChildren)

        self._exclusions_edit.addTopLevelItem(itm)

    def _exclusion_changed(self, itm, column):
        """ Invoked when an exclusion has changed. """

        exc_edit = self._exclusions_edit

        new_exc = itm.data(0, Qt.DisplayRole).strip()
        itm_index = exc_edit.indexOfTopLevelItem(itm)

        if new_exc != '':
            # See if we have added a new one.
            if itm_index == exc_edit.topLevelItemCount() - 1:
                self._add_exclusion_item()
        else:
            # It is empty so remove it.
            exc_edit.takeTopLevelItem(itm_index)

        # Save the new exclusions.
        self.package.exclusions = [
                exc_edit.topLevelItem(i).data(0, Qt.DisplayRole).strip()
                        for i in range(exc_edit.topLevelItemCount() - 1)]

        self.package_changed.emit()

    def _get_items(self):
        """ Return an iterator over the tree widget items. """

        it = QTreeWidgetItemIterator(self._package_edit)

        if self._show_root:
            it += 1

        itm = it.value()
        while itm is not None:
            yield itm
            it += 1
            itm = it.value()

    def _include_all(self, _):
        """ Invoked when the user clicks on the include all button. """

        for itm in self._get_items():
            itm.setCheckState(0, Qt.Checked)

    def _exclude_all(self, _):
        """ Invoked when the user clicks on the exclude all button. """

        for itm in self._get_items():
            if not itm.isDisabled():
                itm.setCheckState(0, Qt.Unchecked)
                itm.setExpanded(False)

    def _remove_all(self, _):
        """ Invoked when the use clicks on the remove all button. """

        blocked = self._package_edit.blockSignals(True)
        self._package_edit.clear()
        self._package_edit.blockSignals(blocked)

        self._enable_buttons()

        # This is a bit of a hack but is currently the only way to completely
        # remove the application package.
        if self._show_root:
            self.package.name = ''

        del self.package.contents[:]
        self.package_changed.emit()

    def _enable_buttons(self):
        """ Set the enabled state of those buttons that require content. """

        enable = (len(list(self._get_items())) != 0)

        self._remove_button.setEnabled(enable)
        self._include_button.setEnabled(enable)
        self._exclude_button.setEnabled(enable)

    def _scan(self, _):
        """ Invoked when the user clicks on the scan button. """

        project = self.project
        package = self.package

        # Get the root directory to scan.
        root = self.get_root_dir()
        if root == '':
            return

        # Save the included state of any existing contents so that they can be
        # restored after the scan.
        old_state = {}

        for itm in self._get_items():
            rel_path = [itm.data(0, Qt.DisplayRole)]

            parent = itm.parent()
            while parent is not None:
                rel_path.append(parent.data(0, Qt.DisplayRole))
                parent = parent.parent()

            rel_path.reverse()

            if self._show_root:
                rel_path = rel_path[1:]

            old_state['/'.join(rel_path)] = (itm.checkState(0) == Qt.Checked)

        # Walk the package.
        root_dir = QDir(root)
        if not root_dir.exists():
            QMessageBox.warning(self.parentWidget(), "Scan Directory",
                    "{0} is not a valid directory.".format(
                            QDir.toNativeSeparators(root)))
            return

        self._add_to_container(package, root_dir, [], old_state)
        self._visualise()

        self.package_changed.emit()

    def _add_to_container(self, container, content_dir, dir_stack, old_state):
        """ Add the files and directories of a package or sub-package to a
        container.
        """

        dir_contents = content_dir.entryInfoList(
                QDir.Files|QDir.Dirs|QDir.NoDotAndDotDot)

        # Make sure any filter is applied in a predictable order.
        dir_contents.sort(key=lambda fi: fi.fileName().lower()[1:] if fi.fileName().startswith('_') else fi.fileName().lower())

        dir_stack.append(content_dir.dirName())
        contents = []

        for content in dir_contents:
            name = content.fileName()

            # Apply any exclusions.
            for exc in self.package.exclusions:
                if fnmatch.fnmatch(name, exc):
                    name = None
                    break

            if name is None:
                continue

            # Apply any filter.
            if len(dir_stack) > 1:
                module_path = dir_stack[1:]
                module_path.append(name)
                path_name = '/'.join(module_path)
            else:
                path_name = name

            if self.filter(path_name):
                continue

            # See if we already know the included state.
            included = old_state.get(path_name, False)

            # Add the content.
            if content.isDir():
                qrc = QrcDirectory(name, included)

                self._add_to_container(qrc, QDir(content.canonicalFilePath()),
                        dir_stack, old_state)
            elif content.isFile():
                qrc = QrcFile(name, included)
            else:
                continue

            contents.append(qrc)

        container.contents = contents
        dir_stack.pop()

    def _visualise(self):
        """ Update the GUI with the package content. """

        blocked = self._package_edit.blockSignals(True)

        self._package_edit.clear()

        if self.package.name is not None:
            if self._show_root:
                parent = QTreeWidgetItem([':/' + self.package.name])
                self._package_edit.addTopLevelItem(parent)
                parent.setExpanded(True)
            else:
                parent = self._package_edit

            self._visualise_contents(self.package.contents, parent)

        self._package_edit.blockSignals(blocked)

        self._enable_buttons()

    def _visualise_contents(self, contents, parent):
        """ Visualise the contents for a parent. """

        p = parent
        while p is not None and isinstance(p, QTreeWidgetItem):
            p = p.parent()

        for content in contents:
            itm = QTreeWidgetItem(parent, [content.name])

            itm.setCheckState(0,
                    Qt.Checked if content.included else Qt.Unchecked)

            itm.setData(0, Qt.UserRole, content)

            if isinstance(content, QrcDirectory):
                self._visualise_contents(content.contents, itm)

    def _package_changed(self, itm, column):
        """ Invoked when part of the package changes. """

        if itm.checkState(0) == Qt.Checked:
            itm.data(0, Qt.UserRole).included = True
            itm.setExpanded(True)
        else:
            self._exclude(itm)
            itm.setExpanded(False)

        self.package_changed.emit()

    def _exclude(self, itm):
        """ Exclude an item and any children it may have. """

        for idx in range(itm.childCount()):
            self._exclude(itm.child(idx))

        itm.data(0, Qt.UserRole).included = False
        itm.setCheckState(0, Qt.Unchecked)
Beispiel #40
0
class PugdebugExpressionViewer(QWidget):

    expression_added_signal = pyqtSignal(int, str)
    expression_changed_signal = pyqtSignal(int, str)

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

        # Action for adding a new expression
        self.add_action = QAction(QIcon.fromTheme('list-add'), "&Add", self)
        self.add_action.triggered.connect(self.handle_add_action)

        # Action for deleting selected expressions
        self.delete_action = QAction(
            QIcon.fromTheme('list-remove'),
            "&Delete", self
        )
        self.delete_action.setShortcut(QKeySequence("Del"))
        self.delete_action.triggered.connect(self.handle_delete_action)

        self.toolbar = QToolBar()
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.addAction(self.add_action)
        self.toolbar.addAction(self.delete_action)

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setHeaderLabels(['Expression', 'Type', 'Value'])
        self.tree.setSelectionMode(QAbstractItemView.ContiguousSelection)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.show_context_menu)

        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.tree)
        self.setLayout(layout)

        self.restore_state()

        self.tree.itemChanged.connect(self.handle_item_changed)

    def show_context_menu(self, point):
        # Create the context menu on the tree widget
        context_menu = QMenu(self)

        # Add action is always visible
        context_menu.addAction(self.add_action)

        # If clicked on an row, offer to delete it
        if self.tree.itemAt(point):
            context_menu.addAction(self.delete_action)

        point = self.tree.mapToGlobal(point)
        context_menu.popup(point)

    def add_expression(self, expression):
        item = QTreeWidgetItem([expression, '', ''])
        item.setFlags(
            Qt.ItemIsEnabled |
            Qt.ItemIsEditable |
            Qt.ItemIsSelectable
        )
        self.tree.addTopLevelItem(item)

        #  Emit the signal to evaluate the expression
        index = self.tree.indexOfTopLevelItem(item)
        self.expression_added_signal.emit(index, expression)

    def delete_selected(self):
        """Deletes currently selected items from the tree"""
        for item in self.tree.selectedItems():
            index = self.tree.indexOfTopLevelItem(item)
            self.delete_expression(item)
            self.select_next(index)

    def select_next(self, index):
        """Selects the next item after an item has been deleted"""
        prev_item = self.tree.topLevelItem(index - 1)
        next_item = self.tree.topLevelItem(index)

        if prev_item:
            prev_item.setSelected(True)
        elif next_item:
            next_item.setSelected(True)

    def clear_values(self):
        """Deletes values for all expressions"""
        count = self.tree.topLevelItemCount()
        for index in range(0, count):
            item = self.tree.topLevelItem(index)
            item.setData(1, Qt.DisplayRole, '')
            item.setData(2, Qt.DisplayRole, '')
            item.takeChildren()

    def delete_expression(self, item):
        """Deletes the given item from the tree"""
        index = self.tree.indexOfTopLevelItem(item)
        self.tree.takeTopLevelItem(index)

    def get_expressions(self):
        """Returns a list of expressions which are to be evaluated"""
        expressions = []
        for x in range(0, self.tree.topLevelItemCount()):
            expression = self.tree.topLevelItem(x).text(0)
            expressions.append(expression)

        return expressions

    def set_evaluated(self, index, result):
        """Displays an evaluated expression result"""
        type = self.decode_type(result)
        value = self.decode_value(result)

        item = self.tree.topLevelItem(index)
        item.setText(1, type)
        item.setText(2, value)

        variables = result['variables'] if 'variables' in result else []
        self.set_variables(item, variables)

    def set_variables(self, parent, variables):
        """Display an array of variables for the given parent item"""
        for index, variable in enumerate(variables):
            self.set_variable(parent, index, variable)

        # Delete any children which no longer exist
        # Last displayed index should be len(variables) - 1
        index = len(variables)
        while parent.child(index):
            parent.takeChild(index)

    def set_variable(self, parent, index, variable):
        """Display a single variable within the given parent item"""
        name = variable['name']
        type = self.decode_type(variable)
        value = self.decode_value(variable)

        item = parent.child(index)
        if item is None:
            # Item does not exist, create it
            item = QTreeWidgetItem([name, type, value])
            parent.insertChild(index, item)
        else:
            # Item exists, modify it
            item.setData(0, Qt.DisplayRole, name)
            item.setData(1, Qt.DisplayRole, type)
            item.setData(2, Qt.DisplayRole, value)

        # Recurse (we need to go deeper)
        if 'variables' in variable:
            self.set_variables(item, variable['variables'])

    def decode_type(self, result):
        if 'type' not in result:
            return ''

        # Display the class name instead of type for objects
        if result['type'] == 'object':
            return result['classname']

        return result['type']

    def decode_value(self, result):
        value = None

        if 'value' in result:
            value = result['value']

        if 'encoding' in result and value is not None:
            value = base64.b64decode(value).decode()

        if result['type'] == 'bool':
            value = 'false' if value == '0' else 'true'

        return value

    def save_state(self):
        """Save current expressions to settings"""
        set_setting('expressions_viewer/expressions', self.get_expressions())

    def restore_state(self):
        """Load expressions from settings"""
        expressions = []

        if has_setting('expressions_viewer/expressions'):
            expressions = get_setting('expressions_viewer/expressions')

        if expressions is not None:
            for expression in expressions:
                self.add_expression(expression)

    def handle_add_action(self):
        self.add_expression('$x')
        self.save_state()

    def handle_delete_action(self):
        self.delete_selected()
        self.save_state()

    def handle_item_changed(self, item, column):
        """Called when the user changes an item"""

        # Only check top level items
        if item.parent():
            return

        # Only check changes to the first column which contains the expressions
        if column > 0:
            return

        index = self.tree.indexOfTopLevelItem(item)
        expression = item.text(0)

        self.expression_changed_signal.emit(index, expression)
        self.save_state()
Beispiel #41
0
class OTMainWindow(QWidget):
    def __init__(self, parent=None):
        super(OTMainWindow, self).__init__(parent, Qt.Window)
        self.setWindowTitle('OPC Python Tester')
        self.layout = QVBoxLayout()
        #
        self.tree = QTreeWidget(self)
        self.tree.setHeaderLabel('OPC server tree')
        self.tree_root = QTreeWidgetItem()
        self.tree_root.setText(0, 'not connected')
        self.tree.addTopLevelItem(self.tree_root)
        self.tree.itemDoubleClicked.connect(self.on_tree_item_double_clicked)
        #
        self.table = QTableWidget(self)
        self.table.setRowCount(0)
        self.table_column_labels = [
            'item_id', 'value', 'type', 'access', 'quality', 'timestamp']
        self.table.setColumnCount(len(self.table_column_labels))
        self.table.setHorizontalHeaderLabels(self.table_column_labels)
        self.table.horizontalHeader().setStretchLastSection(True)
        #
        self.splitter = QSplitter(Qt.Horizontal, self)
        self.splitter.setChildrenCollapsible(False)
        self.splitter.setHandleWidth(10)
        self.layout.addWidget(self.splitter)
        # final
        self.splitter.addWidget(self.tree)
        self.splitter.addWidget(self.table)
        self.splitter.setSizes([150, 300])
        self.setLayout(self.layout)

        # self.opcsrv = None
        self.cur_server_info = {}
        self.cur_comp_name = ''
        self.watched_itemids = []

        self.ssdialog = ServerSelectDialog(self)
        ssel_ret = self.ssdialog.exec_()
        if ssel_ret == QDialog.Accepted:
            self.do_connect(self.ssdialog.selected_server, self.ssdialog.selected_comp_name)
        else:
            print('Connection cancelled')

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.on_timer_timeout)
        self.timer.start(1000)  # every 1 second

    def do_connect(self, srv_info: dict, comp_name: str):
        print('Connecting to "{0}" ({1}) on comp: {2}...'.format(
            srv_info['desc'], srv_info['guid'], comp_name))
        self.opcsrv = opc_helper.opc_connect(srv_info['guid'], comp_name)
        if self.opcsrv is None:
            return
        self.cur_comp_name = comp_name
        self.cur_server_info = srv_info
        print(self.opcsrv.get_status())
        self.fill_tree()

    def fill_tree(self):
        self.tree.clear()
        if self.opcsrv is None:
            return
        self.tree_root = QTreeWidgetItem(self.tree)
        self.tree_root.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless)
        root_title = '{0}'.format(self.cur_server_info['desc'])
        if self.cur_comp_name != '':
            root_title = '{0} ({1})'.format(self.cur_server_info['desc'], self.cur_comp_name)
        self.tree_root.setText(0, root_title)
        self.tree.addTopLevelItem(self.tree_root)
        server_tree = self.opcsrv.browse(flat=False)
        #
        for oitem in server_tree:
            self.fill_item(oitem, self.tree_root)

    def fill_item(self, item: dict, parent: QTreeWidgetItem):
        tree_item = QTreeWidgetItem()
        tree_item.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless)
        tree_item.setText(0, item['name'])
        if item['children'] is None:
            # set userdata = item_id only if this IS a LEAF node
            tree_item.setData(0, Qt.UserRole, item['item_id'])  # column, role, data
        parent.addChild(tree_item)
        # recurse into children
        if item['children'] is not None:
            for oitem in item['children']:
                self.fill_item(oitem, tree_item)

    @pyqtSlot(QTreeWidgetItem, int)
    def on_tree_item_double_clicked(self, item: QTreeWidgetItem, column: int):
        # void	itemDoubleClicked(QTreeWidgetItem * item, int column)
        # virtual QVariant	data(int column, int role) const
        item_data = item.data(0, Qt.UserRole)
        if item_data is None:
            return
        item_id = str(item_data)
        print('Double click on [{0}]'.format(item_id))
        self.opcsrv.get_item(item_id)
        if item_id not in self.watched_itemids:
            self.watched_itemids.append(item_id)

    @pyqtSlot()
    def on_timer_timeout(self):
        num_items = len(self.watched_itemids)
        self.table.setRowCount(num_items)
        i = 0
        while i < num_items:
            item_id = self.watched_itemids[i]
            item_value = self.opcsrv.get_item(item_id)
            item_info = self.opcsrv.get_item_info(item_id)
            #
            twi = QTableWidgetItem(str(item_id))
            self.table.setItem(i, 0, twi)
            #
            twi = QTableWidgetItem(str(item_value))
            self.table.setItem(i, 1, twi)
            #
            twi = QTableWidgetItem(str(item_info['type']))
            self.table.setItem(i, 2, twi)
            #
            twi = QTableWidgetItem(str(item_info['access_rights']))
            self.table.setItem(i, 3, twi)
            #
            twi = QTableWidgetItem(str(item_info['quality']))
            self.table.setItem(i, 4, twi)
            #
            ts_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(item_info['timestamp']))
            twi = QTableWidgetItem(str(ts_str))
            self.table.setItem(i, 5, twi)
            #
            i += 1
Beispiel #42
0
class GuiProjectLoad(QDialog):

    NONE_STATE = 0
    NEW_STATE  = 1
    OPEN_STATE = 2

    C_NAME  = 0
    C_COUNT = 1
    C_TIME  = 2

    def __init__(self, theParent):
        QDialog.__init__(self, theParent)

        logger.debug("Initialising GuiProjectLoad ...")
        self.setObjectName("GuiProjectLoad")

        self.mainConf  = nw.CONFIG
        self.theParent = theParent
        self.theTheme  = theParent.theTheme
        self.openState = self.NONE_STATE
        self.openPath  = None

        sPx = self.mainConf.pxInt(16)
        nPx = self.mainConf.pxInt(96)
        iPx = self.theTheme.baseIconSize

        self.outerBox = QVBoxLayout()
        self.innerBox = QHBoxLayout()
        self.outerBox.setSpacing(sPx)
        self.innerBox.setSpacing(sPx)

        self.setWindowTitle(self.tr("Open Project"))
        self.setMinimumWidth(self.mainConf.pxInt(650))
        self.setMinimumHeight(self.mainConf.pxInt(400))
        self.setModal(True)

        self.nwIcon = QLabel()
        self.nwIcon.setPixmap(self.theParent.theTheme.getPixmap("novelwriter", (nPx, nPx)))
        self.innerBox.addWidget(self.nwIcon, 0, Qt.AlignTop)

        self.projectForm = QGridLayout()
        self.projectForm.setContentsMargins(0, 0, 0, 0)

        self.listBox = QTreeWidget()
        self.listBox.setSelectionMode(QAbstractItemView.SingleSelection)
        self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
        self.listBox.setColumnCount(3)
        self.listBox.setHeaderLabels([
            self.tr("Working Title"),
            self.tr("Words"),
            self.tr("Last Opened"),
        ])
        self.listBox.setRootIsDecorated(False)
        self.listBox.itemSelectionChanged.connect(self._doSelectRecent)
        self.listBox.itemDoubleClicked.connect(self._doOpenRecent)
        self.listBox.setIconSize(QSize(iPx, iPx))

        treeHead = self.listBox.headerItem()
        treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight)
        treeHead.setTextAlignment(self.C_TIME, Qt.AlignRight)

        self.lblRecent = QLabel("<b>%s</b>" % self.tr("Recently Opened Projects"))
        self.lblPath   = QLabel("<b>%s</b>" % self.tr("Path"))
        self.selPath   = QLineEdit("")
        self.selPath.setReadOnly(True)

        self.browseButton = QPushButton("...")
        self.browseButton.setMaximumWidth(int(2.5*self.theTheme.getTextWidth("...")))
        self.browseButton.clicked.connect(self._doBrowse)

        self.projectForm.addWidget(self.lblRecent,    0, 0, 1, 3)
        self.projectForm.addWidget(self.listBox,      1, 0, 1, 3)
        self.projectForm.addWidget(self.lblPath,      2, 0, 1, 1)
        self.projectForm.addWidget(self.selPath,      2, 1, 1, 1)
        self.projectForm.addWidget(self.browseButton, 2, 2, 1, 1)
        self.projectForm.setColumnStretch(0, 0)
        self.projectForm.setColumnStretch(1, 1)
        self.projectForm.setColumnStretch(2, 0)
        self.projectForm.setVerticalSpacing(self.mainConf.pxInt(4))
        self.projectForm.setHorizontalSpacing(self.mainConf.pxInt(8))

        self.innerBox.addLayout(self.projectForm)

        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Open | QDialogButtonBox.Cancel)
        self.buttonBox.accepted.connect(self._doOpenRecent)
        self.buttonBox.rejected.connect(self._doCancel)

        self.newButton = self.buttonBox.addButton(self.tr("New"), QDialogButtonBox.ActionRole)
        self.newButton.clicked.connect(self._doNewProject)

        self.delButton = self.buttonBox.addButton(self.tr("Remove"), QDialogButtonBox.ActionRole)
        self.delButton.clicked.connect(self._doDeleteRecent)

        self.outerBox.addLayout(self.innerBox)
        self.outerBox.addWidget(self.buttonBox)
        self.setLayout(self.outerBox)

        self._populateList()
        self._doSelectRecent()

        keyDelete = QShortcut(self.listBox)
        keyDelete.setKey(QKeySequence(Qt.Key_Delete))
        keyDelete.activated.connect(self._doDeleteRecent)

        logger.debug("GuiProjectLoad initialisation complete")

        return

    ##
    #  Buttons
    ##

    def _doOpenRecent(self):
        """Close the dialog window with a recent project selected.
        """
        logger.verbose("GuiProjectLoad open button clicked")
        self._saveSettings()

        self.openPath = None
        self.openState = self.NONE_STATE

        selItems = self.listBox.selectedItems()
        if selItems:
            self.openPath = selItems[0].data(self.C_NAME, Qt.UserRole)
            self.openState = self.OPEN_STATE
            self.accept()

        return

    def _doSelectRecent(self):
        """A recent item has been selected.
        """
        selList = self.listBox.selectedItems()
        if selList:
            self.selPath.setText(selList[0].data(self.C_NAME, Qt.UserRole))
        return

    def _doBrowse(self):
        """Browse for a folder path.
        """
        logger.verbose("GuiProjectLoad browse button clicked")
        extFilter = [
            self.tr("novelWriter Project File ({0})").format(nwFiles.PROJ_FILE),
            self.tr("All files ({0})").format("*"),
        ]
        projFile, _ = QFileDialog.getOpenFileName(
            self, self.tr("Open Project"), "", filter=";;".join(extFilter)
        )
        if projFile:
            thePath = os.path.abspath(os.path.dirname(projFile))
            self.selPath.setText(thePath)
            self.openPath = thePath
            self.openState = self.OPEN_STATE
            self.accept()

        return

    def _doCancel(self):
        """Close the dialog window without doing anything.
        """
        logger.verbose("GuiProjectLoad close button clicked")
        self.openPath = None
        self.openState = self.NONE_STATE
        self.close()
        return

    def _doNewProject(self):
        """Create a new project.
        """
        logger.verbose("GuiProjectLoad new project button clicked")
        self._saveSettings()
        self.openPath = None
        self.openState = self.NEW_STATE
        self.accept()
        return

    def _doDeleteRecent(self):
        """Remove an entry from the recent projects list.
        """
        selList = self.listBox.selectedItems()
        if selList:
            projName = selList[0].text(self.C_NAME)
            msgYes = self.theParent.askQuestion(
                self.tr("Remove Entry"),
                self.tr(
                    "Remove '{0}' from the recent projects list? "
                    "The project files will not be deleted."
                ).format(projName)
            )
            if msgYes:
                self.mainConf.removeFromRecentCache(
                    selList[0].data(self.C_NAME, Qt.UserRole)
                )
                self._populateList()

        return

    ##
    #  Events
    ##

    def closeEvent(self, theEvent):
        """Capture the user closing the dialog so we can save settings.
        """
        self._saveSettings()
        theEvent.accept()
        return

    ##
    #  Internal Functions
    ##

    def _saveSettings(self):
        """Save the changes made to the dialog.
        """
        colWidths = [0, 0, 0]
        colWidths[self.C_NAME]  = self.listBox.columnWidth(self.C_NAME)
        colWidths[self.C_COUNT] = self.listBox.columnWidth(self.C_COUNT)
        colWidths[self.C_TIME]  = self.listBox.columnWidth(self.C_TIME)
        self.mainConf.setProjColWidths(colWidths)
        return

    def _populateList(self):
        """Populate the list box with recent project data.
        """
        dataList = []
        for projPath in self.mainConf.recentProj:
            theEntry = self.mainConf.recentProj[projPath]
            theTitle = theEntry.get("title", "")
            theTime  = theEntry.get("time", 0)
            theWords = theEntry.get("words", 0)
            dataList.append([theTitle, theTime, theWords, projPath])

        self.listBox.clear()
        sortList = sorted(dataList, key=lambda x: x[1], reverse=True)
        for theTitle, theTime, theWords, projPath in sortList:
            newItem = QTreeWidgetItem([""]*4)
            newItem.setIcon(self.C_NAME,  self.theParent.theTheme.getIcon("proj_nwx"))
            newItem.setText(self.C_NAME,  theTitle)
            newItem.setData(self.C_NAME,  Qt.UserRole, projPath)
            newItem.setText(self.C_COUNT, formatInt(theWords))
            newItem.setText(self.C_TIME,  datetime.fromtimestamp(theTime).strftime("%x %X"))
            newItem.setTextAlignment(self.C_NAME,  Qt.AlignLeft  | Qt.AlignVCenter)
            newItem.setTextAlignment(self.C_COUNT, Qt.AlignRight | Qt.AlignVCenter)
            newItem.setTextAlignment(self.C_TIME,  Qt.AlignRight | Qt.AlignVCenter)
            newItem.setFont(self.C_TIME, self.theTheme.guiFontFixed)
            self.listBox.addTopLevelItem(newItem)

        if self.listBox.topLevelItemCount() > 0:
            self.listBox.topLevelItem(0).setSelected(True)

        projColWidth = self.mainConf.getProjColWidths()
        if len(projColWidth) == 3:
            self.listBox.setColumnWidth(self.C_NAME,  projColWidth[self.C_NAME])
            self.listBox.setColumnWidth(self.C_COUNT, projColWidth[self.C_COUNT])
            self.listBox.setColumnWidth(self.C_TIME,  projColWidth[self.C_TIME])

        return
class OtherPackagesPage(QWidget):
    """ The GUI for the other packages page of a project. """

    # The page's label.
    label = "Other Packages"

    @property
    def project(self):
        """ The project property getter. """

        return self._project

    @project.setter
    def project(self, value):
        """ The project property setter. """

        if self._project != value:
            self._project = value
            self._package_delegate.set_project(value)
            self._update_page()

    def __init__(self):
        """ Initialise the page. """

        super().__init__()

        self._project = None

        # Create the page's GUI.
        layout = QHBoxLayout()

        self._package_selector = QTreeWidget(
                whatsThis="This shows a list of directories containing "
                        "additional Python packages which can be scanned when "
                        "selected. Double-click on a directory to edit or "
                        "remove it. Double-click below the last directory in "
                        "order to add a new one.")
        self._package_selector.setHeaderLabel("Packages Directory")
        self._package_selector.setEditTriggers(
                QTreeWidget.DoubleClicked|QTreeWidget.SelectedClicked|
                QTreeWidget.EditKeyPressed)
        self._package_selector.setRootIsDecorated(False)
        self._package_selector.currentItemChanged.connect(
                self._package_selector_changed)
        self._package_selector.itemChanged.connect(self._package_dir_changed)

        self._package_delegate = FilenameEditorDelegate("Packages Directory",
                directory=True)

        self._package_selector.setItemDelegateForColumn(0,
                self._package_delegate)

        layout.addWidget(self._package_selector)

        self._package_edit = _PackageDirectoryEditor()
        self._package_edit.package_changed.connect(self._package_changed)

        package_edit_gb = QGroupBox(self._package_edit.title)
        package_edit_gb.setLayout(self._package_edit)
        layout.addWidget(package_edit_gb)

        self.setLayout(layout)

    def _update_page(self):
        """ Update the page using the current project. """

        project = self.project

        self._package_selector.clear()

        for package in project.other_packages:
            self._add_package_dir(package)

        self._add_package_dir()

    def _add_package_dir(self, package=None):
        """ Add a QTreeWidgetItem that holds a package directory. """

        if package is None:
            package = QrcPackage()
            name = ''
        else:
            name = package.name

        itm = QTreeWidgetItem([name])
        itm.setData(0, Qt.UserRole, package)
        itm.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled|Qt.ItemNeverHasChildren|Qt.ItemIsEditable)

        self._package_selector.addTopLevelItem(itm)

    def _package_selector_changed(self, new, old):
        """ Invoked when the user selects a package directory. """

        if new is not None:
            self._package_edit.configure(new.data(0, Qt.UserRole),
                    self.project)

    def _package_dir_changed(self, itm, column):
        """ Invoked when the user edits a package directory name. """

        project = self.project

        selector = self._package_selector

        new_dir = itm.data(0, Qt.DisplayRole).strip()
        itm_index = selector.indexOfTopLevelItem(itm)

        if new_dir != '':
            itm.data(0, Qt.UserRole).name = project.path_to_user(new_dir)

            # See if we have added a new one.
            if itm_index == selector.topLevelItemCount() - 1:
                self._add_package_dir()
        else:
            # It is empty so remove it.
            selector.takeTopLevelItem(itm_index)

        # Save the new packages.
        project.other_packages = [
                selector.topLevelItem(i).data(0, Qt.UserRole)
                        for i in range(selector.topLevelItemCount() - 1)]

        self.project.modified = True

    def _package_changed(self):
        """ Invoked when the user edits a package contents. """

        self.project.modified = True
class Preferences(QDialog):
#
    configuration = {}
    weight = 0
#
    savePreferences = pyqtSignal()
#
    def __init__(self, parent=None):
        super(Preferences, self).__init__(parent, Qt.Dialog)
        self.setWindowTitle(translations.TR_PREFERENCES_TITLE)
        self.setMinimumSize(QSize(900, 600))
        vbox = QVBoxLayout(self)
        hbox = QHBoxLayout()
        vbox.setContentsMargins(0, 0, 5, 5)
        hbox.setContentsMargins(0, 0, 0, 0)
#
        self.tree = QTreeWidget()
        self.tree.header().setHidden(True)
        self.tree.setSelectionMode(QTreeWidget.SingleSelection)
        self.tree.setAnimated(True)
        self.tree.header().setHorizontalScrollMode(
            QAbstractItemView.ScrollPerPixel)
        self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setStretchLastSection(False)
        self.tree.setFixedWidth(200)
        self.stacked = QStackedLayout()
        hbox.addWidget(self.tree)
        hbox.addLayout(self.stacked)
        vbox.addLayout(hbox)
#
        hbox_footer = QHBoxLayout()
        self._btnSave = QPushButton(translations.TR_SAVE)
        self._btnCancel = QPushButton(translations.TR_CANCEL)
        hbox_footer.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        hbox_footer.addWidget(self._btnCancel)
        hbox_footer.addWidget(self._btnSave)
        vbox.addLayout(hbox_footer)
#
        self.tree.itemSelectionChanged.connect(self._change_current)
        self._btnCancel.clicked['bool'].connect(self.close)
        self._btnSave.clicked['bool'].connect(self._save_preferences)
#
        self.load_ui()
        self.tree.setCurrentItem(self.tree.topLevelItem(0))
#
    def _save_preferences(self):
        self.savePreferences.emit()
        self.close()
#
    def load_ui(self):
        sections = sorted(
            list(Preferences.configuration.keys()),
            key=lambda item: Preferences.configuration[item]['weight'])
        for section in sections:
            text = Preferences.configuration[section]['text']
            Widget = Preferences.configuration[section]['widget']
            widget = Widget(self)
            area = QScrollArea()
            area.setWidgetResizable(True)
            area.setWidget(widget)
            self.stacked.addWidget(area)
            index = self.stacked.indexOf(area)
            item = QTreeWidgetItem([text])
            item.setData(0, Qt.UserRole, index)
            self.tree.addTopLevelItem(item)
#
            #Sort Item Children
            subcontent = Preferences.configuration[section].get(
                'subsections', {})
            subsections = sorted(list(subcontent.keys()),
                                 key=lambda item: subcontent[item]['weight'])
            for sub in subsections:
                text = subcontent[sub]['text']
                Widget = subcontent[sub]['widget']
                widget = Widget(self)
                area = QScrollArea()
                area.setWidgetResizable(True)
                area.setWidget(widget)
                self.stacked.addWidget(area)
                index = self.stacked.indexOf(area)
                subitem = QTreeWidgetItem([text])
                subitem.setData(0, Qt.UserRole, index)
                item.addChild(subitem)
#
        self.tree.expandAll()
#
    def _change_current(self):
        item = self.tree.currentItem()
        index = item.data(0, Qt.UserRole)
        self.stacked.setCurrentIndex(index)
#
    @classmethod
    def register_configuration(cls, section, widget, text, weight=None,
                               subsection=None):
        if weight is None:
            Preferences.weight += 1
            weight = Preferences.weight
        if not subsection:
            Preferences.configuration[section] = {'widget': widget,
                                                  'weight': weight,
                                                  'text': text}
        else:
            config = Preferences.configuration.get(section, {})
            if not config:
                config[section] = {'widget': None, 'weight': 100}
            subconfig = config.get('subsections', {})
            subconfig[subsection] = {'widget': widget, 'weight': weight,
                                     'text': text}
            config['subsections'] = subconfig
            Preferences.configuration[section] = config
Beispiel #45
0
class PugdebugExpressionViewer(QWidget):

    expression_added_signal = pyqtSignal(int, str)
    expression_changed_signal = pyqtSignal(int, str)

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

        # Action for adding a new expression
        self.add_action = QAction(QIcon.fromTheme('list-add'), "&Add", self)
        self.add_action.triggered.connect(self.handle_add_action)

        # Action for deleting selected expressions
        self.delete_action = QAction(QIcon.fromTheme('list-remove'), "&Delete",
                                     self)
        self.delete_action.setShortcut(QKeySequence("Del"))
        self.delete_action.triggered.connect(self.handle_delete_action)

        self.toolbar = QToolBar()
        self.toolbar.setIconSize(QSize(16, 16))
        self.toolbar.addAction(self.add_action)
        self.toolbar.addAction(self.delete_action)

        self.tree = QTreeWidget()
        self.tree.setColumnCount(3)
        self.tree.setHeaderLabels(['Expression', 'Type', 'Value'])
        self.tree.setSelectionMode(QAbstractItemView.ContiguousSelection)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.show_context_menu)

        layout = QVBoxLayout()
        layout.addWidget(self.toolbar)
        layout.addWidget(self.tree)
        self.setLayout(layout)

        self.restore_state()

        self.tree.itemChanged.connect(self.handle_item_changed)

    def show_context_menu(self, point):
        # Create the context menu on the tree widget
        context_menu = QMenu(self)

        # Add action is always visible
        context_menu.addAction(self.add_action)

        # If clicked on an row, offer to delete it
        if self.tree.itemAt(point):
            context_menu.addAction(self.delete_action)

        point = self.tree.mapToGlobal(point)
        context_menu.popup(point)

    def add_expression(self, expression):
        item = QTreeWidgetItem([expression, '', ''])
        item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable
                      | Qt.ItemIsSelectable)
        self.tree.addTopLevelItem(item)

        #  Emit the signal to evaluate the expression
        index = self.tree.indexOfTopLevelItem(item)
        self.expression_added_signal.emit(index, expression)

    def delete_selected(self):
        """Deletes currently selected items from the tree"""
        for item in self.tree.selectedItems():
            index = self.tree.indexOfTopLevelItem(item)
            self.delete_expression(item)
            self.select_next(index)

    def select_next(self, index):
        """Selects the next item after an item has been deleted"""
        prev_item = self.tree.topLevelItem(index - 1)
        next_item = self.tree.topLevelItem(index)

        if prev_item:
            prev_item.setSelected(True)
        elif next_item:
            next_item.setSelected(True)

    def clear_values(self):
        """Deletes values for all expressions"""
        count = self.tree.topLevelItemCount()
        for index in range(0, count):
            item = self.tree.topLevelItem(index)
            item.setData(1, Qt.DisplayRole, '')
            item.setData(2, Qt.DisplayRole, '')
            item.takeChildren()

    def delete_expression(self, item):
        """Deletes the given item from the tree"""
        index = self.tree.indexOfTopLevelItem(item)
        self.tree.takeTopLevelItem(index)

    def get_expressions(self):
        """Returns a list of expressions which are to be evaluated"""
        expressions = []
        for x in range(0, self.tree.topLevelItemCount()):
            expression = self.tree.topLevelItem(x).text(0)
            expressions.append(expression)

        return expressions

    def set_evaluated(self, index, result):
        """Displays an evaluated expression result"""
        type = self.decode_type(result)
        value = self.decode_value(result)

        item = self.tree.topLevelItem(index)
        item.setText(1, type)
        item.setText(2, value)

        variables = result['variables'] if 'variables' in result else []
        self.set_variables(item, variables)

    def set_variables(self, parent, variables):
        """Display an array of variables for the given parent item"""
        for index, variable in enumerate(variables):
            self.set_variable(parent, index, variable)

        # Delete any children which no longer exist
        # Last displayed index should be len(variables) - 1
        index = len(variables)
        while parent.child(index):
            parent.takeChild(index)

    def set_variable(self, parent, index, variable):
        """Display a single variable within the given parent item"""
        name = variable['name']
        type = self.decode_type(variable)
        value = self.decode_value(variable)

        item = parent.child(index)
        if item is None:
            # Item does not exist, create it
            item = QTreeWidgetItem([name, type, value])
            parent.insertChild(index, item)
        else:
            # Item exists, modify it
            item.setData(0, Qt.DisplayRole, name)
            item.setData(1, Qt.DisplayRole, type)
            item.setData(2, Qt.DisplayRole, value)

        # Recurse (we need to go deeper)
        if 'variables' in variable:
            self.set_variables(item, variable['variables'])

    def decode_type(self, result):
        if 'type' not in result:
            return ''

        # Display the class name instead of type for objects
        if result['type'] == 'object':
            return result['classname']

        return result['type']

    def decode_value(self, result):
        value = None

        if 'value' in result:
            value = result['value']

        if 'encoding' in result and value is not None:
            value = base64.b64decode(value)
            try:
                value = value.decode()
            except:
                value = repr(value)

        if result['type'] == 'bool':
            value = 'false' if value == '0' else 'true'

        return value

    def save_state(self):
        """Save current expressions to settings"""
        set_setting('expressions_viewer/expressions', self.get_expressions())

    def restore_state(self):
        """Load expressions from settings"""
        expressions = []

        if has_setting('expressions_viewer/expressions'):
            expressions = get_setting('expressions_viewer/expressions')

        if expressions is not None:
            for expression in expressions:
                self.add_expression(expression)

    def handle_add_action(self):
        self.add_expression('$x')
        self.save_state()

    def handle_delete_action(self):
        self.delete_selected()
        self.save_state()

    def handle_item_changed(self, item, column):
        """Called when the user changes an item"""

        # Only check top level items
        if item.parent():
            return

        # Only check changes to the first column which contains the expressions
        if column > 0:
            return

        index = self.tree.indexOfTopLevelItem(item)
        expression = item.text(0)

        self.expression_changed_signal.emit(index, expression)
        self.save_state()
class CueListDialog(QDialog):

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.setMinimumSize(400, 300)

        self._cues = []

        self.list = QTreeWidget(self)
        self.list.setSelectionMode(self.list.SingleSelection)
        self.list.setSelectionBehavior(self.list.SelectRows)
        self.list.setAlternatingRowColors(True)
        self.list.setIndentation(0)
        self.list.setHeaderLabels(['Index', 'Name'])
        self.list.header().setSectionResizeMode(QHeaderView.Fixed)
        self.list.header().setSectionResizeMode(1, QHeaderView.Stretch)
        self.list.header().setStretchLastSection(False)

        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.list)

        self.buttons = QDialogButtonBox(self)
        self.buttons.addButton(QDialogButtonBox.Cancel)
        self.buttons.addButton(QDialogButtonBox.Ok)
        self.layout().addWidget(self.buttons)

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

    def add_cue(self, cue):
        try:
            item = QTreeWidgetItem()
            item.setTextAlignment(0, Qt.AlignCenter)

            for n, prop in enumerate(['index', 'name']):
                item.setText(n, str(cue.properties().get(prop, 'Undefined')))

            self._cues.append(cue)
            self.list.addTopLevelItem(item)
        except Exception:
            pass

    def add_cues(self, cues):
        for cue in cues:
            self.add_cue(cue)

    def remove_cue(self, index):
        self.list.takeTopLevelItem(index)
        return self._cues.pop(index)

    def reset(self):
        self.list.clear()
        self._cues.clear()

    def selected_cues(self):
        cues = []
        for item in self.list.selectedItems():
            index = self.list.indexOfTopLevelItem(item)
            cues.append(self._cues[index])
        return cues
class EditorConfiguration(QWidget):
    """EditorConfiguration widget class"""
    def __init__(self, parent):
        super(EditorConfiguration, self).__init__()
        self._preferences, vbox = parent, QVBoxLayout(self)

        # groups
        group1 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_INDENT)
        group2 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN)
        group3 = QGroupBox(translations.TR_LINT_DIRTY_TEXT)
        group4 = QGroupBox(translations.TR_PEP8_DIRTY_TEXT)
        group5 = QGroupBox(translations.TR_HIGHLIGHTER_EXTRAS)
        group6 = QGroupBox(translations.TR_TYPING_ASSISTANCE)
        group7 = QGroupBox(translations.TR_DISPLAY)

        # groups container
        container_widget_with_all_preferences = QWidget()
        formFeatures = QGridLayout(container_widget_with_all_preferences)

        # Indentation
        hboxg1 = QHBoxLayout(group1)
        hboxg1.setContentsMargins(5, 15, 5, 5)
        self._spin, self._checkUseTabs = QSpinBox(), QComboBox()
        self._spin.setRange(1, 10)
        self._spin.setValue(settings.INDENT)
        hboxg1.addWidget(self._spin)
        self._checkUseTabs.addItems([
            translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES.capitalize(),
            translations.TR_PREFERENCES_EDITOR_CONFIG_TABS.capitalize()
        ])
        self._checkUseTabs.setCurrentIndex(int(settings.USE_TABS))
        hboxg1.addWidget(self._checkUseTabs)
        formFeatures.addWidget(group1, 0, 0)

        # Margin Line
        hboxg2 = QHBoxLayout(group2)
        hboxg2.setContentsMargins(5, 15, 5, 5)
        self._checkShowMargin = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE)
        self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE)
        hboxg2.addWidget(self._checkShowMargin)
        self._spinMargin = QSpinBox()
        self._spinMargin.setRange(50, 100)
        self._spinMargin.setSingleStep(2)
        self._spinMargin.setValue(settings.MARGIN_LINE)
        hboxg2.addWidget(self._spinMargin)
        hboxg2.addWidget(QLabel(translations.TR_CHARACTERS))
        formFeatures.addWidget(group2, 0, 1)

        # Display Errors
        vboxDisplay = QVBoxLayout(group7)
        vboxDisplay.setContentsMargins(5, 15, 5, 5)
        self._checkHighlightLine = QComboBox()
        self._checkHighlightLine.addItems([
            translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_BACKGROUND,
            translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_UNDERLINE
        ])
        self._checkHighlightLine.setCurrentIndex(
            int(settings.UNDERLINE_NOT_BACKGROUND))
        hboxDisplay1 = QHBoxLayout()
        hboxDisplay1.addWidget(QLabel(translations.TR_DISPLAY_ERRORS))
        hboxDisplay1.addWidget(self._checkHighlightLine)
        hboxDisplay2 = QHBoxLayout()
        self._checkDisplayLineNumbers = QCheckBox(
            translations.TR_DISPLAY_LINE_NUMBERS)
        self._checkDisplayLineNumbers.setChecked(settings.SHOW_LINE_NUMBERS)
        hboxDisplay2.addWidget(self._checkDisplayLineNumbers)
        vboxDisplay.addLayout(hboxDisplay1)
        vboxDisplay.addLayout(hboxDisplay2)
        formFeatures.addWidget(group7, 1, 0, 1, 0)

        # Find Lint Errors (highlighter)
        vboxg3 = QVBoxLayout(group3)
        self._checkErrors = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS)
        self._checkErrors.setChecked(settings.FIND_ERRORS)
        self._checkErrors.stateChanged[int].connect(self._disable_show_errors)
        self._showErrorsOnLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS)
        self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE)
        self._showErrorsOnLine.stateChanged[int].connect(
            self._enable_errors_inline)
        vboxg3.addWidget(self._checkErrors)
        vboxg3.addWidget(self._showErrorsOnLine)
        vboxg3.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding))
        formFeatures.addWidget(group3, 2, 0)

        # Find PEP8 Errors (highlighter)
        vboxg4 = QHBoxLayout(group4)
        vboxg4.setContentsMargins(5, 15, 5, 5)
        vvbox = QVBoxLayout()
        self._checkStyle = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8)
        self._checkStyle.setChecked(settings.CHECK_STYLE)
        self._checkStyle.stateChanged[int].connect(self._disable_check_style)
        vvbox.addWidget(self._checkStyle)
        self._checkStyleOnLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8)
        self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE)
        self._checkStyleOnLine.stateChanged[int].connect(
            self._enable_check_inline)
        vvbox.addWidget(self._checkStyleOnLine)
        vvbox.addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        vboxg4.addLayout(vvbox)
        # Container for tree widget and buttons
        widget = QWidget()
        hhbox = QHBoxLayout(widget)
        hhbox.setContentsMargins(0, 0, 0, 0)
        # Tree Widget with custom item delegate
        # always adds uppercase text
        self._listIgnoreViolations = QTreeWidget()
        self._listIgnoreViolations.setObjectName("ignore_pep8")
        self._listIgnoreViolations.setItemDelegate(ui_tools.CustomDelegate())
        self._listIgnoreViolations.setMaximumHeight(80)
        self._listIgnoreViolations.setHeaderLabel(
            translations.TR_PREFERENCES_EDITOR_CONFIG_IGNORE_PEP8)
        for ic in settings.IGNORE_PEP8_LIST:
            self._listIgnoreViolations.addTopLevelItem(QTreeWidgetItem([ic]))
        hhbox.addWidget(self._listIgnoreViolations)
        box = QVBoxLayout()
        box.setContentsMargins(0, 0, 0, 0)
        btn_add = QPushButton(QIcon(":img/add_small"), '')
        btn_add.setMaximumSize(26, 24)
        btn_add.clicked.connect(self._add_code_pep8)
        box.addWidget(btn_add)
        btn_remove = QPushButton(QIcon(":img/delete_small"), '')
        btn_remove.setMaximumSize(26, 24)
        btn_remove.clicked.connect(self._remove_code_pep8)
        box.addWidget(btn_remove)
        box.addItem(QSpacerItem(0, 0, QSizePolicy.Fixed,
                                QSizePolicy.Expanding))
        hhbox.addLayout(box)
        vboxg4.addWidget(widget)
        formFeatures.addWidget(group4)

        # Show Python3 Migration, DocStrings and Spaces (highlighter)
        vboxg5 = QVBoxLayout(group5)
        vboxg5.setContentsMargins(5, 15, 5, 5)
        self._showMigrationTips = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION)
        self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS)
        vboxg5.addWidget(self._showMigrationTips)
        self._checkForDocstrings = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS)
        self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS)
        vboxg5.addWidget(self._checkForDocstrings)
        self._checkShowSpaces = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES)
        self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES)
        vboxg5.addWidget(self._checkShowSpaces)
        self._checkIndentationGuide = QCheckBox(
            translations.TR_SHOW_INDENTATION_GUIDE)
        self._checkIndentationGuide.setChecked(settings.SHOW_INDENTATION_GUIDE)
        vboxg5.addWidget(self._checkIndentationGuide)
        formFeatures.addWidget(group5, 3, 0)

        # End of line, Stop Scrolling At Last Line, Trailing space, Word wrap
        vboxg6 = QVBoxLayout(group6)
        vboxg6.setContentsMargins(5, 15, 5, 5)
        self._checkEndOfLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE)
        self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE)
        vboxg6.addWidget(self._checkEndOfLine)
        self._checkEndAtLastLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_END_AT_LAST_LINE)
        self._checkEndAtLastLine.setChecked(settings.END_AT_LAST_LINE)
        vboxg6.addWidget(self._checkEndAtLastLine)
        self._checkTrailing = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING)
        self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES)
        vboxg6.addWidget(self._checkTrailing)
        self._allowWordWrap = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP)
        self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP)
        vboxg6.addWidget(self._allowWordWrap)
        formFeatures.addWidget(group6, 3, 1)

        # pack all the groups
        vbox.addWidget(container_widget_with_all_preferences)
        vbox.addItem(
            QSpacerItem(0, 10, QSizePolicy.Expanding, QSizePolicy.Expanding))

        self._preferences.savePreferences.connect(self.save)

    def _add_code_pep8(self):
        item = QTreeWidgetItem()
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self._listIgnoreViolations.addTopLevelItem(item)
        self._listIgnoreViolations.setCurrentItem(item)
        self._listIgnoreViolations.editItem(item, 0)

    def _remove_code_pep8(self):
        index = self._listIgnoreViolations.indexOfTopLevelItem(
            self._listIgnoreViolations.currentItem())
        self._listIgnoreViolations.takeTopLevelItem(index)

    def _enable_check_inline(self, val):
        """Method that takes a value to enable the inline style checking"""
        if val == Qt.Checked:
            self._checkStyle.setChecked(True)

    def _enable_errors_inline(self, val):
        """Method that takes a value to enable the inline errors checking"""
        if val == Qt.Checked:
            self._checkErrors.setChecked(True)

    def _disable_check_style(self, val):
        """Method that takes a value to disable the inline style checking"""
        if val == Qt.Unchecked:
            self._checkStyleOnLine.setChecked(False)

    def _disable_show_errors(self, val):
        """Method that takes a value to disable the inline errors checking"""
        if val == Qt.Unchecked:
            self._showErrorsOnLine.setChecked(False)

    def save(self):
        """Method to save settings"""
        qsettings = IDE.ninja_settings()
        settings.USE_TABS = bool(self._checkUseTabs.currentIndex())
        qsettings.setValue('preferences/editor/useTabs', settings.USE_TABS)
        margin_line = self._spinMargin.value()
        settings.MARGIN_LINE = margin_line
        settings.pycodestylemod_update_margin_line_length(margin_line)
        qsettings.setValue('preferences/editor/marginLine', margin_line)
        settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked()
        qsettings.setValue('preferences/editor/showMarginLine',
                           settings.SHOW_MARGIN_LINE)
        settings.INDENT = self._spin.value()
        qsettings.setValue('preferences/editor/indent', settings.INDENT)
        endOfLine = self._checkEndOfLine.isChecked()
        settings.USE_PLATFORM_END_OF_LINE = endOfLine
        qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine)
        settings.UNDERLINE_NOT_BACKGROUND = \
            bool(self._checkHighlightLine.currentIndex())
        qsettings.setValue('preferences/editor/errorsUnderlineBackground',
                           settings.UNDERLINE_NOT_BACKGROUND)
        settings.FIND_ERRORS = self._checkErrors.isChecked()
        qsettings.setValue('preferences/editor/errors', settings.FIND_ERRORS)
        settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked()
        qsettings.setValue('preferences/editor/errorsInLine',
                           settings.ERRORS_HIGHLIGHT_LINE)
        settings.CHECK_STYLE = self._checkStyle.isChecked()
        qsettings.setValue('preferences/editor/checkStyle',
                           settings.CHECK_STYLE)
        settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked()
        qsettings.setValue('preferences/editor/showMigrationTips',
                           settings.SHOW_MIGRATION_TIPS)
        settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked()
        qsettings.setValue('preferences/editor/checkStyleInline',
                           settings.CHECK_HIGHLIGHT_LINE)
        settings.END_AT_LAST_LINE = self._checkEndAtLastLine.isChecked()
        qsettings.setValue('preferences/editor/endAtLastLine',
                           settings.END_AT_LAST_LINE)
        settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked()
        qsettings.setValue('preferences/editor/removeTrailingSpaces',
                           settings.REMOVE_TRAILING_SPACES)
        settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked()
        qsettings.setValue('preferences/editor/allowWordWrap',
                           settings.ALLOW_WORD_WRAP)
        settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked()
        qsettings.setValue('preferences/editor/showTabsAndSpaces',
                           settings.SHOW_TABS_AND_SPACES)
        settings.SHOW_INDENTATION_GUIDE = (
            self._checkIndentationGuide.isChecked())
        qsettings.setValue('preferences/editor/showIndentationGuide',
                           settings.SHOW_INDENTATION_GUIDE)
        settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked()
        qsettings.setValue('preferences/editor/checkForDocstrings',
                           settings.CHECK_FOR_DOCSTRINGS)
        settings.SHOW_LINE_NUMBERS = self._checkDisplayLineNumbers.isChecked()
        qsettings.setValue('preferences/editor/showLineNumbers',
                           settings.SHOW_LINE_NUMBERS)
        current_ignores = set(settings.IGNORE_PEP8_LIST)
        new_ignore_codes = []
        # Get pep8 from tree widget
        for index in range(self._listIgnoreViolations.topLevelItemCount()):
            ignore_code = self._listIgnoreViolations.topLevelItem(index).text(
                0)
            if ignore_code:
                new_ignore_codes.append(ignore_code.strip())
        # pep8 list that will be removed
        to_remove = [x for x in current_ignores if x not in new_ignore_codes]
        # Update list
        settings.IGNORE_PEP8_LIST = new_ignore_codes
        qsettings.setValue('preferences/editor/defaultIgnorePep8',
                           settings.IGNORE_PEP8_LIST)
        # Add
        for ignore_code in settings.IGNORE_PEP8_LIST:
            settings.pycodestylemod_add_ignore(ignore_code)
        # Remove
        for ignore_code in to_remove:
            settings.pycodestylemod_remove_ignore(ignore_code)
        if settings.USE_TABS:
            settings.pycodestylemod_add_ignore("W191")
        else:
            settings.pycodestylemod_remove_ignore("W191")
class EditorConfiguration(QWidget):
    """EditorConfiguration widget class"""

    def __init__(self, parent):
        super(EditorConfiguration, self).__init__()
        self._preferences, vbox = parent, QVBoxLayout(self)

        # groups
        group1 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_INDENT)
        group2 = QGroupBox(translations.TR_PREFERENCES_EDITOR_CONFIG_MARGIN)
        group3 = QGroupBox(translations.TR_LINT_DIRTY_TEXT)
        group4 = QGroupBox(translations.TR_PEP8_DIRTY_TEXT)
        group5 = QGroupBox(translations.TR_HIGHLIGHTER_EXTRAS)
        group6 = QGroupBox(translations.TR_TYPING_ASSISTANCE)
        group7 = QGroupBox(translations.TR_DISPLAY)

        # groups container
        container_widget_with_all_preferences = QWidget()
        formFeatures = QGridLayout(container_widget_with_all_preferences)

        # Indentation
        hboxg1 = QHBoxLayout(group1)
        hboxg1.setContentsMargins(5, 15, 5, 5)
        self._spin, self._checkUseTabs = QSpinBox(), QComboBox()
        self._spin.setRange(1, 10)
        self._spin.setValue(settings.INDENT)
        hboxg1.addWidget(self._spin)
        self._checkUseTabs.addItems([
            translations.TR_PREFERENCES_EDITOR_CONFIG_SPACES.capitalize(),
            translations.TR_PREFERENCES_EDITOR_CONFIG_TABS.capitalize()])
        self._checkUseTabs.setCurrentIndex(int(settings.USE_TABS))
        hboxg1.addWidget(self._checkUseTabs)
        formFeatures.addWidget(group1, 0, 0)

        # Margin Line
        hboxg2 = QHBoxLayout(group2)
        hboxg2.setContentsMargins(5, 15, 5, 5)
        self._checkShowMargin = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MARGIN_LINE)
        self._checkShowMargin.setChecked(settings.SHOW_MARGIN_LINE)
        hboxg2.addWidget(self._checkShowMargin)
        self._spinMargin = QSpinBox()
        self._spinMargin.setRange(50, 100)
        self._spinMargin.setSingleStep(2)
        self._spinMargin.setValue(settings.MARGIN_LINE)
        hboxg2.addWidget(self._spinMargin)
        hboxg2.addWidget(QLabel(translations.TR_CHARACTERS))
        formFeatures.addWidget(group2, 0, 1)

        # Display Errors
        vboxDisplay = QVBoxLayout(group7)
        vboxDisplay.setContentsMargins(5, 15, 5, 5)
        self._checkHighlightLine = QComboBox()
        self._checkHighlightLine.addItems([
            translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_BACKGROUND,
            translations.TR_PREFERENCES_EDITOR_CONFIG_ERROR_USE_UNDERLINE])
        self._checkHighlightLine.setCurrentIndex(
            int(settings.UNDERLINE_NOT_BACKGROUND))
        hboxDisplay1 = QHBoxLayout()
        hboxDisplay1.addWidget(QLabel(translations.TR_DISPLAY_ERRORS))
        hboxDisplay1.addWidget(self._checkHighlightLine)
        hboxDisplay2 = QHBoxLayout()
        self._checkDisplayLineNumbers = QCheckBox(
            translations.TR_DISPLAY_LINE_NUMBERS)
        self._checkDisplayLineNumbers.setChecked(settings.SHOW_LINE_NUMBERS)
        hboxDisplay2.addWidget(self._checkDisplayLineNumbers)
        vboxDisplay.addLayout(hboxDisplay1)
        vboxDisplay.addLayout(hboxDisplay2)
        formFeatures.addWidget(group7, 1, 0, 1, 0)

        # Find Lint Errors (highlighter)
        vboxg3 = QVBoxLayout(group3)
        self._checkErrors = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_FIND_ERRORS)
        self._checkErrors.setChecked(settings.FIND_ERRORS)
        self._checkErrors.stateChanged[int].connect(self._disable_show_errors)
        self._showErrorsOnLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_ERRORS)
        self._showErrorsOnLine.setChecked(settings.ERRORS_HIGHLIGHT_LINE)
        self._showErrorsOnLine.stateChanged[int].connect(
            self._enable_errors_inline)
        vboxg3.addWidget(self._checkErrors)
        vboxg3.addWidget(self._showErrorsOnLine)
        vboxg3.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding))
        formFeatures.addWidget(group3, 2, 0)

        # Find PEP8 Errors (highlighter)
        vboxg4 = QHBoxLayout(group4)
        vboxg4.setContentsMargins(5, 15, 5, 5)
        vvbox = QVBoxLayout()
        self._checkStyle = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_PEP8)
        self._checkStyle.setChecked(settings.CHECK_STYLE)
        self._checkStyle.stateChanged[int].connect(self._disable_check_style)
        vvbox.addWidget(self._checkStyle)
        self._checkStyleOnLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TOOLTIP_PEP8)
        self._checkStyleOnLine.setChecked(settings.CHECK_HIGHLIGHT_LINE)
        self._checkStyleOnLine.stateChanged[int].connect(
            self._enable_check_inline)
        vvbox.addWidget(self._checkStyleOnLine)
        vvbox.addItem(QSpacerItem(0, 0,
                      QSizePolicy.Expanding, QSizePolicy.Expanding))
        vboxg4.addLayout(vvbox)
        # Container for tree widget and buttons
        widget = QWidget()
        hhbox = QHBoxLayout(widget)
        hhbox.setContentsMargins(0, 0, 0, 0)
        # Tree Widget with custom item delegate
        # always adds uppercase text
        self._listIgnoreViolations = QTreeWidget()
        self._listIgnoreViolations.setObjectName("ignore_pep8")
        self._listIgnoreViolations.setItemDelegate(ui_tools.CustomDelegate())
        self._listIgnoreViolations.setMaximumHeight(80)
        self._listIgnoreViolations.setHeaderLabel(
            translations.TR_PREFERENCES_EDITOR_CONFIG_IGNORE_PEP8)
        for ic in settings.IGNORE_PEP8_LIST:
            self._listIgnoreViolations.addTopLevelItem(QTreeWidgetItem([ic]))
        hhbox.addWidget(self._listIgnoreViolations)
        box = QVBoxLayout()
        box.setContentsMargins(0, 0, 0, 0)
        btn_add = QPushButton(QIcon(":img/add_small"), '')
        btn_add.setMaximumSize(26, 24)
        btn_add.clicked.connect(self._add_code_pep8)
        box.addWidget(btn_add)
        btn_remove = QPushButton(QIcon(":img/delete_small"), '')
        btn_remove.setMaximumSize(26, 24)
        btn_remove.clicked.connect(self._remove_code_pep8)
        box.addWidget(btn_remove)
        box.addItem(QSpacerItem(0, 0,
                    QSizePolicy.Fixed, QSizePolicy.Expanding))
        hhbox.addLayout(box)
        vboxg4.addWidget(widget)
        formFeatures.addWidget(group4)

        # Show Python3 Migration, DocStrings and Spaces (highlighter)
        vboxg5 = QVBoxLayout(group5)
        vboxg5.setContentsMargins(5, 15, 5, 5)
        self._showMigrationTips = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_MIGRATION)
        self._showMigrationTips.setChecked(settings.SHOW_MIGRATION_TIPS)
        vboxg5.addWidget(self._showMigrationTips)
        self._checkForDocstrings = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_CHECK_FOR_DOCSTRINGS)
        self._checkForDocstrings.setChecked(settings.CHECK_FOR_DOCSTRINGS)
        vboxg5.addWidget(self._checkForDocstrings)
        self._checkShowSpaces = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_SHOW_TABS_AND_SPACES)
        self._checkShowSpaces.setChecked(settings.SHOW_TABS_AND_SPACES)
        vboxg5.addWidget(self._checkShowSpaces)
        self._checkIndentationGuide = QCheckBox(
            translations.TR_SHOW_INDENTATION_GUIDE)
        self._checkIndentationGuide.setChecked(settings.SHOW_INDENTATION_GUIDE)
        vboxg5.addWidget(self._checkIndentationGuide)
        formFeatures.addWidget(group5, 3, 0)

        # End of line, Stop Scrolling At Last Line, Trailing space, Word wrap
        vboxg6 = QVBoxLayout(group6)
        vboxg6.setContentsMargins(5, 15, 5, 5)
        self._checkEndOfLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_END_OF_LINE)
        self._checkEndOfLine.setChecked(settings.USE_PLATFORM_END_OF_LINE)
        vboxg6.addWidget(self._checkEndOfLine)
        self._checkEndAtLastLine = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_END_AT_LAST_LINE)
        self._checkEndAtLastLine.setChecked(settings.END_AT_LAST_LINE)
        vboxg6.addWidget(self._checkEndAtLastLine)
        self._checkTrailing = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_REMOVE_TRAILING)
        self._checkTrailing.setChecked(settings.REMOVE_TRAILING_SPACES)
        vboxg6.addWidget(self._checkTrailing)
        self._allowWordWrap = QCheckBox(
            translations.TR_PREFERENCES_EDITOR_CONFIG_WORD_WRAP)
        self._allowWordWrap.setChecked(settings.ALLOW_WORD_WRAP)
        vboxg6.addWidget(self._allowWordWrap)
        formFeatures.addWidget(group6, 3, 1)

        # pack all the groups
        vbox.addWidget(container_widget_with_all_preferences)
        vbox.addItem(QSpacerItem(0, 10, QSizePolicy.Expanding,
                     QSizePolicy.Expanding))

        self._preferences.savePreferences.connect(self.save)

    def _add_code_pep8(self):
        item = QTreeWidgetItem()
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self._listIgnoreViolations.addTopLevelItem(item)
        self._listIgnoreViolations.setCurrentItem(item)
        self._listIgnoreViolations.editItem(item, 0)

    def _remove_code_pep8(self):
        index = self._listIgnoreViolations.indexOfTopLevelItem(
            self._listIgnoreViolations.currentItem())
        self._listIgnoreViolations.takeTopLevelItem(index)

    def _enable_check_inline(self, val):
        """Method that takes a value to enable the inline style checking"""
        if val == Qt.Checked:
            self._checkStyle.setChecked(True)

    def _enable_errors_inline(self, val):
        """Method that takes a value to enable the inline errors checking"""
        if val == Qt.Checked:
            self._checkErrors.setChecked(True)

    def _disable_check_style(self, val):
        """Method that takes a value to disable the inline style checking"""
        if val == Qt.Unchecked:
            self._checkStyleOnLine.setChecked(False)

    def _disable_show_errors(self, val):
        """Method that takes a value to disable the inline errors checking"""
        if val == Qt.Unchecked:
            self._showErrorsOnLine.setChecked(False)

    def save(self):
        """Method to save settings"""
        qsettings = IDE.ninja_settings()
        settings.USE_TABS = bool(self._checkUseTabs.currentIndex())
        qsettings.setValue('preferences/editor/useTabs',
                           settings.USE_TABS)
        margin_line = self._spinMargin.value()
        settings.MARGIN_LINE = margin_line
        settings.pycodestylemod_update_margin_line_length(margin_line)
        qsettings.setValue('preferences/editor/marginLine', margin_line)
        settings.SHOW_MARGIN_LINE = self._checkShowMargin.isChecked()
        qsettings.setValue('preferences/editor/showMarginLine',
                           settings.SHOW_MARGIN_LINE)
        settings.INDENT = self._spin.value()
        qsettings.setValue('preferences/editor/indent', settings.INDENT)
        endOfLine = self._checkEndOfLine.isChecked()
        settings.USE_PLATFORM_END_OF_LINE = endOfLine
        qsettings.setValue('preferences/editor/platformEndOfLine', endOfLine)
        settings.UNDERLINE_NOT_BACKGROUND = \
            bool(self._checkHighlightLine.currentIndex())
        qsettings.setValue('preferences/editor/errorsUnderlineBackground',
                           settings.UNDERLINE_NOT_BACKGROUND)
        settings.FIND_ERRORS = self._checkErrors.isChecked()
        qsettings.setValue('preferences/editor/errors', settings.FIND_ERRORS)
        settings.ERRORS_HIGHLIGHT_LINE = self._showErrorsOnLine.isChecked()
        qsettings.setValue('preferences/editor/errorsInLine',
                           settings.ERRORS_HIGHLIGHT_LINE)
        settings.CHECK_STYLE = self._checkStyle.isChecked()
        qsettings.setValue('preferences/editor/checkStyle',
                           settings.CHECK_STYLE)
        settings.SHOW_MIGRATION_TIPS = self._showMigrationTips.isChecked()
        qsettings.setValue('preferences/editor/showMigrationTips',
                           settings.SHOW_MIGRATION_TIPS)
        settings.CHECK_HIGHLIGHT_LINE = self._checkStyleOnLine.isChecked()
        qsettings.setValue('preferences/editor/checkStyleInline',
                           settings.CHECK_HIGHLIGHT_LINE)
        settings.END_AT_LAST_LINE = self._checkEndAtLastLine.isChecked()
        qsettings.setValue('preferences/editor/endAtLastLine',
                           settings.END_AT_LAST_LINE)
        settings.REMOVE_TRAILING_SPACES = self._checkTrailing.isChecked()
        qsettings.setValue('preferences/editor/removeTrailingSpaces',
                           settings.REMOVE_TRAILING_SPACES)
        settings.ALLOW_WORD_WRAP = self._allowWordWrap.isChecked()
        qsettings.setValue('preferences/editor/allowWordWrap',
                           settings.ALLOW_WORD_WRAP)
        settings.SHOW_TABS_AND_SPACES = self._checkShowSpaces.isChecked()
        qsettings.setValue('preferences/editor/showTabsAndSpaces',
                           settings.SHOW_TABS_AND_SPACES)
        settings.SHOW_INDENTATION_GUIDE = (
            self._checkIndentationGuide.isChecked())
        qsettings.setValue('preferences/editor/showIndentationGuide',
                           settings.SHOW_INDENTATION_GUIDE)
        settings.CHECK_FOR_DOCSTRINGS = self._checkForDocstrings.isChecked()
        qsettings.setValue('preferences/editor/checkForDocstrings',
                           settings.CHECK_FOR_DOCSTRINGS)
        settings.SHOW_LINE_NUMBERS = self._checkDisplayLineNumbers.isChecked()
        qsettings.setValue('preferences/editor/showLineNumbers',
                           settings.SHOW_LINE_NUMBERS)
        current_ignores = set(settings.IGNORE_PEP8_LIST)
        new_ignore_codes = []
        # Get pep8 from tree widget
        for index in range(self._listIgnoreViolations.topLevelItemCount()):
            ignore_code = self._listIgnoreViolations.topLevelItem(
                index).text(0)
            if ignore_code:
                new_ignore_codes.append(ignore_code.strip())
        # pep8 list that will be removed
        to_remove = [x for x in current_ignores
                     if x not in new_ignore_codes]
        # Update list
        settings.IGNORE_PEP8_LIST = new_ignore_codes
        qsettings.setValue('preferences/editor/defaultIgnorePep8',
                           settings.IGNORE_PEP8_LIST)
        # Add
        for ignore_code in settings.IGNORE_PEP8_LIST:
            settings.pycodestylemod_add_ignore(ignore_code)
        # Remove
        for ignore_code in to_remove:
            settings.pycodestylemod_remove_ignore(ignore_code)
        if settings.USE_TABS:
            settings.pycodestylemod_add_ignore("W191")
        else:
            settings.pycodestylemod_remove_ignore("W191")
Beispiel #49
0
    for i in range(3):
        l1_child = QTreeWidgetItem(["Child A" + str(i), "Child B" + str(i), "Child C" + str(i)])
        l1.addChild(l1_child)

    for j in range(2):
        l2_child = QTreeWidgetItem(["Child AA" + str(j), "Child BB" + str(j), "Child CC" + str(j)])
        l2.addChild(l2_child)

    w = QWidget()
    w.resize(510, 210)

    tw = QTreeWidget(w)
    tw.resize(500, 200)
    tw.setColumnCount(3)
    tw.setHeaderLabels(["Column 1", "Column 2", "Column 3"])
    tw.addTopLevelItem(l1)
    tw.addTopLevelItem(l2)

    w.show()
    sys.exit(app.exec_())


### 딕셔너리 추가
#le = {123:'aaa'}
le = {}
le[456] = 'bbb' or le.update(456='bbb')

### url 열기
import webbrowser
webbrowser.open("http://172.21.0.129:8080/yPLM")
Beispiel #50
0
class ImperiumWidget(QWidget):
    def __init__(self, parent=None):
        super(ImperiumWidget, self).__init__(parent)
        # objects, sub-windows
        self._world = XNovaWorld_instance()
        self._layout = None
        self._layout_topbuttons = None
        self._tree = None
        self._btn_reload = None
        # initialization
        self.setup_ui()

    def setup_ui(self):
        self._layout = QVBoxLayout()
        self.setLayout(self._layout)
        # create layout for top line of buttons
        self._layout_topbuttons = QHBoxLayout()
        self._layout.addLayout(self._layout_topbuttons)
        # create reload button
        self._btn_reload = QPushButton(self.tr('Refresh imperium'), self)
        self._btn_reload.setIcon(QIcon(':i/reload.png'))
        self._btn_reload.clicked.connect(self.on_btn_refresh_imperium)
        self._layout_topbuttons.addWidget(self._btn_reload)
        # finalize top buttons layout
        self._layout_topbuttons.addStretch()
        # create tree
        self._tree = QTreeWidget(self)
        self._tree.setAnimated(False)
        self._tree.setExpandsOnDoubleClick(True)
        self._tree.setHeaderHidden(False)
        self._tree.setItemsExpandable(True)
        self._tree.setRootIsDecorated(True)
        self._tree.setSortingEnabled(False)
        self._tree.setColumnCount(1)
        self._tree.setHeaderLabels(['None'])
        self._layout.addWidget(self._tree)
        self._tree.show()

    # called once after full world load
    def update_planets(self):
        def additem_helper(item_texts, twi_parent=None, align_flag=0):
            # align_flag = Qt::AlignLeft / Qt::AlignRight / Qt::AlignHCenter
            if align_flag == 0:
                align_flag = Qt.AlignHCenter | Qt.AlignVCenter
            twi = QTreeWidgetItem(item_texts)
            for it_col in range(len(item_texts)):
                if it_col > 0:
                    # void QTreeWidgetItem::setTextAlignment(int column, int alignment)
                    twi.setTextAlignment(it_col, align_flag)
            if twi_parent is None:
                self._tree.addTopLevelItem(twi)
            else:
                twi_parent.addChild(twi)
            return True

        self._tree.clear()  # clear the tree first
        planets = self._world.get_planets()  # get planets from the world
        #
        # setup header and its labels
        header_labels = ['-']
        for i in range(len(planets)):
            header_labels.append(planets[i].name)
        header_labels.append(self.tr('Total'))  # last column - totals
        self._tree.setHeaderLabels(header_labels)
        # alignment of text in header labels
        self._tree.header().setDefaultAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        # default column widths
        for i in range(len(planets)):
            if i < 1:
                self._tree.setColumnWidth(i, 150)
            else:
                self._tree.setColumnWidth(i, 75)
        #
        # planets names
        item_strings = [self.tr('Name')]
        for pl in planets:
            item_strings.append(pl.name)
        additem_helper(item_strings)
        #
        # planets coords
        item_strings = [self.tr('Coords')]
        for pl in planets:
            item_strings.append('[{0}:{1}:{2}]'.format(pl.coords.galaxy, pl.coords.system, pl.coords.position))
        additem_helper(item_strings)
        #
        # planets fields
        item_strings = [self.tr('Fields')]
        total_busy = 0
        total_fields = 0
        for pl in planets:
            total_busy += pl.fields_busy
            total_fields = pl.fields_total
            item_strings.append('{0} / {1}'.format(pl.fields_busy, pl.fields_total))
        item_strings.append('{0} / {1}'.format(total_busy, total_fields))
        additem_helper(item_strings)
        #
        # resources
        res_root = QTreeWidgetItem([self.tr('Resources')])
        item_strings = [self.tr('Metal')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_current.met
            item_strings.append('{0}'.format(number_format(pl.res_current.met)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, res_root)
        #
        item_strings = [self.tr('Crystal')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_current.cry
            item_strings.append('{0}'.format(number_format(pl.res_current.cry)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, res_root)
        #
        item_strings = [self.tr('Deit')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_current.deit
            item_strings.append('{0}'.format(number_format(pl.res_current.deit)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, res_root)
        #
        item_strings = [self.tr('Energy')]
        total_busy = 0
        total_fields = 0
        for pl in planets:
            total_busy += pl.energy.energy_left
            total_fields += pl.energy.energy_total
            item_strings.append('{0} / {1}'.format(
                    pl.energy.energy_left,
                    pl.energy.energy_total))
        item_strings.append('{0} / {1}'.format(total_busy, total_fields))
        additem_helper(item_strings, res_root)
        #
        item_strings = [self.tr('Charge')]
        for pl in planets:
            item_strings.append('{0}%'.format(pl.energy.charge_percent))
        additem_helper(item_strings, res_root)
        self._tree.addTopLevelItem(res_root)
        res_root.setExpanded(True)
        #
        # resources per hour
        rph_root = QTreeWidgetItem([self.tr('Production')])
        item_strings = [self.tr('Met/h')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_per_hour.met
            item_strings.append('{0}'.format(number_format(pl.res_per_hour.met)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, rph_root)
        #
        item_strings = [self.tr('Cry/h')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_per_hour.cry
            item_strings.append('{0}'.format(number_format(pl.res_per_hour.cry)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, rph_root)
        #
        item_strings = [self.tr('Deit/h')]
        total_res = 0
        for pl in planets:
            total_res += pl.res_per_hour.deit
            item_strings.append('{0}'.format(number_format(pl.res_per_hour.deit)))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, rph_root)
        self._tree.addTopLevelItem(rph_root)
        rph_root.setExpanded(True)
        #
        # buildings
        buildings_root = QTreeWidgetItem([self.tr('Buildings')])
        item_strings = [self.tr('Metal factory')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.met_factory))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Crystal factory')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.cry_factory))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Deit factory')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.deit_factory))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Solar station')]
        for pl in planets:
            # testing: detect solar station level up
            addstr = '{0}'.format(pl.buildings.solar_station)
            if pl.is_build_in_progress('Солнечная батарея'):
                addstr = '{0} -> {1}'.format(pl.buildings.solar_station, pl.buildings.solar_station+1)
            item_strings.append(addstr)
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Nuclear station')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.nuclear_station))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Robotics factory')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.robotics_factory))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Nanites factory')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.nanites_factory))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Shipyard')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.shipyard))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Metal silo')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.met_silo))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Crystal silo')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.cry_silo))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Deit silo')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.deit_silo))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Lab')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.lab))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('TerraFormer')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.terraformer))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Alliance silo')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.alliance_silo))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Rocket silo')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.rocket_silo))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Lunar Base')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.lunar_base))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Lunar Phalanx')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.lunar_phalanx))
        additem_helper(item_strings, buildings_root)
        item_strings = [self.tr('Gates')]
        for pl in planets:
            item_strings.append('{0}'.format(pl.buildings.gates))
        additem_helper(item_strings, buildings_root)
        # add/expand
        self._tree.addTopLevelItem(buildings_root)
        buildings_root.setExpanded(True)
        #
        # defense
        defense_root = QTreeWidgetItem([self.tr('Defense')])
        item_strings = [self.tr('Rocket Launcher')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.ru
            item_strings.append(number_format(pl.defense.ru))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Light Laser')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.ll
            item_strings.append(number_format(pl.defense.ll))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Heavy Laser')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.tl
            item_strings.append(number_format(pl.defense.tl))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Gauss')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.gauss
            item_strings.append(number_format(pl.defense.gauss))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Ion')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.ion
            item_strings.append(number_format(pl.defense.ion))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Plasma')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.plasma
            item_strings.append(number_format(pl.defense.plasma))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Small Dome')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.small_dome
            item_strings.append(number_format(pl.defense.small_dome))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Big Dome')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.big_dome
            item_strings.append(number_format(pl.defense.big_dome))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Defender Missile')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.defender_rocket
            item_strings.append(number_format(pl.defense.defender_rocket))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        #
        item_strings = [self.tr('Attack Missile')]
        total_res = 0
        for pl in planets:
            total_res += pl.defense.attack_rocket
            item_strings.append(number_format(pl.defense.attack_rocket))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, defense_root)
        # add/expand
        self._tree.addTopLevelItem(defense_root)
        defense_root.setExpanded(True)
        #
        # fleet
        fleet_root = QTreeWidgetItem([self.tr('Fleet')])
        item_strings = [self.tr('Small Transport')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.mt
            item_strings.append(number_format(pl.ships.mt))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Big Transport')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.bt
            item_strings.append(number_format(pl.ships.bt))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Light Fighter')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.li
            item_strings.append(number_format(pl.ships.li))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Heavy Fighter')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.ti
            item_strings.append(number_format(pl.ships.ti))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Cruiser')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.crus
            item_strings.append(number_format(pl.ships.crus))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Battleship')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.link
            item_strings.append(number_format(pl.ships.link))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Colonizer')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.col
            item_strings.append(number_format(pl.ships.col))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Refiner')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.rab
            item_strings.append(number_format(pl.ships.rab))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Spy')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.spy
            item_strings.append(number_format(pl.ships.spy))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Bomber')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.bomber
            item_strings.append(number_format(pl.ships.bomber))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Solar Satellite')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.ss
            item_strings.append(number_format(pl.ships.ss))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Destroyer')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.unik
            item_strings.append(number_format(pl.ships.unik))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Death Star')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.zs
            item_strings.append(number_format(pl.ships.zs))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('BattleCruiser')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.lk
            item_strings.append(number_format(pl.ships.lk))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('War Base')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.warbase
            item_strings.append(number_format(pl.ships.warbase))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Corvett')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.f_corvett
            item_strings.append(number_format(pl.ships.f_corvett))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Interceptor')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.f_ceptor
            item_strings.append(number_format(pl.ships.f_ceptor))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Dreadnought')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.f_dread
            item_strings.append(number_format(pl.ships.f_dread))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        #
        item_strings = [self.tr('Corsair')]
        total_res = 0
        for pl in planets:
            total_res += pl.ships.f_corsair
            item_strings.append(number_format(pl.ships.f_corsair))
        item_strings.append(number_format(total_res))
        additem_helper(item_strings, fleet_root)
        # add/expand
        self._tree.addTopLevelItem(fleet_root)
        fleet_root.setExpanded(True)

    def update_planet_resources(self):
        res_top_twi = self._tree.topLevelItem(3)  # 4th top level item is "Resources"
        if res_top_twi is None:
            return
        res_met_twi = res_top_twi.child(0)   # first child is metal
        res_cry_twi = res_top_twi.child(1)   # 2nd is crystal
        res_deit_twi = res_top_twi.child(2)  # 3rd is deit
        res_en_twi = res_top_twi.child(3)    # 4th is energy
        if (res_met_twi is None) or (res_cry_twi is None) or (res_deit_twi is None) \
                or (res_en_twi is None):
            return
        planets = self._world.get_planets()  # get planets from the world
        ncolumn = 1  # column #0 is description, planets start at #1
        totals = [0, 0, 0]  # count total resources
        for planet in planets:
            res_met_twi.setText(ncolumn, number_format(int(planet.res_current.met)))
            res_cry_twi.setText(ncolumn, number_format(int(planet.res_current.cry)))
            res_deit_twi.setText(ncolumn, number_format(int(planet.res_current.deit)))
            res_en_twi.setText(ncolumn, '{0} / {1}'.format(
                planet.energy.energy_left, planet.energy.energy_total))
            ncolumn += 1
            totals[0] += int(planet.res_current.met)
            totals[1] += int(planet.res_current.cry)
            totals[2] += int(planet.res_current.deit)
        # set values for "totals" column
        res_met_twi.setText(ncolumn, number_format(totals[0]))
        res_cry_twi.setText(ncolumn, number_format(totals[1]))
        res_deit_twi.setText(ncolumn, number_format(totals[2]))

    @pyqtSlot()
    def on_btn_refresh_imperium(self):
        self._world.signal(self._world.SIGNAL_RELOAD_PAGE, page_name='imperium')
class CrossSearchSimilarImagesDialog(QDialog):
    itemDoubleClicked = pyqtSignal(str)

    window_title = 'Cross search similar images'

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

        self.setWindowTitle(self.window_title)
        self.resize(600, 600)

        self.tree_widget = QTreeWidget()
        self.tree_widget.setHeaderLabels(['FILE NAME', 'SCORE'])
        self.tree_widget.header().setSectionResizeMode(1, QHeaderView.Fixed)
        self.tree_widget.header().resizeSection(0, 450)
        self.tree_widget.header().resizeSection(1, 75)
        self.tree_widget.setAlternatingRowColors(True)
        self.tree_widget.setExpandsOnDoubleClick(False)
        self.tree_widget.itemDoubleClicked.connect(
            lambda item, _: self.itemDoubleClicked.emit(
                item.data(0, Qt.UserRole)))

        self.progress_bar = QProgressBar()
        self.progress_bar.setTextVisible(False)
        self.progress_bar.setRange(0, 0)
        self.progress_bar.setValue(0)
        self.progress_bar.hide()

        self.thread = CrossSearchSimilarImagesThread()
        self.thread.started.connect(lambda: self.progress_bar.show())
        self.thread.finished.connect(lambda: self.progress_bar.hide())
        self.thread.about_found_similars.connect(self._on_about_found_similars)

        layout = QVBoxLayout()
        layout.addWidget(self.progress_bar)
        layout.addWidget(self.tree_widget)
        self.setLayout(layout)

    def _on_about_found_similars(self, file_name: str, similars: List[str]):
        item = QTreeWidgetItem([f'{file_name} ({len(similars)})'])
        item.setData(0, Qt.UserRole, file_name)

        self.tree_widget.addTopLevelItem(item)

        for x, score in similars:
            child = QTreeWidgetItem([x, str(score)])
            child.setData(0, Qt.UserRole, x)
            item.addChild(child)

    def start(self, image_by_hashes: dict, hash_algo: str, max_score: int):
        self.setWindowTitle(
            f'{self.window_title}. hash_algo={hash_algo} max_score={max_score}'
        )
        self.tree_widget.clear()

        self.thread.image_by_hashes = image_by_hashes
        self.thread.hash_algo = hash_algo
        self.thread.max_score = max_score
        self.thread.start()

        self.show()
class CueListDialog(QDialog):
    def __init__(self, cues=None, properties=('index', 'name'), **kwargs):
        super().__init__(**kwargs)

        self.setMinimumSize(600, 400)

        self._properties = list(properties)
        self._cues = {}

        self.list = QTreeWidget(self)
        self.list.setSelectionMode(QTreeWidget.SingleSelection)
        self.list.setSelectionBehavior(QTreeWidget.SelectRows)
        self.list.setAlternatingRowColors(True)
        self.list.setIndentation(0)
        self.list.setHeaderLabels([prop.title() for prop in properties])
        self.list.header().setSectionResizeMode(QHeaderView.Fixed)
        self.list.header().setSectionResizeMode(1, QHeaderView.Stretch)
        self.list.header().setStretchLastSection(False)
        self.list.sortByColumn(0, Qt.AscendingOrder)
        self.list.setSortingEnabled(True)

        if cues is not None:
            self.add_cues(cues)

        self.setLayout(QVBoxLayout())
        self.layout().addWidget(self.list)

        self.buttons = QDialogButtonBox(self)
        self.buttons.addButton(QDialogButtonBox.Cancel)
        self.buttons.addButton(QDialogButtonBox.Ok)
        self.layout().addWidget(self.buttons)

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

    def add_cue(self, cue):
        item = QTreeWidgetItem()
        item.setTextAlignment(0, Qt.AlignCenter)

        for n, prop in enumerate(self._properties):
            try:
                item.setData(n, Qt.DisplayRole, getattr(cue, prop, 'Undefined'))
            except Exception as e:
                logging.exception('Cannot display {0} property'.format(prop), e,
                                  dialog=False)

        self._cues[cue] = item
        item.setData(0, Qt.UserRole, cue)
        self.list.addTopLevelItem(item)

    def add_cues(self, cues):
        self.list.setSortingEnabled(False)
        for cue in cues:
            self.add_cue(cue)
        self.list.setSortingEnabled(True)

    def remove_cue(self, cue):
        index = self.list.indexOfTopLevelItem(self._cues.pop(cue))
        self.list.takeTopLevelItem(index)

    def reset(self):
        self.list.clear()
        self._cues.clear()

    def selected_cues(self):
        cues = []
        for item in self.list.selectedItems():
            cues.append(item.data(0, Qt.UserRole))
        return cues