Beispiel #1
0
 def editItem(self, item, column):
     if column in self.editable_columns:
         self.editing_itemcol = (item, column, item.text(column))
         # Calling setFlags causes on_changed events for some reason
         item.setFlags(item.flags() | Qt.ItemIsEditable)
         QTreeWidget.editItem(self, item, column)
         item.setFlags(item.flags() & ~Qt.ItemIsEditable)
Beispiel #2
0
 def editItem(self, item, column):
     if column in self.editable_columns:
         try:
             self.editing_itemcol = (item, column, item.text(column))
             # Calling setFlags causes on_changed events for some reason
             item.setFlags(item.flags() | Qt.ItemIsEditable)
             QTreeWidget.editItem(self, item, column)
             item.setFlags(item.flags() & ~Qt.ItemIsEditable)
         except RuntimeError:
             # (item) wrapped C/C++ object has been deleted
             pass
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 #4
0
class MenuEditor(AnimateableEditor):
    contentChanged = pyqtSignal(object)
    menuChanged = pyqtSignal(str)

    def __init__(self, win, menu, site):
        AnimateableEditor.__init__(self)
        self.win = win
        self.menu = menu
        self.site = site
        self.changed = False

        self.setAutoFillBackground(True)

        titleLabel = QLabel("Menu Editor")
        fnt = titleLabel.font()
        fnt.setPointSize(20)
        fnt.setBold(True)
        titleLabel.setFont(fnt)

        self.close = FlatButton(":/images/close_normal.png",
                                ":/images/close_hover.png")
        self.close.setToolTip("Close Content Editor")
        self.undo = FlatButton(":/images/undo_normal.png",
                               ":/images/undo_hover.png", "",
                               ":/images/undo_disabled.png")
        self.redo = FlatButton(":/images/redo_normal.png",
                               ":/images/redo_hover.png", "",
                               ":/images/redo_disabled.png")
        self.undo.setToolTip("Undo")
        self.redo.setToolTip("Redo")
        self.undo.setEnabled(False)
        self.redo.setEnabled(False)
        hbox = QHBoxLayout()
        hbox.addStretch(0)
        hbox.addWidget(self.undo)
        hbox.addWidget(self.redo)
        hbox.addWidget(self.close)

        addButton = QPushButton("Add Menuitem")
        addButton.setMaximumWidth(120)

        self.name = QLineEdit()
        self.name.setText(menu.name)
        self.name.setMaximumWidth(200)

        labels = ["Title", "Url", "Icon", "", "Sort"]

        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(labels)
        self.tree.header().setSectionResizeMode(0, QHeaderView.Stretch)
        self.tree.header().hideSection(4)
        self.tree.setSelectionMode(QAbstractItemView.NoSelection)
        self.tree.setToolTip("Double Click To Edit")
        self.tree.setColumnWidth(2, 40)

        layout = QGridLayout()
        layout.addWidget(titleLabel, 0, 0)
        layout.addLayout(hbox, 0, 2)
        layout.addWidget(QLabel("Name"), 1, 0)
        layout.addWidget(self.name, 2, 0)
        layout.addWidget(addButton, 3, 0)
        layout.addWidget(self.tree, 4, 0, 1, 3)
        self.setLayout(layout)

        self.reloadMenu(menu)

        addButton.clicked.connect(self.addButtonClicked)
        self.close.clicked.connect(self.closeEditor)
        self.name.editingFinished.connect(self.nameChanged)
        self.redo.clicked.connect(self.redoEdit)
        self.undo.clicked.connect(self.undoEdit)
        self.tree.itemChanged.connect(self.itemChanged)

    def reloadMenu(self, menu):
        if not menu:
            self.close.emit()
            return

        self.menu = menu
        self.tree.clear()

        self.name.setText(menu.name)
        for i in range(0, len(self.menu.items)):
            item = self.menu.items[i]
            self.addTreeItem(item)

        self.tree.expandAll()
        self.tree.sortItems(4, Qt.AscendingOrder)
        self.updateButtonStates()

    def addTreeItem(self, item):
        twi = QTreeWidgetItem()
        twi.setFlags(twi.flags() | Qt.ItemIsEditable)
        twi.setText(0, item.title)
        twi.setText(1, item.url)

        twi.setText(4, str(self.tree.topLevelItemCount()))
        twi.setData(0, Qt.UserRole, item)
        self.tree.addTopLevelItem(twi)
        self.addTableCellButtons(item, twi)

        for i in range(len(item.items)):
            sub = item.items[i]
            stwi = QTreeWidgetItem()
            stwi.setFlags(stwi.flags() | Qt.ItemIsEditable)
            stwi.setText(0, sub.title)
            stwi.setText(1, sub.url)
            stwi.setText(4, str(i))
            stwi.setData(0, Qt.UserRole, sub)
            twi.addChild(stwi)
            self.addTableCellButtons(sub, stwi)

    def addTableCellButtons(self, item, twi):
        tcb = MenuEditorTableCellButtons()
        tcb.setMenuItem(item)
        self.tree.setItemWidget(twi, 3, tcb)
        self.tree.setColumnWidth(3, tcb.sizeHint().width())
        if item.isSubitem():
            tcb.deleteItem.connect(self.deleteSubItem)
            tcb.itemLeft.connect(self.itemLeft)
        else:
            tcb.deleteItem.connect(self.deleteItem)
            tcb.itemUp.connect(self.itemUp)
            tcb.itemDown.connect(self.itemDown)
            tcb.itemRight.connect(self.itemRight)
            tcb.editItem.connect(self.editItem)

        imgs = ImageSelector()
        imgs.setToolTip("Click to select image, right click to reset image")
        imgs.setItem(item)
        imgs.setMaximumSize(24, 24)
        isw = QWidget()
        vbox = QVBoxLayout()
        vbox.addWidget(imgs)
        isw.setLayout(vbox)
        if not item.icon:
            imgs.setImage(QImage(":/images/image_placeholder.png"))
        else:
            imgs.setImage(QImage(self.site.source_path + "/" + item.icon))
        self.tree.setItemWidget(twi, 2, isw)
        imgs.clicked.connect(self.iconClicked)

    def registerUndoStack(self, stack):
        self.undoStack = stack
        self.undoStack.canUndoChanged.connect(self.canUndoChanged)
        self.undoStack.canRedoChanged.connect(self.canRedoChanged)
        self.undoStack.undoTextChanged.connect(self.undoTextChanged)
        self.undoStack.redoTextChanged.connect(self.redoTextChanged)
        self.undo.setEnabled(self.undoStack.canUndo())
        self.redo.setEnabled(self.undoStack.canRedo())
        self.undo.setToolTip("Undo " + self.undoStack.undoText())
        self.redo.setToolTip("Redo " + self.undoStack.redoText())

    def canUndoChanged(self, can):
        self.undo.setEnabled(can)

    def canRedoChanged(self, can):
        self.redo.setEnabled(can)

    def undoTextChanged(self, text):
        self.undo.setToolTip("Undo " + text)

    def redoTextChanged(self, text):
        self.redo.setToolTip("Redo " + text)

    def getUndoRedoText(self, item, action):
        return "menuitem (" + item.title + ") from menu (" + self.menu.name + ") " + action

    def undoEdit(self):
        self.undoStack.undo()

    def redoEdit(self):
        self.undoStack.redo()

    def addButtonClicked(self):
        menuitem = MenuItem()
        self.menu.addMenuitem(menuitem)
        self.addTreeItem(menuitem)
        self.menuChanged.emit(self.getUndoRedoText(menuitem, "added"))

        self.updateButtonStates()
        item = self.tree.topLevelItem(self.getRow(menuitem))
        self.tree.editItem(item, 0)

    def closeEditor(self):
        self.closes.emit()

    def nameChanged(self):
        if self.menu.name != self.name.text:
            action = "menu name changed from \"" + self.menu.name + "\" to \"" + self.name.text + "\""
            self.menu.setName(self.name.text())
            self.contentChanged.emit(self.menu)
            self.menuChanged.emit(action)

    def itemChanged(self, twi, column):
        action = ""
        item = twi.data(0, Qt.UserRole)
        if column == 0:
            item.title = twi.text(0)
            action = "title changed"
        elif column == 1:
            item.url = twi.text(1)
            action = "url changed"
        self.menuChanged.emit(self.getUndoRedoText(item, action))

    def getRow(self, menuitem):
        for i in range(0, self.tree.topLevelItemCount()):
            item = self.tree.topLevelItem(i)
            mi = item.data(0, Qt.UserRole)
            if mi == menuitem:
                return i
        return -1

    def deleteSubItem(self, menuitem):
        row = self.getRow(menuitem.parentItem)
        parent = self.tree.topLevelItem(row)
        if parent:
            for i in range(0, parent.childCount()):
                child = parent.child(i)
                mi = child.data(0, Qt.UserRole)
                if mi == menuitem:
                    parent.removeChild(child)
                    del child
                    break

        if menuitem.parentItem:
            menuitem.parentItem.removeMenuitem(menuitem)

        self.updateButtonStates()
        self.menuChanged.emit(self.getUndoRedoText(menuitem, "deleted"))

    def itemLeft(self, menuitem):
        row = self.getRow(menuitem.parentItem())
        parent = self.tree.topLevelItem(row)
        for i in range(parent.childCount()):
            child = parent.child(i)
            mi = child.data(0, Qt.UserRole)
            if mi == menuitem:
                menuitem.parentItem().removeMenuitem(menuitem)
                menuitem.setSubitem(False)
                self.menu.addMenuitem(menuitem)
                parent.takeChild(i)
                self.addTreeItem(menuitem)
                break

        self.updateButtonStates()
        self.menuChanged.emit(
            self.getUndoRedoText(menuitem, "changed to top item"))

    def iconClicked(self, itemselector, button):
        mi = itemselector.item()
        action = ""
        if button == Qt.LeftButton:
            fileName = ""
            dialog = QFileDialog()
            dialog.setFileMode(QFileDialog.AnyFile)
            dialog.setNameFilter("Images (*.png *.gif *.jpg)All (*)")
            dialog.setWindowTitle("Load Image")
            dialog.setOption(QFileDialog.DontUseNativeDialog, True)
            dialog.setAcceptMode(QFileDialog.AcceptOpen)
            if dialog.exec_():
                fileName = dialog.selectedFiles().first()
            del dialog
            if not fileName:
                return

            # copy file to assets dir
            info = QFileInfo(fileName)
            name = info.fileName().replace(" ", "_")
            path = self.site.source_path + "/assets/images/" + name
            QFile.copy(fileName, path)

            # also copy file to deploy dir for previews
            dpath = self.site.deploy_path + "/assets/images/" + name
            QFile.copy(fileName, dpath)

            mi.setIcon(path.mid(path.indexOf("assets/images/")))
            itemselector.setImage(QImage(path))
            action = "icon changed"

        elif button == Qt.RightButton:
            action = "icon removed"
            mi.setIcon("")
            itemselector.setImage(QImage(":/images/image_placeholder.png"))

        self.menuChanged.emit(self.getUndoRedoText(mi, action))

    def updateButtonStates(self):
        for i in range(0, self.tree.topLevelItemCount()):
            twi = self.tree.topLevelItem(i)
            tcb = self.tree.itemWidget(twi, 3)
            menuitem = twi.data(0, Qt.UserRole)
            tcb.setEnableDown(i != self.tree.topLevelItemCount() - 1)
            tcb.setEnableUp(i != 0)
            tcb.setEnableRight(i != 0 and len(menuitem.items) == 0)
            tcb.setEnableLeft(False)
            for j in range(0, twi.childCount()):
                stwi = twi.child(j)
                stcb = self.tree.itemWidget(stwi, 3)
                stcb.setEnableLeft(True)
Beispiel #5
0
class ChannelMetadataWidget(QWidget):
    metadataChange = pyqtSignal(ChannelSet)

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

    def init_ui(self):
        # Create the master layout
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        # # Create the tree widget
        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(["Ch", "Name", "Units",
                                   "Comments", "Tags", "Sample rate",
                                   "Calibration factor",
                                   "Transfer function type"])
        self.tree.header().setResizeMode(3)
        # Connect the signals
        self.tree.itemDoubleClicked.connect(self.edit_item)
        # Add it to the layout
        self.layout.addWidget(self.tree)

        # # Create the buttons
        self.button_layout = QHBoxLayout()
        self.layout.addLayout(self.button_layout)

        self.discard_button = QPushButton("Discard changes", self)
        self.discard_button.clicked.connect(self.discard_changes)
        self.button_layout.addWidget(self.discard_button)

        self.save_button = QPushButton("Save changes", self)
        self.save_button.clicked.connect(self.update_channelset)
        self.button_layout.addWidget(self.save_button)

    def set_channel_set(self, channel_set):
        print("Setting channel set...")
        self.tree.clear()

        self.cs = channel_set

        self.channel_items = []

        for channel_number, channel in enumerate(self.cs.channels):
            # Create a tree widget item for this channel
            channel_item = QTreeWidgetItem(self.tree)
            #channel_item.setFlags(channel_item.flags() | Qt.ItemIsEditable)
            channel_item.setData(0, Qt.DisplayRole, channel_number)
            channel_item.setData(1, Qt.DisplayRole, channel.name)
            channel_item.setData(3, Qt.DisplayRole, channel.comments)
            channel_item.setData(4, Qt.DisplayRole, channel.tags)
            channel_item.setData(5, Qt.DisplayRole, '%.2f' % channel.sample_rate)
            channel_item.setData(6, Qt.DisplayRole, '%.2f' % channel.calibration_factor)
            channel_item.setData(7, Qt.DisplayRole, channel.transfer_function_type)
            # Add it to the list
            self.channel_items.append(channel_item)

            # Create a child tree widget item for each of the channel's datasets
            for dataset in channel.datasets:
                dataset_item = QTreeWidgetItem(channel_item)
                #dataset_item.setFlags(dataset_item.flags() | Qt.ItemIsEditable)
                dataset_item.setData(1, Qt.DisplayRole, dataset.id_)
                dataset_item.setData(2, Qt.DisplayRole, dataset.units)
        print("Done.")

    def update_channelset(self):
        print("Updating channelset from tree...")

        for channel_number, channel_item in enumerate(self.channel_items):
            # Reset data that should be fixed (channel numbers)
            channel_item.setData(0, Qt.DisplayRole, channel_number)

            # Get the metadata from the tree
            # Note: data acquired from tree is string, need to convert some to float/int
            name = channel_item.data(1, Qt.DisplayRole)
            comments = channel_item.data(3, Qt.DisplayRole)
            tags = channel_item.data(4, Qt.DisplayRole)
            sample_rate = float(channel_item.data(5, Qt.DisplayRole))
            calibration_factor = float(channel_item.data(6, Qt.DisplayRole))
            transfer_function_type = channel_item.data(7, Qt.DisplayRole)

            # Set the channel metadata
            metadata_dict = {"name": name,
                             "comments": comments,
                             "tags": tags,
                             "sample_rate": sample_rate,
                             "calibration_factor": calibration_factor,
                             "transfer_function_type": transfer_function_type}
            self.cs.set_channel_metadata(channel_number, metadata_dict)

            # Update the datasets as well
            for i in range(channel_item.childCount()):
                # Find the dataset item
                dataset_item = channel_item.child(i)
                # Extract the data from the tree
                id_ = dataset_item.data(1, Qt.DisplayRole)
                units = dataset_item.data(2, Qt.DisplayRole)
                # Set the dataset units
                self.cs.set_channel_units(channel_number, id_, units)

        self.metadataChange.emit(self.cs)
        print("Done.")

    def edit_item(self, item, column):
        print("Editing item, column {}...".format(column))
        # Channel numbers are non-editable
        if column == 0:
            print("Channel numbers are non-editable")
            pass
        # Dataset ids are a non-editable
        elif item.parent() is not None and column == 1:
            print("Dataset ids are non-editable")
            pass
        else:
            # Set item to be editable
            old_flags = item.flags()
            item.setFlags(item.flags() | Qt.ItemIsEditable)
            # Edit the item
            self.tree.editItem(item, column)
            # Set item to not be editable
            item.setFlags(old_flags)
        print("Done.")

    def discard_changes(self):
        self.set_channel_set(self.cs)
Beispiel #6
0
class MiscTab(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.name = self.tr("Misc")

        self.markColorLabel = QLabel(self.tr("Default flag colors:"), self)
        # TODO: enforce duplicate names avoidance
        self.markColorWidget = QTreeWidget(self)
        self.markColorWidget.setHeaderLabels(
            (self.tr("Color"), self.tr("Name")))
        self.markColorWidget.setRootIsDecorated(False)
        self.markColorWidget.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        # TODO: make this work correctly, top-level items only
        # self.markColorWidget.setDragDropMode(QAbstractItemView.InternalMove)
        self.addItemButton = QPushButton("+", self)
        self.addItemButton.clicked.connect(self.addItem)
        self.removeItemButton = QPushButton("−", self)
        self.removeItemButton.clicked.connect(self.removeItem)

        self.loadRecentFileBox = QCheckBox(
            self.tr("Load most recent file on start"), self)

        layout = QGridLayout(self)
        l = 0
        layout.addWidget(self.markColorLabel, l, 0, 1, 3)
        l += 1
        layout.addWidget(self.markColorWidget, l, 0, 1, 3)
        l += 1
        layout.addWidget(self.addItemButton, l, 0)
        layout.addWidget(self.removeItemButton, l, 1)
        l += 1
        layout.addWidget(self.loadRecentFileBox, l, 0, 1, 3)
        self.setLayout(layout)

        self.readSettings()

    def addItem(self):
        def mangleNewName():
            name = self.tr("New")
            index = 0
            while self.markColorWidget.findItems(name, Qt.MatchExactly, 1):
                index += 1
                name = "{0} ({1})".format(name, index)
            return name

        # TODO: not DRY with ctor
        item = QTreeWidgetItem(self.markColorWidget)
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        widget = ColorVignette(self)
        widget.setColor(QColor(Qt.white))
        widget.setMargins(2, 2, 2, 2)
        widget.setMayClearColor(False)
        self.markColorWidget.setItemWidget(item, 0, widget)
        item.setText(1, mangleNewName())

        self.markColorWidget.setCurrentItem(item)
        self.markColorWidget.editItem(item, 1)
        self.removeItemButton.setEnabled(True)

    def removeItem(self):
        i = self.markColorWidget.selectionModel().currentIndex().row()
        self.markColorWidget.takeTopLevelItem(i)
        if not self.markColorWidget.topLevelItemCount():
            self.removeItemButton.setEnabled(False)

    def readSettings(self):
        entries = settings.readMarkColors()
        for name, color in entries.items():
            item = QTreeWidgetItem(self.markColorWidget)
            item.setFlags(item.flags() | Qt.ItemIsEditable)
            widget = ColorVignette(self)
            widget.setColor(color)
            widget.setMargins(2, 2, 2, 2)
            widget.setMayClearColor(False)
            self.markColorWidget.setItemWidget(item, 0, widget)
            item.setText(1, name)
        if not len(entries):
            self.removeItemButton.setEnabled(False)

        loadRecentFile = settings.loadRecentFile()
        self.loadRecentFileBox.setChecked(loadRecentFile)

    def writeSettings(self):
        markColors = OrderedDict()
        for i in range(self.markColorWidget.topLevelItemCount()):
            item = self.markColorWidget.topLevelItem(i)
            name = item.text(1)
            color = self.markColorWidget.itemWidget(item, 0).color()
            markColors[name] = color
        settings.writeMarkColors(markColors)

        loadRecentFile = self.loadRecentFileBox.isChecked()
        settings.setLoadRecentFile(loadRecentFile)
Beispiel #7
0
class DataTree(QTabWidget):
    """ Class Definition for the Data Tree. """
    def __init__(self, viewer, parent=None):
        """ Initialize the Datatree """
        super(DataTree, self).__init__(parent)
        self.old_trace = []
        self.similar_items = []
        self.checkableItems = []
        self.changing_item = None
        self.viewer = viewer
        self.keys = viewer.keys
        self.noPrintTypes = viewer.noPrintTypes

        # Add the Tree Widgets
        self.Tree = QTreeWidget(self)
        self.Tree.setSizePolicy(QSP(QSP.Fixed, QSP.Expanding))
        self.Tree.headerItem().setText(0, "")
        self.Tree.headerItem().setText(1, "")
        self.Tree.setTreePosition(1)
        header = self.Tree.header()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        header.setStretchLastSection(False)
        header.setVisible(False)
        self.Tree.setColumnWidth(0, 10)
        self.Tree.setColumnHidden(0, True)
        self.Tree.currentItemChanged.connect(self.viewer._change_tree)
        self.addTab(self.Tree, "Files")
        self.Tree.contextMenuEvent = self.viewer._dropdown
        self.Tree.resizeColumnToContents(1)

        # Add an alternative Tree Widget
        self.secTree = QTreeWidget(parent)
        self.secTree.setSizePolicy(QSP(QSP.Fixed, QSP.Expanding))
        self.secTree.headerItem().setText(0, "")
        self.secTree.headerItem().setText(1, "")
        self.secTree.setTreePosition(1)
        header = self.secTree.header()
        header.setSectionResizeMode(0, QHeaderView.ResizeToContents)
        header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
        header.setStretchLastSection(False)
        header.setVisible(False)
        self.secTree.setColumnWidth(0, 10)
        self.secTree.setColumnHidden(0, True)
        self.secTree.currentItemChanged.connect(self.viewer._change_tree)
        self.secTree.resizeColumnToContents(1)
        self.addTab(self.secTree, "Data")

        # Connect Signal at the end to avoid errors
        self.root = self.currentWidget().invisibleRootItem()
        self.currentChanged.connect(self._update_treetab)
        self.setAcceptDrops(True)

    def clear_tree(self):
        """ Clear the Tree. """
        self.checkableItems = []
        self.update_tree()

    def current_item(self):
        """ Return the currently selected Item. """
        return self.currentWidget().currentItem()

    def is_files_tree(self):
        """ Return True if the currently open Tree is the "Files"-Tree. """
        return self.currentWidget() == self.Tree

    def _finish_renaming(self):
        """ Finish the renaming of a data-key. """
        if not self.old_trace:
            return
        new_trace = self.viewer._get_obj_trace(self.changing_item)
        if new_trace == self.old_trace:
            return
        self.Tree.itemChanged.disconnect(self._finish_renaming)
        # Check if the name exists in siblings
        itemIndex = self.Tree.indexFromItem(self.changing_item, 1)
        siblingTxt = []
        if self.changing_item.parent():
            for n in range(self.changing_item.parent().childCount()):
                if itemIndex.sibling(n, 1) != itemIndex:
                    siblingTxt.append(itemIndex.sibling(n, 1).data(0))
        else:
            for n in range(self.Tree.topLevelItemCount()):
                if self.Tree.topLevelItem(n) != self.changing_item:
                    siblingTxt.append(itemIndex.sibling(n, 1).data(0))
        if new_trace[-1] in siblingTxt:
            self.changing_item.setData(0, 1, self.old_trace[-1])
            self.old_trace = []
            return
        # Replace the key
        self.viewer.set_data(new_trace, self.viewer.pop(self.old_trace))
        # If element is top-level-item
        if not self.changing_item.parent() and self.old_trace[0] in self.keys:
            self.keys[self.keys.index(self.old_trace[0])] = new_trace[0]
        self.old_trace = []
        # Make Item non-editable
        self.changing_item.setFlags(Qt.ItemFlag(61))

    def remove_from_checkables(self, item_list):
        """ Remove items from the checkableItems list. As it causes errors. """
        for item in item_list:
            if item in self.checkableItems:
                self.checkableItems.remove(item)
            if item.childCount() > 0:
                self.remove_from_checkables(item.takeChildren())

    def rename_key(self):
        """ Start the renaming of a data-key. """
        self.changing_item = self.Tree.currentItem()
        self.old_trace = self.viewer._get_obj_trace(self.changing_item)
        # Make Item editable
        self.changing_item.setFlags(Qt.ItemFlag(63))
        self.Tree.editItem(self.changing_item, 1)
        self.Tree.itemChanged.connect(self._finish_renaming)

    def _update_subtree(self, item, data):
        """ Add a new subtree to the current QTreeWidgetItem. """
        for n, k in enumerate(realsorted(data.keys(), key=_lowercase)):
            item.addChild(QTreeWidgetItem([None, k]))
            child = item.child(n)
            if isinstance(data[k], dict):
                self._update_subtree(child, data[k])
            elif not isinstance(data[k], self.noPrintTypes):
                child.setCheckState(0, Qt.Unchecked)
                self.checkableItems.append(child)

    def _update_subtree_sec(self, item, data):
        """ Add a new subtree to the current QTreeWidgetItem. """
        if not isinstance(data, dict):
            for s in self.similar_items:
                sitem = QTreeWidgetItem([None, s])
                sitem.setToolTip(1, s)
                item.addChild(sitem)
            if not isinstance(data, self.noPrintTypes):
                for c in range(item.childCount()):
                    item.child(c).setCheckState(0, Qt.Unchecked)
                    self.checkableItems.append(item.child(c))
        else:
            for n, k in enumerate(realsorted(data.keys(), key=_lowercase)):
                item.addChild(QTreeWidgetItem([None, k]))
                child = item.child(n)
                if isinstance(data[k], dict):
                    self._update_subtree(child, data[k])
                else:
                    for s in self.similar_items:
                        sitem = QTreeWidgetItem([None, s])
                        sitem.setToolTip(0, s)
                        child.addChild(sitem)
                    if not isinstance(data[k], self.noPrintTypes):
                        for c in range(child.childCount()):
                            child.child(c).setCheckState(0, Qt.Unchecked)
                            self.checkableItems.append(child.child(c))

    def update_tree(self):
        """ Add new data to TreeWidget. """
        itemList = []
        self.checkableItems = []
        for i in self.keys:
            item = QTreeWidgetItem([None, i])
            item.setToolTip(0, i)
            self._update_subtree(item, self.viewer._data[i])
            itemList.append(item)
        self.Tree.clear()
        self.Tree.addTopLevelItems(itemList)
        if self.currentWidget() == self.secTree:
            self._update_treetab(1)

    def _update_treetab(self, index):
        """ Update the currently selected treetab, on switching. """
        if self.viewer.diffBtn.isVisible():
            self.viewer._start_diff()
        if index == 1:
            self._update_tree_sec()
        else:
            self.update_tree()

    def _update_tree_sec(self):
        """ Generate the data tree. """
        self.checkableItems = []
        # get TopLevelItem of the current item as a reference
        ref = self.Tree.currentItem()
        self.secTree.clear()
        if ref is None:
            ref = self.Tree.topLevelItem(0)
            if ref is None:
                return
        while ref.parent() is not None:
            ref = ref.parent()
        flipped_var = self.viewer._data[ref.text(1)].keys()
        # Find all with a similar structure
        self.similar_items = []
        for i in range(self.Tree.topLevelItemCount()):
            top_level_key = self.Tree.topLevelItem(i).text(1)
            if self.viewer._data[top_level_key].keys() == flipped_var:
                self.similar_items.append(top_level_key)
        # Build the tree
        itemList = []
        for k in flipped_var:
            item = QTreeWidgetItem([None, k])
            self._update_subtree_sec(item, self.viewer._data[ref.text(1)][k])
            itemList.append(item)
        for k in self.keys:
            if k[:4] == "Diff":
                item = QTreeWidgetItem([None, k])
                self._update_subtree(item, self.viewer._data[k])
                itemList.append(item)
        self.secTree.addTopLevelItems(itemList)

    def dragEnterEvent(self, ev):
        """ Catch dragEnterEvents for file dropdown. """
        if ev.mimeData().hasUrls():
            ev.acceptProposedAction()

    def dropEvent(self, ev):
        """ Catch dropEvent to load the dropped file. """
        fnames = []
        for url in ev.mimeData().urls():
            fnames.append(url.toLocalFile())
        self.viewer.load_files(fnames)
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")