class Ui_Form(object):
    """default range slider form"""
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("QRangeSlider"))
        Form.resize(300, 30)
        Form.setStyleSheet(_fromUtf8(DEFAULT_CSS))
        self.gridLayout = QGridLayout(Form)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self._splitter = QSplitter(Form)
        self._splitter.setMinimumSize(QtCore.QSize(0, 0))
        self._splitter.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self._splitter.setOrientation(QtCore.Qt.Horizontal)
        self._splitter.setObjectName(_fromUtf8("splitter"))
        self._head = QGroupBox(self._splitter)
        self._head.setTitle(_fromUtf8(""))
        self._head.setObjectName(_fromUtf8("Head"))
        self._handle = QGroupBox(self._splitter)
        self._handle.setTitle(_fromUtf8(""))
        self._handle.setObjectName(_fromUtf8("Span"))
        self._tail = QGroupBox(self._splitter)
        self._tail.setTitle(_fromUtf8(""))
        self._tail.setObjectName(_fromUtf8("Tail"))
        self.gridLayout.addWidget(self._splitter, 0, 0, 1, 1)

        QtCore.QMetaObject.connectSlotsByName(Form)
Exemple #2
0
class Ui_Form(object):
    """default range slider form"""
    def setupUi(self, Form):
        Form.setObjectName(_fromUtf8("QRangeSlider"))
        Form.resize(300, 30)
        Form.setStyleSheet(_fromUtf8(DEFAULT_CSS))
        self.gridLayout = QGridLayout(Form)
        # self.gridLayout.setMargin(0)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self._splitter = QSplitter(Form)
        self._splitter.setMinimumSize(QtCore.QSize(0, 0))
        self._splitter.setMaximumSize(QtCore.QSize(16777215, 16777215))
        self._splitter.setOrientation(QtCore.Qt.Horizontal)
        self._splitter.setObjectName(_fromUtf8("splitter"))
        self._head = QGroupBox(self._splitter)
        self._head.setTitle(_fromUtf8(""))
        self._head.setObjectName(_fromUtf8("Head"))
        self._handle = QGroupBox(self._splitter)
        self._handle.setTitle(_fromUtf8(""))
        self._handle.setObjectName(_fromUtf8("Span"))
        self._tail = QGroupBox(self._splitter)
        self._tail.setTitle(_fromUtf8(""))
        self._tail.setObjectName(_fromUtf8("Tail"))
        self.gridLayout.addWidget(self._splitter, 0, 0, 1, 1)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        # encoding = QApplication.UnicodeUTF8
        # Form.setWindowTitle(QApplication.translate("QRangeSlider",
        #                                                  "QRangeSlider",
        #                                                  None, encoding))
        pass
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(400, 300)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QLabel(self.centralwidget)
        self.label.setGeometry(QRect(100, 10, 200, 31))
        font = QFont()
        font.setFamily("Georgia")
        font.setPointSize(16)
        self.label.setFont(font)
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setObjectName("label")
        self.splitter = QSplitter(self.centralwidget)
        self.splitter.setGeometry(QRect(20, 70, 351, 151))
        self.splitter.setOrientation(Qt.Vertical)
        self.splitter.setObjectName("splitter")
        self.label_2 = QLabel(self.splitter)
        font = QFont()
        font.setFamily("Georgia")
        font.setPointSize(12)
        self.label_2.setFont(font)
        self.label_2.setAlignment(Qt.AlignCenter)
        self.label_2.setWordWrap(True)
        self.label_2.setObjectName("label_22")
        self.label_3 = QLabel(self.splitter)
        font = QFont()
        font.setFamily("Georgia")
        font.setPointSize(12)
        self.label_3.setFont(font)
        self.label_3.setAlignment(Qt.AlignCenter)
        self.label_3.setWordWrap(True)
        self.label_3.setObjectName("label_3")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setGeometry(QRect(0, 0, 400, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Новая вкладка"))
        self.label.setText(_translate("MainWindow", "Добро Пожаловать"))
        self.label_2.setText(_translate("MainWindow", "Чтобы начать нажмите PgUp."))
        self.label_3.setText(_translate("MainWindow", "Чтобы завершить нажмите PgUp и подождите."))
Exemple #4
0
    def __init__(self):
        super().__init__()

        self.leftWidget = JSONNavigation()
        self.leftWidget.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        self.leftWidget.currentChange.connect(self.fileSelected)
        self.leftWidget.alert.connect(lambda txt: self.alert.emit(
            txt, Parapluie.Alert_Error, None, None))
        self.addWidget(self.leftWidget)

        self.jsonEdit = TextEditWidget()
        # self.jsonEdit.setObjectName(Parapluie.Object_Editor_Flat)
        self.jsonEdit.alert.connect(lambda txt, tpe, button1, button2: self.
                                    alert.emit(txt, tpe, button1, button2))
        self.jsonEdit.saveDataDone.connect(self.leftWidget.fileChanged)

        self.paramEdit = ParamEditor()
        # self.paramEdit.setObjectName(Parapluie.Object_Table)
        self.paramEdit.error.connect(
            lambda s: self.alert.emit(s, Parapluie.Alert_Error, None, None))

        self.paramConnect = ParamEditorConnect(self.paramEdit, self.jsonEdit)

        splitter = QSplitter()
        splitter.setObjectName(Parapluie.Object_BorderPane)
        splitter.addWidget(self.jsonEdit)
        splitter.addWidget(self.paramEdit)
        splitter.setContentsMargins(8, 8, 8, 8)
        PFunction.applyShadow(splitter)

        layout = QVBoxLayout()
        layout.addWidget(splitter)
        layout.setContentsMargins(0, 8, 8, 8)

        widget = PWidget()
        widget.setLayout(layout)

        self.addWidget(widget)

        self.setChildrenCollapsible(False)
        self.setObjectName(Parapluie.Object_QSplitter)

        self.leftWidget.newFile()
        self.jsonEdit.setEditorType(EditorType.JSON)
    def __init__(self):
        super().__init__()
        self.setObjectName(Parapluie.Object_Raised)

        self.editor = TextEditWidget(save=False)

        self.paramEditor = ParamEditor()
        self.paramConnect = ParamEditorConnect(self.paramEditor, self.editor)
        self.editor.setEditorType(EditorType.Text)

        l3 = QSplitter()
        l3.setObjectName(Parapluie.Object_QSplitter)
        l3.setOrientation(Qt.Horizontal)
        l3.addWidget(self.editor)
        l3.addWidget(self.paramEditor)

        layout = QVBoxLayout()
        layout.addWidget(l3)
        self.setLayout(layout)
        self.layout().setContentsMargins(0, 8, 0, 0)
    def __init__(self):
        super().__init__()
        self.setObjectName(Parapluie.Object_Raised)
        self.setMinimumHeight(400)
        self.resizable(True)
        self.setSizeBox(400, 1000, 200)
        self.sizeBox.setValue(800)

        self.header = ParamEditor(ParamType.Param)
        self.header.setEditable(False)

        self.analysis = ParamEditor(ParamType.JSON)
        self.analysis.setEditable(False)

        self.result = ParamEditor(ParamType.JSON)

        self.editor = TextEditWidget(save=True)
        self.editor.setTitle('Result')
        self.editor.title.setVisible(False)
        self.editor.alert.connect(
            lambda a, b, c, d: self.alert.emit(a, b, c, d))

        self.paramConnect = ParamEditorConnect(self.result, self.editor)
        self.editor.setEditorType(EditorType.Text)

        self.webView = QWebEngineView()

        splitter = QSplitter()
        splitter.addWidget(self.editor)
        splitter.addWidget(self.result)
        splitter.setObjectName(Parapluie.Object_QSplitter)

        self.addTab(splitter, "Data")
        self.addTab(self.webView, "Preview")
        self.addTab(self.header, "Header")
        self.addTab(self.analysis, "Analysis")

        self.response: APIResponse = APIResponse()
        self.data: APIData = APIData()
        self.currentChanged.connect(self.tabChanged)
class PlaylistTab(QWidget):
    '''A widget for administrating the all models of the playlist data.'''
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setObjectName('tabPlaylist')
        self.horizontalLayout = QHBoxLayout(self)
        self.horizontalLayout.setObjectName("horizontalLayoutPlaylist")
        self.horizontalLayout.setContentsMargins(6, 6, 6, 6)
        self.horizontalLayout.setSpacing(6)

        self.horizontalSplitter = QSplitter(self)
        self.horizontalSplitter.setObjectName("horizontalSplitterPlaylist")
        self.horizontalSplitter.setChildrenCollapsible(False)

        # Artists/Albums/Games Layout Widget
        self.verticalSplitter = QSplitter(Qt.Vertical, self)
        self.verticalSplitter.setObjectName('verticalSplitterPlaylist')
        self.verticalSplitter.setChildrenCollapsible(False)
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setHeightForWidth(
            self.verticalSplitter.sizePolicy().hasHeightForWidth())
        self.verticalSplitter.setSizePolicy(sizePolicy)
        self.horizontalSplitter.addWidget(self.verticalSplitter)

        # Create the group box widgets for the playlist items
        self.groupBoxArtists = ArtistGroupBox(self)
        self.groupBoxAlbums = AlbumGroupBox(self)
        self.groupBoxGames = GameGroupBox(self)
        self.groupBoxSongs = SongGroupBox(self)

        # Add group boxes to layouts
        self.verticalSplitter.addWidget(self.groupBoxArtists)
        self.verticalSplitter.addWidget(self.groupBoxAlbums)
        self.verticalSplitter.addWidget(self.groupBoxGames)

        self.horizontalSplitter.addWidget(self.groupBoxSongs)
        self.horizontalLayout.addWidget(self.horizontalSplitter)
Exemple #8
0
class Ui_MainWindow(object):
    def setupUi(self, main_window):

        main_window.setObjectName("mainWindow")
        main_window.resize(1024, 768)
        main_window.setMinimumSize(QSize(1024, 768))
        main_window.setToolButtonStyle(Qt.ToolButtonIconOnly)

        self.central_widget = QWidget(main_window)
        self.central_widget.setObjectName("central_widget")

        self.horizontalLayout = QHBoxLayout(self.central_widget)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.topDownSplitter = QSplitter(self.central_widget)
        self.topDownSplitter.setOrientation(Qt.Vertical)
        self.topDownSplitter.setOpaqueResize(True)
        self.topDownSplitter.setHandleWidth(5)
        self.topDownSplitter.setObjectName("topDownSplitter")

        self.leftRightSplitter = QSplitter(self.topDownSplitter)
        self.leftRightSplitter.setOrientation(Qt.Horizontal)
        self.leftRightSplitter.setObjectName("leftRightSplitter")

        self.leftPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.leftPanel.sizePolicy().hasHeightForWidth())

        self.leftPanel.setSizePolicy(sizePolicy)
        self.leftPanel.setMinimumSize(QSize(245, 550))
        self.leftPanel.setMaximumSize(QSize(245, 16777215))
        self.leftPanel.setFrameShape(QFrame.StyledPanel)
        self.leftPanel.setFrameShadow(QFrame.Raised)
        self.leftPanel.setObjectName("leftPanel")

        self.leftPanelVLayout = QVBoxLayout(self.leftPanel)
        self.leftPanelVLayout.setObjectName("leftPanelVLayout")

        self.colorPickerFrame = QFrame(self.leftPanel)
        self.colorPickerFrame.setMinimumSize(QSize(0, 0))
        self.colorPickerFrame.setMaximumSize(QSize(16777215, 16777215))
        self.colorPickerFrame.setFrameShape(QFrame.StyledPanel)
        self.colorPickerFrame.setFrameShadow(QFrame.Raised)
        self.colorPickerFrame.setObjectName("colorPickerFrame")

        self.leftPanelVLayout.addWidget(self.colorPickerFrame)
        self.leftPanelVLayout.setStretch(0, 5)

        self.mainPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.mainPanel.sizePolicy().hasHeightForWidth())

        self.mainPanel.setSizePolicy(sizePolicy)
        self.mainPanel.setMinimumSize(QSize(320, 240))
        self.mainPanel.setAutoFillBackground(False)
        self.mainPanel.setFrameShape(QFrame.StyledPanel)
        self.mainPanel.setFrameShadow(QFrame.Raised)
        self.mainPanel.setObjectName("mainPanel")

        self.verticalLayout = QVBoxLayout(self.mainPanel)
        self.verticalLayout.setObjectName("verticalLayout")

        self.canvasFrame = QFrame(self.mainPanel)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.canvasFrame.sizePolicy().hasHeightForWidth())

        self.canvasFrame.setSizePolicy(sizePolicy)
        self.canvasFrame.setMinimumSize(310, 230)
        self.canvasFrame.setFrameShape(QFrame.StyledPanel)
        self.canvasFrame.setFrameShadow(QFrame.Raised)
        self.canvasFrame.setObjectName("canvasFrame")

        self.verticalLayout.addWidget(self.canvasFrame)
        self.verticalLayout.setStretch(0, 12)

        self.rightPanel = QFrame(self.leftRightSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.rightPanel.sizePolicy().hasHeightForWidth())

        self.rightPanel.setSizePolicy(sizePolicy)
        self.rightPanel.setMinimumSize(QSize(245, 550))
        self.rightPanel.setMaximumSize(QSize(340, 16777215))
        self.rightPanel.setFrameShape(QFrame.StyledPanel)
        self.rightPanel.setFrameShadow(QFrame.Raised)
        self.rightPanel.setObjectName("rightPanel")

        self.rightPanelLayout = QVBoxLayout(self.rightPanel)
        self.rightPanelLayout.setObjectName("rightPanelLayout")

        self.previewFrame = QFrame(self.rightPanel)
        self.previewFrame.setMaximumSize(320, 500)
        self.previewFrame.setFrameShape(QFrame.StyledPanel)
        self.previewFrame.setFrameShadow(QFrame.Raised)
        self.previewFrame.setObjectName("previewFrame")

        self.rightPanelLayout.addWidget(self.previewFrame)

        self.layerListFrame = QFrame(self.rightPanel)
        self.layerListFrame.setFrameShape(QFrame.StyledPanel)
        self.layerListFrame.setFrameShadow(QFrame.Raised)
        self.layerListFrame.setObjectName("layerListFrame")

        self.rightPanelLayout.addWidget(self.layerListFrame)

        self.animationBarFrame = QFrame(self.topDownSplitter)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.animationBarFrame.sizePolicy().hasHeightForWidth())

        self.animationBarFrame.setSizePolicy(sizePolicy)
        self.animationBarFrame.setMinimumSize(QSize(600, 100))
        self.animationBarFrame.setMaximumSize(QSize(16777215, 100))
        self.animationBarFrame.setFrameShape(QFrame.StyledPanel)
        self.animationBarFrame.setFrameShadow(QFrame.Raised)
        self.animationBarFrame.setObjectName("animationBarFrame")

        self.horizontalLayout.addWidget(self.topDownSplitter)

        main_window.setCentralWidget(self.central_widget)

        self.toolBar = QToolBar(main_window)

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.toolBar.sizePolicy().hasHeightForWidth())

        self.toolBar.setSizePolicy(sizePolicy)
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        self.toolBar.setObjectName("toolBar")

        main_window.addToolBar(Qt.TopToolBarArea, self.toolBar)

        self.actionNew = QAction(main_window)
        self.actionNew.setObjectName("actionNew")

        self.actionQuit = QAction(main_window)
        self.actionQuit.setObjectName("actionQuit")

        self.actionOpen = QAction(main_window)
        self.actionOpen.setObjectName("actionOpen")

        self.actionSave = QAction(main_window)
        self.actionSave.setObjectName("actionSave")

        self.actionSaveAs = QAction(main_window)
        self.actionSaveAs.setObjectName("actionSaveAs")

        self.actionClose = QAction(main_window)
        self.actionClose.setObjectName("actionClose")

        self.actionExport = QAction(main_window)
        self.actionExport.setObjectName("actionExport")

        self.actionImport = QAction(main_window)
        self.actionImport.setObjectName("actionImport")

        self.toolBar.addAction(self.actionNew)
        self.toolBar.addAction(self.actionOpen)
        self.toolBar.addAction(self.actionImport)
        self.toolBar.addAction(self.actionSave)
        self.toolBar.addAction(self.actionSaveAs)
        self.toolBar.addAction(self.actionExport)
        self.toolBar.addAction(self.actionClose)
        self.toolBar.addAction(self.actionQuit)

        self.retranslateUi(main_window)
        QMetaObject.connectSlotsByName(main_window)

    def retranslateUi(self, main_window):

        _translate = QCoreApplication.translate

        main_window.setWindowTitle(_translate("MainWindow", "SpriteMator"))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))

        self.actionNew.setText(_translate("MainWindow", "New"))
        self.actionNew.setIconText(_translate("MainWindow", "New"))
        self.actionNew.setToolTip(_translate("MainWindow", "New Sprite"))
        self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+N"))

        self.actionQuit.setText(_translate("MainWindow", "Quit"))
        self.actionQuit.setToolTip(
            _translate("MainWindow", "Close Application"))
        self.actionQuit.setShortcut(_translate("MainWindow", "Esc"))

        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionOpen.setToolTip(_translate("MainWindow", "Open Sprite"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))

        self.actionSave.setText(_translate("MainWindow", "Save"))
        self.actionSave.setToolTip(_translate("MainWindow", "Save Sprite"))
        self.actionSave.setShortcut(_translate("MainWindow", "Ctrl+S"))

        self.actionSaveAs.setText(_translate("MainWindow", "SaveAs"))
        self.actionSaveAs.setToolTip(
            _translate("MainWindow", "Save Sprite with another name"))
        self.actionSaveAs.setShortcut(_translate("MainWindow", "Ctrl+Shift+S"))

        self.actionClose.setText(_translate("MainWindow", "Close"))
        self.actionClose.setToolTip(_translate("MainWindow", "Close Sprite"))
        self.actionClose.setShortcut(_translate("MainWindow", "Ctrl+Q"))

        self.actionExport.setText(_translate("MainWindow", "Export"))
        self.actionExport.setToolTip(
            _translate(
                "MainWindow",
                "Export Sprite animations : Either as separate images or as a spritesheet"
            ))
        self.actionExport.setShortcut(_translate("MainWindow", "Ctrl+E"))

        self.actionImport.setText(_translate("MainWindow", "Import"))
        self.actionImport.setToolTip(
            _translate("MainWindow",
                       "Create a Sprite from one or more images"))
        self.actionImport.setShortcut(_translate("MainWindow", "Ctrl+I"))
class QuadView(QWidget):
    def __init__(self, parent, view1, view2, view3, view4=None):
        QWidget.__init__(self, parent)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.installEventFilter(self)

        self.dockableContainer = []

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

        self.splitVertical = QSplitter(Qt.Vertical, self)
        self.layout.addWidget(self.splitVertical)
        self.splitHorizontal1 = QSplitter(Qt.Horizontal, self.splitVertical)
        self.splitHorizontal1.setObjectName("splitter1")
        self.splitHorizontal2 = QSplitter(Qt.Horizontal, self.splitVertical)
        self.splitHorizontal2.setObjectName("splitter2")
        self.splitHorizontal1.splitterMoved.connect(
            self.horizontalSplitterMoved)
        self.splitHorizontal2.splitterMoved.connect(
            self.horizontalSplitterMoved)

        self.imageView2D_1 = view1

        self.imageView2D_2 = view2

        self.imageView2D_3 = view3

        self.dock1_ofSplitHorizontal1 = ImageView2DDockWidget(
            self.imageView2D_1)
        self.dock1_ofSplitHorizontal1.connectHud()
        self.dockableContainer.append(self.dock1_ofSplitHorizontal1)
        self.dock1_ofSplitHorizontal1.onDockButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_dock(arg))
        self.dock1_ofSplitHorizontal1.onMaxButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_max(arg))
        self.dock1_ofSplitHorizontal1.onMinButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_min(arg))
        self.splitHorizontal1.addWidget(self.dock1_ofSplitHorizontal1)

        self.dock2_ofSplitHorizontal1 = ImageView2DDockWidget(
            self.imageView2D_2)
        self.dock2_ofSplitHorizontal1.onDockButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_dock(arg))
        self.dock2_ofSplitHorizontal1.onMaxButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_max(arg))
        self.dock2_ofSplitHorizontal1.onMinButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_min(arg))
        self.dock2_ofSplitHorizontal1.connectHud()
        self.dockableContainer.append(self.dock2_ofSplitHorizontal1)
        self.splitHorizontal1.addWidget(self.dock2_ofSplitHorizontal1)

        self.dock1_ofSplitHorizontal2 = ImageView2DDockWidget(
            self.imageView2D_3)
        self.dock1_ofSplitHorizontal2.onDockButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_dock(arg))
        self.dock1_ofSplitHorizontal2.onMaxButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_max(arg))
        self.dock1_ofSplitHorizontal2.onMinButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_min(arg))
        self.dock1_ofSplitHorizontal2.connectHud()
        self.dockableContainer.append(self.dock1_ofSplitHorizontal2)
        self.splitHorizontal2.addWidget(self.dock1_ofSplitHorizontal2)

        self.dock2_ofSplitHorizontal2 = ImageView2DDockWidget(view4)
        self.dockableContainer.append(self.dock2_ofSplitHorizontal2)
        self.splitHorizontal2.addWidget(self.dock2_ofSplitHorizontal2)

        #this is a hack: with 0 ms it does not work...
        QTimer.singleShot(250, self._resizeEqual)

    def _resizeEqual(self):
        if not all([dock.isVisible() for dock in self.dockableContainer]):
            return
        w, h = self.size().width() - self.splitHorizontal1.handleWidth(
        ), self.size().height() - self.splitVertical.handleWidth()

        self.splitVertical.setSizes([h // 2, h // 2])

        if self.splitHorizontal1.count() == 2 and self.splitHorizontal2.count(
        ) == 2:
            #docks = [self.imageView2D_1, self.imageView2D_2, self.imageView2D_3, self.testView4]
            docks = []
            for splitter in [self.splitHorizontal1, self.splitHorizontal2]:
                for i in range(splitter.count()):
                    docks.append(splitter.widget(i).graphicsView)

            w1 = [docks[i].minimumSize().width() for i in [0, 2]]
            w2 = [docks[i].minimumSize().width() for i in [1, 3]]
            wLeft = max(w1)
            wRight = max(w2)
            if wLeft > wRight and wLeft > w // 2:
                wRight = w - wLeft
            elif wRight >= wLeft and wRight > w // 2:
                wLeft = w - wRight
            else:
                wLeft = w // 2
                wRight = w // 2
            self.splitHorizontal1.setSizes([wLeft, wRight])
            self.splitHorizontal2.setSizes([wLeft, wRight])

    def eventFilter(self, obj, event):
        if (event.type() in [QEvent.WindowActivate, QEvent.Show]):
            self._synchronizeSplitter()
        return False

    def _synchronizeSplitter(self):
        sizes1 = self.splitHorizontal1.sizes()
        sizes2 = self.splitHorizontal2.sizes()
        if len(sizes1) > 0 and sizes1[0] > 0:
            self.splitHorizontal2.setSizes(sizes1)
        elif len(sizes2) > 0 and sizes2[0] > 0:
            self.splitHorizontal1.setSizes(sizes2)

    def resizeEvent(self, event):
        QWidget.resizeEvent(self, event)
        self._synchronizeSplitter()

    def horizontalSplitterMoved(self, x, y):
        if self.splitHorizontal1.count() != 2 or self.splitHorizontal2.count(
        ) != 2:
            return
        sizes = self.splitHorizontal1.sizes()
        #What. Nr2
        if self.splitHorizontal2.closestLegalPosition(
                x, y) < self.splitHorizontal2.closestLegalPosition(x, y):
            sizeLeft = self.splitHorizontal1.closestLegalPosition(x, y)
        else:
            sizeLeft = self.splitHorizontal2.closestLegalPosition(x, y)

        sizeRight = sizes[0] + sizes[1] - sizeLeft
        sizes = [sizeLeft, sizeRight]

        self.splitHorizontal1.setSizes(sizes)
        self.splitHorizontal2.setSizes(sizes)

    def addStatusBar(self, bar):
        self.statusBar = bar
        self.layout.addLayout(self.statusBar)

    def setGrayScaleToQuadStatusBar(self, gray):
        self.quadViewStatusBar.setGrayScale(gray)

    def setMouseCoordsToQuadStatusBar(self, x, y, z):
        self.quadViewStatusBar.setMouseCoords(x, y, z)

    def ensureMaximized(self, axis):
        """
        Maximize the view for the given axis if it isn't already maximized.
        """
        axisDict = {
            0: self.dock2_ofSplitHorizontal1,  # x
            1: self.dock1_ofSplitHorizontal2,  # y
            2: self.dock1_ofSplitHorizontal1
        }  # z

        if not axisDict[axis]._isMaximized:
            self.switchMinMax(axis)

    def ensureMinimized(self, axis):
        """
        Minimize the view for the given axis if it isn't already minimized.
        """
        axisDict = {
            0: self.dock2_ofSplitHorizontal1,  # x
            1: self.dock1_ofSplitHorizontal2,  # y
            2: self.dock1_ofSplitHorizontal1
        }  # z

        if axisDict[axis]._isMaximized:
            self.switchMinMax(axis)

    def switchMinMax(self, axis):
        """Switch an AxisViewWidget between from minimized to maximized and vice
        versa.

        Keyword arguments:
        axis -- the axis which is represented by the widget (no default)
                either string or integer 
                'x' - 0
                'y' - 1
                'z' - 2
        """

        #TODO: get the mapping information from where it is set! if this is not
        #done properly - do it properly

        if type(axis) == str:
            axisDict = {
                'x': self.dock2_ofSplitHorizontal1,  # x
                'y': self.dock1_ofSplitHorizontal2,  # y
                'z': self.dock1_ofSplitHorizontal1
            }  # z
        elif type(axis) == int:
            axisDict = {
                0: self.dock2_ofSplitHorizontal1,  # x
                1: self.dock1_ofSplitHorizontal2,  # y
                2: self.dock1_ofSplitHorizontal1
            }  # z

        dockWidget = axisDict.pop(axis)
        for dWidget in list(axisDict.values()):
            if dWidget._isMaximized:
                dWidget.graphicsView._hud.maximizeButtonClicked.emit()
        dockWidget.graphicsView._hud.maximizeButtonClicked.emit()

    def switchXMinMax(self):
        self.switchMinMax('x')

    def switchYMinMax(self):
        self.switchMinMax('y')

    def switchZMinMax(self):
        self.switchMinMax('z')

    def on_dock(self, dockWidget):
        if dockWidget._isDocked:
            dockWidget.undockView()
            self.on_min(dockWidget)
            dockWidget.minimizeView()
        else:
            dockWidget.dockView()

    def on_max(self, dockWidget):
        dockWidget.setVisible(True)
        for dock in self.dockableContainer:
            if not dockWidget == dock:
                dock.setVisible(False)

        # Force sizes to be updated now
        QApplication.processEvents()

        # On linux, the vertical splitter doesn't seem to refresh unless we do so manually
        # Presumably, this is a QT bug.
        self.splitVertical.refresh()

        # Viewport doesn't update automatically...
        view = dockWidget.graphicsView
        view.viewport().setGeometry(view.rect())

    def on_min(self, dockWidget):

        for dock in self.dockableContainer:
            dock.setVisible(True)

        # Force sizes to be updated now
        QApplication.processEvents()
        self._resizeEqual()

        # Viewports don't update automatically...
        for dock in self.dockableContainer:
            view = dock.graphicsView
            if hasattr(view, 'viewport'):
                view.viewport().setGeometry(view.rect())
class Ui_MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # self.initUI()
        self.init_ui()
        self.generateData()
        self.UI_style()

    def init_ui(self):
        self.setFixedSize(1200, 700)
        self.setWindowTitle('STalking')
        self.setWindowIcon(QIcon("icon/stlogo.ico"))
        self.main_widget = QtWidgets.QWidget()  # 创建窗口主部件
        self.main_widget.setObjectName('main_widget')
        self.main_layout = QtWidgets.QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局

        self.left_widget = QtWidgets.QWidget()  # 创建左侧部件 左侧为功能按钮
        self.left_widget.setObjectName('left_widget')
        self.left_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_widget.setLayout(self.left_layout)  # 设置左侧部件布局为网格

        self.center_Splitter = QSplitter(Qt.Horizontal)
        self.center_Splitter.setObjectName('center_Splitter')
        self.center_layout = QtWidgets.QGridLayout()
        self.center_Splitter.setLayout(self.center_layout)  # 设置右侧部件布局为网格

        self.main_layout.addWidget(self.left_widget, 0, 0, 16,
                                   3)  # 左侧部件在第0行第0列,占8行3列
        # self.main_layout.addWidget(self.center_QWidget, 0, 3, 16, 17)  # 左侧部件在第0行第3列,占8行3列
        self.main_layout.addWidget(self.center_Splitter, 0, 3, 16,
                                   17)  # 左侧部件在第0行第3列,占8行3列
        self.setCentralWidget(self.main_widget)  # 设置窗口主部件

        self.icon_button = QtWidgets.QToolButton()
        self.icon_button.setIcon(QtGui.QIcon('icon/stlogo.ico'))  # 设置按钮图标
        self.icon_button.setIconSize(QtCore.QSize(150, 100))  # 设置图标大小

        self.left_label_1 = QtWidgets.QPushButton("模型选择")
        self.left_label_1.setObjectName('left_label')
        self.left_label_2 = QtWidgets.QPushButton("保存与设置")
        self.left_label_2.setObjectName('left_label')
        self.left_label_3 = QtWidgets.QPushButton("其他")
        self.left_label_3.setObjectName('left_label')

        self.left_button_1 = QtWidgets.QPushButton(
            qtawesome.icon('fa.database', color='gray'), "选择GMM")
        self.left_button_1.setObjectName('left_button')
        self.left_button_2 = QtWidgets.QPushButton(
            qtawesome.icon('fa.file', color='gray'), "选择UBM")
        self.left_button_2.setObjectName('left_button')
        self.left_button_3 = QtWidgets.QPushButton(
            qtawesome.icon('fa.plus-circle', color='gray'), "选择视频")
        self.left_button_3.setObjectName('left_button')
        self.left_button_4 = QtWidgets.QPushButton(
            qtawesome.icon('fa.save', color='gray'), "保存模型")
        self.left_button_4.setObjectName('left_button')
        self.left_button_5 = QtWidgets.QPushButton(
            qtawesome.icon('fa.file', color='gray'), "模型路径")
        self.left_button_5.setObjectName('left_button')
        self.left_button_6 = QtWidgets.QPushButton(
            qtawesome.icon('fa.folder-open', color='gray'), "文件路径")
        self.left_button_6.setObjectName('left_button')
        self.left_button_7 = QtWidgets.QPushButton(
            qtawesome.icon('fa.comment', color='gray'), "使用向导")
        self.left_button_7.setObjectName('left_button')
        self.left_button_8 = QtWidgets.QPushButton(
            qtawesome.icon('fa.star', color='gray'), "版权说明")
        self.left_button_8.setObjectName('left_button')
        self.left_button_9 = QtWidgets.QPushButton(
            qtawesome.icon('fa.question', color='gray'), "关于我们")
        self.left_button_9.setObjectName('left_button')
        self.left_xxx = QtWidgets.QPushButton(" ")

        self.left_layout.addWidget(self.icon_button, 0, 0.5, 1, 3)
        self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3)
        self.left_layout.addWidget(self.left_label_2, 5, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_4, 6, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_5, 7, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3)
        self.left_layout.addWidget(self.left_label_3, 9, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_7, 10, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_9, 12, 0, 1, 3)

        self.model_list_widget = QtWidgets.QWidget()
        self.model_list_widget.setObjectName('model_widget')
        self.model_list_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.model_list_widget.setLayout(self.model_list_layout)  # 设置左侧部件布局为网格

        self.model_list_label = QtWidgets.QLabel("模型列表")
        self.model_list_label.setObjectName('my_lable')

        self.model_view_list = QListWidget()  # 文件列表
        self.model_view_list.setObjectName('my_list')
        # self.model_view_list.setFixedWidth(200)
        self.right_Splitter = QSplitter(Qt.Vertical)
        self.right_Splitter.setObjectName('right_Splitter')

        self.model_list_layout.addWidget(self.model_list_label, 0, 0, 1, 1)
        self.model_list_layout.addWidget(self.model_view_list, 1, 0, 9, 1)

        self.center_Splitter.addWidget(self.model_list_widget)
        self.center_Splitter.addWidget(self.right_Splitter)
        self.center_Splitter.setStretchFactor(0, 2)
        self.center_Splitter.setStretchFactor(1, 8)

        self.result_label = QtWidgets.QLabel("数据分析")
        self.result_label.setFixedHeight(80)
        self.result_label.setObjectName('my_lable')

        self.right_html_page_TabWidget = QtWidgets.QTabWidget()
        self.right_html_page_TabWidget.setObjectName(
            'right_html_page_TabWidget')
        self.right_log_widget = QtWidgets.QWidget()  # log 框 = button + log
        self.right_log_widget.setObjectName('right_log_widget')
        self.right_log_layout = QtWidgets.QGridLayout()
        self.right_log_widget.setLayout(self.right_log_layout)  # 设置右侧部件布局为网格

        self.right_Splitter.addWidget(self.result_label)
        self.right_Splitter.addWidget(self.right_html_page_TabWidget)
        self.right_Splitter.addWidget(self.right_log_widget)
        self.right_Splitter.setStretchFactor(0, 1)
        self.right_Splitter.setStretchFactor(1, 9)
        self.right_Splitter.setStretchFactor(2, 1)

        self.right_log_toolbar = QToolBar()
        self.right_log_toolbar.setObjectName('right_log_toolbar')
        self.right_log_toolbar.setOrientation(Qt.Vertical)
        # self.right_button_layout.addWidget(self.toolbarGmm)
        delete_action = QAction(QIcon('icon/delete-gray.png'), '清空日志', self)
        self.right_log_toolbar.addAction(delete_action)
        export_action = QAction(QIcon('icon/save_m.png'), '导出日志', self)
        self.right_log_toolbar.addAction(export_action)
        # self.right_log_layout.setSpacing(0)
        self.right_log_contend = QListWidget()
        # self.right_log_contend.setFixedHeight(100)
        self.right_log_contend.setObjectName('my_list')
        self.right_log_layout.addWidget(self.right_log_toolbar, 0, 0, 1, 3)
        self.right_log_layout.addWidget(self.right_log_contend, 0, 1, 1, 18)

    # 定义 css
    def UI_style(self):
        self.main_widget.setStyleSheet('''
            QWidget#main_widget{
                background:#EBEBEB;
                border-top:1px solid #EBEBEB;
                border-bottom:1px solid #EBEBEB;
                border-left:1px solid #EBEBEB;
                border-top-left-radius:10px;
                border-bottom-left-radius:10px;
            }

        ''')
        self.result_label.setStyleSheet('''
            QLabel{
                border:none;
                background:#EBEBEB;
                font-size:20px;
                font-weight:900;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        ''')
        self.model_list_label.setStyleSheet('''
                    QLabel{
                        border:none;
                        background:#EBEBEB;
                        font-size:20px;
                        font-weight:900;
                        font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
                    }

                ''')
        self.icon_button.setStyleSheet('''
            QToolButton{
                border:none;
                background:#EBEBEB;
            }
        ''')
        self.main_widget.setStyleSheet('''
            QWidget#center_QWidget{
                color:#232C51;
                background:#EBEBEB;
                border-top:1px solid #EBEBEB;
                border-bottom:1px solid #EBEBEB;
                border-right:1px solid #EBEBEB;
                border-top-right-radius:10px;
                border-bottom-right-radius:10px;
            }
            QWidget#left_widget{
                        background:#EBEBEB;
                        border-top:1px solid #EBEBEB;
                        border-bottom:1px solid #EBEBEB;
                        border-left:1px solid #EBEBEB;
                        border-top-left-radius:10px;
                        border-bottom-left-radius:10px;
                    }
        ''')
        self.model_list_widget.setStyleSheet('''
            QListWidget#my_list{
                background:light white;
                border:none;
                width:300px;
                border-radius:10px;
                padding:2px 4px;
            }
        ''')
        self.left_widget.setStyleSheet('''
            QPushButton{border:none;color:gray;font-size:18px;font-weight:700;}
            QPushButton#left_label{
                    border:none;
                    border-bottom:1px solid dark gray;
                    font-size:20px;
                    font-weight:900;
                    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;}
        ''')
        self.center_Splitter.setStyleSheet('''
            QSplitter#center_Splitter{
                background:#EBEBEB;
            }
            QSplitter#right_Splitter{
                background:#EBEBEB;
            }
            QTabWidget#right_html_page_TabWidget{
                width:300px;
                border-radius:10px;
                padding:2px 4px;
                border:none;
                font-size:16px;
                font-weight:700;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            }
            QLabel#my_lable{
                background-color:#EBEBEB;
                border:none;
                font-size:20px;
                font-weight:bold;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
             QToolBar#right_log_toolbar{
                border:none;
                background-color: #EBEBEB;
            }
            QListWidget#my_list{
                background:light white;
                border:none;
                width:300px;
                border-radius:10px;
                padding:2px 4px;
            }

        ''')
        self.model_list_label.setAlignment(Qt.AlignCenter)
        self.result_label.setAlignment(Qt.AlignCenter)
        self.model_list_label.setStyleSheet('''
            QLabel{
                background-color:light gray;
                border:none;
                font-size:20px;
                font-weight:bold;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        ''')

        self.right_log_widget.setStyleSheet('''
            QListWidget#right_log_widget{
                width:300px;
                border-radius:10px;
                padding:2px 4px;
            }
            QToolBar#right_log_toolbar{
                border:none;
                background-color: light gray;
            }
            QListWidget#right_log_contend{
                background:#EBEBEB;
                border:none;
                border:1px solid gray;
                width:300px;
                border-radius:10px;
                padding:2px 4px;
            }
        ''')

        # self.setWindowOpacity(1)  # 设置窗口透明度
        # self.setAttribute(QtCore.Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        # self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框
        # self.main_layout.setSpacing(0)

    def generateData(self):
        for group in range(1, 100):
            self.model_view_list.addItem("model_{0}".format(group))
        for group in range(1, 100):
            self.right_log_contend.addItem(
                (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') +
                 " : operation_{0}").format(group))
        for group in range(1, 4):
            self.tabItem = QTextBrowser()
            self.right_html_page_TabWidget.addTab(self.tabItem,
                                                  "page_{0}".format(group))
            self.tabItem.setHtml("""<table bgcolor=yellow>
        <tr><td>Groups:</td><td>comp.lang.python.announce</td></tr>
        <tr><td>From:</td><td>"Fuzzyman" &lt;[email protected]&gt;</td></tr>
        <tr><td>Subject:</td><td><b>[ANN] Movable Python 2.0.0 Final
        Available</b></td></tr>
        </table>

        <h3>Movable Python 2.0.0 Final</h3>
        <p>
        <a href="http://www.voidspace.org.uk/python/movpy/">
        http://www.voidspace.org.uk/python/movpy/</a>
        is now available.

        <p>
        The new binaries are available for download from the groups page :

        <p>Movable Python Groups Page
        <a href="http://voidspace.tradebit.com/groups.php">
        http://voidspace.tradebit.com/groups.php</a>
        <p>
        Binaries are uploaded for Python 2.2.3, 2.3.5, 2.4.4, 2.5 and the
        MegaPack
        <a href="http://www.voidspace.org.uk/python/movpy/megapack.html">
        http://www.voidspace.org.uk/python/movpy/megapack.html</a>.
        <p>
        There is also a fresh version of the free demo, based on Python 2.3.5:

        <p>Movable Python Trial Version
        <a href="http://voidspace.tradebit.com/files.php/7007">
        http://voidspace.tradebit.com/files.php/7007</a>

        <h3>What is Movable Python</h3>

        <p>
        <b><i>Movable Python</i></b> is a distribution of Python, for Windows,
        that can run without being installed. It means you can carry a full
        development environment round on a USB stick.

        <p>
        It is also useful for testing programs with a 'clean Python install',
        and testing programs with multiple versions of Python.

        <p>
        The GUI program launcher makes it a useful programmers tool, including
        features like :

        <ul>
        <li>Log the output of all Python scripts run
        <li>Enable Psyco for all scripts
        <li>Quick Launch buttons for commonly used programs
        <li>Configure multiple interpreters for use from a single interface
        </ul>
        <p>
        It comes with the Pythonwin IDE and works fine with other IDEs like
        SPE
        <a href="http://developer.berlios.de/projects/python/">
        http://developer.berlios.de/projects/python/</a>.
        <p>
        Plus many other features and bundled libraries.""")
Exemple #11
0
class NeuralNetSection(QWidget):

    added_to_set = pyqtSignal(str)
    removed_from_set = pyqtSignal(str)
    deleted_set = pyqtSignal(str)

    def __init__(self, sets=None):
        super().__init__()
        self.sets = sets if sets else []
        self.trash_set = None
        self.expand_state = False
        self.dont_ask = False
        self.dont_ask_trash = False
        self.initial_image_grid_visible = True
        self.settings = QSettings("Theo Styles",
                                  "Convolutional Neural Network")
        self.current_index = 0
        self.selected_items = []
        self.init_ui()

    def expand_clicked(self):
        if self.expand_state:
            self.expand_all()
            self.expand_all_button.setText("Hide all -")
        else:
            self.hide_all()
            self.expand_all_button.setText("Expand all +")

        self.expand_state = not self.expand_state

    def expand_all(self):
        if self.trash_set: self.trash_set.expand()
        for set in self.sets:
            set.expand()

    def hide_all(self):
        if self.trash_set: self.trash_set.hide()
        for set in self.sets:
            set.hide()

    def trash_clicked(self):
        ok = False
        if not self.dont_ask_trash:
            ok, dont_ask_trash = CustomDialog.dialog(
                self, "Are you sure you want to add items to the trash set?")
            self.dont_ask_trash = dont_ask_trash

        if self.dont_ask_trash or ok:
            index = self.initial_image_grid.currentRow()
            trash_set = self.add_or_create_set("Trash")
            self.initial_image_grid.setCurrentRow(index)
            if not self.trash_set:
                self.sets.remove(trash_set)
            self.trash_set = trash_set

    def clicked_set(self, set):
        othersSelected = False
        trash_selected = False if not self.trash_set else len(
            self.trash_set.image_grid.selectedIndexes()) > 0
        for otherSet in self.sets:
            if len(otherSet.image_grid.selectedIndexes()
                   ) > 0 or trash_selected:
                othersSelected = True
                break
        if not othersSelected: return
        if len(set.image_grid.selectedIndexes()) > 0: return

        if not self.dont_ask:
            ok, dont_ask = CustomDialog.dialog(
                self,
                "Are you sure you want to add items to set " + set.name + "?")
            self.dont_ask = dont_ask

        if self.dont_ask or ok:
            for oneSet in self.sets:
                selectedItems = oneSet.image_grid.selectedItems()
                oneSet.incorrectly_classified += len(selectedItems)
                oneSet.incorrectly_classified_local += len(selectedItems)
                for selectedItem in selectedItems:
                    item = oneSet.takeFromBoth(
                        oneSet.image_grid.row(selectedItem))
                    set.addItem(item)

            if self.trash_set:
                for selectedItem in self.trash_set.image_grid.selectedItems():
                    item = self.trash_set.takeFromBoth(
                        self.trash_set.image_grid.row(selectedItem))
                    set.addItem(item)

        set.hidden = True

    def added_to_set_event(self, set_name):
        self.added_to_set.emit(set_name)

    def removed_from_set_event(self, set_name):
        self.removed_from_set.emit(set_name)

    def is_existing_set(self, name):
        for set in self.sets:
            if set.name == name:
                ErrorDialog.dialog(self,
                                   "There is already a set with this name")
                return True
        return False

    def rename_set(self, set, new_name):
        if self.is_existing_set(new_name): return
        set.set_name(new_name)

    def delete_set(self, to_delete):
        self.deleted_set.emit(to_delete.name)
        self.main_layout.removeWidget(to_delete)
        if not to_delete == self.trash_set:
            self.sets.remove(to_delete)
        to_delete.deleteLater()

    def create_new_set_with_selected(self, name, old_set):
        if self.is_existing_set(name): return
        selected = old_set.image_grid.selectedItems()
        items = []
        old_set.incorrectly_classified += len(selected)
        old_set.incorrectly_classified_local += len(selected)
        for sItem in selected:
            item = old_set.takeFromBoth(old_set.image_grid.row(sItem))
            items.append(item)
        self.create_new_set(name, items)

    def move_to_set(self, name, old_set):
        if name == old_set.name: return
        selected = old_set.image_grid.selectedItems()
        setToAdd = self.get_set(name)
        if name == "Trash":
            if not self.trash_set:
                self.trash_set = self.create_new_set("Trash", [])
            setToAdd = self.trash_set
        items = []
        if not setToAdd:
            ErrorDialog.dialog(self, "Cannot find a set with that name")
            return

        old_set.incorrectly_classified += len(selected)
        old_set.incorrectly_classified_local += len(selected)
        for sItem in selected:
            item = old_set.takeFromBoth(old_set.image_grid.row(sItem))
            items.append(item)
        setToAdd.add_items(items)

    def clear_sets(self):
        for set in self.sets:
            self.main_layout.removeWidget(set)
            set.deleteLater()
        self.sets = []

    def add_sets(self):
        for set in self.sets:
            if set.name == "Trash":
                self.trash_set = set
            self.main_layout.insertWidget(self.main_layout.count() - 1, set)
        self.search_and_sort()

    def create_new_set(self, name, items):
        if name == "": return
        new_set = Set(name)
        new_set.added_image.connect(self.added_to_set_event)
        new_set.removed_image.connect(self.removed_from_set_event)
        new_set.clicked_set.connect(self.clicked_set)
        new_set.create_new_set.connect(self.create_new_set_with_selected)
        new_set.rename_set_sig.connect(self.rename_set)
        new_set.delete_set_sig.connect(self.delete_set)
        new_set.move_to_set.connect(self.move_to_set)

        if len(items) > 0:
            if isinstance(items[0], (np.ndarray, np.generic)):
                new_set.add_images(items)
            else:
                new_set.add_items(items)

        if self.empty_label:
            self.main_layout.removeWidget(self.empty_label)
            self.empty_label.deleteLater()
            self.empty_label = None
            self.buttons_widget.setVisible(True)

        self.main_layout.insertWidget(self.main_layout.count() - 1, new_set)

        if name == "Trash":
            self.trash_set = new_set
        else:
            self.sets.append(new_set)
        self.search_and_sort()
        return new_set

    def get_set(self, set_name):
        for set in self.sets:
            if set.name == set_name:
                return set
        return None

    def set_classified_for_set(self, set_name, incorrectly_classified_local,
                               incorrectly_classified):
        set = self.get_set(set_name)
        if set:
            set.incorrectly_classified = incorrectly_classified
            set.incorrectly_classified_local = incorrectly_classified_local

    def add_images_to_set(self, name, items):
        to_add = self.get_set(name)
        if to_add:
            for item in items:
                to_add.add_image(item)
        elif name == "Trash" and self.trash_set:
            for item in items:
                self.trash_set.add_image(item)

    def add_or_create_set(self, name):
        to_add = []
        exists = False
        setToAdd = None

        for set in self.sets:
            if set.name == name:
                exists = True
                setToAdd = set

        if name == "Trash" and self.trash_set:
            setToAdd = self.trash_set
            exists = True

        for item in self.initial_image_grid.selectedItems():
            taken = self.initial_image_grid.takeItem(
                self.initial_image_grid.row(item))
            to_add.append(taken)
            if exists:
                setToAdd.addItem(taken)

        if not exists:
            return self.create_new_set(name, to_add)
        else:
            return setToAdd

    def ask_for_set_name(self):

        if len(self.initial_image_grid.selectedItems()) == 0:
            self.show_error("Please select items to create a new set")
        else:
            text, ok = InputDialog.dialog(self,
                                          'Enter the name for the new set:',
                                          "Set name...")
            if ok:
                if len(text) == 0:
                    return self.show_error("You must enter a set name")
                for set in self.sets:
                    if self.settings.value("limit_to_one_initially") == "true":
                        if set.name == text:
                            ErrorDialog.dialog(
                                self, "There is already a set with this name")
                            index = self.initial_image_grid.currentRow() + 1
                            self.initial_image_grid.setCurrentRow(index)
                            return
                index = self.initial_image_grid.currentRow()
                self.add_or_create_set(text)
                self.initial_image_grid.setCurrentRow(index)

    def show_error(self, message):
        ErrorDialog.dialog(self, message)

    def search(self, query):
        titles = []
        matching = []

        sets_copy = self.sets[:]

        if self.trash_set:
            sets_copy.append(self.trash_set)

        for set in sets_copy:
            titles.append(set.name)
            set.setVisible(False)

        for i, title in enumerate(titles):
            if query in title:
                matching.append(i)

        for match in matching:
            sets_copy[match].setVisible(True)

    def sort_sets(self, sort_by):
        sets_copy = self.sets[:]

        if self.trash_set:
            sets_copy.append(self.trash_set)

        if sort_by == 0:
            sets_copy.sort(key=lambda x: x.name, reverse=False)
        elif sort_by == 1:
            sets_copy.sort(key=lambda x: x.name, reverse=True)
        elif sort_by == 2:
            sets_copy.sort(key=lambda x: x.count(), reverse=False)
        elif sort_by == 3:
            sets_copy.sort(key=lambda x: x.count(), reverse=True)

        for set in sets_copy:
            self.main_layout.removeWidget(set)

        for set in sets_copy:
            self.main_layout.insertWidget(self.main_layout.count() - 1, set)

        if self.trash_set:
            sets_copy.remove(self.trash_set)

        self.sets = sets_copy

    def search_and_sort(self):
        self.sort_sets(self.sort_button.currentIndex())
        self.search(self.search_field.text())

    def init_ui(self):
        self.overall_layout = QVBoxLayout()

        self.main_splitter = QSplitter()
        self.main_splitter.setOrientation(Qt.Vertical)

        self.top_widget = QWidget()
        self.top_layout = QHBoxLayout()

        self.initial_image_grid = ImageGrid()
        self.add_button = CustomPushButton("+ SET")
        self.add_button.setToolTip("Create a new set with the selected images")
        self.trash_button = CustomPushButton("DELETE")
        self.trash_button.clicked.connect(self.trash_clicked)
        self.trash_button.setToolTip("Add to the trash set")

        self.top_widget.setLayout(self.top_layout)

        self.top_widget.setVisible(False)

        self.top_grid_buttons = QVBoxLayout()
        self.top_grid_buttons.addWidget(self.add_button)
        self.top_grid_buttons.addStretch()
        self.top_grid_buttons.addWidget(self.trash_button)

        self.add_button.clicked.connect(self.ask_for_set_name)

        self.top_layout.addWidget(self.initial_image_grid)
        self.top_layout.addLayout(self.top_grid_buttons)

        self.lower_layout = QVBoxLayout()
        self.lower_widget = QWidget()
        self.lower_widget.setLayout(self.lower_layout)

        self.buttons_widget = QWidget()
        self.buttons_widget.setVisible(False)
        self.buttons_layout = QHBoxLayout()
        self.buttons_widget.setLayout(self.buttons_layout)

        self.expand_all_button = CustomPushButton("Hide All -")
        self.expand_all_button.setToolTip("Toggles visibility of sets below")
        self.expand_all_button.clicked.connect(self.expand_clicked)

        self.search_field = QLineEdit()
        self.search_field.setAttribute(Qt.WA_MacShowFocusRect, False)
        self.search_field.setObjectName("searchField")
        self.search_field.setPlaceholderText("Search for sets...")
        self.search_field.textChanged.connect(self.search_and_sort)
        self.sort_button = CustomComboBox()

        self.sort_button.addItem("Name (Ascending)")
        self.sort_button.addItem("Name (Descending)")
        self.sort_button.addItem("Item count (Ascending)")
        self.sort_button.addItem("Item count (Descending)")
        self.sort_button.setEditable(False)
        self.sort_button.activated.connect(self.search_and_sort)
        self.buttons_layout.addWidget(self.expand_all_button)
        self.buttons_layout.addWidget(self.search_field)
        self.buttons_layout.addWidget(self.sort_button)

        self.lower_layout.addWidget(self.buttons_widget)

        self.main_layout = QVBoxLayout()

        self.scroll = QScrollArea()
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scroll.setWidgetResizable(True)

        self.main_widget = QWidget()
        self.empty_label = QLabel(
            "Add a folder of images using the + button above!")
        self.main_layout.addWidget(self.empty_label)
        self.main_layout.addStretch()
        self.main_widget.setLayout(self.main_layout)
        self.scroll.setWidget(self.main_widget)

        self.scroll.setContentsMargins(0, 0, 0, 0)
        self.main_widget.setContentsMargins(0, 0, 30, 0)
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.lower_layout.addWidget(self.scroll, 1)
        self.lower_layout.addStretch()

        self.main_splitter.setObjectName("horizontalSplitter")
        self.main_splitter.addWidget(self.top_widget)
        self.main_splitter.addWidget(self.lower_widget)

        self.overall_layout.addWidget(self.main_splitter)
        self.setLayout(self.overall_layout)
Exemple #12
0
class MainWindow(QMainWindow):
    """
    主窗口界面
    """

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

        # 初始化
        self.init()
        # ui设计
        self.setup_ui()
        # 创建右键菜单
        self.create_context_menu()
        # 主框体设计
        self.set_main_form()
        # 加载qss样式
        self.load_qss()

    def init(self):
        self.setGeometry(Const.WIN_X, Const.WIN_Y, Const.WIN_WIDTH, Const.WIN_HEIGHT)
        self.setObjectName('mainWindow')
        self.setWindowIcon(QIcon("./image/Logo/logo.png"))
        self.setWindowTitle('IFR智能公式识别系统')

        # 加载图片缩放公共类
        self.imageScale = ImageScale()

    def setup_ui(self):
        """
        创建状态栏、菜单栏、工具栏
        """

        # 状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage('准备就绪', 5000)
        # self.statusBar().setStyleSheet('background-color:lightGray;')

        # 菜单栏
        self.menubar = QMenuBar()
        self.setMenuBar(self.menubar)
        # self.menuBar().setStyleSheet('background-color:lightGray;')

        # 文件
        self.fileMenu = self.menubar.addMenu('&文件(F)')

        # 调用自定义action
        self.openPimax = Action.action_b_2(self, 'openPimax', '&打开图片文件', 'Ctrl+P', '打开图片文件')
        self.openPimax.setIcon(QIcon('./image/openQpixmap.jpg'))
        self.openText = Action.action_b_2(self, 'openText', '&打开文本文件', 'Ctrl+T', '打开文本文件')
        self.openText.setIcon(QIcon('./image/openText.ico'))
        self.openFile = Action.action_b_3(self, 'openFile', '打开文件', '打开文件', self.fileMenu)
        self.openFile.addAction(self.openPimax)
        self.openFile.addAction(self.openText)

        self.openPimax.triggered.connect(lambda: self.get_image())
        self.openText.triggered.connect(lambda: self.get_text())
        self.openRecentFile = Action.action_a_2(self, 'openRecentFile', '&最近打开的文件', 'Ctrl+O', '最近打开的文件', self.fileMenu)
        # self.openRecentFile.triggered.connect(self.)
        self.save = Action.action_a_2(self, 'save', '&保存分析结果', 'Ctrl+S', '保存数据分析结果', self.fileMenu)
        # self.save.triggered.connect(self.)
        self.saveAs = Action.action_a_2(self, 'saveAs', '&另保存分析结果', 'Ctrl+Shift+S', '另保存数据分析结果', self.fileMenu)
        # self.saveAs.triggered.connect(self.)
        self.printf = Action.action_a_2(self, 'printef', '&打印分析结果', 'Ctrl+P', '打印数据分析结果', self.fileMenu)
        # self.printf.triggered.connect(self.)
        self.exitAction = Action.action_a_1(self, 'exitAction', './image/mainWindowIcon/toolBarIcon/exit.png', '&退出',
                                            'Ctrl+Q', '退出应用程序',
                                            self.fileMenu)
        self.exitAction.triggered.connect(self.close)

        # 编辑
        self.exitMenu = self.menubar.addMenu('&编辑(E)')
        #
        # ####################查找与替换####################开始
        self.search = Action.action_b_2(self, 'search', '&快速查找', 'Ctrl+F', '快速查找')
        self.replace = Action.action_b_2(self, 'replace', '&快速替换', 'Ctrl+H', '快速替换')

        # 新增二级菜单
        self.searchAndReplaceMenu = Action.action_b_3(self, 'searchAndReplaceMenu', '查找与替换', '查找与替换', self.exitMenu)
        self.searchAndReplaceMenu.addAction(self.search)
        self.searchAndReplaceMenu.addAction(self.replace)

        # self.search.triggered.connect(self.)
        # self.replace.triggered.connect(self.)

        # ####################查找与替换####################结束

        self.cut = Action.action_a_2(self, 'cut', '&剪切', 'Ctrl+X', '剪切', self.exitMenu)
        # self.cut.triggered.connect(self.)
        self.copy = Action.action_a_2(self, 'copy', '&复制', 'Ctrl+C', '复制', self.exitMenu)
        # self.copy.triggered.connect(self.)
        self.paste = Action.action_a_2(self, 'paste', '&粘贴', 'Ctrl+V', '粘贴', self.exitMenu)
        # self.paste.triggered.connect(self.)
        self.delete = Action.action_a_2(self, 'delect', '&删除', 'Del', '删除', self.exitMenu)
        # self.delect.triggered.connect(self.)
        self.selectAll = Action.action_a_2(self, 'selectAll', '&全选', 'Ctrl+Alt', '全选', self.exitMenu)
        # self.selectAll.triggered.connect(self.)

        # 视图
        self.viewMenu = self.menubar.addMenu('&视图(V)')

        self.notice = Action.action_a_2(self, 'notice', '&通知', 'Ctrl+Alt+X', '信息通知提醒', self.viewMenu)
        # self.notice.triggered.connect(self.)

        # ####################窗口管理####################开始
        self.window = Action.action_b_3(self, 'window', '&窗口', '展示一些基本窗口', self.viewMenu)

        # ####################窗口管理####################结束
        #
        #
        #
        # ####################工具栏####################开始
        self.tool = Action.action_b_3(self, 'tool', '&工具栏', '基本工具', self.viewMenu)

        self.calculator = Action.action_a_1(self, 'calculator', './image/calculator.jpg', '&计算器',
                                            'C', '计算器', self.viewMenu)
        self.calculator.triggered.connect(lambda: self.calculator_win())

        # ####################工具####################结束
        self.fullScreen = Action.action_a_2(self, 'fullScreen', '&全屏幕', 'Shift+Alt+Enter', '全屏', self.viewMenu)
        # self.fullScreen.triggered.connect(self.)
        self.propertyWindow = Action.action_a_2(self, 'propertyWindow', '&属性窗口', 'F4', '属性窗口', self.viewMenu)
        # self.propertyWindow.triggered.connect(self.)
        #

        # 分析
        self.navigateMenu = self.menubar.addMenu('&分析(N)')
        #

        # 工具
        self.toolMenu = self.menubar.addMenu('&工具(T)')
        #

        # 扩展
        self.extendMenu = self.menubar.addMenu('&扩展(X)')
        #

        # 窗口
        self.windowMenu = self.menubar.addMenu('&窗口(W)')
        #

        # 帮助
        self.helpMenu = self.menubar.addMenu('&帮助(H)')

        self.help = Action.action_a_2(self, 'help ', '&查看帮助', 'Ctrl+F1', '查看帮助', self.helpMenu)
        # self.help.triggered.connect(self.)
        # ####################菜单####################结束

        ################################################################################################################

        # ####################工具栏####################开始
        # 工具

        self.pixmapToolbar = self.addToolBar('打开图形文件')
        self.textToolbar = self.addToolBar('打开文本文件')
        self.pixmapToolbar.addAction(self.openPimax)
        self.textToolbar.addAction(self.openText)

        self.exitToolbar = self.addToolBar('退出')
        self.exitToolbar.addAction(self.exitAction)

        self.calculatorTooolbar = self.addToolBar('计算器')
        self.calculatorTooolbar.addAction(self.calculator)

        # ####################工具栏####################结束

        #  槽函数线程

    # 创建右键菜单
    def create_context_menu(self):
        """
        创建右键菜单
        :return:
        """
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)

        # 创建QMenu
        self.contextMenu = QMenu(self)

        # ####################工具栏管理####################开始
        self.toolBarManagementMenu = Action.action_b_4(self, 'toolBarManagementMenu', '&工具栏管理', self.contextMenu)
        # 未完成
        # ####################工具栏管理####################结束

        self.minAtion = Action.action_a_1(self, 'minAction', './image/min.png', '&最小化', 'Ctrl+M', '最小化窗口',
                                          self.contextMenu)

        self.contextMenu.addSeparator()  # 添加分隔线

        self.cutAction = Action.action_a_2(self, 'cutAction', '&剪切', 'Ctrl+X', '剪切', self.contextMenu)
        self.copyAction = Action.action_a_2(self, 'copyAction', '&复制', 'Ctrl+C', '复制', self.contextMenu)
        self.pasteAction = Action.action_a_2(self, 'pasteAction', '&粘贴', 'Ctrl+V', '粘贴', self.contextMenu)
        self.deleteAction = Action.action_a_2(self, 'delectAction', '&删除', 'Del', '删除', self.contextMenu)
        self.selectAllAction = Action.action_a_2(self, 'selectAllAction', '&全选', 'Ctrl+Alt', '全选', self.contextMenu)

        self.contextMenu.addSeparator()  # 添加分隔线

        self.closeAction = Action.action_a_1(self, 'closeAction', './image/Exit.png', '&退出', 'Ctrl+W', '退出',
                                             self.contextMenu)

        self.minAtion.triggered.connect(self.show_mininized_window)

        self.closeAction.triggered.connect(self.quit_window)
        # self.selectAllAction.triggered.connect(self.)
        # self.cutAction.triggered.connect(self.)
        # self.copyAction.triggered.connect(self.)
        # self.pasteAction.triggered.connect(self.)
        # self.delectAction.triggered.connect(self.)

    # ****************************** 业务逻辑 *********************************
    def load_qss(self):
        """
         加载Qss样式表
        :return:
        """
        style_file = './Window/mainWindow/Qss/mainWindow.qss'
        qss_style = CommonhelperQss.read_qss(style_file)
        self.setStyleSheet(qss_style)

    def set_action_connect(self):
        """
        菜单栏、工具栏槽函数连接
        :return:
        """
        pass

    def calculator_win(self):
        """
        加载计算器窗口
        :return:
        """
        self.calculator_Win = Calculatormainwindow()
        self.calculator_Win.show()

    def set_main_form(self):
        """
        窗体布局以及主框体设计
        :return:
        """
        # 主框体
        self.mainSpiltter = QSplitter(Qt.Vertical)
        self.mainSpiltter.setObjectName('mainSpiltter')

        self.mainSpiltterLayout = QVBoxLayout()

        # 设置主窗口中心窗体
        self.setCentralWidget(self.mainSpiltter)

        # *******工作区间*******
        self.workWidget = QSplitter()
        self.workWidget.setObjectName('workWidget')
        self.mainSpiltter.addWidget(self.workWidget)

        self.workWidgetLayout = QHBoxLayout()
        self.workWidget.setLayout(self.workWidgetLayout)

        self.leftWidget = QFrame()
        self.leftWidget.setObjectName('leftWidget')
        self.leftWidget.setFrameShape(QFrame.StyledPanel)
        self.leftWidget.setMaximumWidth(230)

        self.leftWidgetLayout = QVBoxLayout()
        self.leftWidgetLayout.setContentsMargins(0, 0, 0, 0)
        self.leftWidget.setLayout(self.leftWidgetLayout)

        # self.hideBtn = QLabel()
        # self.hideBtn.setObjectName('hideBtn')
        # self.hideBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/hide0.ico'))
        #
        # self.showBtn = QLabel()
        # self.showBtn.setObjectName('showBtn')
        # self.showBtn.setPixmap(QPixmap('./image/mainWindowIcon/showAndHideIcon/show0.ico'))

        # 存放按钮
        self.widget = QWidget()
        self.widget.setObjectName('widget')
        self.leftWidgetLayout.addWidget(self.widget)

        pixmap = self.imageScale.pixmap_scale('./image/Logo/logo0.png', 204, 80)

        self.logoIamgeLabel = QLabel(self.widget)
        self.logoIamgeLabel.setObjectName('logoImageLabel')
        self.logoIamgeLabel.setPixmap(pixmap)

        self.widgetLayout = QGridLayout()
        self.widget.setLayout(self.widgetLayout)

        self.widgetLayout.addWidget(self.logoIamgeLabel, 0, 1)

        # 多界面
        # QListWidget + QStackedWidget实现
        self.leftListWidget = QListWidget()  # 左侧选项列表
        self.leftListWidget.setObjectName('leftListWidget')
        self.rightWidget = QStackedWidget()  # 右侧框体
        self.rightWidget.setObjectName('rightWidget')

        self.leftWidgetLayout.addWidget(self.leftListWidget)

        self.workWidgetLayout.addWidget(self.leftWidget)
        self.workWidgetLayout.addWidget(self.rightWidget)

        # ********左侧选项列表布局以及设置******************************
        # 设置左侧选项列表大小
        self.leftListWidget.setMinimumWidth(Const.LEFTWIDGET_WIDTH)
        # 左侧选项列表与右侧框体的index对应绑定
        self.leftListWidget.currentRowChanged.connect(self.rightWidget.setCurrentIndex)
        # 去掉边框
        self.leftListWidget.setFrameShape(QListWidget.NoFrame)
        # 隐藏滚动条
        self.leftListWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.leftListWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        list_str = ['智能识别', '公式生成器', '学习资源区', '设置', '关于']

        # 左侧选项添加
        for i in range(5):
            self.item = QListWidgetItem(list_str[i], self.leftListWidget)
            self.item.setSizeHint(QSize(Const.ITEM_WIDTH, Const.ITEM_HEIGHT))
            # 居中显示
            self.item.setTextAlignment(Qt.AlignCenter)

        # 设置默认选中item[1]
        self.leftListWidget.setCurrentRow(0)

        # ********右侧主框体布局以及设置**********************************
        self.rightForm1 = RightForm1()
        self.rightForm2 = RightForm2()
        self.rightForm3 = RightForm3()
        self.rightForm4 = RightForm4()
        self.rightForm5 = RightForm5()
        self.rightWidget.addWidget(self.rightForm1)
        self.rightWidget.addWidget(self.rightForm2)
        self.rightWidget.addWidget(self.rightForm3)
        self.rightWidget.addWidget(self.rightForm4)
        self.rightWidget.addWidget(self.rightForm5)

        # #############################################################
        # 消息通知框
        self.messageInform = MesageFrame()
        self.messageInform.setObjectName('messageInform')
        # 消息通知框默认隐藏
        self.messageInform.hide()

        self.mainSpiltter.addWidget(self.messageInform)

        # *****侧边栏*****
        # 右侧边栏
        self.rightBar = QFrame()
        self.rightBar.setObjectName('rightBar')
        self.rightBar.setFixedWidth(35)
        self.rightBar.setFrameShape(QFrame.StyledPanel)

        self.rightBarLayout = QVBoxLayout()
        self.rightBar.setLayout(self.rightBarLayout)

        self.workWidgetLayout.addWidget(self.rightBar)

        # 右侧边栏控件

        # 右侧边栏添加控件

        # 下侧边栏
        self.bottomBar = QFrame()
        self.bottomBar.setObjectName('bottomBar')
        self.bottomBar.setMaximumHeight(35)
        self.bottomBar.setFrameShape(QFrame.StyledPanel)

        self.bottomBarLayout = QHBoxLayout()
        self.bottomBarLayout.setAlignment(Qt.AlignRight)  # 右对齐
        self.bottomBar.setLayout(self.bottomBarLayout)

        self.mainSpiltter.addWidget(self.bottomBar)

        # 下侧边栏控件
        # 留白控件
        blank = QLabel(self.bottomBar)
        blank.setObjectName('blank')

        self.informText = QLabel(self.bottomBar)
        self.informText.setObjectName('informText')
        self.informText.setText('通知')

        self.informBtn = QPushButton(self.bottomBar)
        self.informBtn.setObjectName('informBtn')
        self.informBtn.resize(QSize(35, 35))
        self.informBtn.setIcon(QIcon('./image/mainWindowIcon/messageBarBtnIcon/inform0.png'))
        self.informBtn.clicked.connect(lambda: self.open_inform_frame())

        # 下侧边栏添加控件

        self.bottomBarLayout.addWidget(self.informBtn)
        self.bottomBarLayout.addWidget(self.informText)
        self.bottomBarLayout.addWidget(blank)

    # ****************************业务逻辑******************************
    # 右键菜单
    def show_context_menu(self):
        """
        右键点击时调用的函数
        :return:
        """
        # 显示菜单前,将它移动到鼠标点击的位置
        self.contextMenu.exec_(QCursor.pos())

    # 最小化窗口
    def show_mininized_window(self):
        """
        :return:
        """
        self.showMinimized()

    # 最大化窗口
    def show_maximized_window(self):
        """

        :return:
        """
        self.showMaximized()

    # 复原窗口
    def show_restore_window(self):
        """

        :return:
        """
        if self.isMaximized():
            self.showNormal()
        else:
            self.showMaximized()

    # 关闭窗口
    def quit_window(self):
        """

        :return:
        """
        self.close()

    # 打开文件
    def get_image(self):

        """
            getOpenFileName():返回用户所选择文件的名称,并打开该文件
            第一个参数用于指定父组件
            第二个参数指定对话框标题
            第三个参数指定目录
            第四个参数是文件扩展名过滤器
        """
        pass
        # fname, _ = QFileDialog.getOpenFileName(self, '选择图形文件', 'C:\\', "*.jpg *.gif *.png")
        # self.pixmapLabel.setPixmap(QPixmap(fname))

    def get_text(self):
        """

        :return:
        """
        pass
        # # 初始化实例,并设置一些参数
        # # textDialog = QFileDialog()
        # # textDialog.setFileMode(QFileDialog.AnyFile)
        # # textDialog.setFilter(QDir.Files)
        # textDialog = QFileDialog.getOpenFileName(self, '选择文本文件', 'C:\\', "*.txt *.doc *.docx")
        # # 当选择器关闭的时候
        # if textDialog.exec_():
        #     # 拿到所选择的文本
        #     filenames = textDialog.selectedFiles()
        #     # 读取文本内容设置到textEdit中
        #     f = open(filenames[0], 'r')
        #     with f:
        #         data = f.read()
        #         self.textEdit.setText(data)

    def open_inform_frame(self):
        self.messageInform.show()
Exemple #13
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(1010, 754)

        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName(
            _fromUtf8("centralwidget"))  # do not change this name
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        self.splitter_2 = QSplitter(self.centralwidget)
        self.splitter_2.setOrientation(Qt.Vertical)
        self.splitter_2.setObjectName(_fromUtf8("splitter_2"))

        self.MainTabWidget = QTabWidget(self.splitter_2)
        self.MainTabWidget.setObjectName(_fromUtf8("MainTabWidget"))
        self.ScanTab = QWidget()
        self.ScanTab.setObjectName(_fromUtf8("ScanTab"))
        self.gridLayout_2 = QGridLayout(self.ScanTab)
        self.gridLayout_2.setObjectName(_fromUtf8("gridLayout_2"))
        self.splitter = QSplitter(self.ScanTab)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.setObjectName(_fromUtf8("splitter"))

        # size policies
        self.sizePolicy = QSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
        self.sizePolicy.setHorizontalStretch(
            0
        )  # this specifies that the widget will keep its width when the window is resized
        self.sizePolicy.setVerticalStretch(0)

        self.sizePolicy2 = QSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.sizePolicy2.setHorizontalStretch(
            1
        )  # this specifies that the widget will expand its width when the window is resized
        self.sizePolicy2.setVerticalStretch(0)

        self.setupLeftPanel()
        self.setupRightPanel()
        self.setupMainTabs()
        self.setupBottomPanel()

        self.gridLayout.addWidget(self.splitter_2, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        self.setupMenuBar(MainWindow)
        self.retranslateUi(MainWindow)
        self.setDefaultIndexes()
        QMetaObject.connectSlotsByName(MainWindow)

    def setupLeftPanel(self):
        self.HostsTabWidget = QTabWidget(self.splitter)
        self.sizePolicy.setHeightForWidth(
            self.HostsTabWidget.sizePolicy().hasHeightForWidth())
        self.HostsTabWidget.setSizePolicy(self.sizePolicy)
        self.HostsTabWidget.setObjectName(_fromUtf8("HostsTabWidget"))

        self.HostsTab = QWidget()
        self.HostsTab.setObjectName(_fromUtf8("HostsTab"))
        self.keywordTextInput = QLineEdit()
        self.FilterApplyButton = QToolButton()
        self.searchIcon = QIcon()
        self.searchIcon.addPixmap(QPixmap(_fromUtf8("./images/search.png")),
                                  QIcon.Normal, QIcon.Off)
        self.FilterApplyButton.setIconSize(QSize(29, 21))
        self.FilterApplyButton.setIcon(self.searchIcon)
        self.FilterAdvancedButton = QToolButton()
        self.advancedIcon = QIcon()
        self.advancedIcon.addPixmap(
            QPixmap(_fromUtf8("./images/advanced.png")), QIcon.Normal,
            QIcon.Off)
        self.FilterAdvancedButton.setIconSize(QSize(19, 19))
        self.FilterAdvancedButton.setIcon(self.advancedIcon)
        self.vlayout = QVBoxLayout(self.HostsTab)
        self.vlayout.setObjectName(_fromUtf8("vlayout"))
        self.HostsTableView = QTableView(self.HostsTab)
        self.HostsTableView.setObjectName(_fromUtf8("HostsTableView"))
        self.vlayout.addWidget(self.HostsTableView)

        self.addHostsOverlay = QTextEdit(
            self.HostsTab
        )  # the overlay widget that appears over the hosttableview
        self.addHostsOverlay.setObjectName(_fromUtf8("addHostsOverlay"))
        self.addHostsOverlay.setText('Click here to add host(s) to scope')
        self.addHostsOverlay.setReadOnly(True)
        self.addHostsOverlay.setContextMenuPolicy(Qt.NoContextMenu)

        ###
        self.addHostsOverlay.setFont(QFont('', 12))
        self.addHostsOverlay.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        ###

        self.vlayout.addWidget(self.addHostsOverlay)
        self.hlayout = QHBoxLayout()
        self.hlayout.addWidget(self.keywordTextInput)
        self.hlayout.addWidget(self.FilterApplyButton)
        self.hlayout.addWidget(self.FilterAdvancedButton)
        self.vlayout.addLayout(self.hlayout)
        self.HostsTabWidget.addTab(self.HostsTab, _fromUtf8(""))

        self.ServicesLeftTab = QWidget()
        self.ServicesLeftTab.setObjectName(_fromUtf8("ServicesLeftTab"))
        self.horizontalLayout_2 = QHBoxLayout(self.ServicesLeftTab)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.ServiceNamesTableView = QTableView(self.ServicesLeftTab)
        self.ServiceNamesTableView.setObjectName(
            _fromUtf8("ServiceNamesTableView"))
        self.horizontalLayout_2.addWidget(self.ServiceNamesTableView)
        self.HostsTabWidget.addTab(self.ServicesLeftTab, _fromUtf8(""))

        self.ToolsTab = QWidget()
        self.ToolsTab.setObjectName(_fromUtf8("ToolsTab"))
        self.horizontalLayout_3 = QHBoxLayout(self.ToolsTab)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.ToolsTableView = QTableView(self.ToolsTab)
        self.ToolsTableView.setObjectName(_fromUtf8("ToolsTableView"))
        self.horizontalLayout_3.addWidget(self.ToolsTableView)
        self.HostsTabWidget.addTab(self.ToolsTab, _fromUtf8(""))

    def setupRightPanel(self):
        self.ServicesTabWidget = QTabWidget()
        self.ServicesTabWidget.setEnabled(True)
        self.sizePolicy2.setHeightForWidth(
            self.ServicesTabWidget.sizePolicy().hasHeightForWidth())
        self.ServicesTabWidget.setSizePolicy(self.sizePolicy2)
        self.ServicesTabWidget.setObjectName(_fromUtf8("ServicesTabWidget"))
        self.splitter.addWidget(self.ServicesTabWidget)

        ###

        self.splitter_3 = QSplitter()
        self.splitter_3.setOrientation(Qt.Horizontal)
        self.splitter_3.setObjectName(_fromUtf8("splitter_3"))
        self.splitter_3.setSizePolicy(
            self.sizePolicy2
        )  # this makes the tools tab stay the same width when resizing the window

        ###

        self.ToolHostsWidget = QWidget()
        self.ToolHostsWidget.setObjectName(_fromUtf8("ToolHostsTab"))
        self.ToolHostsLayout = QVBoxLayout(self.ToolHostsWidget)
        self.ToolHostsLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.ToolHostsTableView = QTableView(self.ToolHostsWidget)
        self.ToolHostsTableView.setObjectName(_fromUtf8("ServicesTableView"))
        self.ToolHostsLayout.addWidget(self.ToolHostsTableView)
        self.splitter_3.addWidget(self.ToolHostsWidget)

        self.DisplayWidget = QWidget()
        self.DisplayWidget.setObjectName('ToolOutput')
        self.DisplayWidget.setSizePolicy(self.sizePolicy2)
        #self.toolOutputTextView = QTextEdit(self.DisplayWidget)
        self.toolOutputTextView = QPlainTextEdit(self.DisplayWidget)
        self.toolOutputTextView.setReadOnly(True)
        self.DisplayWidgetLayout = QHBoxLayout(self.DisplayWidget)
        self.DisplayWidgetLayout.addWidget(self.toolOutputTextView)
        self.splitter_3.addWidget(self.DisplayWidget)

        self.ScreenshotWidget = ImageViewer()
        self.ScreenshotWidget.setObjectName('Screenshot')
        self.ScreenshotWidget.scrollArea.setSizePolicy(self.sizePolicy2)
        self.ScreenshotWidget.scrollArea.setContextMenuPolicy(
            Qt.CustomContextMenu)
        self.splitter_3.addWidget(self.ScreenshotWidget.scrollArea)

        self.splitter.addWidget(self.splitter_3)

        ###

        self.ServicesRightTab = QWidget()
        self.ServicesRightTab.setObjectName(_fromUtf8("ServicesRightTab"))
        self.verticalLayout = QVBoxLayout(self.ServicesRightTab)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.ServicesTableView = QTableView(self.ServicesRightTab)
        self.ServicesTableView.setObjectName(_fromUtf8("ServicesTableView"))
        self.verticalLayout.addWidget(self.ServicesTableView)
        self.ServicesTabWidget.addTab(self.ServicesRightTab, _fromUtf8(""))

        self.ScriptsTab = QWidget()
        self.ScriptsTab.setObjectName(_fromUtf8("ScriptsTab"))
        self.horizontalLayout_6 = QHBoxLayout(self.ScriptsTab)
        self.horizontalLayout_6.setObjectName(_fromUtf8("horizontalLayout_6"))

        self.splitter_4 = QSplitter(self.ScriptsTab)
        self.splitter_4.setOrientation(Qt.Horizontal)
        self.splitter_4.setObjectName(_fromUtf8("splitter_4"))

        self.ScriptsTableView = QTableView()
        self.ScriptsTableView.setObjectName(_fromUtf8("ScriptsTableView"))
        self.splitter_4.addWidget(self.ScriptsTableView)

        self.ScriptsOutputTextEdit = QPlainTextEdit()
        self.ScriptsOutputTextEdit.setObjectName(
            _fromUtf8("ScriptsOutputTextEdit"))
        self.ScriptsOutputTextEdit.setReadOnly(True)
        self.splitter_4.addWidget(self.ScriptsOutputTextEdit)
        self.horizontalLayout_6.addWidget(self.splitter_4)
        self.ServicesTabWidget.addTab(self.ScriptsTab, _fromUtf8(""))

        self.InformationTab = QWidget()
        self.InformationTab.setObjectName(_fromUtf8("InformationTab"))
        self.ServicesTabWidget.addTab(self.InformationTab, _fromUtf8(""))

        self.NotesTab = QWidget()
        self.NotesTab.setObjectName(_fromUtf8("NotesTab"))
        self.horizontalLayout_4 = QHBoxLayout(self.NotesTab)
        self.horizontalLayout_4.setObjectName(_fromUtf8("horizontalLayout_4"))
        #self.NotesTextEdit = QTextEdit(self.NotesTab)
        self.NotesTextEdit = QPlainTextEdit(self.NotesTab)
        self.NotesTextEdit.setObjectName(_fromUtf8("NotesTextEdit"))
        self.horizontalLayout_4.addWidget(self.NotesTextEdit)
        self.ServicesTabWidget.addTab(self.NotesTab, _fromUtf8(""))

    def setupMainTabs(self):
        self.gridLayout_2.addWidget(self.splitter, 0, 0, 1, 1)
        self.gridLayout_3 = QGridLayout()
        self.gridLayout_3.setObjectName(_fromUtf8("gridLayout_3"))
        self.gridLayout_2.addLayout(self.gridLayout_3, 0, 0, 1, 1)
        self.MainTabWidget.addTab(self.ScanTab, _fromUtf8(""))

        self.BruteTab = QWidget()
        self.BruteTab.setObjectName(_fromUtf8("BruteTab"))
        self.horizontalLayout_7 = QHBoxLayout(self.BruteTab)
        self.horizontalLayout_7.setObjectName(_fromUtf8("horizontalLayout_7"))
        self.BruteTabWidget = QTabWidget(self.BruteTab)
        self.BruteTabWidget.setObjectName(_fromUtf8("BruteTabWidget"))
        self.horizontalLayout_7.addWidget(self.BruteTabWidget)
        self.MainTabWidget.addTab(self.BruteTab, _fromUtf8(""))

    def setupBottomPanel(self):
        self.BottomTabWidget = QTabWidget(self.splitter_2)
        self.BottomTabWidget.setSizeIncrement(QSize(0, 0))
        self.BottomTabWidget.setBaseSize(QSize(0, 0))
        self.BottomTabWidget.setObjectName(_fromUtf8("BottomTabWidget"))

        self.LogTab = QWidget()
        self.LogTab.setObjectName(_fromUtf8("LogTab"))
        self.horizontalLayout_5 = QHBoxLayout(self.LogTab)
        self.horizontalLayout_5.setObjectName(_fromUtf8("horizontalLayout_5"))
        self.ProcessesTableView = QTableView(self.LogTab)
        self.ProcessesTableView.setObjectName(_fromUtf8("ProcessesTableView"))
        self.horizontalLayout_5.addWidget(self.ProcessesTableView)
        self.BottomTabWidget.addTab(self.LogTab, _fromUtf8(""))


#       self.TerminalTab = QWidget()
#       self.TerminalTab.setObjectName(_fromUtf8("TerminalTab"))
#       self.BottomTabWidget.addTab(self.TerminalTab, _fromUtf8(""))
#       self.PythonTab = QWidget()
#       self.PythonTab.setObjectName(_fromUtf8("PythonTab"))
#       self.BottomTabWidget.addTab(self.PythonTab, _fromUtf8(""))

    def setupMenuBar(self, MainWindow):
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setGeometry(QRect(0, 0, 1010, 25))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        self.menuFile = QMenu(self.menubar)
        self.menuFile.setObjectName(_fromUtf8("menuFile"))
        #       self.menuEdit = QMenu(self.menubar)
        #       self.menuEdit.setObjectName(_fromUtf8("menuEdit"))
        #        self.menuSettings = QMenu(self.menubar)
        #        self.menuSettings.setObjectName(_fromUtf8("menuSettings"))
        self.menuHelp = QMenu(self.menubar)
        self.menuHelp.setObjectName(_fromUtf8("menuHelp"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.actionExit = QAction(MainWindow)
        self.actionExit.setObjectName(_fromUtf8("actionExit"))
        self.actionOpen = QAction(MainWindow)
        self.actionOpen.setObjectName(_fromUtf8("actionOpen"))
        self.actionSave = QAction(MainWindow)
        self.actionSave.setObjectName(_fromUtf8("actionSave"))
        self.actionImportNmap = QAction(MainWindow)
        self.actionImportNmap.setObjectName(_fromUtf8("actionImportNmap"))
        self.actionSaveAs = QAction(MainWindow)
        self.actionSaveAs.setObjectName(_fromUtf8("actionSaveAs"))
        self.actionNew = QAction(MainWindow)
        self.actionNew.setObjectName(_fromUtf8("actionNew"))
        self.actionAddHosts = QAction(MainWindow)
        self.actionAddHosts.setObjectName(_fromUtf8("actionAddHosts"))
        self.menuFile.addAction(self.actionNew)
        self.menuFile.addAction(self.actionOpen)
        self.menuFile.addAction(self.actionSave)
        self.menuFile.addAction(self.actionSaveAs)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.actionAddHosts)
        self.menuFile.addAction(self.actionImportNmap)
        self.menuFile.addSeparator()
        self.menuFile.addAction(self.actionExit)
        self.menubar.addAction(self.menuFile.menuAction())
        #       self.menubar.addAction(self.menuEdit.menuAction())
        #       self.menubar.addAction(self.menuSettings.menuAction())
        #        self.menubar.addAction(self.menuSettings.menuAction())
        #        self.actionSettings = QAction(MainWindow)
        #        self.actionSettings.setObjectName(_fromUtf8("getSettingsMenu"))
        #        self.menuSettings.addAction(self.actionSettings)

        self.actionHelp = QAction(MainWindow)
        self.actionHelp.setObjectName(_fromUtf8("getHelp"))
        self.menuHelp.addAction(self.actionHelp)
        self.menubar.addAction(self.menuHelp.menuAction())

    def setDefaultIndexes(self):
        self.MainTabWidget.setCurrentIndex(1)
        self.HostsTabWidget.setCurrentIndex(1)
        self.ServicesTabWidget.setCurrentIndex(1)
        self.BruteTabWidget.setCurrentIndex(1)
        self.BottomTabWidget.setCurrentIndex(0)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(
            QApplication.translate("MainWindow", "SPARTA 2.0", None))
        self.HostsTabWidget.setTabText(
            self.HostsTabWidget.indexOf(self.HostsTab),
            QApplication.translate("MainWindow", "Hosts", None))
        self.HostsTabWidget.setTabText(
            self.HostsTabWidget.indexOf(self.ServicesLeftTab),
            QApplication.translate("MainWindow", "Services", None))
        self.HostsTabWidget.setTabText(
            self.HostsTabWidget.indexOf(self.ToolsTab),
            QApplication.translate("MainWindow", "Tools", None))
        self.ServicesTabWidget.setTabText(
            self.ServicesTabWidget.indexOf(self.ServicesRightTab),
            QApplication.translate("MainWindow", "Services", None))
        self.ServicesTabWidget.setTabText(
            self.ServicesTabWidget.indexOf(self.ScriptsTab),
            QApplication.translate("MainWindow", "Scripts", None))
        self.ServicesTabWidget.setTabText(
            self.ServicesTabWidget.indexOf(self.InformationTab),
            QApplication.translate("MainWindow", "Information", None))
        self.ServicesTabWidget.setTabText(
            self.ServicesTabWidget.indexOf(self.NotesTab),
            QApplication.translate("MainWindow", "Notes", None))
        #       self.ServicesTabWidget.setTabText(self.ServicesTabWidget.indexOf(self.ScreenshotsTab), QApplication.translate("MainWindow", "Screenshots", None))
        self.MainTabWidget.setTabText(
            self.MainTabWidget.indexOf(self.ScanTab),
            QApplication.translate("MainWindow", "Scan", None))
        #self.BruteTabWidget.setTabText(self.BruteTabWidget.indexOf(self.tab), QApplication.translate("MainWindow", "Tab 1", None))
        #self.BruteTabWidget.setTabText(self.BruteTabWidget.indexOf(self.tab_2), QApplication.translate("MainWindow", "Tab 2", None))
        self.MainTabWidget.setTabText(
            self.MainTabWidget.indexOf(self.BruteTab),
            QApplication.translate("MainWindow", "Brute", None))
        self.BottomTabWidget.setTabText(
            self.BottomTabWidget.indexOf(self.LogTab),
            QApplication.translate("MainWindow", "Log", None))
        #       self.BottomTabWidget.setTabText(self.BottomTabWidget.indexOf(self.TerminalTab), QApplication.translate("MainWindow", "Terminal", None))
        #       self.BottomTabWidget.setTabText(self.BottomTabWidget.indexOf(self.PythonTab), QApplication.translate("MainWindow", "Python", None))
        self.menuFile.setTitle(
            QApplication.translate("MainWindow", "File", None))
        #       self.menuEdit.setTitle(QApplication.translate("MainWindow", "Edit", None))
        #       self.menuSettings.setTitle(QApplication.translate("MainWindow", "Settings", None))
        self.menuHelp.setTitle(
            QApplication.translate("MainWindow", "Help", None))
        self.actionExit.setText(
            QApplication.translate("MainWindow", "Exit", None))
        self.actionExit.setToolTip(
            QApplication.translate("MainWindow", "Exit the application", None))
        self.actionExit.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+Q", None))
        self.actionOpen.setText(
            QApplication.translate("MainWindow", "Open", None))
        self.actionOpen.setToolTip(
            QApplication.translate("MainWindow",
                                   "Open an existing project file", None))
        self.actionOpen.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+O", None))
        self.actionSave.setText(
            QApplication.translate("MainWindow", "Save", None))
        self.actionSave.setToolTip(
            QApplication.translate("MainWindow", "Save the current project",
                                   None))
        self.actionSave.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+S", None))
        self.actionImportNmap.setText(
            QApplication.translate("MainWindow", "Import nmap", None))
        self.actionImportNmap.setToolTip(
            QApplication.translate("MainWindow", "Import an nmap xml file",
                                   None))
        self.actionImportNmap.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+I", None))
        self.actionSaveAs.setText(
            QApplication.translate("MainWindow", "Save As", None))
        self.actionNew.setText(
            QApplication.translate("MainWindow", "New", None))
        self.actionNew.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+N", None))
        self.actionAddHosts.setText(
            QApplication.translate("MainWindow", "Add host(s) to scope", None))
        self.actionAddHosts.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+H", None))
        #self.actionSettings.setText(QApplication.translate("MainWindow", "Preferences", None))
        self.actionHelp.setText(
            QApplication.translate("MainWindow", "Help", None))
        self.actionHelp.setShortcut(
            QApplication.translate("MainWindow", "F1", None))
Exemple #14
0
class QuadView(QWidget):
    def __init__(self, parent, view1, view2, view3, view4=None):
        QWidget.__init__(self, parent)

        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        self.installEventFilter(self)

        self.dockableContainer = []

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

        self.splitVertical = QSplitter(Qt.Vertical, self)
        self.layout.addWidget(self.splitVertical)
        self.splitHorizontal1 = QSplitter(Qt.Horizontal, self.splitVertical)
        self.splitHorizontal1.setObjectName("splitter1")
        self.splitHorizontal2 = QSplitter(Qt.Horizontal, self.splitVertical)
        self.splitHorizontal2.setObjectName("splitter2")
        self.splitHorizontal1.splitterMoved.connect(self.horizontalSplitterMoved)
        self.splitHorizontal2.splitterMoved.connect(self.horizontalSplitterMoved)

        self.imageView2D_1 = view1

        self.imageView2D_2 = view2

        self.imageView2D_3 = view3

        self.dock1_ofSplitHorizontal1 = ImageView2DDockWidget(self.imageView2D_1)
        self.dock1_ofSplitHorizontal1.connectHud()
        self.dockableContainer.append(self.dock1_ofSplitHorizontal1)
        self.dock1_ofSplitHorizontal1.onDockButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_dock(arg)
        )
        self.dock1_ofSplitHorizontal1.onMaxButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_max(arg)
        )
        self.dock1_ofSplitHorizontal1.onMinButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal1: self.on_min(arg)
        )
        self.splitHorizontal1.addWidget(self.dock1_ofSplitHorizontal1)

        self.dock2_ofSplitHorizontal1 = ImageView2DDockWidget(self.imageView2D_2)
        self.dock2_ofSplitHorizontal1.onDockButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_dock(arg)
        )
        self.dock2_ofSplitHorizontal1.onMaxButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_max(arg)
        )
        self.dock2_ofSplitHorizontal1.onMinButtonClicked.connect(
            lambda arg=self.dock2_ofSplitHorizontal1: self.on_min(arg)
        )
        self.dock2_ofSplitHorizontal1.connectHud()
        self.dockableContainer.append(self.dock2_ofSplitHorizontal1)
        self.splitHorizontal1.addWidget(self.dock2_ofSplitHorizontal1)

        self.dock1_ofSplitHorizontal2 = ImageView2DDockWidget(self.imageView2D_3)
        self.dock1_ofSplitHorizontal2.onDockButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_dock(arg)
        )
        self.dock1_ofSplitHorizontal2.onMaxButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_max(arg)
        )
        self.dock1_ofSplitHorizontal2.onMinButtonClicked.connect(
            lambda arg=self.dock1_ofSplitHorizontal2: self.on_min(arg)
        )
        self.dock1_ofSplitHorizontal2.connectHud()
        self.dockableContainer.append(self.dock1_ofSplitHorizontal2)
        self.splitHorizontal2.addWidget(self.dock1_ofSplitHorizontal2)

        self.dock2_ofSplitHorizontal2 = ImageView2DDockWidget(view4)
        self.dockableContainer.append(self.dock2_ofSplitHorizontal2)
        self.splitHorizontal2.addWidget(self.dock2_ofSplitHorizontal2)

        # this is a hack: with 0 ms it does not work...
        QTimer.singleShot(250, self._resizeEqual)

    def _resizeEqual(self):
        if not all([dock.isVisible() for dock in self.dockableContainer]):
            return
        w, h = (
            self.size().width() - self.splitHorizontal1.handleWidth(),
            self.size().height() - self.splitVertical.handleWidth(),
        )

        self.splitVertical.setSizes([h // 2, h // 2])

        if self.splitHorizontal1.count() == 2 and self.splitHorizontal2.count() == 2:
            # docks = [self.imageView2D_1, self.imageView2D_2, self.imageView2D_3, self.testView4]
            docks = []
            for splitter in [self.splitHorizontal1, self.splitHorizontal2]:
                for i in range(splitter.count()):
                    docks.append(splitter.widget(i).graphicsView)

            w1 = [docks[i].minimumSize().width() for i in [0, 2]]
            w2 = [docks[i].minimumSize().width() for i in [1, 3]]
            wLeft = max(w1)
            wRight = max(w2)
            if wLeft > wRight and wLeft > w // 2:
                wRight = w - wLeft
            elif wRight >= wLeft and wRight > w // 2:
                wLeft = w - wRight
            else:
                wLeft = w // 2
                wRight = w // 2
            self.splitHorizontal1.setSizes([wLeft, wRight])
            self.splitHorizontal2.setSizes([wLeft, wRight])

    def eventFilter(self, obj, event):
        if event.type() in [QEvent.WindowActivate, QEvent.Show]:
            self._synchronizeSplitter()
        return False

    def _synchronizeSplitter(self):
        sizes1 = self.splitHorizontal1.sizes()
        sizes2 = self.splitHorizontal2.sizes()
        if len(sizes1) > 0 and sizes1[0] > 0:
            self.splitHorizontal2.setSizes(sizes1)
        elif len(sizes2) > 0 and sizes2[0] > 0:
            self.splitHorizontal1.setSizes(sizes2)

    def resizeEvent(self, event):
        QWidget.resizeEvent(self, event)
        self._synchronizeSplitter()

    def horizontalSplitterMoved(self, x, y):
        if self.splitHorizontal1.count() != 2 or self.splitHorizontal2.count() != 2:
            return
        sizes = self.splitHorizontal1.sizes()
        # What. Nr2
        if self.splitHorizontal2.closestLegalPosition(x, y) < self.splitHorizontal2.closestLegalPosition(x, y):
            sizeLeft = self.splitHorizontal1.closestLegalPosition(x, y)
        else:
            sizeLeft = self.splitHorizontal2.closestLegalPosition(x, y)

        sizeRight = sizes[0] + sizes[1] - sizeLeft
        sizes = [sizeLeft, sizeRight]

        self.splitHorizontal1.setSizes(sizes)
        self.splitHorizontal2.setSizes(sizes)

    def addStatusBar(self, bar):
        self.statusBar = bar
        self.layout.addLayout(self.statusBar)

    def setGrayScaleToQuadStatusBar(self, gray):
        self.quadViewStatusBar.setGrayScale(gray)

    def setMouseCoordsToQuadStatusBar(self, x, y, z):
        self.quadViewStatusBar.setMouseCoords(x, y, z)

    def ensureMaximized(self, axis):
        """
        Maximize the view for the given axis if it isn't already maximized.
        """
        axisDict = {
            0: self.dock2_ofSplitHorizontal1,  # x
            1: self.dock1_ofSplitHorizontal2,  # y
            2: self.dock1_ofSplitHorizontal1,
        }  # z

        if not axisDict[axis]._isMaximized:
            self.switchMinMax(axis)

    def ensureMinimized(self, axis):
        """
        Minimize the view for the given axis if it isn't already minimized.
        """
        axisDict = {
            0: self.dock2_ofSplitHorizontal1,  # x
            1: self.dock1_ofSplitHorizontal2,  # y
            2: self.dock1_ofSplitHorizontal1,
        }  # z

        if axisDict[axis]._isMaximized:
            self.switchMinMax(axis)

    def switchMinMax(self, axis):
        """Switch an AxisViewWidget between from minimized to maximized and vice
        versa.

        Keyword arguments:
        axis -- the axis which is represented by the widget (no default)
                either string or integer
                'x' - 0
                'y' - 1
                'z' - 2
        """

        # TODO: get the mapping information from where it is set! if this is not
        # done properly - do it properly

        if type(axis) == str:
            axisDict = {
                "x": self.dock2_ofSplitHorizontal1,  # x
                "y": self.dock1_ofSplitHorizontal2,  # y
                "z": self.dock1_ofSplitHorizontal1,
            }  # z
        elif type(axis) == int:
            axisDict = {
                0: self.dock2_ofSplitHorizontal1,  # x
                1: self.dock1_ofSplitHorizontal2,  # y
                2: self.dock1_ofSplitHorizontal1,
            }  # z

        dockWidget = axisDict.pop(axis)
        for dWidget in list(axisDict.values()):
            if dWidget._isMaximized:
                dWidget.graphicsView._hud.maximizeButtonClicked.emit()
        dockWidget.graphicsView._hud.maximizeButtonClicked.emit()

    def switchXMinMax(self):
        self.switchMinMax("x")

    def switchYMinMax(self):
        self.switchMinMax("y")

    def switchZMinMax(self):
        self.switchMinMax("z")

    def on_dock(self, dockWidget):
        if dockWidget._isDocked:
            dockWidget.undockView()
            self.on_min(dockWidget)
            dockWidget.minimizeView()
        else:
            dockWidget.dockView()

    def on_max(self, dockWidget):
        dockWidget.setVisible(True)
        for dock in self.dockableContainer:
            if not dockWidget == dock:
                dock.setVisible(False)

        # Force sizes to be updated now
        QApplication.processEvents()

        # On linux, the vertical splitter doesn't seem to refresh unless we do so manually
        # Presumably, this is a QT bug.
        self.splitVertical.refresh()

        # Viewport doesn't update automatically...
        view = dockWidget.graphicsView
        view.viewport().setGeometry(view.rect())

    def on_min(self, dockWidget):

        for dock in self.dockableContainer:
            dock.setVisible(True)

        # Force sizes to be updated now
        QApplication.processEvents()
        self._resizeEqual()

        # Viewports don't update automatically...
        for dock in self.dockableContainer:
            view = dock.graphicsView
            if hasattr(view, "viewport"):
                view.viewport().setGeometry(view.rect())
Exemple #15
0
class BrowserWindow(QMainWindow):
    class SavedWindow(object):
        def __init__(self, window=None):
            '''
            @param: window BrowserWindow
            '''
            self.windowState = QByteArray()
            self.windowGeometry = QByteArray()
            self.windowUiState = {}  # QString -> QVariant
            self.virtualDesktop = -1
            self.currentTab = -1
            self.tabs = []  # WebTab.SavedTab
            if window:
                self.init(window)

        def init(self, window):
            if window.isFullScreen():
                self.windowState = QByteArray()
            else:
                self.windowState = window.saveState()
            self.windowGeometry = window.saveGeometry()
            self.windowUiState = window._saveUiState()

            tabsCount = window.tabCount()
            for idx in range(tabsCount):
                # TabbedWebView
                webView = window.weView(idx)
                if not webView:
                    continue
                webTab = webView.webTab()
                if not webTab:
                    continue
                tab = WebTab.SavedTab(webTab)
                if not tab.isValid():
                    continue
                if webTab.isCurrentTab():
                    self.currentTab = len(self.tabs)
                self.tabs.append(tab)

        def isValid(self):
            for tab in self.tabs:
                if not tab.isValid():
                    return False
            return self.currentTab > -1

        def clear(self):
            self.windowState.clear()
            self.windowGeometry.clear()
            self.virtualDesktop = -1
            self.currentTab = -1
            self.tabs.clear()

    def __init__(self, type_, startUrl=QUrl()):
        super().__init__(None)
        self._startUrl = startUrl
        self._homepage = QUrl()
        self._windowType = type_
        self._startTab = None  # WebTab
        self._startPage = None  # WebPage
        self._mainLayout = None  # QVBoxLayout
        self._mainSplitter = None  # QSplitter
        self._tabWidget = None  # TabWidget
        self._sideBar = None  # QPointer<SideBar>
        self._sideBarManager = SideBarManager(self)
        self._statusBar = None

        self._navigationContainer = None  # NavigationContainer
        self._navigationToolbar = None  # NavigationBar
        self._bookmarksToolbar = None  # BookmarksToolbar

        self._progressBar = None  # ProgressBar
        self._ipLabel = None  # QLabel
        self._superMenu = None  # QMenu
        self._mainMenu = None  # MainMenu

        self._tabModel = None  # TabModel
        self._tabMruModel = None  # TabMruModel

        self._sideBarWidth = 0
        self._webViewWidth = 0

        # Shortcuts
        self._useTabNumberShortcuts = False
        self._useSpeedDialNumberShortcuts = False
        self._useSingleKeyShortcuts = False

        # Remember visibility of menubar and statusbar after entering Fullscreen
        self._menuBarVisible = False
        self._statusBarVisible = False
        self._htmlFullScreenView = None  # TabbedWebView
        self._hideNavigationTimer = None  # QTimer

        self._deleteOnCloseWidgets = []  # QList<QPointer<QWidget>>

        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setAttribute(Qt.WA_DontCreateNativeAncestors)

        self.setObjectName('mainwindow')
        self.setWindowTitle(const.APPNAME)
        self.setProperty('private', gVar.app.isPrivate())

        self._setupUi()
        self._setupMenu()

        self._hideNavigationTimer = QTimer(self)
        self._hideNavigationTimer.setInterval(1000)
        self._hideNavigationTimer.setSingleShot(True)
        self._hideNavigationTimer.timeout.connect(self._hideNavigationSlot)

        gVar.app.settingsReloaded.connect(self._loadSettings)

        QTimer.singleShot(0, self._postLaunch)

        if gVar.app.isPrivate():
            gVar.appTools.setWmClass(
                '%s Browser (Private Window)' % const.APPNAME, self)
        else:
            gVar.appTools.setWmClass('%s Browser' % const.APPNAME, self)

    def __del__(self):
        gVar.app.plugins().emitMainWindowDeleted(self)
        for widget in self._deleteOnCloseWidgets:
            widget.deleteLater()

    def setStartTab(self, tab):
        '''
        @param: tab WebTab
        '''
        self._startTab = tab

    def setStartPage(self, page):
        '''
        @param: page WebPage
        '''
        self._startPage = page

    def restoreWindow(self, window):
        '''
        @param: window SavedWindow
        '''
        self.restoreState(window.windowState)
        self.restoreGeometry(window.windowGeometry)
        self._restoreUiState(window.windowUiState)
        if not gVar.app.isTestModeEnabled():
            self.show(
            )  # Window has to be visible before adding QWebEngineView's
        self._tabWidget.restoreState(window.tabs, window.currentTab)
        self._updateStartupFocus()

    def fullScreenNavigationVisible(self):
        return self._navigationContainer.isVisible()

    def showNavigationWithFullScreen(self):
        if self._htmlFullScreenView:
            return
        if self._hideNavigationTimer.isActive():
            self._hideNavigationTimer.stop()
        self._navigationContainer.show()

    def hideNavigationWithFullScreen(self):
        if self._tabWidget.isCurrentTabFresh():
            return
        if not self._hideNavigationTimer.isActive():
            self._hideNavigationTimer.start()

    def currentTabChanged(self):
        view = self.weView()
        self._navigationToolbar.setCurrentView(view)
        if not view:
            return

        title = view.webTab().title(True)  # allowEmpty
        if not title:
            self.setWindowTitle(const.APPNAME)
        else:
            self.setWindowTitle('%s - %s' % (title, const.APPNAME))
        self._ipLabel.setText(view.getIp())
        view.setFocus()

        self.updateLoadingActions()

        # Settings correct tab order (LocationBar -> WebSearchBar -> WebView)
        self.setTabOrder(self.locationBar(),
                         self._navigationToolbar.webSearchBar())
        self.setTabOrder(self._navigationToolbar.webSearchBar(), view)

    def updateLoadingActions(self):
        view = self.weView()
        if not view:
            return

        isLoading = view.isLoading()
        self._ipLabel.setVisible(not isLoading)
        self._progressBar.setVisible(isLoading)
        self.action('View/Stop').setEnabled(isLoading)
        self.action('View/Reload').setEnabled(not isLoading)

        if isLoading:
            self._progressBar.setValue(view.loadingProgress())
            self._navigationToolbar.showStopButton()
        else:
            self._navigationToolbar.showReloadButton()

    def addBookmark(self, url, title):
        BookmarksTools.addBookmarkDilaog(self, url, title)

    def addDeleteOnCloseWidget(self, widget):
        '''
        @param: widget QWidget
        '''
        if widget not in self._deleteOnCloseWidgets:
            self._deleteOnCloseWidgets.append(widget)

    def createToolbarsMenu(self, menu):
        self.removeActions(menu.actions())
        menu.clear()

        action = menu.addAction('&Menu Bar', self.toggleShowMenubar)
        action.setCheckable(True)
        action.setChecked(self.menuBar().isVisible())

        action = menu.addAction('&Navigation Toolbar',
                                self.toggleShowNavigationToolbar)
        action.setCheckable(True)
        action.setChecked(self._navigationToolbar.isVisible())

        action = menu.addAction('&Bookmarks Toolbar',
                                self.toggleShowBookmarksToolbar)
        action.setCheckable(True)
        action.setChecked(Settings().value(
            'Browser-View-Settings/showBookmarksToolbar', True))

        menu.addSeparator()

        action = menu.addAction('&Tabs on Top', self.toggleTabsOnTop)
        action.setCheckable(True)
        action.setChecked(gVar.appSettings.tabsOnTop)

        self.addActions(menu.actions())

    def createSidebarsMenu(self, menu):
        self._sideBarManager.createMenu(menu)

    def createEncodingMenu(self, menu):
        isoCodecs = []
        utfCodecs = []
        windowsCodecs = []
        isciiCodecs = []
        ibmCodecs = []
        otherCodecs = []
        allCodecs = []

        for mib in QTextCodec.availableMibs():
            codecName = QTextCodec.codecForMib(mib).name()
            codecName = codecName.data().decode('utf8')
            if codecName in allCodecs:
                continue
            allCodecs.append(codecName)
            if codecName.startswith('ISO'):
                isoCodecs.append(codecName)
            elif codecName.startswith('UTF'):
                utfCodecs.append(codecName)
            elif codecName.startswith('windows'):
                windowsCodecs.append(codecName)
            elif codecName.startswith('Iscii'):
                isciiCodecs.append(codecName)
            elif codecName.startswith('IBM'):
                ibmCodecs.append(codecName)
            else:
                otherCodecs.append(codecName)

        if not menu.isEmpty():
            menu.addSeperator()

        self._createEncodingSubMenu('ISO', isoCodecs, menu)
        self._createEncodingSubMenu('UTF', utfCodecs, menu)
        self._createEncodingSubMenu('Windows', windowsCodecs, menu)
        self._createEncodingSubMenu('Iscii', isciiCodecs, menu)
        self._createEncodingSubMenu('IBM', ibmCodecs, menu)
        self._createEncodingSubMenu('Other', otherCodecs, menu)

    def removeActions(self, actions):
        '''
        @param: actions QList<QAction*>
        '''
        for action in actions:
            self.removeAction(action)

    def addSideBar(self):
        '''
        @return SideBar*
        '''
        if self._sideBar:
            return self._sideBar
        self._sideBar = SideBar(self._sideBarManager, self)
        self._mainSplitter.insertWidget(0, self._sideBar)
        self._mainSplitter.setCollapsible(0, False)
        self._mainSplitter.setSizes([self._sideBarWidth, self._webViewWidth])
        return self._sideBar

    def setSideBarNone(self):
        '''
        @note: when sideBar is notified destroyed, we should clean python ref in
        window
        '''
        self._sideBar = None

    def saveSideBarSettings(self):
        if self._sideBar:
            # That +1 is important here, without it, the sidebar width would
            # decrease by 1 pixel every close
            self._sideBarWidth = self._mainSplitter.sizes()[0] + 1
            self._webViewWidth = self.width() - self._sideBarWidth
        Settings().setValue('Browser-View-Settings/SideBar',
                            self._sideBarManager.activeSideBar())

    def tabCount(self):
        return self._tabWidget.count()

    def weView(self, index=None):
        '''
        @return TabbedWebView
        '''

        if index is None:
            index = self._tabWidget.currentIndex()
        webTab = self._tabWidget.widget(index)
        if not webTab:
            return None
        return webTab.webView()

    def windowType(self):
        '''
        @return const.BrowserWindowType
        '''
        return self._windowType

    def locationBar(self):
        '''
        @return LocationBar
        '''
        return self._tabWidget.locationBars().currentWidget()

    def tabWidget(self):
        return self._tabWidget

    def bookmarksToolbar(self):
        '''
        @return BookmarksToolbar
        '''
        return self._bookmarksToolbar

    def statusBar(self):
        '''
        @return StatusBar
        '''
        return self._statusBar

    def navigationBar(self):
        '''
        @return NavigationBar
        '''
        return self._navigationToolbar

    def sideBarManager(self):
        '''
        @return SideBarManager
        '''
        return self._sideBarManager

    def ipLabel(self):
        '''
        @return QLabel
        '''
        return self._ipLabel

    def superMenu(self):
        '''
        @return QMenu
        '''
        return self._superMenu

    def homepageUrl(self):
        return self._homepage

    def action(self, name):
        '''
        @return QAction
        '''
        return self._mainMenu.action(name)

    def tabModel(self):
        '''
        @return TabModel
        '''
        return self._tabModel

    def tabMruModel(self):
        '''
        @return TabMruModel
        '''
        return self._tabMruModel

    # public Q_SIGNALS:
    startingCompleted = pyqtSignal()
    aboutToClose = pyqtSignal()

    # public Q_SLOTS:
    def addTab(self):
        self._tabWidget.addViewByUrl(QUrl(), const.NT_SelectedNewEmptyTab,
                                     True)
        self._tabWidget.setCurrentTabFresh(True)

        if self.isFullScreen():
            self.showNavigationWithFullScreen()

    def goHome(self):
        self.loadAddress(self._homepage)

    def goHomeInNewTab(self):
        self._tabWidget.addViewByUrl(self._homepage, const.NT_SelectedTab)

    def goBack(self):
        self.weView().back()

    def goForward(self):
        self.weView().forward()

    def reload(self):
        self.weView().reload()

    def reloadBypassCache(self):
        self.weView().reloadBypassCache()

    def setWindowTitle(self, title):
        if gVar.app.isPrivate():
            title = '%s (Private Browsing)' % title
        super().setWindowTitle(title)

    def showWebInspector(self):
        webView = self.weView()
        if webView and webView.webTab():
            webView.webTab().showWebInspector()

    def toggleWebInspector(self):
        webView = self.weView()
        if webView and webView.webTab():
            webView.webTab().toggleWebInspector()

    def showHistoryManager(self):
        gVar.app.browsingLibrary().showHistory(self)

    def toggleShowMenubar(self):
        self.setUpdatesEnabled(False)
        menuBar = self.menuBar()
        menuBar.setVisible(not menuBar.isVisible())
        self._navigationToolbar.setSuperMenuVisible(not menuBar.isVisible())
        self.setUpdatesEnabled(True)

        Settings().setValue('Browser-View-Settings/showMenuBar',
                            menuBar.isVisible())

        # Make sure we show Navigation Toolbar when Menu Bar is hidden
        if not self._navigationToolbar.isVisible() and not menuBar.isVisible():
            self.toggleShowNavigationToolbar()

    def toggleShowStatusBar(self):
        self.setUpdatesEnabled(False)
        self._statusBar.setVisible(not self._statusBar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showStatusBar',
                            self._statusBar.isVisible())

    def toggleShowBookmarksToolbar(self):
        self.setUpdatesEnabled(False)
        self._bookmarksToolbar.setVisible(
            not self._bookmarksToolbar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showBookmarksToolbar',
                            self._bookmarksToolbar.isVisible())
        Settings().setValue('Browser-View-Settings/instantBookmarksToolbar',
                            False)

    def toggleShowNavigationToolbar(self):
        self.setUpdatesEnabled(False)
        self._navigationToolbar.setVisible(
            not self._navigationToolbar.isVisible())
        self.setUpdatesEnabled(True)
        Settings().setValue('Browser-View-Settings/showNavigationToolbar',
                            self._navigationToolbar.isVisible())

        # Make sure we show Navigation Toolbar when Menu Bar is hidden
        if not self._navigationToolbar.isVisible() and not self.menuBar(
        ).isVisible():
            self.toggleShowMenubar()

    def toggleTabsOnTop(self, enable):
        gVar.appSettings.tabsOnTop = enable
        self._navigationContainer.toggleTabsOnTop(enable)

    def toggleFullScreen(self):
        if self._htmlFullScreenView:
            self.weView().triggerPageAction(QWebEnginePage.ExitFullScreen)
            return
        if self.isFullScreen():
            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
        else:
            self.setWindowState(self.windowState() | Qt.WindowFullScreen)

    def requestHtmlFullScreen(self, view, enable):
        '''
        @param: view TabbedWebView
        @param: enable bool
        '''
        if enable:
            self.setWindowState(self.windowState() | Qt.WindowFullScreen)
        else:
            self.setWindowState(self.windowState() & ~Qt.WindowFullScreen)
        if self._sideBar:
            self._sideBar.setHidden(enable)
        self._htmlFullScreenView = enable and view or None

    def loadActionUrl(self, obj=None):
        if not obj:
            obj = self.sender()
        action = obj
        if isinstance(action, QAction):
            self.loadAddress(action.data().toUrl())

    def loadActionUrlInNewTab(self, obj=None):
        if not obj:
            obj = self.sender()
        action = obj
        if isinstance(action, QAction):
            self.loadAddress(action.data().toUrl(),
                             const.NT_SelectedTabAtTheEnd)

    def bookmarkPage(self):
        view = self.weView()
        BookmarksTools.addBookmarkDialog(self, view.url(), view.title())

    def bookmarkAllTabs(self):
        BookmarksTools.bookmarkAllTabsDialog(self, self._tabWidget)

    def loadAddress(self, url):
        webView = self.weView()
        if webView.webTab().isPinned():
            index = self._tabWidget.addViewByUrl(
                url, gVar.appSettings.newTabPosition)
            self.weView(index).setFocus()
        else:
            webView.setFocus()
            webView.loadByReq(LoadRequest(url))

    def showSource(self, view=None):
        if not view:
            view = self.weView()
        if not view:
            return
        view.showSource()

    # private Q_SLOTS:
    def _openLocation(self):
        if self.isFullScreen():
            self.showNavigationWithFullScreen()
        self.locationBar().setFocus()
        self.locationBar().selectAll()

    def _openFile(self):
        fileTypes = ("%s(*.html *.htm *.shtml *.shtm *.xhtml);;"
                     "%s(*.png *.jpg *.jpeg *.bmp *.gif *.svg *.tiff);;"
                     "%s(*.txt);;"
                     "%s(*.*)")
        fileTypes %= ("HTML files", "Image files", "Text files", "All files")
        filePath = gVar.appTools.getOpenFileName("MainWindow-openFile",
                                                 self, "Open file...",
                                                 QDir.homePath(), fileTypes)

        if filePath:
            self.loadAddress(QUrl.fromLocalFile(filePath))

    def _closeWindow(self):
        if const.OS_MAC:
            self.close()
            return
        if gVar.app.windowCount() > 1:
            self.close()

    def _closeTab(self):
        # Don't close pinned tabs with keyboard shortcuts (Ctrl+w, Ctrl+F4)
        webView = self.weView()
        if webView and not webView.webTab().isPinned():
            self._tabWidget.requestCloseTab()

    def _loadSettings(self):
        settings = Settings()
        # Url settings
        settings.beginGroup('Web-URL-Settings')
        self._homepage = settings.value('homepage', 'app:start', type=QUrl)
        settings.endGroup()
        # Browser Window settings
        settings.beginGroup('Browser-View-Settings')
        showStatusBar = settings.value('showStatusBar', False)
        showBookmarksToolbar = settings.value('showBookmarksToolbar', False)
        showNavigationToolbar = settings.value('showNavigationToolbar', True)
        showMenuBar = settings.value('showMenuBar', False)
        # Make sure both menubar and navigationbar are not hidden
        if not showNavigationToolbar:
            showMenuBar = True
            settings.setValue('showMenubar', True)
        settings.endGroup()

        settings.beginGroup('Shortcuts')
        self._useTabNumberShortcuts = settings.value('useTabNumberShortcuts',
                                                     True)
        self._useSpeedDialNumberShortcuts = settings.value(
            'useSpeedDialNumberShortcuts', True)
        self._useSingleKeyShortcuts = settings.value('useSingleKeyShortcuts',
                                                     False)
        settings.endGroup()

        settings.beginGroup('Web-Browser-Settings')
        quitAction = self._mainMenu.action('Standard/Quit')
        if settings.value('closeAppWithCtrlQ', True):
            quitAction.setShortcut(
                gVar.appTools.actionShortcut(QKeySequence.Quit,
                                             QKeySequence('Ctrl+Q')))
        else:
            quitAction.setShortcut(QKeySequence())
        settings.endGroup()

        self._statusBarVisible = showStatusBar
        self.statusBar().setVisible(not self.isFullScreen() and showStatusBar)
        self._bookmarksToolbar.setVisible(showBookmarksToolbar)
        self._navigationToolbar.setVisible(showNavigationToolbar)
        if not const.OS_MACOS:
            self._menuBarVisible = showMenuBar
            self.menuBar().setVisible(not self.isFullScreen() and showMenuBar)
        showSuperMenu = self.isFullScreen() or not showMenuBar
        # TODO: debug code
        showSuperMenu = True
        self._navigationToolbar.setSuperMenuVisible(showSuperMenu)

    def _postLaunch(self):  # noqa C901
        self._loadSettings()
        addTab = True
        startUrl = QUrl()

        from .MainApplication import MainApplication
        afterLaunch = gVar.app.afterLaunch()
        if afterLaunch == MainApplication.OpenBlankPage:
            startUrl = QUrl()
        elif afterLaunch == MainApplication.OpenSpeedDial:
            startUrl = QUrl('app:speeddial')
        elif afterLaunch in (MainApplication.OpenHomePage,
                             MainApplication.RestoreSession,
                             MainApplication.SelectSession):
            startUrl = QUrl(self._homepage)

        if not gVar.app.isTestModeEnabled():
            self.show()

        if self._windowType == const.BW_FirstAppWindow:
            if gVar.app.isStartingAfterCrash():
                addTab = False
                startUrl.clear()
                self._tabWidget.addViewByUrl(QUrl('app:restore'),
                                             const.NT_CleanSelectedTabAtTheEnd)
            elif afterLaunch in (MainApplication.SelectSession,
                                 MainApplication.RestoreSession):
                addTab = self._tabWidget.count() <= 0
        elif self._windowType in (const.BW_NewWindow, const.BW_MacFirstWindow):
            addTab = True
        elif self._windowType == const.BW_OtherRestoredWindow:
            addTab = False

        if not self._startUrl.isEmpty():
            startUrl = QUrl(self._startUrl)
            addTab = True
        if self._startTab:
            addTab = False
            self._tabWidget.addViewByTab(self._startTab, const.NT_SelectedTab)
        if self._startPage:
            addTab = False
            self._tabWidget.addViewByUrl(QUrl())
            self.weView().setPage(self._startPage)
        if addTab:
            self._tabWidget.addViewByUrl(startUrl,
                                         const.NT_CleanSelectedTabAtTheEnd)
            if not startUrl or startUrl == 'app:speeddial':
                self.locationBar().setFocus()
        # Someting went really wrong .. add one tab
        if self._tabWidget.count() <= 0:
            self._tabWidget.addViewByUrl(self._homepage,
                                         const.NT_SelectedTabAtTheEnd)

        gVar.app.plugins().emitMainWindowCreated(self)
        self.startingCompleted.emit()

        self.raise_()
        self.activateWindow()
        self._updateStartupFocus()

    def _webSearch(self):
        self._navigationToolbar.webSearchBar().setFocus()
        self._navigationToolbar.webSearchBar().selectAll()

    def _searchOnPage(self):
        webView = self.weView()
        if webView and webView.webTab():
            searchText = webView.page().selectedText()
            if '\n' not in searchText:
                webView.webTab().showSearchToolBar(searchText)
            else:
                webView.webTab().showSearchToolBar()

    def _changeEncoding(self):
        action = self.sender()
        if action:
            encoding = action.data()
            gVar.app.webSettings().setDefaultTextEncoding(encoding)
            Settings().setValue('Web-Browser-Settings/DefaultEncoding',
                                encoding)
            self.weView().reload()

    def _printPage(self):
        self.weView().printPage()

    def _saveSettings(self):
        if gVar.app.isPrivate():
            return
        settings = Settings()
        settings.beginGroup('Browser-View-Settings')
        settings.setValue('WindowGeometry', self.saveGeometry())

        state = self._saveUiState()
        for key, val in state.items():
            settings.setValue(key, val)

        settings.endGroup()

    def _hideNavigationSlot(self):
        view = self.weView()
        mouseInView = view and view.underMouse()
        if self.isFullScreen() and mouseInView:
            self._navigationContainer.hide()

    # private
    # override
    def event(self, event):
        '''
        @param: event QEvent
        '''
        if event.type() == QEvent.WindowStateChange:
            e = event
            assert (isinstance(e, QWindowStateChangeEvent))
            if not (e.oldState() & Qt.WindowFullScreen) and (
                    self.windowState() & Qt.WindowFullScreen):
                # Enter fullscreen
                self._statusBarVisible = self._statusBar.isVisible()
                if not const.OS_MACOS:
                    self._menuBarVisible = self.menuBar().isVisible()
                    self.menuBar().hide()
                self._statusBar.hide()

                self._navigationContainer.hide()
                self._navigationToolbar.enterFullScreen()

                # Show main menu button since menubar is hidden
                self._navigationToolbar.setSuperMenuVisible(True)
            elif (e.oldState() & Qt.WindowFullScreen
                  ) and not (self.windowState() & Qt.WindowFullScreen):
                # Leave fullscreen
                self._statusBar.setVisible(self._statusBarVisible)
                if not const.OS_MACOS:
                    self.menuBar().setVisible(self._menuBarVisible)

                self._navigationContainer.show()
                self._navigationToolbar.setSuperMenuVisible(
                    not self._menuBarVisible)
                self._navigationToolbar.leaveFullScreen()
                self._htmlFullScreenView = None

            if self._hideNavigationTimer:
                self._hideNavigationTimer.stop()

        return super().event(event)

    # override
    def resizeEvent(self, event):
        '''
        @param: event QResizeEvent
        '''
        self._bookmarksToolbar.setMaximumWidth(self.width())
        super().resizeEvent(event)

    # override
    def keyPressEvent(self, event):  # noqa C901
        '''
        @param: event QKeyEvent
        '''
        if gVar.app.plugins().processKeyPress(const.ON_BrowserWindow, self,
                                              event):
            return

        number = -1
        # TabbedWebView
        view = self.weView()
        evtKey = event.key()

        if evtKey == Qt.Key_Back:
            if view:
                view.back()
                event.accept()

        elif evtKey == Qt.Key_Forward:
            if view:
                view.forward()
                event.accept()

        elif evtKey == Qt.Key_Stop:
            if view:
                view.stop()
                event.accept()

        elif evtKey in (Qt.Key_Reload, Qt.Key_Refresh):
            if view:
                view.reload()
                event.accept()

        elif evtKey == Qt.Key_HomePage:
            self.goHome()
            event.accept()

        elif evtKey == Qt.Key_Favorites:
            gVar.app.browsingLibrary().showBookmarks(self)
            event.accept()

        elif evtKey == Qt.Key_Search:
            self.searchOnPage()
            event.accept()

        elif evtKey in (Qt.Key_F6, Qt.Key_OpenUrl):
            self.openLocation()
            event.accept()

        elif evtKey == Qt.Key_History:
            self.showHistoryManager()
            event.accept()

        elif evtKey == Qt.Key_AddFavorite:
            self.bookmarkPage()
            event.accept()

        elif evtKey == Qt.Key_News:
            self.action("Tools/RssReader").trigger()
            event.accept()

        elif evtKey == Qt.Key_Tools:
            self.action("Standard/Preferences").trigger()
            event.accept()

        elif evtKey == Qt.Key_Tab:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.event(event)

        elif evtKey == Qt.Key_Backtab:
            if event.modifiers() == Qt.ControlModifier + Qt.ShiftModifier:
                self._tabWidget.event(event)

        elif evtKey == Qt.Key_PageDown:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.nextTab()
                event.accept()

        elif evtKey == Qt.Key_PageUp:
            if event.modifiers() == Qt.ControlModifier:
                self._tabWidget.previousTab()
                event.accept()

        elif evtKey == Qt.Key_Equal:
            if view and event.modifiers() == Qt.ControlModifier:
                view.zoomIn()
                event.accept()

        elif evtKey == Qt.Key_I:
            if event.modifiers() == Qt.ControlModifier:
                self.action("Tools/SiteInfo").trigger()
                event.accept()

        elif evtKey == Qt.Key_U:
            if event.modifiers() == Qt.ControlModifier:
                self.action("View/PageSource").trigger()
                event.accept()

        elif evtKey == Qt.Key_F:
            if event.modifiers() == Qt.ControlModifier:
                self.action("Edit/Find").trigger()
                event.accept()

        elif evtKey == Qt.Key_Slash:
            if self._useSingleKeyShortcuts:
                self.action("Edit/Find").trigger()
                event.accept()

        elif evtKey == Qt.Key_1:
            number = 1
        elif evtKey == Qt.Key_2:
            number = 2
        elif evtKey == Qt.Key_3:
            number = 3
        elif evtKey == Qt.Key_4:
            number = 4
        elif evtKey == Qt.Key_5:
            number = 5
        elif evtKey == Qt.Key_6:
            number = 6
        elif evtKey == Qt.Key_7:
            number = 7
        elif evtKey == Qt.Key_8:
            number = 8
        elif evtKey == Qt.Key_9:
            number = 9

        if number != -1:
            modifiers = event.modifiers()
            if modifiers & Qt.AltModifier and self._useTabNumberShortcuts:
                if number == 9:
                    number = self._tabWidget.count()
                self._tabWidget.setCurrentIndex(number - 1)
                event.accept()
                return
            if modifiers & Qt.ControlModifier and self._useSpeedDialNumberShortcuts:
                # QUrl
                url = gVar.app.plugins().speedDial().urlForShortcut(number - 1)
                if url.isValid():
                    self.loadAddress(url)
                    event.accept()
                    return
            if modifiers == Qt.NoModifier and self._useSingleKeyShortcuts:
                if number == 1:
                    self._tabWidget.previousTab()
                if number == 2:
                    self._tabWidget.nextTab()

        super().keyPressEvent(event)

    # override
    def keyReleaseEvent(self, event):
        '''
        @param: event QKeyEvent
        '''
        if gVar.app.plugins().processKeyRelease(const.ON_BrowserWindow, self,
                                                event):
            return

        evtKey = event.key()
        if evtKey == Qt.Key_F:
            if event.modifiers() == Qt.ControlModifier:
                self.action('Edit/Find').trigger()
                event.accept()

        super().keyReleaseEvent(event)

    # override
    def closeEvent(self, event):
        '''
        @param: event QCloseEvent
        '''
        if gVar.app.isClosing():
            self._saveSettings()
            return
        settings = Settings()
        askOnClose = settings.value('Browser-Tabs-Settings/AskOnClosing', True)

        from .MainApplication import MainApplication
        if gVar.app.afterLaunch() in (MainApplication.SelectSession,
                                      MainApplication.RestoreSession
                                      ) and gVar.app.windowCount() == 1:
            askOnClose = False

        if askOnClose and self._tabWidget.normalTabsCount() > 1:
            dialog = CheckBoxDialog(QMessageBox.Yes | QMessageBox.No, self)
            dialog.setDefaultButton(QMessageBox.No)
            dialog.setText(
                "There are still %s open tabs and your session won't be stored.\n"
                % self._tabWidget.count() +
                "Are you sure you want to close this window?")
            dialog.setCheckBoxText("Don't ask again")
            dialog.setWindowTitle('There are still open tabs')
            dialog.setIcon(QMessageBox.Warning)
            if dialog.exec_() != QMessageBox.Yes:
                event.ignore()
                return
            if dialog.isChecked():
                settings.setValue('Browser-Tabs-Settings/AskOnClosing', False)

        self.aboutToClose.emit()

        self._saveSettings()
        gVar.app.closedWindowsManager().saveWindow(self)
        if gVar.app.windowCount() == 1:
            gVar.app.quitApplication()

        event.accept()

    # == private ==
    def _setupUi(self):
        settings = Settings()
        settings.beginGroup('Browser-View-Settings')
        windowGeometry = settings.value('WindowGeometry', b'')

        keys = [
            ('LocationBarWidth', int),
            ('WebSearchBarWidth', int),
            ('SideBarWidth', int),
            ('WebViewWidth', int),
            ('SideBar', str),
        ]

        uiState = {}
        for key, typ in keys:
            if settings.contains(key):
                uiState[key] = typ(settings.value(key))

        settings.endGroup()

        widget = QWidget(self)
        widget.setCursor(Qt.ArrowCursor)
        self.setCentralWidget(widget)

        self._mainLayout = QVBoxLayout(widget)
        self._mainLayout.setContentsMargins(0, 0, 0, 0)
        self._mainLayout.setSpacing(0)
        self._mainSplitter = QSplitter(self)
        self._mainSplitter.setObjectName('sidebar-splitter')
        self._tabWidget = TabWidget(self)
        self._superMenu = QMenu(self)
        self._navigationToolbar = NavigationBar(self)
        self._bookmarksToolbar = BookmarksToolbar(self)

        self._tabModel = TabModel(self, self)
        self._tabMruModel = TabMruModel(self, self)
        self._tabMruModel.setSourceModel(self._tabModel)

        self._navigationContainer = NavigationContainer(self)
        self._navigationContainer.addWidget(self._navigationToolbar)
        self._navigationContainer.addWidget(self._bookmarksToolbar)
        self._navigationContainer.setTabBar(self._tabWidget.tabBar())

        self._mainSplitter.addWidget(self._tabWidget)
        self._mainSplitter.setCollapsible(0, False)

        self._mainLayout.addWidget(self._navigationContainer)
        self._mainLayout.addWidget(self._mainSplitter)

        self._statusBar = StatusBar(self)
        self._statusBar.setObjectName('mainwindow-statusbar')
        self._statusBar.setCursor(Qt.ArrowCursor)
        self.setStatusBar(self._statusBar)
        self._progressBar = ProgressBar(self._statusBar)
        self._ipLabel = QLabel(self)
        self._ipLabel.setObjectName('statusbar-ip-label')
        self._ipLabel.setToolTip('IP Address of current page')

        self._statusBar.addPermanentWidget(self._progressBar)
        self._statusBar.addPermanentWidget(self.ipLabel())

        downloadsButton = DownloadsButton(self)
        self._statusBar.addButton(downloadsButton)
        self._navigationToolbar.addToolButton(downloadsButton)

        desktop = gVar.app.desktop()
        windowWidth = desktop.availableGeometry().width() / 1.3
        windowHeight = desktop.availableGeometry().height() / 1.3

        # Let the WM decides where to put new browser window
        if self._windowType not in (const.BW_FirstAppWindow, const.BW_MacFirstWindow) and \
                gVar.app.getWindow():
            if const.OS_WIN:
                # Windows WM places every new window in the middle of screen .. for some reason
                p = gVar.app.getWindow().geometry().topLeft()
                p.setX(p.x() + 30)
                p.setY(p.y() + 30)
                if not desktop.availableGeometry(
                        gVar.app.getWindow()).contains(p):
                    p.setX(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30)
                    p.setY(
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30)
                self.setGeometry(QRect(p, gVar.app.getWindow().size()))
            else:
                self.resize(gVar.app.getWindow().size())
        elif not self.restoreGeometry(windowGeometry):
            if const.OS_WIN:
                self.setGeometry(
                    QRect(
                        desktop.availableGeometry(gVar.app.getWindow()).x() +
                        30,
                        desktop.availableGeometry(gVar.app.getWindow()).y() +
                        30, windowWidth, windowHeight))
            else:
                self.resize(windowWidth, windowHeight)

        self._restoreUiState(uiState)
        # Set some sane minimum width
        self.setMinimumWidth(300)

    def _setupMenu(self):
        if const.OS_MACOS:
            macMainMenu = None
            if not macMainMenu:
                macMainMenu = MainMenu(self, 0)
                macMainMenu.initMenuBar(QMenuBar(0))
                gVar.app.activeWindowChanged.connect(macMainMenu.setWindow)
            else:
                macMainMenu.setWindow(self)
        else:
            self.setMenuBar(MenuBar(self))
            self._mainMenu = MainMenu(self, self)
            self._mainMenu.initMenuBar(self.menuBar())

        self._mainMenu.initSuperMenu(self._superMenu)

        # Setup other shortcuts
        reloadBypassCacheAction = QShortcut(QKeySequence('Ctrl+F5'), self)
        reloadBypassCacheAction2 = QShortcut(QKeySequence('Ctrl+Shift+R'),
                                             self)
        reloadBypassCacheAction.activated.connect(self.reloadBypassCache)
        reloadBypassCacheAction2.activated.connect(self.reloadBypassCache)

        closeTabAction = QShortcut(QKeySequence('Ctrl+W'), self)
        closeTabAction2 = QShortcut(QKeySequence('Ctrl+F4'), self)

        closeTabAction.activated.connect(self._closeTab)
        closeTabAction2.activated.connect(self._closeTab)

        reloadAction = QShortcut(QKeySequence('Ctrl+R'), self)
        reloadAction.activated.connect(self.reload)

        openLocationAction = QShortcut(QKeySequence('Alt+D'), self)
        openLocationAction.activated.connect(self._openLocation)

        inspectorAction = QShortcut(QKeySequence('F12'), self)
        inspectorAction.activated.connect(self.toggleWebInspector)

        restoreClosedWindow = QShortcut(QKeySequence('Ctrl+Shift+N'), self)
        restoreClosedWindow.activated.connect(
            gVar.app.closedWindowsManager().restoreClosedWindow)

    def _updateStartupFocus(self):
        def _updateStartupFocusCb():
            # Scroll to current tab
            self.tabWidget().tabBar().ensureVisible()
            # Update focus
            page = self.weView().page()
            url = page.requestedUrl()
            if not self._startPage and not LocationBar.convertUrlToText(url):
                self.locationBar().setFocus()
            else:
                self.weView().setFocus()

        QTimer.singleShot(500, _updateStartupFocusCb)

    def _createEncodingAction(self, codecName, activeCodecName, menu):
        '''
        @param: codecName QString
        @param: activeCodecName QString
        @param: menu QMenu
        '''
        action = QAction(codecName, menu)
        action.setData(codecName)
        action.setCheckable(True)
        action.triggered.connect(self._changeEncoding)
        if activeCodecName.lower() == codecName.lower():
            action.setChecked(True)
        return action

    def _createEncodingSubMenu(self, name, codecNames, menu):
        '''
        @param: name QString
        @param: codecName QStringList
        @param: menu QMenu
        '''
        if not codecNames:
            return

        codecNames.sort()
        subMenu = QMenu(name, menu)
        activeCodecName = gVar.app.webSettings().defaultTextEncoding()

        group = QActionGroup(subMenu)

        for codecName in codecNames:
            act = self._createEncodingAction(codecName, activeCodecName,
                                             subMenu)
            group.addAction(act)
            subMenu.addAction(act)

        menu.addMenu(subMenu)

    def _saveUiState(self):
        '''
        @return: QHash<QStirng, QVariant>
        '''
        self.saveSideBarSettings()
        state = {}
        state['LocationBarWidth'] = self._navigationToolbar.splitter().sizes(
        )[0]
        state['WebSearchBarWidth'] = self._navigationToolbar.splitter().sizes(
        )[1]
        state['SideBarWidth'] = self._sideBarWidth
        state['WebViewWidth'] = self._webViewWidth
        state['SideBar'] = self._sideBarManager.activeSideBar()
        return state

    def _restoreUiState(self, state):
        '''
        @param: state QHash<QString, QVariant>
        '''
        locationBarWidth = state.get('LocationBarWidth', 480)
        webSearchBarWidth = state.get('WebSearchBarWidth', 140)
        self._navigationToolbar.setSplitterSizes(locationBarWidth,
                                                 webSearchBarWidth)

        self._sideBarWidth = state.get('SideBarWidth', 250)
        self._webViewWidth = state.get('WebViewWidth', 2000)
        if self._sideBar:
            self._mainSplitter.setSizes(
                [self._sideBarWidth, self._webViewWidth])
        activeSideBar = state.get('SideBar')
        if not activeSideBar and self._sideBar:
            self._sideBar.close()
        else:
            self._sideBarManager.showSideBar(activeSideBar, False)
Exemple #16
0
class SubTabWidget(QWidget):
    _tabChanged = pyqtSignal(int, name = "tabChanged")

    def __init__(self, subtitleData, videoWidget, parent = None):
        super(SubTabWidget, self).__init__(parent)
        self._subtitleData = subtitleData
        self.__initTabWidget(videoWidget)

    def __initTabWidget(self, videoWidget):
        settings = SubSettings()

        mainLayout = QVBoxLayout(self)
        mainLayout.setContentsMargins(0, 0, 0, 0)
        mainLayout.setSpacing(0)

        #TabBar
        self.tabBar = QTabBar(self)

        # Splitter (bookmarks + pages)
        self.splitter = QSplitter(self)
        self.splitter.setObjectName("sidebar_splitter")

        self._toolbox = ToolBox(self._subtitleData, self)
        self._toolbox.setObjectName("sidebar")
        self._toolbox.setMinimumWidth(100)

        self._toolbox.addTool(Details(self._subtitleData, self))
        self._toolbox.addTool(Synchronizer(videoWidget, self._subtitleData, self))
        self._toolbox.addTool(History(self))

        self.rightWidget = QWidget()
        rightLayout = QGridLayout()
        rightLayout.setContentsMargins(0, 0, 0, 0)
        self.rightWidget.setLayout(rightLayout)

        self._mainTab = FileList(_("Subtitles"), self._subtitleData, self)

        self.pages = QStackedWidget(self)
        rightLayout.addWidget(self.pages, 0, 0)

        self.tabBar.addTab(self._mainTab.name)
        self.pages.addWidget(self._mainTab)

        self.splitter.addWidget(self._toolbox)
        self.splitter.addWidget(self.rightWidget)
        self.__drawSplitterHandle(1)

        # Setting widgets
        mainLayout.addWidget(self.tabBar)
        mainLayout.addWidget(self.splitter)

        # Widgets settings
        self.tabBar.setMovable(True)
        self.tabBar.setTabsClosable(True)
        self.tabBar.setExpanding(False)

        # Don't resize left panel if it's not needed
        leftWidgetIndex = self.splitter.indexOf(self._toolbox)
        rightWidgetIndex = self.splitter.indexOf(self.rightWidget)

        self.splitter.setStretchFactor(leftWidgetIndex, 0)
        self.splitter.setStretchFactor(rightWidgetIndex, 1)
        self.splitter.setCollapsible(leftWidgetIndex, False)
        self.splitter.setSizes([250])

        # Some signals
        self.tabBar.currentChanged.connect(self.showTab)
        self.tabBar.tabCloseRequested.connect(self.closeTab)
        self.tabBar.tabMoved.connect(self.moveTab)
        self._mainTab.requestOpen.connect(self.openTab)
        self._mainTab.requestRemove.connect(self.removeFile)

        self.tabChanged.connect(lambda i: self._toolbox.setContentFor(self.tab(i)))

        self.setLayout(mainLayout)

    def __addTab(self, filePath):
        """Returns existing tab index. Creates a new one if it isn't opened and returns its index
        otherwise."""
        for i in range(self.tabBar.count()):
            widget = self.pages.widget(i)
            if not widget.isStatic and filePath == widget.filePath:
                return i
        tab = SubtitleEditor(filePath, self._subtitleData, self)
        newIndex = self.tabBar.addTab(self._createTabName(tab.name, tab.history.isClean()))
        tab.history.cleanChanged.connect(
            lambda clean: self._cleanStateForFileChanged(filePath, clean))
        self.pages.addWidget(tab)
        return newIndex

    def __drawSplitterHandle(self, index):
        splitterHandle = self.splitter.handle(index)

        splitterLayout = QVBoxLayout(splitterHandle)
        splitterLayout.setSpacing(0)
        splitterLayout.setContentsMargins(0, 0, 0, 0)

        line = QFrame(splitterHandle)
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        splitterLayout.addWidget(line)
        splitterHandle.setLayout(splitterLayout)

    def _createTabName(self, name, cleanState):
        if cleanState is True:
            return name
        else:
            return "%s +" % name

    def _cleanStateForFileChanged(self, filePath, cleanState):
        page = self.tabByPath(filePath)
        if page is not None:
            for i in range(self.tabBar.count()):
                if self.tabBar.tabText(i)[:len(page.name)] == page.name:
                    self.tabBar.setTabText(i, self._createTabName(page.name, cleanState))
                    return

    def saveWidgetState(self, settings):
        settings.setState(self.splitter, self.splitter.saveState())
        settings.setHidden(self._toolbox, self._toolbox.isHidden())

    def restoreWidgetState(self, settings):
        self.showPanel(not settings.getHidden(self._toolbox))

        splitterState = settings.getState(self.splitter)
        if not splitterState.isEmpty():
            self.splitter.restoreState(settings.getState(self.splitter))

    @pyqtSlot(str, bool)
    def openTab(self, filePath, background=False):
        if self._subtitleData.fileExists(filePath):
            tabIndex = self.__addTab(filePath)
            if background is False:
                self.showTab(tabIndex)
        else:
            log.error(_("SubtitleEditor not created for %s!" % filePath))

    @pyqtSlot(str)
    def removeFile(self, filePath):
        tab = self.tabByPath(filePath)
        command = RemoveFile(filePath)
        if tab is not None:
            index = self.pages.indexOf(tab)
            if self.closeTab(index):
                self._subtitleData.execute(command)
        else:
            self._subtitleData.execute(command)


    @pyqtSlot(int)
    def closeTab(self, index):
        tab = self.tab(index)
        if tab.canClose():
            widgetToRemove = self.pages.widget(index)
            self.tabBar.removeTab(index)
            self.pages.removeWidget(widgetToRemove)
            widgetToRemove.deleteLater()
            return True
        return False


    def count(self):
        return self.tabBar.count()

    def currentIndex(self):
        return self.tabBar.currentIndex()

    def currentPage(self):
        return self.pages.currentWidget()

    @pyqtSlot(int, int)
    def moveTab(self, fromIndex, toIndex):
        fromWidget = self.pages.widget(fromIndex)
        toWidget = self.pages.widget(toIndex)
        if fromWidget.isStatic or toWidget.isStatic:
            self.tabBar.blockSignals(True) # signals would cause infinite recursion
            self.tabBar.moveTab(toIndex, fromIndex)
            self.tabBar.blockSignals(False)
            return
        else:
            self.pages.removeWidget(fromWidget)
            self.pages.removeWidget(toWidget)

            if fromIndex < toIndex:
                self.pages.insertWidget(fromIndex, toWidget)
                self.pages.insertWidget(toIndex, fromWidget)
            else:
                self.pages.insertWidget(toIndex, fromWidget)
                self.pages.insertWidget(fromIndex, toWidget)

            # Hack
            # Qt changes tabs during mouse drag and dropping. The next line is added
            # to prevent it.
            self.showTab(self.tabBar.currentIndex())

    @pyqtSlot(int)
    def showTab(self, index):
        showWidget = self.pages.widget(index)
        if showWidget:
            self.pages.setCurrentWidget(showWidget)
            self.tabBar.blockSignals(True)
            self.tabBar.setCurrentIndex(index)
            self.tabBar.blockSignals(False)

            # Try to update current tab.
            showWidget.updateTab()

            self._tabChanged.emit(index)

    def showPanel(self, val):
        if val is True:
            self._toolbox.show()
        else:
            self._toolbox.hide()

    def togglePanel(self):
        if self._toolbox.isHidden():
            self._toolbox.show()
        else:
            self._toolbox.hide()

    def tab(self, index):
        return self.pages.widget(index)

    def tabByPath(self, path):
        for i in range(self.pages.count()):
            page = self.tab(i)
            if not page.isStatic and page.filePath == path:
                return page
        return None

    @property
    def fileList(self):
        return self._mainTab
class ConfigurationWidget(QWidget):
    """
    Class implementing a dialog for the configuration of eric6.
    
    @signal preferencesChanged() emitted after settings have been changed
    @signal masterPasswordChanged(str, str) emitted after the master
        password has been changed with the old and the new password
    @signal accepted() emitted to indicate acceptance of the changes
    @signal rejected() emitted to indicate rejection of the changes
    """
    preferencesChanged = pyqtSignal()
    masterPasswordChanged = pyqtSignal(str, str)
    accepted = pyqtSignal()
    rejected = pyqtSignal()

    DefaultMode = 0
    HelpBrowserMode = 1
    TrayStarterMode = 2

    def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode):
        """
        Constructor
        
        @param parent The parent widget of this dialog. (QWidget)
        @keyparam fromEric flag indicating a dialog generation from within the
            eric6 ide (boolean)
        @keyparam displayMode mode of the configuration dialog
            (DefaultMode, HelpBrowserMode, TrayStarterMode)
        @exception RuntimeError raised to indicate an invalid dialog mode
        """
        assert displayMode in (ConfigurationWidget.DefaultMode,
                               ConfigurationWidget.HelpBrowserMode,
                               ConfigurationWidget.TrayStarterMode)

        super(ConfigurationWidget, self).__init__(parent)
        self.fromEric = fromEric
        self.displayMode = displayMode

        self.__setupUi()

        self.itmDict = {}

        if not fromEric:
            from PluginManager.PluginManager import PluginManager
            try:
                self.pluginManager = e5App().getObject("PluginManager")
            except KeyError:
                self.pluginManager = PluginManager(self)
                e5App().registerObject("PluginManager", self.pluginManager)

        if displayMode == ConfigurationWidget.DefaultMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function create to
                # create the configuration page. This must have the method
                # save to save the settings.
                "applicationPage": [
                    self.tr("Application"), "preferences-application.png",
                    "ApplicationPage", None, None
                ],
                "cooperationPage": [
                    self.tr("Cooperation"), "preferences-cooperation.png",
                    "CooperationPage", None, None
                ],
                "corbaPage": [
                    self.tr("CORBA"), "preferences-orbit.png", "CorbaPage",
                    None, None
                ],
                "emailPage": [
                    self.tr("Email"), "preferences-mail_generic.png",
                    "EmailPage", None, None
                ],
                "graphicsPage": [
                    self.tr("Graphics"), "preferences-graphics.png",
                    "GraphicsPage", None, None
                ],
                "iconsPage": [
                    self.tr("Icons"), "preferences-icons.png", "IconsPage",
                    None, None
                ],
                "ircPage": [self.tr("IRC"), "irc.png", "IrcPage", None, None],
                "networkPage": [
                    self.tr("Network"), "preferences-network.png",
                    "NetworkPage", None, None
                ],
                "notificationsPage": [
                    self.tr("Notifications"), "preferences-notifications.png",
                    "NotificationsPage", None, None
                ],
                "pluginManagerPage": [
                    self.tr("Plugin Manager"), "preferences-pluginmanager.png",
                    "PluginManagerPage", None, None
                ],
                "printerPage": [
                    self.tr("Printer"), "preferences-printer.png",
                    "PrinterPage", None, None
                ],
                "pythonPage": [
                    self.tr("Python"), "preferences-python.png", "PythonPage",
                    None, None
                ],
                "qtPage": [
                    self.tr("Qt"), "preferences-qtlogo.png", "QtPage", None,
                    None
                ],
                "securityPage": [
                    self.tr("Security"), "preferences-security.png",
                    "SecurityPage", None, None
                ],
                "shellPage": [
                    self.tr("Shell"), "preferences-shell.png", "ShellPage",
                    None, None
                ],
                "tasksPage":
                [self.tr("Tasks"), "task.png", "TasksPage", None, None],
                "templatesPage": [
                    self.tr("Templates"), "preferences-template.png",
                    "TemplatesPage", None, None
                ],
                "trayStarterPage": [
                    self.tr("Tray Starter"), "erict.png", "TrayStarterPage",
                    None, None
                ],
                "vcsPage": [
                    self.tr("Version Control Systems"), "preferences-vcs.png",
                    "VcsPage", None, None
                ],
                "0debuggerPage": [
                    self.tr("Debugger"), "preferences-debugger.png", None,
                    None, None
                ],
                "debuggerGeneralPage": [
                    self.tr("General"), "preferences-debugger.png",
                    "DebuggerGeneralPage", "0debuggerPage", None
                ],
                "debuggerPythonPage": [
                    self.tr("Python"), "preferences-pyDebugger.png",
                    "DebuggerPythonPage", "0debuggerPage", None
                ],
                "debuggerPython3Page": [
                    self.tr("Python3"), "preferences-pyDebugger.png",
                    "DebuggerPython3Page", "0debuggerPage", None
                ],
                "debuggerRubyPage": [
                    self.tr("Ruby"), "preferences-rbDebugger.png",
                    "DebuggerRubyPage", "0debuggerPage", None
                ],
                "0editorPage": [
                    self.tr("Editor"), "preferences-editor.png", None, None,
                    None
                ],
                "editorAPIsPage": [
                    self.tr("APIs"), "preferences-api.png", "EditorAPIsPage",
                    "0editorPage", None
                ],
                "editorAutocompletionPage": [
                    self.tr("Autocompletion"),
                    "preferences-autocompletion.png",
                    "EditorAutocompletionPage", "0editorPage", None
                ],
                "editorAutocompletionQScintillaPage": [
                    self.tr("QScintilla"), "qscintilla.png",
                    "EditorAutocompletionQScintillaPage",
                    "editorAutocompletionPage", None
                ],
                "editorCalltipsPage": [
                    self.tr("Calltips"), "preferences-calltips.png",
                    "EditorCalltipsPage", "0editorPage", None
                ],
                "editorCalltipsQScintillaPage": [
                    self.tr("QScintilla"), "qscintilla.png",
                    "EditorCalltipsQScintillaPage", "editorCalltipsPage", None
                ],
                "editorGeneralPage": [
                    self.tr("General"), "preferences-general.png",
                    "EditorGeneralPage", "0editorPage", None
                ],
                "editorFilePage": [
                    self.tr("Filehandling"), "preferences-filehandling.png",
                    "EditorFilePage", "0editorPage", None
                ],
                "editorSearchPage": [
                    self.tr("Searching"), "preferences-search.png",
                    "EditorSearchPage", "0editorPage", None
                ],
                "editorSpellCheckingPage": [
                    self.tr("Spell checking"), "preferences-spellchecking.png",
                    "EditorSpellCheckingPage", "0editorPage", None
                ],
                "editorStylesPage": [
                    self.tr("Style"), "preferences-styles.png",
                    "EditorStylesPage", "0editorPage", None
                ],
                "editorSyntaxPage": [
                    self.tr("Code Checkers"), "preferences-debugger.png",
                    "EditorSyntaxPage", "0editorPage", None
                ],
                "editorTypingPage": [
                    self.tr("Typing"), "preferences-typing.png",
                    "EditorTypingPage", "0editorPage", None
                ],
                "editorExportersPage": [
                    self.tr("Exporters"), "preferences-exporters.png",
                    "EditorExportersPage", "0editorPage", None
                ],
                "1editorLexerPage": [
                    self.tr("Highlighters"),
                    "preferences-highlighting-styles.png", None, "0editorPage",
                    None
                ],
                "editorHighlightersPage": [
                    self.tr("Filetype Associations"),
                    "preferences-highlighter-association.png",
                    "EditorHighlightersPage", "1editorLexerPage", None
                ],
                "editorHighlightingStylesPage": [
                    self.tr("Styles"), "preferences-highlighting-styles.png",
                    "EditorHighlightingStylesPage", "1editorLexerPage", None
                ],
                "editorKeywordsPage": [
                    self.tr("Keywords"), "preferences-keywords.png",
                    "EditorKeywordsPage", "1editorLexerPage", None
                ],
                "editorPropertiesPage": [
                    self.tr("Properties"), "preferences-properties.png",
                    "EditorPropertiesPage", "1editorLexerPage", None
                ],
                "0helpPage":
                [self.tr("Help"), "preferences-help.png", None, None, None],
                "helpAppearancePage": [
                    self.tr("Appearance"), "preferences-styles.png",
                    "HelpAppearancePage", "0helpPage", None
                ],
                "helpDocumentationPage": [
                    self.tr("Help Documentation"),
                    "preferences-helpdocumentation.png",
                    "HelpDocumentationPage", "0helpPage", None
                ],
                "helpViewersPage": [
                    self.tr("Help Viewers"), "preferences-helpviewers.png",
                    "HelpViewersPage", "0helpPage", None
                ],
                "helpWebBrowserPage": [
                    self.tr("eric6 Web Browser"), "ericWeb.png",
                    "HelpWebBrowserPage", "0helpPage", None
                ],
                "0projectPage": [
                    self.tr("Project"), "preferences-project.png", None, None,
                    None
                ],
                "projectBrowserPage": [
                    self.tr("Project Viewer"), "preferences-project.png",
                    "ProjectBrowserPage", "0projectPage", None
                ],
                "projectPage": [
                    self.tr("Project"), "preferences-project.png",
                    "ProjectPage", "0projectPage", None
                ],
                "multiProjectPage": [
                    self.tr("Multiproject"), "preferences-multiproject.png",
                    "MultiProjectPage", "0projectPage", None
                ],
                "0interfacePage": [
                    self.tr("Interface"), "preferences-interface.png", None,
                    None, None
                ],
                "interfacePage": [
                    self.tr("Interface"), "preferences-interface.png",
                    "InterfacePage", "0interfacePage", None
                ],
                "viewmanagerPage": [
                    self.tr("Viewmanager"), "preferences-viewmanager.png",
                    "ViewmanagerPage", "0interfacePage", None
                ],
            }

            self.configItems.update(
                e5App().getObject("PluginManager").getPluginConfigData())
        elif displayMode == ConfigurationWidget.HelpBrowserMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function create to
                # create the configuration page. This must have the method
                # save to save the settings.
                "interfacePage": [
                    self.tr("Interface"), "preferences-interface.png",
                    "HelpInterfacePage", None, None
                ],
                "networkPage": [
                    self.tr("Network"), "preferences-network.png",
                    "NetworkPage", None, None
                ],
                "printerPage": [
                    self.tr("Printer"), "preferences-printer.png",
                    "PrinterPage", None, None
                ],
                "securityPage": [
                    self.tr("Security"), "preferences-security.png",
                    "SecurityPage", None, None
                ],
                "0helpPage":
                [self.tr("Help"), "preferences-help.png", None, None, None],
                "helpAppearancePage": [
                    self.tr("Appearance"), "preferences-styles.png",
                    "HelpAppearancePage", "0helpPage", None
                ],
                "helpDocumentationPage": [
                    self.tr("Help Documentation"),
                    "preferences-helpdocumentation.png",
                    "HelpDocumentationPage", "0helpPage", None
                ],
                "helpWebBrowserPage": [
                    self.tr("eric6 Web Browser"), "ericWeb.png",
                    "HelpWebBrowserPage", "0helpPage", None
                ],
            }
        elif displayMode == ConfigurationWidget.TrayStarterMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function create to
                # create the configuration page. This must have the method
                # save to save the settings.
                "trayStarterPage": [
                    self.tr("Tray Starter"), "erict.png", "TrayStarterPage",
                    None, None
                ],
            }
        else:
            raise RuntimeError("Illegal mode value: {0}".format(displayMode))

        # generate the list entries
        for key in sorted(self.configItems.keys()):
            pageData = self.configItems[key]
            if pageData[3]:
                pitm = self.itmDict[pageData[3]]  # get the parent item
            else:
                pitm = self.configList
            self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key,
                                                      pageData[1])
            self.itmDict[key].setData(0, Qt.UserRole, key)
            self.itmDict[key].setExpanded(True)
        self.configList.sortByColumn(0, Qt.AscendingOrder)

        # set the initial size of the splitter
        self.configSplitter.setSizes([200, 600])

        self.configList.itemActivated.connect(self.__showConfigurationPage)
        self.configList.itemClicked.connect(self.__showConfigurationPage)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.rejected)

        if displayMode != ConfigurationWidget.TrayStarterMode:
            self.__initLexers()

    def accept(self):
        """
        Public slot to accept the buttonBox accept signal.
        """
        if not isMacPlatform():
            wdg = self.focusWidget()
            if wdg == self.configList:
                return

        self.accepted.emit()

    def __setupUi(self):
        """
        Private method to perform the general setup of the configuration
        widget.
        """
        self.setObjectName("ConfigurationDialog")
        self.resize(900, 650)
        self.verticalLayout_2 = QVBoxLayout(self)
        self.verticalLayout_2.setSpacing(6)
        self.verticalLayout_2.setContentsMargins(6, 6, 6, 6)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.configSplitter = QSplitter(self)
        self.configSplitter.setOrientation(Qt.Horizontal)
        self.configSplitter.setObjectName("configSplitter")

        self.configListWidget = QWidget(self.configSplitter)
        self.leftVBoxLayout = QVBoxLayout(self.configListWidget)
        self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.leftVBoxLayout.setSpacing(0)
        self.leftVBoxLayout.setObjectName("leftVBoxLayout")
        self.configListFilter = E5ClearableLineEdit(
            self, self.tr("Enter filter text..."))
        self.configListFilter.setObjectName("configListFilter")
        self.leftVBoxLayout.addWidget(self.configListFilter)
        self.configList = QTreeWidget()
        self.configList.setObjectName("configList")
        self.leftVBoxLayout.addWidget(self.configList)
        self.configListFilter.textChanged.connect(self.__filterTextChanged)

        self.scrollArea = QScrollArea(self.configSplitter)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setObjectName("scrollArea")

        self.configStack = QStackedWidget()
        self.configStack.setFrameShape(QFrame.Box)
        self.configStack.setFrameShadow(QFrame.Sunken)
        self.configStack.setObjectName("configStack")
        self.scrollArea.setWidget(self.configStack)

        self.emptyPage = QWidget()
        self.emptyPage.setGeometry(QRect(0, 0, 372, 591))
        self.emptyPage.setObjectName("emptyPage")
        self.vboxlayout = QVBoxLayout(self.emptyPage)
        self.vboxlayout.setSpacing(6)
        self.vboxlayout.setContentsMargins(6, 6, 6, 6)
        self.vboxlayout.setObjectName("vboxlayout")
        spacerItem = QSpacerItem(20, 20, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem)
        self.emptyPagePixmap = QLabel(self.emptyPage)
        self.emptyPagePixmap.setAlignment(Qt.AlignCenter)
        self.emptyPagePixmap.setObjectName("emptyPagePixmap")
        self.emptyPagePixmap.setPixmap(
            QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png')))
        self.vboxlayout.addWidget(self.emptyPagePixmap)
        self.textLabel1 = QLabel(self.emptyPage)
        self.textLabel1.setAlignment(Qt.AlignCenter)
        self.textLabel1.setObjectName("textLabel1")
        self.vboxlayout.addWidget(self.textLabel1)
        spacerItem1 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                  QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem1)
        self.configStack.addWidget(self.emptyPage)

        self.verticalLayout_2.addWidget(self.configSplitter)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Apply
                                          | QDialogButtonBox.Cancel
                                          | QDialogButtonBox.Ok
                                          | QDialogButtonBox.Reset)
        self.buttonBox.setObjectName("buttonBox")
        if not self.fromEric and \
                self.displayMode == ConfigurationWidget.DefaultMode:
            self.buttonBox.button(QDialogButtonBox.Apply).hide()
        self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
        self.verticalLayout_2.addWidget(self.buttonBox)

        self.setWindowTitle(self.tr("Preferences"))

        self.configList.header().hide()
        self.configList.header().setSortIndicator(0, Qt.AscendingOrder)
        self.configList.setSortingEnabled(True)
        self.textLabel1.setText(
            self.tr("Please select an entry of the list \n"
                    "to display the configuration page."))

        QMetaObject.connectSlotsByName(self)
        self.setTabOrder(self.configList, self.configStack)

        self.configStack.setCurrentWidget(self.emptyPage)

        self.configList.setFocus()

    def __filterTextChanged(self, filter):
        """
        Private slot to handle a change of the filter.
        
        @param filter text of the filter line edit (string)
        """
        self.__filterChildItems(self.configList.invisibleRootItem(), filter)

    def __filterChildItems(self, parent, filter):
        """
        Private method to filter child items based on a filter string.
        
        @param parent reference to the parent item (QTreeWidgetItem)
        @param filter filter string (string)
        @return flag indicating a visible child item (boolean)
        """
        childVisible = False
        filter = filter.lower()
        for index in range(parent.childCount()):
            itm = parent.child(index)
            if itm.childCount() > 0:
                visible = self.__filterChildItems(itm, filter) or \
                    filter == "" or filter in itm.text(0).lower()
            else:
                visible = filter == "" or filter in itm.text(0).lower()
            if visible:
                childVisible = True
            itm.setHidden(not visible)

        return childVisible

    def __initLexers(self):
        """
        Private method to initialize the dictionary of preferences lexers.
        """
        import QScintilla.Lexers
        from .PreferencesLexer import PreferencesLexer, \
            PreferencesLexerLanguageError

        self.lexers = {}
        for language in QScintilla.Lexers.getSupportedLanguages():
            if language not in self.lexers:
                try:
                    self.lexers[language] = PreferencesLexer(language, self)
                except PreferencesLexerLanguageError:
                    pass

    def __importConfigurationPage(self, name):
        """
        Private method to import a configuration page module.
        
        @param name name of the configuration page module (string)
        @return reference to the configuration page module
        """
        modName = "Preferences.ConfigurationPages.{0}".format(name)
        try:
            mod = __import__(modName)
            components = modName.split('.')
            for comp in components[1:]:
                mod = getattr(mod, comp)
            return mod
        except ImportError:
            E5MessageBox.critical(
                self, self.tr("Configuration Page Error"),
                self.tr("""<p>The configuration page <b>{0}</b>"""
                        """ could not be loaded.</p>""").format(name))
            return None

    def __showConfigurationPage(self, itm, column):
        """
        Private slot to show a selected configuration page.
        
        @param itm reference to the selected item (QTreeWidgetItem)
        @param column column that was selected (integer) (ignored)
        """
        pageName = itm.getPageName()
        self.showConfigurationPageByName(pageName, setCurrent=False)

    def __initPage(self, pageData):
        """
        Private method to initialize a configuration page.
        
        @param pageData data structure for the page to initialize
        @return reference to the initialized page
        """
        page = None
        if isinstance(pageData[2], types.FunctionType):
            page = pageData[2](self)
        else:
            mod = self.__importConfigurationPage(pageData[2])
            if mod:
                page = mod.create(self)
        if page is not None:
            self.configStack.addWidget(page)
            pageData[-1] = page
            try:
                page.setMode(self.displayMode)
            except AttributeError:
                pass
        return page

    def showConfigurationPageByName(self, pageName, setCurrent=True):
        """
        Public slot to show a named configuration page.
        
        @param pageName name of the configuration page to show (string)
        @param setCurrent flag indicating to set the current item (boolean)
        """
        if pageName == "empty" or pageName not in self.configItems:
            page = self.emptyPage
        else:
            pageData = self.configItems[pageName]
            if pageData[-1] is None and pageData[2] is not None:
                # the page was not loaded yet, create it
                page = self.__initPage(pageData)
            else:
                page = pageData[-1]
            if page is None:
                page = self.emptyPage
            elif setCurrent:
                items = self.configList.findItems(
                    pageData[0], Qt.MatchFixedString | Qt.MatchRecursive)
                for item in items:
                    if item.data(0, Qt.UserRole) == pageName:
                        self.configList.setCurrentItem(item)
        self.configStack.setCurrentWidget(page)
        ssize = self.scrollArea.size()
        if self.scrollArea.horizontalScrollBar():
            ssize.setHeight(ssize.height() -
                            self.scrollArea.horizontalScrollBar().height() - 2)
        if self.scrollArea.verticalScrollBar():
            ssize.setWidth(ssize.width() -
                           self.scrollArea.verticalScrollBar().width() - 2)
        psize = page.minimumSizeHint()
        self.configStack.resize(max(ssize.width(), psize.width()),
                                max(ssize.height(), psize.height()))

        if page != self.emptyPage:
            page.polishPage()
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
        else:
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)

        # reset scrollbars
        for sb in [
                self.scrollArea.horizontalScrollBar(),
                self.scrollArea.verticalScrollBar()
        ]:
            if sb:
                sb.setValue(0)

        self.__currentConfigurationPageName = pageName

    def getConfigurationPageName(self):
        """
        Public method to get the page name of the current page.
        
        @return page name of the current page (string)
        """
        return self.__currentConfigurationPageName

    def calledFromEric(self):
        """
        Public method to check, if invoked from within eric.
        
        @return flag indicating invocation from within eric (boolean)
        """
        return self.fromEric

    def getPage(self, pageName):
        """
        Public method to get a reference to the named page.
        
        @param pageName name of the configuration page (string)
        @return reference to the page or None, indicating page was
            not loaded yet
        """
        return self.configItems[pageName][-1]

    def getLexers(self):
        """
        Public method to get a reference to the lexers dictionary.
        
        @return reference to the lexers dictionary
        """
        return self.lexers

    def setPreferences(self):
        """
        Public method called to store the selected values into the preferences
        storage.
        """
        for key, pageData in list(self.configItems.items()):
            if pageData[-1]:
                pageData[-1].save()
                # page was loaded (and possibly modified)
                QApplication.processEvents()  # ensure HMI is responsive

    def on_buttonBox_clicked(self, button):
        """
        Private slot called by a button of the button box clicked.
        
        @param button button that was clicked (QAbstractButton)
        """
        if button == self.buttonBox.button(QDialogButtonBox.Apply):
            self.on_applyButton_clicked()
        elif button == self.buttonBox.button(QDialogButtonBox.Reset):
            self.on_resetButton_clicked()

    @pyqtSlot()
    def on_applyButton_clicked(self):
        """
        Private slot called to apply the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            page = self.configStack.currentWidget()
            savedState = page.saveState()
            page.save()
            self.preferencesChanged.emit()
            if savedState is not None:
                page.setState(savedState)

    @pyqtSlot()
    def on_resetButton_clicked(self):
        """
        Private slot called to reset the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            currentPage = self.configStack.currentWidget()
            savedState = currentPage.saveState()
            pageName = self.configList.currentItem().getPageName()
            self.configStack.removeWidget(currentPage)
            if pageName == "editorHighlightingStylesPage":
                self.__initLexers()
            self.configItems[pageName][-1] = None

            self.showConfigurationPageByName(pageName)
            if savedState is not None:
                self.configStack.currentWidget().setState(savedState)
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = 'Convolutional Neural Network'
        self.left = 300
        self.top = 300
        self.width = 960
        self.height = 560
        self.first_run = True
        self.current_save = None
        self.running = False
        self.iteration_stats = []
        self.settings = QSettings("Theo Styles",
                                  "Convolutional Neural Network")
        self.img_size = self.settings.value("img_size", 44)
        self.init_ui()

    def update_progress(self, amount=0, status="Running"):
        self.left_area.progressModule.progress.setText(status + " - " +
                                                       str(amount) + "%")
        self.left_area.progressModule.progress.setValue(amount)

    def testing_finished(self, cls_pred):
        self.running = False
        self.main_area_reports.focus()
        for i, prob_array in enumerate(cls_pred):
            image = self.dataset.testing_images[i]
            pred_index = np.argmax(prob_array)
            prob = prob_array[pred_index]
            labelForDigit = self.dataset.labels[pred_index]
            for set in self.main_area_neural.sets:
                if set.name == labelForDigit:
                    item = set.add_image(image)
                    if prob <= 0.5:
                        item.set_important()

        self.toolbar.enable_action(0, 0)

    def run_neural_net(self):
        self.left_area.progressModule.progress.setDefault()
        self.obj = RunNeuralNet(self.dataset, self.img_size,
                                len(self.main_area_neural.sets))  # no parent!
        self.thread = QThread()  # no parent!

        self.obj.moveToThread(self.thread)
        self.obj.one_iteration.connect(self.update_progress)
        self.obj.testing_finished.connect(self.testing_finished)
        self.thread.started.connect(self.obj.long_running)

        self.thread.start()
        self.toolbar.disable_action(0, 0)

    def add_toolbar_clicked(self):
        folder_name = QFileDialog.getExistingDirectory(
            self, "Select Directory With Testing Images")

        if folder_name:
            self.main_area_neural.top_widget.setVisible(True)
            self.main_area_neural.initial_image_grid_visible = True
            if self.main_area_neural.empty_label:
                self.main_area_neural.empty_label.setText(
                    "Now create sets by selecting images and using the + button to the right of the images!"
                )
            self.main_area_neural.initial_image_grid.populate_from_folder(
                folder_name, self.update_progress)

    def export_sets(self):
        sets = self.main_area_neural.sets
        if len(sets) == 0:
            ErrorDialog.dialog(self, "There are no sets to export")
            return

        folder_name = QFileDialog.getExistingDirectory(
            self, "Select a directory to export to")

        if folder_name:
            self.left_area.progressModule.progress.setDefault()
            self.obj = SaveLoad(sets=self.main_area_neural.sets,
                                folder_name=folder_name)  # no parent!
            self.thread = QThread()  # no parent!

            self.obj.moveToThread(self.thread)
            self.obj.one_iteration.connect(self.update_progress)
            self.thread.started.connect(self.obj.export_sets)

            self.thread.start()

    def run_clicked(self):
        sets = self.main_area_neural.sets

        if len(sets) == 0:
            return ErrorDialog.dialog(
                self,
                "Please create at least one set before running the neural network"
            )

        if self.running:
            return ErrorDialog.dialog(self,
                                      "The neural network is already running")

        itemNames = []
        itemData = []
        setCount = 0
        total_incorrect = 0
        self.running = True

        for set in sets:
            setCount += 1
            itemCount = len(set.all_images)
            total_incorrect += set.incorrectly_classified_local
            set.incorrectly_classified_local = 0
            for index in range(itemCount):
                item = set.all_images[index]
                if item == None: continue
                itemNames.append(set.name)
                itemData.append(item.imageData)
            set.clear()

        self.iteration_stats.append(total_incorrect)
        self.dataset.add_sets_to_training_data(setCount, itemNames, itemData)

        if self.first_run or self.main_area_neural.initial_image_grid_visible:
            all_image_count = self.main_area_neural.initial_image_grid.count()
            testing_images = []
            for index in range(all_image_count):
                item = self.main_area_neural.initial_image_grid.item(index)
                if item == None: continue
                testing_images.append(item.imageData)
            self.main_area_neural.initial_image_grid.clear()
            self.main_area_neural.top_widget.setVisible(False)
            self.main_area_neural.initial_image_grid_visible = False
            self.dataset.set_testing_data(testing_images)
        else:
            self.dataset.new_testing_data()

        self.first_run = False

        self.run_neural_net()

    def finished_opening_sets(self):
        self.dataset.new_testing_data()
        self.main_area_reports.focus()

    def set_iteration_stats(self, iteration_stats):
        self.iteration_stats = iteration_stats

    def open_sets(self):
        fileName, filter = QFileDialog.getOpenFileName(
            self, 'Open sets save', PathHelpers.getPath("saves"),
            "Set Files (*.sets)")

        if fileName:
            self.current_save = fileName
            self.main_area_neural.clear_sets()
            self.left_area.progressModule.progress.setDefault()
            self.obj = SaveLoad(self.current_save)  # no parent!
            self.thread = QThread()  # no parent!

            self.obj.moveToThread(self.thread)
            self.obj.one_iteration.connect(self.update_progress)
            self.obj.create_set.connect(self.main_area_neural.create_new_set)
            self.obj.add_to_training_set.connect(
                self.main_area_neural.add_images_to_set)
            self.obj.add_to_testing_set.connect(
                self.dataset.add_to_testing_data)
            self.obj.set_iteration_stats.connect(self.set_iteration_stats)
            self.obj.set_classified_info.connect(
                self.main_area_neural.set_classified_for_set)
            self.obj.finished.connect(self.finished_opening_sets)
            self.thread.started.connect(self.obj.load_images)

            self.thread.start()

    def save_sets_as(self):
        self.current_save = None
        self.save_sets()

    def save_sets(self):

        if self.current_save:
            fileName = self.current_save
        else:
            fileName, filter = QFileDialog.getSaveFileName(
                self, 'Save sets', PathHelpers.getPath("saves"),
                "Set Files (*.sets)")

        if fileName:
            sets = self.main_area_neural.sets[:]
            if self.main_area_neural.trash_set:
                sets.append(self.main_area_neural.trash_set)
            self.current_save = fileName
            self.left_area.progressModule.progress.setDefault()
            self.obj = SaveLoad(
                self.current_save,
                sets,
                self.dataset.all_testing_images,
                iteration_stats=self.iteration_stats)  # no parent!
            self.thread = QThread()  # no parent!

            self.obj.moveToThread(self.thread)
            self.obj.one_iteration.connect(self.update_progress)
            self.thread.started.connect(self.obj.save_images)

            self.thread.start()

    def deleted_set(self, set_name):
        self.datapanel.delete_training_row(set_name)

    def added_to_set(self, set_name):
        self.datapanel.increment_training_table(set_name)

    def removed_from_set(self, set_name):
        self.datapanel.decrement_training_table(set_name)

    def set_testing_amount(self, amount):
        self.datapanel.set_testing_amount(amount)

    def switch_to_neural(self):
        self.left_area.menu.setCurrentRow(0)

    def switch_to_reports(self):
        self.left_area.menu.setCurrentRow(1)

    def switch_to_settings(self):
        self.left_area.menu.setCurrentRow(2)

    def menu_changed(self, index):
        sets = self.main_area_neural.sets[:]
        if self.main_area_neural.trash_set:
            sets.append(self.main_area_neural.trash_set)
        self.main_area_neural.setVisible(False)
        self.main_area_settings.setVisible(False)
        self.main_area_reports.setVisible(False)
        if index == 0:
            self.main_area_neural.setVisible(True)
        elif index == 1:
            self.main_area_reports.setVisible(True)
            self.main_area_reports.focus(sets, self.iteration_stats)
        elif index == 2:
            self.main_area_settings.setVisible(True)
            self.main_area_settings.changed()

    def view_all_training(self):
        sets = self.main_area_neural.sets[:]
        if self.main_area_neural.trash_set:
            sets.append(self.main_area_neural.trash_set)

        self.training_window = TrainingWindow(self, sets)
        self.training_window.show()

    def view_all_testing(self):
        self.testing_window = TestingWindow(self,
                                            self.dataset.all_testing_images)
        self.testing_window.show()

    def exit_app(self):
        sys.exit(0)

    def about_clicked(self):
        d = QDialog(self)
        layout = QVBoxLayout()
        d.setLayout(layout)
        layout.addWidget(
            QLabel("Convolutional Neural Network - Created By Theo Styles"))
        layout.addWidget(QLabel("Credits:"))
        layout.addWidget(
            QLabel("Play icon made by Google from www.flaticon.com"))
        layout.addWidget(
            QLabel("Plus icon made by Madebyoliver from www.flaticon.com"))
        layout.addWidget(
            QLabel("Export icon made by Popcic from www.flaticon.com"))
        layout.addWidget(
            QLabel("Up arrow icon made by Google from www.flaticon.com"))
        layout.addWidget(
            QLabel("Down arrow icon made by Google from www.flaticon.com"))
        layout.addWidget(
            QLabel("Tick icon made by Eleonor Wang from www.flaticon.com"))
        d.setWindowTitle("About")
        d.exec_()

    def init_ui(self):
        self.settings = QSettings("Theo Styles",
                                  "Convolutional Neural Network")
        self.settings.setValue("test", 1)
        self.dataset = DataSet(self.img_size)
        self.dataset.test_set_changed.connect(self.set_testing_amount)
        qss_file = open(
            PathHelpers.getPath("GUI/Stylesheets/default.qss")).read()
        self.setStyleSheet(qss_file)

        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.main_grid = QSplitter()
        self.main_grid.setObjectName("verticalSplitter")

        self.main_grid.setContentsMargins(0, 0, 0, 0)

        self.right_layout = QVBoxLayout()
        self.right_widget = QWidget()
        self.right_widget.setLayout(self.right_layout)

        self.right_grid = QSplitter()
        self.right_grid.setObjectName("verticalSplitter")

        self.right_layout.setContentsMargins(0, 0, 0, 0)
        self.right_layout.setSpacing(0)
        self.right_grid.setContentsMargins(0, 0, 0, 0)

        self.right_stacking = QWidget()
        self.right_stacking_grid = QGridLayout()
        self.right_stacking.setLayout(self.right_stacking_grid)
        self.right_grid.addWidget(self.right_stacking)

        self.right_stacking_grid.setContentsMargins(0, 0, 0, 0)
        self.right_stacking_grid.setSpacing(0)

        self.main_area_neural = NeuralNetSection()
        self.main_area_neural.added_to_set.connect(self.added_to_set)
        self.main_area_neural.removed_from_set.connect(self.removed_from_set)
        self.main_area_neural.deleted_set.connect(self.deleted_set)
        self.right_stacking_grid.addWidget(self.main_area_neural, 0, 0)

        self.main_area_settings = SettingsSection()
        self.right_stacking_grid.addWidget(self.main_area_settings, 0, 0)
        self.main_area_settings.setVisible(False)

        self.main_area_reports = ReportsSection(self.main_area_neural.sets,
                                                self.iteration_stats)
        self.right_stacking_grid.addWidget(self.main_area_reports, 0, 0)
        self.main_area_reports.setVisible(False)

        self.datapanel = DataInfoPanel()
        self.datapanel.clicked_training_view_all_sig.connect(
            self.view_all_training)
        self.datapanel.clicked_testing_view_all_sig.connect(
            self.view_all_testing)
        self.right_grid.addWidget(self.datapanel)

        self.right_grid.setStretchFactor(0, 10)
        self.right_grid.setStretchFactor(1, 11)

        self.left_area = MenuPanel()
        self.left_area.selectedItem.connect(self.menu_changed)

        self.toolbar = ToolbarPanel()
        self.toolbar.run_clicked.connect(self.run_clicked)
        self.toolbar.add_clicked.connect(self.add_toolbar_clicked)
        self.toolbar.export_clicked.connect(self.export_sets)

        self.right_layout.addWidget(self.toolbar)
        self.right_layout.addWidget(self.right_grid)

        self.main_grid.addWidget(self.left_area)
        self.main_grid.addWidget(self.right_widget)

        self.setCentralWidget(self.main_grid)
        self.main_grid.setStretchFactor(0, 6)
        self.main_grid.setStretchFactor(1, 10)

        save_action = QAction("&Save", self)
        save_action.setShortcut("Ctrl+S")
        save_action.setStatusTip('Save the current sets')
        save_action.triggered.connect(self.save_sets)

        save_action_as = QAction("&Save As", self)
        save_action_as.setStatusTip('New save for the current sets')
        save_action_as.triggered.connect(self.save_sets_as)

        open_action = QAction("&Open", self)
        open_action.setShortcut("Ctrl+O")
        open_action.setStatusTip('Open a sets save file')
        open_action.triggered.connect(self.open_sets)

        exit_action = QAction("&Exit", self)
        exit_action.setStatusTip('Exit the application')
        exit_action.triggered.connect(self.exit_app)

        menubar = self.menuBar()
        file_menu = menubar.addMenu('&File')
        file_menu.addAction(open_action)
        file_menu.addAction(save_action)
        file_menu.addAction(save_action_as)
        file_menu.addAction(exit_action)

        neural_action = QAction("&Neural Net", self)
        neural_action.setStatusTip('View the neural network')
        neural_action.triggered.connect(self.switch_to_neural)

        reports_action = QAction("&Reports", self)
        reports_action.setStatusTip('View reports and statistics')
        reports_action.triggered.connect(self.switch_to_reports)

        settings_action = QAction("&Settings", self)
        settings_action.setStatusTip('View settings')
        settings_action.triggered.connect(self.switch_to_settings)

        view_menu = menubar.addMenu('&View')
        view_menu.addAction(neural_action)
        view_menu.addAction(reports_action)
        view_menu.addAction(settings_action)

        import_action = QAction("&Import folder", self)
        import_action.setStatusTip('Import a folder of images')
        import_action.triggered.connect(self.add_toolbar_clicked)

        export_action = QAction("&Export sets", self)
        export_action.setStatusTip('Export sets to folder')
        export_action.triggered.connect(self.export_sets)

        settings_action = QAction("&Settings", self)
        settings_action.setStatusTip('View settings')
        settings_action.triggered.connect(self.switch_to_settings)

        tools_menu = menubar.addMenu('&Tools')
        tools_menu.addAction(import_action)
        tools_menu.addAction(export_action)

        run_action = QAction("&Run Neural Network", self)
        run_action.setStatusTip('Start running the neural network')
        run_action.triggered.connect(self.run_clicked)

        run_menu = menubar.addMenu('&Run')
        run_menu.addAction(run_action)

        about_action = QAction("&About", self)
        about_action.setStatusTip('About the application')
        about_action.triggered.connect(self.about_clicked)

        help_menu = menubar.addMenu('&Help')
        help_menu.addAction(about_action)

        self.show()
class Ui_PerpetualWindow():
    def __init__(self, perpetual_page):
        self.perpetual_page = perpetual_page
    
    def setupUi(self):
        self.setupTitle()
        self.setupFileListUi()
        self.setupFileListView()
#        self.setupAdjustTab()
        self.setupAdjustmentView()
        self.setupResult()
        
    
    def setupTitle(self):
        self.outer_vertical_layout = QtWidgets.QVBoxLayout(self.perpetual_page)
        self.outer_vertical_layout.setContentsMargins(11, 0, 11, 0)
        self.outer_vertical_layout.setSpacing(6)
        self.outer_vertical_layout.setObjectName("outer_vertical_layout")
        
        self.perpetual_title_label = QtWidgets.QLabel(self.perpetual_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.perpetual_title_label.sizePolicy().hasHeightForWidth())
        self.perpetual_title_label.setSizePolicy(sizePolicy)
        self.perpetual_title_label.setMinimumSize(QtCore.QSize(0, 20))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(True)
        font.setWeight(75)
        self.perpetual_title_label.setFont(font)
        self.perpetual_title_label.setAlignment(QtCore.Qt.AlignCenter)
        self.perpetual_title_label.setObjectName("perpetual_title_label")
        self.outer_vertical_layout.addWidget(self.perpetual_title_label)
        self.perpetual_title_label.setText(translate("MainWindow", "Perpetual Series Maker"))
        
        self.outer_horizontalSplitter = QSplitter()
        self.outer_horizontalSplitter.setContentsMargins(11, 6, 11, 0)
        #total_size = self.outer_horizontalSplitter.size()
        self.outer_horizontalSplitter.setSizes([320, 320])
        #self.outer_horizontalSplitter.setSpacing(6)
        self.outer_horizontalSplitter.setObjectName("outer_horizontalSplitter")
        #self.outer_horizontalSplitter.setOrientation(Qt.Vertical)
        self.outer_vertical_layout.addWidget(self.outer_horizontalSplitter)

    def setupFileListUi(self):
#         self.file_window = QtWidgets.QWidget()
#         self.outer_horizontalSplitter.addWidget(self.file_window)
        
        self.file_verticalSplitter = QSplitter()
        self.file_verticalSplitter.setContentsMargins(11, 6, 11, 0)
        #self.file_verticalSplitter.setSpacing(6)
        self.file_verticalSplitter.setObjectName("file_verticalSplitter")
        self.file_verticalSplitter.setOrientation(Qt.Vertical)
        self.outer_horizontalSplitter.addWidget(self.file_verticalSplitter)
        #self.outer_horizontalSplitter.addWidget(self.file_verticalSplitter)
        #self.outer_horizontalSplitter.addLayout(self.file_verticalLayout)
 
        self.filelist_widget = QtWidgets.QWidget()
        self.filelist_widget.setMinimumWidth(550)
        policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
        self.filelist_widget.setSizePolicy(policy)
        self.file_verticalSplitter.addWidget(self.filelist_widget)
        
        self.filelist_verticalLayout = QtWidgets.QVBoxLayout(self.filelist_widget)
        self.filelist_verticalLayout.setContentsMargins(0, 11, 0, 0)
        self.filelist_verticalLayout.setSpacing(6)
        self.filelist_verticalLayout.setObjectName("filelist_verticalLayout")
    
        
        self.filelistButton_horizontalLayout = QtWidgets.QHBoxLayout(self.filelist_widget)
        self.filelistButton_horizontalLayout.setContentsMargins(0, 11, 0, 6)
        self.filelistButton_horizontalLayout.setSpacing(6)
        self.filelistButton_horizontalLayout.setObjectName("filelistButton_horizontalLayout")
        self.filelist_verticalLayout.addLayout(self.filelistButton_horizontalLayout)
                
         
        self.add_files_button = QtWidgets.QPushButton()
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.add_files_button.sizePolicy().hasHeightForWidth())
        self.add_files_button.setSizePolicy(sizePolicy)
        self.add_files_button.setObjectName("add_files_button")
        self.add_files_button.setText(translate("MainWindow", "Add Files"))          
        self.filelistButton_horizontalLayout.addWidget(self.add_files_button)        
 
         
        self.clear_list_button = QtWidgets.QPushButton()
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.clear_list_button.sizePolicy().hasHeightForWidth())
        self.clear_list_button.setSizePolicy(sizePolicy)
        self.clear_list_button.setObjectName("clear_list_button")
        self.clear_list_button.setText(translate("MainWindow", "Clear List"))
        self.filelistButton_horizontalLayout.addWidget(self.clear_list_button)        
        
#         spacerItem = QSpacerItem(20, 40, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
#         self.filelistButton_horizontalLayout.addItem(spacerItem)

    def setupFileListView(self):        
        tableviewTitle = QLabel()
        tableviewTitle.setText("Contract List")
        font = QFont()
        font.setPointSize(10)
        #font.setBold(True)
        tableviewTitle.setFont(font)
        tableviewTitle.setAlignment(Qt.AlignLeft)
        self.filelist_verticalLayout.addWidget(tableviewTitle)
         
        self.filelistView = QtWidgets.QTableView()
        self.filelistView.setObjectName("filelistView")
        self.filelist_verticalLayout.addWidget(self.filelistView)    

        
    def setupAdjustmentView(self):   
        self.adjustWidget = QtWidgets.QWidget()
        self.file_verticalSplitter.addWidget(self.adjustWidget)
        
        self.adjust_veritcalLayout = QtWidgets.QVBoxLayout(self.adjustWidget)
        self.adjust_veritcalLayout.setContentsMargins(0, 11, 0, 0)
             
        adjustViewTitle = QLabel()
        adjustViewTitle.setText("Adjustment contract pair")
        font = QFont()
        font.setPointSize(10)
        adjustViewTitle.setFont(font)
        adjustViewTitle.setAlignment(Qt.AlignLeft)
        self.adjust_veritcalLayout.addWidget(adjustViewTitle)
        
        self.adjustView = QtWidgets.QTableView(self.adjustWidget)
        self.adjustView.setObjectName("adjustView")
        self.adjust_veritcalLayout.addWidget(self.adjustView)
        
          
    def setupResult(self):
        self.result_window = QtWidgets.QWidget()
        self.outer_horizontalSplitter.addWidget(self.result_window)

        self.result_verticalLayout = QtWidgets.QVBoxLayout(self.result_window)
        self.result_verticalLayout.setContentsMargins(0, 8, 0, 0)
        #self.result_verticalLayout.setSpacing(6)
        self.result_verticalLayout.setObjectName("result_verticalLayout")
        
        self.result_option_horizontalLayout = QtWidgets.QHBoxLayout()
        self.result_option_horizontalLayout.setContentsMargins(0, 0, 0, 0)
        #self.result_option_horizontalLayout.setSpacing(6)
        self.result_option_horizontalLayout.setObjectName("result_option_horizontalLayout")
        self.result_verticalLayout.addLayout(self.result_option_horizontalLayout)
        
        self.matchingLabel = QLabel()
        self.matchingLabel.setText("Matching price:")
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.matchingLabel.setSizePolicy(sizePolicy)
        self.matchingLabel.setMinimumSize(QtCore.QSize(20, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)    
        self.matchingLabel.setFont(font) 
        self.result_option_horizontalLayout.addWidget(self.matchingLabel)
        
        self.matchingCombo = QComboBox()
        self.result_option_horizontalLayout.addWidget(self.matchingCombo)
        
#         
#         vline = QFrame()
#         vline.setGeometry(QRect(0, 0, 2, 2))
#         vline.setFrameShape(QFrame.VLine)
#         vline.setFrameShadow(QFrame.Sunken)
#         self.result_option_horizontalLayout.addWidget(vline)
        
        self.rollingPeriodLabel = QLabel()
        self.rollingPeriodLabel.setText("Rolling period:")
        self.rollingPeriodLabel.setIndent(30)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.rollingPeriodLabel.setSizePolicy(sizePolicy)
        self.rollingPeriodLabel.setMinimumSize(QtCore.QSize(20, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)    
        self.rollingPeriodLabel.setFont(font) 
        self.result_option_horizontalLayout.addWidget(self.rollingPeriodLabel)
        
        self.rollingPeriodCombo = QComboBox()
        self.result_option_horizontalLayout.addWidget(self.rollingPeriodCombo)
        
        self.weightLabel = QLabel()
        self.weightLabel.setText("Adjust Weight:")
        self.weightLabel.setIndent(30)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.weightLabel.setSizePolicy(sizePolicy)
        self.weightLabel.setMinimumSize(QtCore.QSize(20, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)    
        self.weightLabel.setFont(font) 
        self.result_option_horizontalLayout.addWidget(self.weightLabel)
        
        self.weightCombo = QComboBox()
        self.result_option_horizontalLayout.addWidget(self.weightCombo)
        
        
        spacerItem = QtWidgets.QSpacerItem(20, 40, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.result_option_horizontalLayout.addItem(spacerItem)
        
        self.result_button_horizontalLayout = QtWidgets.QHBoxLayout()
        self.result_button_horizontalLayout.setContentsMargins(0,0, 0, 6)
        self.result_button_horizontalLayout.setSpacing(6)
        self.result_button_horizontalLayout.setObjectName("result_button_horizontalLayout")
        self.result_verticalLayout.addLayout(self.result_button_horizontalLayout)
        
        self.start_adjust_button = QtWidgets.QPushButton(self.perpetual_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.start_adjust_button.sizePolicy().hasHeightForWidth())
        self.start_adjust_button.setSizePolicy(sizePolicy)
        self.start_adjust_button.setObjectName("start_adjust_button")
        self.start_adjust_button.setText(translate("MainWindow", "Start Adjustment"))
        self.result_button_horizontalLayout.addWidget(self.start_adjust_button)
        
        self.draw_graph_button = QtWidgets.QPushButton(self.perpetual_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.draw_graph_button.sizePolicy().hasHeightForWidth())
        self.draw_graph_button.setSizePolicy(sizePolicy)
        self.draw_graph_button.setObjectName("draw_graph_button")
        self.draw_graph_button.setText(translate("MainWindow", "Draw Graph"))
        self.result_button_horizontalLayout.addWidget(self.draw_graph_button)
        
        self.save_result_button = QtWidgets.QPushButton(self.perpetual_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.save_result_button.sizePolicy().hasHeightForWidth())
        self.save_result_button.setSizePolicy(sizePolicy)
        self.save_result_button.setObjectName("save_result_button")
        self.save_result_button.setText(translate("MainWindow", "Save Result"))
        self.result_button_horizontalLayout.addWidget(self.save_result_button)
        
        
        
        resultviewTitle = QLabel()
        resultviewTitle.setText("Adjustment Result")
        font = QFont()
        font.setPointSize(10)
        #font.setBold(True)
        resultviewTitle.setFont(font)
        resultviewTitle.setAlignment(Qt.AlignLeft)
        self.result_verticalLayout.addWidget(resultviewTitle)
        
        
        self.resultView = QtWidgets.QTableView(self.perpetual_page)
        self.resultView.setObjectName("resultView")
        self.result_verticalLayout.addWidget(self.resultView)
Exemple #20
0
class RightForm1(QFrame):
    """
    右侧框体1
    """
    def __init__(self):
        super(RightForm1, self).__init__()
        self.init()
        self.setup_ui()
        self.set_form_layout()

    def init(self):
        pass

    def setup_ui(self):
        # ***************左侧******************
        self.loadingFrame = QFrame()
        self.loadingFrame.setObjectName('loadingFrame')
        self.loadingFrame.setFrameShape(QFrame.StyledPanel)
        # 最小化以及设置按钮管理栏
        self.loadingFrameBar = QWidget(self.loadingFrame)
        self.loadingFrameBar.setObjectName('loadingFrameBar')
        self.loadingFrameBar.resize(self.loadingFrame.width(), 20)

        self.loadingFrameSettingBtn = QPushButton(self.loadingFrameBar)
        self.loadingFrameSettingBtn.setIcon(
            QIcon('./image/mainWindowIcon/RightForm1Image/setting.png'))
        self.loadingFrameSettingBtn.setMaximumWidth(30)
        self.loadingFrameMinBtn = QPushButton(self.loadingFrameBar)
        self.loadingFrameMinBtn.setIcon(
            QIcon('./image/mainWindowIcon/RightForm1Image/min.png'))
        self.loadingFrameMinBtn.setMaximumWidth(30)
        self.loadingFrameMinBtn.clicked.connect(lambda: self.hide_loadframe())

        # 选项卡面板
        self.loadingTab = QTabWidget(self.loadingFrame)
        self.loadingTab.setObjectName('loadingTab')

        # *********图片加载模式UI设计**********
        self.imageLoadingForm = QWidget(self.loadingTab)
        self.imageLoadingForm.setObjectName('imageLoadingForm')

        self.form1_a = QWidget(self.imageLoadingForm)
        self.form1_a.setObjectName('form1_a')

        self.groupBox1 = QGroupBox(self.form1_a)
        self.groupBox1.setObjectName('groupBox1')
        self.groupBox1.setTitle('图片显示:')

        self.graphicsView = QGraphicsView(self.groupBox1)
        self.graphicsView.setObjectName('graphicsView')

        # 显示图片信息框
        self.textEdit1 = QTextEdit(self.form1_a)
        self.textEdit1.setObjectName('textEdit1')
        self.textEdit1.setReadOnly(True)
        self.textEdit1.setText('当前还没加载图片,' + '\n' + '无法查看图片信息!!!')

        self.form2_a = QWidget(self.imageLoadingForm)
        self.form2_a.setObjectName('form2_a')

        self.groupBox2 = QGroupBox(self.form2_a)
        self.groupBox2.setObjectName('groupBox2')
        self.groupBox2.setTitle('图片列表')

        # 加载图片列表
        self.imageListWidget = QListWidget(self.form2_a)
        self.imageListWidget.setObjectName('imageListWidget')
        self.imageListWidget.setToolTip('图片加载列表')
        self.imageListWidget.setMinimumWidth(600)

        self.buttonWidget = QWidget()
        self.buttonWidget.setObjectName('buttonWidget')

        self.imageOpenBtn = QPushButton('打开图片')
        self.imageOpenBtn.setObjectName('imageOpenBtn')

        self.imageOpenBtn.clicked.connect(lambda: self.load_image())

        # 图片选择改变事件监听
        self.imageListWidget.currentRowChanged.connect(
            lambda: self.image_selecttion_change(self.imageListWidget.
                                                 currentItem().text()))
        self.imageListWidget.currentItemChanged.connect(
            lambda: self.display_image_message(self.imageListWidget.
                                               currentItem().text()))

        # 工具栏
        self.imageToolFrame = QFrame(self.form2_a)
        self.imageToolFrame.setObjectName('imageToolFrame')
        self.imageToolFrame.setFrameShape(QFrame.StyledPanel)

        # 开始识别按钮
        self.startIdentifyBtn = QPushButton('开始识别')
        self.startIdentifyBtn.setObjectName('startIdentifyBtn')

        # ######################################################

        # **********文档加载模式UI设计***********
        self.textLoadingForm = QWidget(self.loadingFrame)
        # self.textLoadingForm.setObjectName('textLoadingForm')
        #
        # self.form1_b = QWidget(self.textLoadingForm)
        # self.form1_b.setObjectName('form1_b')
        # # 显示文档信息框
        # self.textEdit2 = QTextEdit(self.form1_b)
        # self.textEdit2.setObjectName('textEdit2')
        #
        # # 工具栏
        # self.toolWidget2 = QWidget()
        # self.toolWidget2.setObjectName('toolWidget2')
        # self.textOpenBtn = QPushButton('打开文档')
        # self.textOpenBtn.setObjectName('textOpenBtn')

        # ############################################################################
        #
        # ***************右侧******************
        self.resultFrame = QFrame()
        self.resultFrame.setObjectName('resultFrame')
        self.resultFrame.setFrameShape(QFrame.StyledPanel)
        # 最小化以及设置按钮管理栏
        self.resultFrameBar = QWidget()
        self.resultFrameBar.setObjectName('resultFrameBar')
        self.resultFrameBar.resize(self.resultFrame.width(), 20)

        self.resultFrameSettingBtn = QPushButton(self.loadingFrameBar)
        self.resultFrameSettingBtn.setObjectName('resultFrameSettingBtn')
        self.resultFrameSettingBtn.setIcon(
            QIcon('./image/mainWindowIcon/RightForm1Image/setting.png'))
        self.resultFrameSettingBtn.setMaximumWidth(30)
        self.resultFrameMinBtn = QPushButton(self.loadingFrameBar)
        self.resultFrameMinBtn.setIcon(
            QIcon('./image/mainWindowIcon/RightForm1Image/min.png'))
        self.resultFrameMinBtn.setMaximumWidth(30)
        self.resultFrameMinBtn.clicked.connect(lambda: self.hide_resultframe())

        self.resultEdit = QTextEdit()
        self.resultEdit.setObjectName('resultEdit')

        # ###########################################################################
        # 分隔符部件
        self.mainSplitter = QSplitter(Qt.Horizontal)
        self.mainSplitter.setObjectName('mainSplitter')

    def set_form_layout(self):
        # 主框体总布局
        self.allLayout = QHBoxLayout()
        self.setLayout(self.allLayout)
        self.allLayout.addWidget(self.mainSplitter)

        self.mainSplitter.addWidget(self.loadingFrame)
        self.mainSplitter.addWidget(self.resultFrame)

        # 左侧布局
        self.loadingFrameLayout = QGridLayout()
        self.loadingFrame.setLayout(self.loadingFrameLayout)
        self.loadingFrameLayout.addWidget(self.loadingFrameBar, 0, 0)
        self.loadingFrameLayout.addWidget(self.loadingTab, 1, 0)

        # ******************加载图片模式********************
        self.imageLoadingFormLayout = QGridLayout()
        self.imageLoadingForm.setLayout(self.imageLoadingFormLayout)

        self.imageLoadingFormLayout.addWidget(self.form1_a, 0, 0, 3, 1)
        self.imageLoadingFormLayout.addWidget(self.form2_a, 3, 0, 2, 1)

        self.loadingFrameBarLayout = QHBoxLayout()
        self.loadingFrameBar.setLayout(self.loadingFrameBarLayout)
        self.loadingFrameBarLayout.setAlignment(Qt.AlignRight)
        self.loadingFrameBarLayout.addWidget(self.loadingFrameSettingBtn)
        self.loadingFrameBarLayout.addWidget(self.loadingFrameMinBtn)

        self.form1Layout = QHBoxLayout()
        self.form1_a.setLayout(self.form1Layout)
        self.form1Layout.addWidget(self.groupBox1, 3)
        self.form1Layout.addWidget(self.textEdit1, 1)

        self.qHBoxLayout = QHBoxLayout()
        self.groupBox1.setLayout(self.qHBoxLayout)
        self.qHBoxLayout.addWidget(self.graphicsView)

        self.form2Layout = QGridLayout()
        self.form2_a.setLayout(self.form2Layout)
        self.form2Layout.addWidget(self.groupBox2, 0, 0, 1, 3)
        self.form2Layout.addWidget(self.imageToolFrame, 0, 4)

        self.groupBox2Layout = QHBoxLayout()
        self.groupBox2.setLayout(self.groupBox2Layout)
        self.groupBox2Layout.addWidget(self.imageListWidget)
        self.groupBox2Layout.addWidget(self.buttonWidget)

        self.buttonWidgetLayout = QGridLayout()
        self.buttonWidget.setLayout(self.buttonWidgetLayout)
        self.buttonWidgetLayout.addWidget(self.imageOpenBtn)

        self.imageToolFrameLayout = QVBoxLayout()
        self.imageToolFrame.setLayout(self.imageToolFrameLayout)
        self.imageToolFrameLayout.addWidget(self.startIdentifyBtn)
        # ******************加载文档模式********************

        self.loadingTab.addTab(self.imageLoadingForm, '图片加载智能识别 ')
        self.loadingTab.addTab(self.textLoadingForm, '文档加载智能识别')

        # 右侧布局
        self.resultFrameBarLayout = QHBoxLayout()
        self.resultFrameBar.setLayout(self.resultFrameBarLayout)

        self.resultFrameBarLayout.setAlignment(Qt.AlignRight)
        self.resultFrameBarLayout.addWidget(self.resultFrameSettingBtn)
        self.resultFrameBarLayout.addWidget(self.resultFrameMinBtn)

        self.resultFrameLayout = QGridLayout()
        self.resultFrame.setLayout(self.resultFrameLayout)
        self.resultFrameLayout.addWidget(self.resultFrameBar)
        self.resultFrameLayout.addWidget(self.resultEdit)

    # ******************************业务逻辑**********************************

    def load_image(self):
        """
        将图片加载到图片列表
        :return:
        """
        image_path, image_type = QFileDialog.getOpenFileName(
            self, '选择图片', 'c:\\', 'Image files(*.jpg *.gif *.png)')
        # 增加图片目录
        self.imageListWidget.addItem(image_path)
        # 显示图片
        self.display_image(image_path)
        # self.display_image_message(image_path)

    def display_image(self, image_path):
        """
        显示图片
        :param image_path:
        :return:
        """
        self.image_path = image_path
        self.image = QPixmap()
        self.image.load(self.image_path)
        self.graphicsView.scene = QGraphicsScene()
        item = QGraphicsPixmapItem(self.image)
        self.graphicsView.scene.addItem(item)
        self.graphicsView.setScene(self.graphicsView.scene)

    def image_selecttion_change(self, current_path):
        self.current_path = current_path

        self.display_image(self.current_path)
        # self.display_image_message(self.current_path)

    def display_image_message(self, image_path):
        message = ''
        self.image_path = image_path

        message = self.load_image_message(self.image_path)

        self.textEdit1.setText(message)

    def load_image_message(self, image_path):
        """
        会返回一个字典,包含图像的各种属性信息
        :param image_path:
        :return:
        """
        self.image_path = image_path
        message = ''
        image = Image.open(self.image_path)

        # 还没有完成**************
        return message

    def load_text(self):
        pass

    def hide_loadframe(self):
        self.loadingFrame.hide()

    def hide_resultframe(self):
        self.resultFrame.hide()
Exemple #21
0
class Gui(QWidget):
    def __init__(self, config, core, language='de'):
        super(Gui, self).__init__()

        # setup the translation object
        self.language = language
        self.tran = cc_texts.Texts(self.language)
        self.helper = cc_help.Help(self.language)
        self.configparser = config
        self.config = config.read_config()
        self.core_ref = core
        self.messages = set()
        self.thread = None
        self.mainLayout = None
        self.mainsplitter = None
        self.maintabwidget = None
        self.status_line = None
        self.settab = None
        self.advtab = None
        self.keytab = None
        self.ugtab = None
        self_selected_tab = None

        # set the main window name and icon
        self.setWindowTitle(self.tran.get_text("title"))
        self.setWindowIcon(
            QIcon(join(dirname(__file__), "resources/Logo_v2.png")))

        # configure the main window
        self.setObjectName('main_window')
        self.resize(800, 700)
        self.center()

        self.status_line = QTextBrowser(self.mainsplitter)
        self.status_line.setObjectName('status_line')

        # setup the main layout
        self.mainLayout = QGridLayout(self)
        self.mainLayout.setObjectName('main_layout')

        # setup the main splitter
        self.mainsplitter = QSplitter(self)
        self.mainsplitter.setOrientation(Qt.Vertical)
        self.mainsplitter.setObjectName('main_splitter')

        # setup the tab widget
        self.maintabwidget = QTabWidget(self.mainsplitter)
        self.maintabwidget.setObjectName('main_tab_widget')

        # make sure, the tab are is bigger than the message area
        self.maintabwidget_sizepolicy = QSizePolicy()
        self.maintabwidget_sizepolicy.setVerticalStretch(2)
        self.maintabwidget.setSizePolicy(self.maintabwidget_sizepolicy)
        self.maintabwidget.currentChanged.connect(self._sync)

        # setup the settings tab
        self.settab = NorSetTab(self)
        self._selected_tab = self.settab
        self.advtab = AdvSetTab(self)
        self.maintabwidget.addTab(self.settab,
                                  self.tran.get_text('settings_title'))
        self.settab.init()

        # setup the status line
        self.status_line = QTextBrowser(self.mainsplitter)
        self.status_line.setObjectName('status_line')

        # add the elements to the main layout
        self.mainLayout.addWidget(self.mainsplitter, 0, 0, 1, 1)
        self.menubar = QMenuBar()
        self.help_menu = QMenu(self.tran.get_text('help_menu_title'), self)
        self.help_action = self.help_menu.addAction(
            self.tran.get_text('help_menu_action'))
        self.help_action.triggered.connect(self.open_help_page)
        self.menubar.addMenu(self.help_menu)
        self.mainLayout.setMenuBar(self.menubar)

        self.set_style_sheet()

    def set_style_sheet(self):
        if cc_con.THEME in self.config:
            try:
                with open(
                        cc_con.THEME_PREFIX + self.config[cc_con.THEME] +
                        cc_con.THEME_POSTFIX, "r") as theme:
                    self.setStyleSheet(theme.read())
            except EnvironmentError:
                print("ERROR: Theme not found, using default theme")
                with open(
                        cc_con.THEME_PREFIX +
                        self.config[cc_con.THEME_DEFAULT] +
                        cc_con.THEME_POSTFIX, "r") as theme:
                    self.setStyleSheet(theme.read())

    def show_adv_tab(self, onoff):
        """
        Show or hide the advanced settings tab

        :param onoff: True to show the advanced settings tab and false to hide it
        :return: None
        """
        # check if the advanced tab is already in the tablist
        tab_in_tablist = True if self.maintabwidget.indexOf(
            self.advtab) != -1 else False
        if onoff and not tab_in_tablist:
            self.maintabwidget.addTab(self.advtab,
                                      self.tran.get_text('advanced_title'))
        elif tab_in_tablist:
            self.maintabwidget.removeTab(
                self.maintabwidget.indexOf(self.advtab))

    def browse_config(self):
        """
        Opens a file browser to select the config file and
        sets the QEditLine according to the selection.

        :return: None
        """
        filename, _ = QFileDialog.getOpenFileName(
            self, self.tran.get_text('adv_tab_button_config_desc'),
            self.advtab_input_config.text(), "XML (*.xml)")
        if filename:
            self.advtab_input_config.setText(str(filename))

    def get_config_path(self):
        if self.advtab_input_config == "":
            return None
        else:
            return self.advtab_input_config.text()

    def get_plain_path(self):
        if self.settab_input_clear == "":
            return None
        else:
            return self.settab_input_clear.text()

    def get_cipher_path(self):
        if self.settab_input_enc == "":
            return None
        else:
            return self.settab_input_enc.text()

    def open_help_page(self):
        self.helper.open_help("index.html", "")

    def write_config(self):
        self.messages.add(str(self.config))
        self.messages.add(self.tran.get_text('writing_config'))
        self._renew_message_area()
        self.configparser.write_config(self.config)

    def _renew_message_area(self):
        self.status_line.setText("")
        for message in self.messages:
            self.status_line.append(message)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def add_message(self, message):
        self.messages.add(message)
        self._renew_message_area()

    def del_message(self, message):
        """
        Remove a message from the message area

        :param message: the message to remove
        :return: True if the message was removed sucessfully and False if the message was not there to begin with
        """
        try:
            self.messages.remove(message)
            self._renew_message_area()
            return True
        except KeyError:
            return False

    def str_to_bool(self, text):
        if text in 'True':
            return True
        else:
            return False

    def _sync(self):
        self.config = self._selected_tab.config()
        self.configparser.write_config(self._selected_tab.config())
        if self.maintabwidget.count() > 0:
            self.maintabwidget.currentWidget().init()
            if self.settab.is_running():
                self.maintabwidget.currentWidget().lock()
            else:
                self.maintabwidget.currentWidget().unlock()
            if self.settab.tooltip_state():
                self.maintabwidget.currentWidget().toggle_tooltips("True")
            else:
                self.maintabwidget.currentWidget().toggle_tooltips("False")
            self._selected_tab = self.maintabwidget.currentWidget()

    def closeEvent(self, event):
        reply = QMessageBox.question(None, '',
                                     self.tran.get_text('exit_cloudcrypt'),
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        self.write_config()
        if reply == QMessageBox.Yes:
            self.settab.slider_moved("off")
            event.accept()
        else:
            event.ignore()
Exemple #22
0
class MSplitter(QFrame, MHierarchicalElement):

    VERTICAL = 'vertical'
    HORIZONTAL = 'horizontal'

    def __init__(self, parent_window):
        super().__init__()
        self.setObjectName("main_frame")

        # Construct top-level window elements
        self.main_layout = QVBoxLayout()
        self.setLayout(self.main_layout)
        self.parent_container = None

        #self.set_parent_he(parent_window)

        self.main_splitter = QSplitter()
        self.main_splitter.setObjectName("main_splitter")
        self.main_splitter.show()
        self.main_layout.setContentsMargins(0, 0, 0, 0)

        #self.header_frame = MHeaderBar(self)

        #self.main_layout.addWidget(self.header_frame)
        self.content = self.main_splitter
        self.main_layout.addWidget(self.main_splitter)
        self.show()

        self.setStyleSheet(
            self.styleSheet() +
            "QFrame#main_frame{background-color:rgb(200,200,200)}\r\n"
            "QSplitter::handle#main_splitter"
            "{"
            "    border: 2px solid rgb(50,50,50);"
            "    background-color:rgb(100,100,100)"
            "}"
            "QSplitter::handle:pressed#main_splitter"
            "{"
            "    border: 2px solid rgb(100,100,100);"
            "    background-color:rgb(200,100,20)"
            "}")

        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

        self.orientation = None

    def set_sizes(self, one, two):
        self.main_splitter.setSizes([one, two])

    def get_sizes(self):
        return self.main_splitter.sizes()

    def add_content(self, container, location=None):

        # if not (type(container) is MContainer):
        #     raise TypeError("Expected type %s, got %s" % (str(MWindow), type(container)))

        if location is None:
            self.main_splitter.addWidget(container)

        elif location is "top":
            self.main_splitter.setOrientation(Qt.Vertical)
            self.main_splitter.insertWidget(0, container)
            self.orientation = self.VERTICAL

        elif location is "left":
            self.main_splitter.setOrientation(Qt.Horizontal)
            self.main_splitter.insertWidget(0, container)
            self.orientation = self.HORIZONTAL

        elif location is "right":
            self.main_splitter.setOrientation(Qt.Horizontal)
            self.main_splitter.insertWidget(1, container)
            self.orientation = self.HORIZONTAL

        elif location is "bottom":
            self.main_splitter.setOrientation(Qt.Vertical)
            self.main_splitter.insertWidget(1, container)
            self.orientation = self.VERTICAL

        container.set_parent_he(self.get_parent_he())
        self.updateGeometry()

    def get_orientation(self):
        return self.orientation

    def get_position(self):
        return self.main_splitter.sizes()

    def get_num_widgets(self):
        return self.main_splitter.count()

    def get_item_at(self, index):
        return self.main_splitter.widget(index)

    #
    # def get_parent_container(self):
    #     return self.parent_container
    #
    # def set_parent_container(self, win):
    #
    #     if type(win) is MWindow or win is None:
    #
    #         # Remove self from old parent
    #         if self.parent_container is not None:
    #             self.parent_container._remove_child_container(self)
    #
    #         # Add self to new parent
    #         if (win is not None):
    #             win._add_child_container(self)
    #
    #         # Set local reference to parent
    #         self.parent_container = win
    #
    #     else:
    #         raise TypeError("Parent window must be type %s, not %s" % (str(type(MWindow)), str(type(win))))

    def show_drop_regions(self):
        pass

    def hide_drop_regions(self):
        pass
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.connectDatabase(DBPATH)
        self.importer = VideoImporter()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Naming convenience
        self.videoTable = self.ui.videoTable
        self.tableSearchBar = self.ui.tableSearchBar
        self.menuBar = self.ui.menubar
        self.actionUpdate = self.ui.actionUpdate
        self.actionForceUpdate = self.ui.actionForceUpdate
        self.actionManageTags = self.ui.actionManageTags
        self.actionManagePlaylists = self.ui.actionManagePlaylists
        self.tableSortDropDown = self.ui.tableSortDropDown
        self.tableSortDirDropDown = self.ui.tableSortDirDropDown
        self.statusBar = self.ui.statusbar

        # UI layout setup
        self.horizontalLayout = QHBoxLayout(self.ui.mainWidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.splitter = QSplitter(self.ui.mainWidget)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.setObjectName("splitter")
        self.leftPanel = LeftPanel(self)
        self.splitter.addWidget(self.leftPanel)
        self.splitter.addWidget(self.ui.centralPanel)
        self.rightPanel = RightPanel(self)
        self.splitter.addWidget(self.rightPanel)
        self.horizontalLayout.addWidget(self.splitter)

        # Initialization
        self.launch = False  # Track first panel update
        self.videoTableUpdate()
        self.lastUsedFilters = []

        # Signals
        self.splitter.splitterMoved.connect(self.rightPanel.thumbnailUpdate)
        self.actionUpdate.triggered.connect(self.update)
        self.actionForceUpdate.triggered.connect(self.forceUpdate)
        self.actionManageTags.triggered.connect(self.openTagManager)
        self.tableSearchBar.returnPressed.connect(self.tableUpdateTriggered)
        self.tableSortDropDown.currentTextChanged['QString'].connect(
            self.tableUpdateTriggered)
        self.tableSortDirDropDown.currentTextChanged['QString'].connect(
            self.tableUpdateTriggered)

    def connectDatabase(self, path):
        '''
        Connect to SQLite database
        '''
        self.db = QSqlDatabase.addDatabase("QSQLITE")
        initializeDb(DBPATH, self.db)

    def openTagManager(self):
        tagManager = TagManager(self)
        tagManager.exec()
        self.leftPanel.filterListUpdate()
        self.leftPanel.tagListUpdate()

    def videoTableUpdate(self, filters=[]):
        '''
        Generate SQL query from filters (filterName, categoryIndex)
        '''
        tableSorts = [
            "publish_date", "save_date", "video_title", "C.channel_title"
        ]
        sortDirs = ["ASC", "DESC"]

        self.lastUsedFilters = filters
        queries = []
        search = self.tableSearchBar.text()
        tokens = split(search)
        query = QSqlQuery()

        if len(filters) == 0 and len(search) == 0:
            queryTemplate = """SELECT video_id, video_title, publish_date, save_date, C.channel_title
                               FROM videos V INNER JOIN channels C
                               ON V.channel_id = C.channel_id
                               ORDER BY """ + f"{tableSorts[self.tableSortDropDown.currentIndex()]} {sortDirs[self.tableSortDirDropDown.currentIndex()]}"
            query.prepare(queryTemplate)

        else:
            if len(filters) > 0:
                filterTables = [
                    "videos_playlists_link", "videos", "videos_tags_link",
                    "videos_yt_tags_link"
                ]
                filterColumns = [
                    "playlist_id", "channel_id", "tag_name", "tag_name"
                ]
                # queryTemplates = ["SELECT video_id FROM videos_playlists_link WHERE playlist_id = (?)",
                #                   "SELECT video_id FROM videos WHERE channel_id = (?)",
                #                   "SELECT video_id FROM videos_tags_link WHERE tag_name = (?)",
                # "SELECT video_id FROM videos_yt_tags_link WHERE tag_name = (?)"]
                selections = []
                for filterName, categoryIndex in filters:
                    selections.append(
                        f"SELECT video_id FROM {filterTables[categoryIndex]} WHERE {filterColumns[categoryIndex]} = (?)"
                    )
                    # selections.append(queryTemplates[categoryIndex])
                queryTemplate = "\nINTERSECT\n".join(selections)
                queryTemplate = """SELECT video_id, video_title, publish_date, save_date, C.channel_title
                                   FROM videos V INNER JOIN channels C
                                   ON V.channel_id = C.channel_id
                                   WHERE video_id IN (\n""" + queryTemplate + "\n)"
                queries.append(queryTemplate)

            if len(tokens) > 0:
                posQuery = """
                SELECT video_id FROM videos WHERE channel_id IN (
                    SELECT channel_id FROM channels WHERE channel_title LIKE (?)
                )
                UNION
                SELECT video_id FROM videos_playlists_link WHERE playlist_id IN (
                   SELECT playlist_id FROM playlists WHERE playlist_title LIKE (?)
                )
                UNION
                SELECT video_id FROM videos WHERE video_id LIKE (?) OR video_title LIKE (?) OR description LIKE (?) OR notes LIKE (?)
                UNION
                SELECT video_id FROM videos_tags_link WHERE tag_name LIKE (?)
                UNION
                SELECT video_id FROM videos_yt_tags_link WHERE tag_name LIKE (?)
                """

                posQuery = """

                SELECT video_id, video_title, publish_date, save_date, C.channel_title
                FROM videos V INNER JOIN channels C
                ON V.channel_id =C.channel_id
                WHERE video_id IN (\n""" + posQuery + "\n)\n"

                negQuery = """
                SELECT video_id FROM videos WHERE channel_id IN (
                    SELECT channel_id FROM channels WHERE channel_title NOT LIKE (?)
                )
                INTERSECT
                SELECT video_id FROM videos_playlists_link WHERE playlist_id IN (
                   SELECT playlist_id FROM playlists WHERE playlist_title NOT LIKE (?)
                )
                INTERSECT
                SELECT video_id FROM videos WHERE video_id NOT LIKE (?) AND video_title NOT LIKE (?)
                INTERSECT
                SELECT video_id FROM videos_tags_link WHERE tag_name NOT LIKE (?)
                """

                negQuery = """
                SELECT video_id, video_title, publish_date, save_date, C.channel_title
                FROM videos V INNER JOIN channels C
                ON V.channel_id =C.channel_id
                WHERE video_id IN (\n""" + negQuery + "\n)\n"

                searchQuery = ""
                for i, t in enumerate(tokens):
                    if i != 0:
                        searchQuery += "\nINTERSECT\n"
                    subquery = posQuery if t[0] != '-' else negQuery
                    searchQuery += subquery
                queries.append(searchQuery)

            # if len(search) > 0:
            # searchQuery = """SELECT video_id FROM videos WHERE channel_id IN (
            #                     SELECT channel_id FROM channels WHERE channel_title LIKE (?)
            #                  )
            #                  UNION
            #                  SELECT video_id FROM videos_playlists_link WHERE playlist_id IN (
            #                      SELECT playlist_id FROM playlists WHERE playlist_title LIKE (?)
            #                  )
            #                  UNION
            #                  SELECT video_id FROM videos WHERE video_id LIKE (?) OR video_title LIKE (?) OR description LIKE (?) OR notes LIKE (?)
            #                  UNION
            #                  SELECT video_id FROM videos_tags_link WHERE tag_name LIKE (?)
            #                  UNION
            #                  SELECT video_id FROM videos_yt_tags_link WHERE tag_name LIKE (?)"""
            # searchQuery = """SELECT video_id, video_title, publish_date, save_date, C.channel_title
            #                  FROM videos V INNER JOIN channels C
            #                  ON V.channel_id =C.channel_id
            #                  WHERE video_id IN (\n""" + searchQuery + "\n)"
            # queries.append(searchQuery)

            preQuery = "\nINTERSECT\n".join(
                queries
            ) + f"\nORDER BY {tableSorts[self.tableSortDropDown.currentIndex()]} {sortDirs[self.tableSortDirDropDown.currentIndex()]}"
            query.prepare(preQuery)

            if len(filters) > 0:
                for filterName, categoryIndex in filters:
                    query.addBindValue(filterName)

            if len(tokens) > 0:
                for t in tokens:
                    if t[0] != '-':
                        for _ in range(posQuery.count("(?)")):
                            query.addBindValue(f"%{t}%")
                    else:
                        for _ in range(negQuery.count("(?)")):
                            query.addBindValue(f"%{t[1:]}%")

            # if len(search) > 0:
            # for _ in range(8):
            #     query.addBindValue(f"%{search}%")

        query.exec()
        self.videoTableQuery(query)

    def tableUpdateTriggered(self):
        self.videoTableUpdate(self.lastUsedFilters)

    def videoTableQuery(self, query):
        '''
        Updates videoTable with query
        '''
        model = QSqlQueryModel()
        model.setQuery(query)
        self.videoTable.setModel(model)
        self.videoTable.show()

        if self.launch is False:  # Shitty fix to prevent inconsistent behavior when launching
            self.launch = True
        else:
            self.videoTable.selectRow(0)

        self.videoTable.selectionModel().selectionChanged.connect(
            self.videoTableSelectionChanged
        )  # Not placed under signals because selectionModel changes
        self.videoTableSelectionChanged()
        self.statusBarUpdate()

    def videoTableSelectionChanged(self):
        '''
        Updates tagListAlpha with list of selected video_ids when selection changes
        '''
        # update preview panel with currentIndex()
        self.leftPanel.tagListUpdate()
        self.rightPanel.panelUpdate()
        self.statusBarUpdate()

    def getVideoTableSelectionVideoIds(self):
        return [
            index.data()
            for index in self.videoTable.selectionModel().selectedRows(0)
        ]

    def videoTableHasSelection(self):
        return self.videoTable.selectionModel().hasSelection()

    def getVideoTableCurrentVideo(self):
        # rewrite to allow for table custom view
        if self.videoTableHasSelection():
            video_id = self.videoTable.selectionModel().currentIndex(
            ).siblingAtColumn(0).data()
            query = QSqlQuery()
            query.prepare("SELECT * FROM videos WHERE video_id = (?)")
            query.addBindValue(video_id)
            query.exec()
            query.first()
            video = [
                query.value(0),
                query.value(1),
                query.value(2),
                query.value(3),
                query.value(4),
                query.value(5),
                query.value(6)
            ]
        else:
            video = [None] * 7
        return video

    def statusBarUpdate(self):
        displayedVids = self.videoTable.model().rowCount()
        totalVids = 0
        query = QSqlQuery("SELECT count(*) FROM videos")
        query.exec()
        query.first()
        totalVids = query.value(0)
        msg = f"[{displayedVids} of {totalVids} videos"
        if self.videoTableHasSelection():
            msg += f", {len(self.videoTable.selectionModel().selectedRows(0))} selected"
        msg += "]"
        self.statusBar.showMessage(msg)

    def update(self):
        self.importer.importVideosFromAllPlaylists(refresh=False, update=True)
        self.leftPanel.filterListBetaUpdate()
        self.videoTableUpdate()

    def forceUpdate(self):
        self.importer.importVideosFromAllPlaylists(refresh=True, update=False)
        self.leftPanel.filterListBetaUpdate()
        self.videoTableUpdate()
class Ui_ShiftWindow():
    def __init__(self, shift_page):
        self.shift_page = shift_page

    def setupUi(self):
        self.setupShiftTitle()
        self.setupFileListUi()
        self.setupFileListView()
        #        self.setupAdjustTab()
        self.setupAdjustmentView()
        self.setupShiftResult()

    def setupShiftTitle(self):
        self.outer_vertical_layout = QtWidgets.QVBoxLayout(self.shift_page)
        self.outer_vertical_layout.setContentsMargins(11, 0, 11, 0)
        self.outer_vertical_layout.setSpacing(6)
        self.outer_vertical_layout.setObjectName("outer_vertical_layout")

        self.shift_title_label = QtWidgets.QLabel(self.shift_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.shift_title_label.sizePolicy().hasHeightForWidth())
        self.shift_title_label.setSizePolicy(sizePolicy)
        self.shift_title_label.setMinimumSize(QtCore.QSize(0, 20))
        font = QtGui.QFont()
        font.setPointSize(15)
        font.setBold(True)
        font.setWeight(75)
        self.shift_title_label.setFont(font)
        self.shift_title_label.setAlignment(QtCore.Qt.AlignCenter)
        self.shift_title_label.setObjectName("shift_title_label")
        self.outer_vertical_layout.addWidget(self.shift_title_label)
        self.shift_title_label.setText(
            translate("MainWindow", "Forward/Backward Adjustment"))

        self.outer_horizontalSplitter = QSplitter()
        self.outer_horizontalSplitter.setContentsMargins(11, 6, 11, 0)
        #self.outer_horizontalSplitter.setSpacing(6)
        self.outer_horizontalSplitter.setObjectName("outer_horizontalSplitter")
        #self.outer_horizontalSplitter.setOrientation(Qt.Vertical)
        self.outer_vertical_layout.addWidget(self.outer_horizontalSplitter)

    def setupFileListUi(self):
        #         self.file_window = QtWidgets.QWidget()
        #         self.outer_horizontalSplitter.addWidget(self.file_window)

        self.file_verticalSplitter = QSplitter()
        self.file_verticalSplitter.setContentsMargins(11, 6, 11, 0)
        #self.file_verticalSplitter.setSpacing(6)
        self.file_verticalSplitter.setObjectName("file_verticalSplitter")
        self.file_verticalSplitter.setOrientation(Qt.Vertical)
        self.outer_horizontalSplitter.addWidget(self.file_verticalSplitter)
        #self.outer_horizontalSplitter.addWidget(self.file_verticalSplitter)
        #self.outer_horizontalSplitter.addLayout(self.file_verticalLayout)

        self.filelist_widget = QtWidgets.QWidget()
        self.file_verticalSplitter.addWidget(self.filelist_widget)

        self.filelist_verticalLayout = QtWidgets.QVBoxLayout(
            self.filelist_widget)
        self.filelist_verticalLayout.setContentsMargins(0, 11, 0, 0)
        self.filelist_verticalLayout.setSpacing(6)
        self.filelist_verticalLayout.setObjectName("filelist_verticalLayout")

        self.filelistButton_horizontalLayout = QtWidgets.QHBoxLayout(
            self.filelist_widget)
        self.filelistButton_horizontalLayout.setContentsMargins(0, 11, 0, 6)
        self.filelistButton_horizontalLayout.setSpacing(6)
        self.filelistButton_horizontalLayout.setObjectName(
            "filelistButton_horizontalLayout")
        self.filelist_verticalLayout.addLayout(
            self.filelistButton_horizontalLayout)

        self.add_files_button = QtWidgets.QPushButton()
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.add_files_button.sizePolicy().hasHeightForWidth())
        self.add_files_button.setSizePolicy(sizePolicy)
        self.add_files_button.setObjectName("add_files_button")
        self.add_files_button.setText(translate("MainWindow", "Add Files"))
        self.filelistButton_horizontalLayout.addWidget(self.add_files_button)

        self.clear_list_button = QtWidgets.QPushButton()
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.clear_list_button.sizePolicy().hasHeightForWidth())
        self.clear_list_button.setSizePolicy(sizePolicy)
        self.clear_list_button.setObjectName("clear_list_button")
        self.clear_list_button.setText(translate("MainWindow", "Clear List"))
        self.filelistButton_horizontalLayout.addWidget(self.clear_list_button)

        spacerItem = QSpacerItem(20, 40, QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Minimum)
        self.filelistButton_horizontalLayout.addItem(spacerItem)

    def setupFileListView(self):
        tableviewTitle = QLabel()
        tableviewTitle.setText("Contract List")
        font = QFont()
        font.setPointSize(10)
        #font.setBold(True)
        tableviewTitle.setFont(font)
        tableviewTitle.setAlignment(Qt.AlignLeft)
        self.filelist_verticalLayout.addWidget(tableviewTitle)

        self.filelistView = QtWidgets.QTableView()
        self.filelistView.setObjectName("filelistView")
        self.filelist_verticalLayout.addWidget(self.filelistView)

    def setupAdjustmentView(self):
        self.adjustWidget = QtWidgets.QWidget()
        self.file_verticalSplitter.addWidget(self.adjustWidget)

        self.adjust_veritcalLayout = QtWidgets.QVBoxLayout(self.adjustWidget)
        self.adjust_veritcalLayout.setContentsMargins(0, 11, 0, 0)

        adjustViewTitle = QLabel()
        adjustViewTitle.setText("Adjustment contract pair")
        font = QFont()
        font.setPointSize(10)
        adjustViewTitle.setFont(font)
        adjustViewTitle.setAlignment(Qt.AlignLeft)
        self.adjust_veritcalLayout.addWidget(adjustViewTitle)

        self.adjustView = QtWidgets.QTableView(self.adjustWidget)
        self.adjustView.setObjectName("adjustView")
        self.adjust_veritcalLayout.addWidget(self.adjustView)

    def setupShiftResult(self):
        self.result_window = QtWidgets.QWidget()
        self.outer_horizontalSplitter.addWidget(self.result_window)

        self.result_verticalLayout = QtWidgets.QVBoxLayout(self.result_window)
        self.result_verticalLayout.setContentsMargins(0, 8, 0, 0)
        #self.result_verticalLayout.setSpacing(6)
        self.result_verticalLayout.setObjectName("result_verticalLayout")

        self.result_option_horizontalLayout = QtWidgets.QHBoxLayout()
        self.result_option_horizontalLayout.setContentsMargins(0, 0, 0, 0)
        #self.result_option_horizontalLayout.setSpacing(6)
        self.result_option_horizontalLayout.setObjectName(
            "result_option_horizontalLayout")
        self.result_verticalLayout.addLayout(
            self.result_option_horizontalLayout)

        self.matchingLabel = QLabel()
        self.matchingLabel.setText("Matching price:")
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.matchingLabel.setSizePolicy(sizePolicy)
        self.matchingLabel.setMinimumSize(QtCore.QSize(20, 0))
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        self.matchingLabel.setFont(font)
        self.result_option_horizontalLayout.addWidget(self.matchingLabel)

        self.matchingCombo = QComboBox()
        self.result_option_horizontalLayout.addWidget(self.matchingCombo)

        spacerItem = QtWidgets.QSpacerItem(20, 40,
                                           QSizePolicy.MinimumExpanding,
                                           QSizePolicy.Minimum)
        self.result_option_horizontalLayout.addItem(spacerItem)

        self.result_button_horizontalLayout = QtWidgets.QHBoxLayout()
        self.result_button_horizontalLayout.setContentsMargins(0, 0, 0, 6)
        self.result_button_horizontalLayout.setSpacing(6)
        self.result_button_horizontalLayout.setObjectName(
            "result_button_horizontalLayout")
        self.result_verticalLayout.addLayout(
            self.result_button_horizontalLayout)

        self.start_adjust_button = QtWidgets.QPushButton(self.shift_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.start_adjust_button.sizePolicy().hasHeightForWidth())
        self.start_adjust_button.setSizePolicy(sizePolicy)
        self.start_adjust_button.setObjectName("start_adjust_button")
        self.start_adjust_button.setText(
            translate("MainWindow", "Start Adjustment"))
        self.result_button_horizontalLayout.addWidget(self.start_adjust_button)

        self.draw_graph_button = QtWidgets.QPushButton(self.shift_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.draw_graph_button.sizePolicy().hasHeightForWidth())
        self.draw_graph_button.setSizePolicy(sizePolicy)
        self.draw_graph_button.setObjectName("draw_graph_button")
        self.draw_graph_button.setText(translate("MainWindow", "Draw Graph"))
        self.result_button_horizontalLayout.addWidget(self.draw_graph_button)

        self.save_result_button = QtWidgets.QPushButton(self.shift_page)
        sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(1)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.save_result_button.sizePolicy().hasHeightForWidth())
        self.save_result_button.setSizePolicy(sizePolicy)
        self.save_result_button.setObjectName("save_result_button")
        self.save_result_button.setText(translate("MainWindow", "Save Result"))
        self.result_button_horizontalLayout.addWidget(self.save_result_button)

        resultviewTitle = QLabel()
        resultviewTitle.setText("Adjustment Result")
        font = QFont()
        font.setPointSize(10)
        #font.setBold(True)
        resultviewTitle.setFont(font)
        resultviewTitle.setAlignment(Qt.AlignLeft)
        self.result_verticalLayout.addWidget(resultviewTitle)

        self.resultView = QtWidgets.QTableView(self.shift_page)
        self.resultView.setObjectName("resultView")
        self.result_verticalLayout.addWidget(self.resultView)
class DestinationPanel(ScrollAreaNoFrame):
    def __init__(self, parent) -> None:
        super().__init__(parent)
        assert parent is not None
        self.rapidApp = parent
        self.prefs = self.rapidApp.prefs

        self.setObjectName("destinationPanelScrollArea")

        self.splitter = QSplitter(parent=self)

        self.splitter.setObjectName("destinationPanelSplitter")
        self.splitter.setOrientation(Qt.Vertical)

        self.createDestinationViews()
        self.splitter.addWidget(self.photoDestinationContainer)
        self.splitter.addWidget(self.videoDestination)

        self.splitter.setCollapsible(0, False)
        self.splitter.setCollapsible(1, False)
        self.setWidget(self.splitter)
        self.setWidgetResizable(True)

    def createDestinationViews(self) -> None:
        """
        Create the widgets that let the user choose where to download photos and videos
        to, and that show them how much storage space there is available for their
        files.
        """

        self.photoDestination = QPanelView(label=_("Photos"), )
        self.photoDestination.setObjectName("photoDestinationPanelView")
        self.videoDestination = QPanelView(label=_("Videos"), )
        self.videoDestination.setObjectName("videoDestinationPanelView")

        # Display storage space when photos and videos are being downloaded to the same
        # partition. That is, "combined" means not combined widgets, but combined
        # display of destination download stats the user sees

        self.combinedDestinationDisplay = DestinationDisplay(
            parent=self, rapidApp=self.rapidApp)
        self.combinedDestinationDisplayContainer = QPanelView(
            _("Projected Storage Use"), )
        self.combinedDestinationDisplay.setObjectName(
            "combinedDestinationDisplay")
        self.combinedDestinationDisplayContainer.addWidget(
            self.combinedDestinationDisplay)
        self.combinedDestinationDisplayContainer.setObjectName(
            "combinedDestinationDisplayContainer")

        # Display storage space when photos and videos are being downloaded to different
        # partitions.
        # Also display the file system folder chooser for both destinations.

        self.photoDestinationDisplay = DestinationDisplay(
            menu=True,
            file_type=FileType.photo,
            parent=self,
            rapidApp=self.rapidApp)
        self.photoDestinationDisplay.setDestination(
            self.prefs.photo_download_folder)
        self.photoDestinationDisplay.setObjectName("photoDestinationDisplay")
        self.photoDestinationWidget = ComputerWidget(
            objectName="photoDestination",
            view=self.photoDestinationDisplay,
            fileSystemView=self.rapidApp.photoDestinationFSView,
            select_text=_("Select a destination folder"),
        )

        self.videoDestinationDisplay = DestinationDisplay(
            menu=True,
            file_type=FileType.video,
            parent=self,
            rapidApp=self.rapidApp)
        self.videoDestinationDisplay.setObjectName("videoDestinationDisplay")
        self.videoDestinationDisplay.setDestination(
            self.prefs.video_download_folder)
        self.videoDestinationWidget = ComputerWidget(
            objectName="videoDestination",
            view=self.videoDestinationDisplay,
            fileSystemView=self.rapidApp.videoDestinationFSView,
            select_text=_("Select a destination folder"),
        )

        self.photoDestination.addWidget(self.photoDestinationWidget)
        self.videoDestination.addWidget(self.videoDestinationWidget)

        for widget in (self.photoDestinationWidget,
                       self.videoDestinationWidget,
                       self.combinedDestinationDisplay):
            self.verticalScrollBarVisible.connect(
                widget.containerVerticalScrollBar)
        self.horizontalScrollBarVisible.connect(
            self.videoDestinationWidget.containerHorizontalScrollBar)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(self.splitter.handleWidth())
        layout.addWidget(self.combinedDestinationDisplayContainer)
        layout.addWidget(self.photoDestination)

        self.photoDestinationContainer = QWidget()
        self.photoDestinationContainer.setObjectName(
            "photoDestinationContainer")
        self.photoDestinationContainer.setLayout(layout)

    def updateDestinationPanelViews(
        self,
        same_dev: bool,
        merge: bool,
        marked_summary: MarkedSummary,
        downloading_to: Optional[DefaultDict[int, Set[FileType]]] = None,
    ) -> bool:
        """
        Updates the header bar and storage space view for the
        photo and video download destinations.

        :return True if destinations required for the download exist,
         and there is sufficient space on them, else False.
        """

        size_photos_marked = marked_summary.size_photos_marked
        size_videos_marked = marked_summary.size_videos_marked
        marked = marked_summary.marked

        destinations_good = True

        if same_dev:
            files_to_display = DisplayingFilesOfType.photos_and_videos
            self.combinedDestinationDisplay.downloading_to = downloading_to
            self.combinedDestinationDisplay.setDestination(
                self.prefs.photo_download_folder)
            self.combinedDestinationDisplay.setDownloadAttributes(
                marked=marked,
                photos_size=size_photos_marked,
                videos_size=size_videos_marked,
                files_to_display=files_to_display,
                display_type=DestinationDisplayType.usage_only,
                merge=merge,
            )
            display_type = DestinationDisplayType.folder_only
            self.combinedDestinationDisplayContainer.setVisible(True)
            destinations_good = (
                self.combinedDestinationDisplay.sufficientSpaceAvailable())
        else:
            files_to_display = DisplayingFilesOfType.photos
            display_type = DestinationDisplayType.folders_and_usage
            self.combinedDestinationDisplayContainer.setVisible(False)

        if self.prefs.photo_download_folder:
            self.photoDestinationDisplay.downloading_to = downloading_to
            self.photoDestinationDisplay.setDownloadAttributes(
                marked=marked,
                photos_size=size_photos_marked,
                videos_size=0,
                files_to_display=files_to_display,
                display_type=display_type,
                merge=merge,
            )
            self.photoDestinationWidget.setViewVisible(True)
            if display_type == DestinationDisplayType.folders_and_usage:
                destinations_good = (
                    self.photoDestinationDisplay.sufficientSpaceAvailable())
        else:
            # Photo download folder was invalid or simply not yet set
            self.photoDestinationWidget.setViewVisible(False)
            if size_photos_marked:
                destinations_good = False

        if not same_dev:
            files_to_display = DisplayingFilesOfType.videos
        if self.prefs.video_download_folder:
            self.videoDestinationDisplay.downloading_to = downloading_to
            self.videoDestinationDisplay.setDownloadAttributes(
                marked=marked,
                photos_size=0,
                videos_size=size_videos_marked,
                files_to_display=files_to_display,
                display_type=display_type,
                merge=merge,
            )
            self.videoDestinationWidget.setViewVisible(True)
            if display_type == DestinationDisplayType.folders_and_usage:
                destinations_good = (
                    self.videoDestinationDisplay.sufficientSpaceAvailable()
                    and destinations_good)
        else:
            # Video download folder was invalid or simply not yet set
            self.videoDestinationWidget.setViewVisible(False)
            if size_videos_marked:
                destinations_good = False

        return destinations_good
Exemple #26
-1
class ConfigurationWidget(QWidget):
    """
    Class implementing a dialog for the configuration of eric6.
    
    @signal preferencesChanged() emitted after settings have been changed
    @signal masterPasswordChanged(str, str) emitted after the master
        password has been changed with the old and the new password
    @signal accepted() emitted to indicate acceptance of the changes
    @signal rejected() emitted to indicate rejection of the changes
    """
    preferencesChanged = pyqtSignal()
    masterPasswordChanged = pyqtSignal(str, str)
    accepted = pyqtSignal()
    rejected = pyqtSignal()
    
    DefaultMode = 0
    HelpBrowserMode = 1
    TrayStarterMode = 2
    HexEditorMode = 3
    
    def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode,
                 expandedEntries=[]):
        """
        Constructor
        
        @param parent The parent widget of this dialog. (QWidget)
        @keyparam fromEric flag indicating a dialog generation from within the
            eric6 ide (boolean)
        @keyparam displayMode mode of the configuration dialog
            (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode)
        @exception RuntimeError raised to indicate an invalid dialog mode
        @keyparam expandedEntries list of entries to be shown expanded
            (list of strings)
        """
        assert displayMode in (
            ConfigurationWidget.DefaultMode,
            ConfigurationWidget.HelpBrowserMode,
            ConfigurationWidget.TrayStarterMode,
            ConfigurationWidget.HexEditorMode,
        )
        
        super(ConfigurationWidget, self).__init__(parent)
        self.fromEric = fromEric
        self.displayMode = displayMode
        
        self.__setupUi()
        
        self.itmDict = {}
        
        if not fromEric:
            from PluginManager.PluginManager import PluginManager
            try:
                self.pluginManager = e5App().getObject("PluginManager")
            except KeyError:
                self.pluginManager = PluginManager(self)
                e5App().registerObject("PluginManager", self.pluginManager)
        
        if displayMode == ConfigurationWidget.DefaultMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "applicationPage":
                [self.tr("Application"), "preferences-application.png",
                 "ApplicationPage", None, None],
                "cooperationPage":
                [self.tr("Cooperation"), "preferences-cooperation.png",
                 "CooperationPage", None, None],
                "corbaPage":
                [self.tr("CORBA"), "preferences-orbit.png",
                 "CorbaPage", None, None],
                "emailPage":
                [self.tr("Email"), "preferences-mail_generic.png",
                 "EmailPage", None, None],
                "graphicsPage":
                [self.tr("Graphics"), "preferences-graphics.png",
                 "GraphicsPage", None, None],
                "hexEditorPage":
                [self.tr("Hex Editor"), "hexEditor.png",
                 "HexEditorPage", None, None],
                "iconsPage":
                [self.tr("Icons"), "preferences-icons.png",
                 "IconsPage", None, None],
                "ircPage":
                [self.tr("IRC"), "irc.png",
                 "IrcPage", None, None],
                "logViewerPage":
                [self.tr("Log-Viewer"), "preferences-logviewer.png",
                 "LogViewerPage", None, None],
                "mimeTypesPage":
                [self.tr("Mimetypes"), "preferences-mimetypes.png",
                 "MimeTypesPage", None, None],
                "networkPage":
                [self.tr("Network"), "preferences-network.png",
                 "NetworkPage", None, None],
                "notificationsPage":
                [self.tr("Notifications"),
                 "preferences-notifications.png",
                 "NotificationsPage", None, None],
                "pluginManagerPage":
                [self.tr("Plugin Manager"),
                 "preferences-pluginmanager.png",
                 "PluginManagerPage", None, None],
                "printerPage":
                [self.tr("Printer"), "preferences-printer.png",
                 "PrinterPage", None, None],
                "pythonPage":
                [self.tr("Python"), "preferences-python.png",
                 "PythonPage", None, None],
                "qtPage":
                [self.tr("Qt"), "preferences-qtlogo.png",
                 "QtPage", None, None],
                "securityPage":
                [self.tr("Security"), "preferences-security.png",
                 "SecurityPage", None, None],
                "shellPage":
                [self.tr("Shell"), "preferences-shell.png",
                 "ShellPage", None, None],
                "tasksPage":
                [self.tr("Tasks"), "task.png",
                 "TasksPage", None, None],
                "templatesPage":
                [self.tr("Templates"), "preferences-template.png",
                 "TemplatesPage", None, None],
                "trayStarterPage":
                [self.tr("Tray Starter"), "erict.png",
                 "TrayStarterPage", None, None],
                "vcsPage":
                [self.tr("Version Control Systems"),
                 "preferences-vcs.png",
                 "VcsPage", None, None],
                
                "0debuggerPage":
                [self.tr("Debugger"), "preferences-debugger.png",
                 None, None, None],
                "debuggerGeneralPage":
                [self.tr("General"), "preferences-debugger.png",
                 "DebuggerGeneralPage", "0debuggerPage", None],
                "debuggerPythonPage":
                [self.tr("Python"), "preferences-pyDebugger.png",
                 "DebuggerPythonPage", "0debuggerPage", None],
                "debuggerPython3Page":
                [self.tr("Python3"), "preferences-pyDebugger.png",
                 "DebuggerPython3Page", "0debuggerPage", None],
                
                "0editorPage":
                [self.tr("Editor"), "preferences-editor.png",
                 None, None, None],
                "editorAPIsPage":
                [self.tr("APIs"), "preferences-api.png",
                 "EditorAPIsPage", "0editorPage", None],
                "editorAutocompletionPage":
                [self.tr("Autocompletion"),
                 "preferences-autocompletion.png",
                 "EditorAutocompletionPage", "0editorPage", None],
                "editorAutocompletionQScintillaPage":
                [self.tr("QScintilla"), "qscintilla.png",
                 "EditorAutocompletionQScintillaPage",
                 "editorAutocompletionPage", None],
                "editorCalltipsPage":
                [self.tr("Calltips"), "preferences-calltips.png",
                 "EditorCalltipsPage", "0editorPage", None],
                "editorCalltipsQScintillaPage":
                [self.tr("QScintilla"), "qscintilla.png",
                 "EditorCalltipsQScintillaPage", "editorCalltipsPage", None],
                "editorGeneralPage":
                [self.tr("General"), "preferences-general.png",
                 "EditorGeneralPage", "0editorPage", None],
                "editorFilePage":
                [self.tr("Filehandling"),
                 "preferences-filehandling.png",
                 "EditorFilePage", "0editorPage", None],
                "editorSearchPage":
                [self.tr("Searching"), "preferences-search.png",
                 "EditorSearchPage", "0editorPage", None],
                "editorSpellCheckingPage":
                [self.tr("Spell checking"),
                 "preferences-spellchecking.png",
                 "EditorSpellCheckingPage", "0editorPage", None],
                "editorStylesPage":
                [self.tr("Style"), "preferences-styles.png",
                 "EditorStylesPage", "0editorPage", None],
                "editorSyntaxPage":
                [self.tr("Code Checkers"), "preferences-debugger.png",
                 "EditorSyntaxPage", "0editorPage", None],
                "editorTypingPage":
                [self.tr("Typing"), "preferences-typing.png",
                 "EditorTypingPage", "0editorPage", None],
                "editorExportersPage":
                [self.tr("Exporters"), "preferences-exporters.png",
                 "EditorExportersPage", "0editorPage", None],
                
                "1editorLexerPage":
                [self.tr("Highlighters"),
                 "preferences-highlighting-styles.png",
                 None, "0editorPage", None],
                "editorHighlightersPage":
                [self.tr("Filetype Associations"),
                 "preferences-highlighter-association.png",
                 "EditorHighlightersPage", "1editorLexerPage", None],
                "editorHighlightingStylesPage":
                [self.tr("Styles"),
                 "preferences-highlighting-styles.png",
                 "EditorHighlightingStylesPage", "1editorLexerPage", None],
                "editorKeywordsPage":
                [self.tr("Keywords"), "preferences-keywords.png",
                 "EditorKeywordsPage", "1editorLexerPage", None],
                "editorPropertiesPage":
                [self.tr("Properties"), "preferences-properties.png",
                 "EditorPropertiesPage", "1editorLexerPage", None],
                
                "1editorMouseClickHandlers":
                [self.tr("Mouse Click Handlers"),
                 "preferences-mouse-click-handler.png",
                 "EditorMouseClickHandlerPage", "0editorPage", None],
                
                "0helpPage":
                [self.tr("Help"), "preferences-help.png",
                 None, None, None],
                "helpDocumentationPage":
                [self.tr("Help Documentation"),
                 "preferences-helpdocumentation.png",
                 "HelpDocumentationPage", "0helpPage", None],
                "helpViewersPage":
                [self.tr("Help Viewers"),
                 "preferences-helpviewers.png",
                 "HelpViewersPage", "0helpPage", None],
                
                "0projectPage":
                [self.tr("Project"), "preferences-project.png",
                 None, None, None],
                "projectBrowserPage":
                [self.tr("Project Viewer"), "preferences-project.png",
                 "ProjectBrowserPage", "0projectPage", None],
                "projectPage":
                [self.tr("Project"), "preferences-project.png",
                 "ProjectPage", "0projectPage", None],
                "multiProjectPage":
                [self.tr("Multiproject"),
                 "preferences-multiproject.png",
                 "MultiProjectPage", "0projectPage", None],
                
                "0interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 None, None, None],
                "interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 "InterfacePage", "0interfacePage", None],
                "viewmanagerPage":
                [self.tr("Viewmanager"), "preferences-viewmanager.png",
                 "ViewmanagerPage", "0interfacePage", None],
            }
            try:
                from PyQt5 import QtWebKit      # __IGNORE_WARNING__
                self.configItems.update({
                    "helpAppearancePage":
                    [self.tr("Appearance"), "preferences-styles.png",
                     "HelpAppearancePage", "0helpPage", None],
                    "helpFlashCookieManagerPage":
                    [self.tr("Flash Cookie Manager"),
                     "flashCookie16.png",
                     "HelpFlashCookieManagerPage", "0helpPage", None],
                    "helpVirusTotalPage":
                    [self.tr("VirusTotal Interface"), "virustotal.png",
                     "HelpVirusTotalPage", "0helpPage", None],
                    "helpWebBrowserPage":
                    [self.tr("eric6 Web Browser"), "ericWeb.png",
                     "HelpWebBrowserPage", "0helpPage", None],
                })
            except ImportError:
                pass
            
            self.configItems.update(
                e5App().getObject("PluginManager").getPluginConfigData())
        
        elif displayMode == ConfigurationWidget.HelpBrowserMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "interfacePage":
                [self.tr("Interface"), "preferences-interface.png",
                 "HelpInterfacePage", None, None],
                "networkPage":
                [self.tr("Network"), "preferences-network.png",
                 "NetworkPage", None, None],
                "printerPage":
                [self.tr("Printer"), "preferences-printer.png",
                 "PrinterPage", None, None],
                "securityPage":
                [self.tr("Security"), "preferences-security.png",
                 "SecurityPage", None, None],
                
                "0helpPage":
                [self.tr("Help"), "preferences-help.png",
                 None, None, None],
                "helpDocumentationPage":
                [self.tr("Help Documentation"),
                 "preferences-helpdocumentation.png",
                 "HelpDocumentationPage", "0helpPage", None],
            }
            try:
                from PyQt5 import QtWebKit      # __IGNORE_WARNING__
                self.configItems.update({
                    "helpAppearancePage":
                    [self.tr("Appearance"), "preferences-styles.png",
                     "HelpAppearancePage", "0helpPage", None],
                    "helpFlashCookieManagerPage":
                    [self.tr("Flash Cookie Manager"),
                     "flashCookie16.png",
                     "HelpFlashCookieManagerPage", "0helpPage", None],
                    "helpVirusTotalPage":
                    [self.tr("VirusTotal Interface"), "virustotal.png",
                     "HelpVirusTotalPage", "0helpPage", None],
                    "helpWebBrowserPage":
                    [self.tr("eric6 Web Browser"), "ericWeb.png",
                     "HelpWebBrowserPage", "0helpPage", None],
                })
            except ImportError:
                pass
        
        elif displayMode == ConfigurationWidget.TrayStarterMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "trayStarterPage":
                [self.tr("Tray Starter"), "erict.png",
                 "TrayStarterPage", None, None],
            }
        
        elif displayMode == ConfigurationWidget.HexEditorMode:
            self.configItems = {
                # key : [display string, pixmap name, dialog module name or
                #        page creation function, parent key,
                #        reference to configuration page (must always be last)]
                # The dialog module must have the module function 'create' to
                # create the configuration page. This must have the method
                # 'save' to save the settings.
                "hexEditorPage":
                [self.tr("Hex Editor"), "hexEditor.png",
                 "HexEditorPage", None, None],
            }
        
        else:
            raise RuntimeError("Illegal mode value: {0}".format(displayMode))
        
        # generate the list entries
        self.__expandedEntries = []
        for key in sorted(self.configItems.keys()):
            pageData = self.configItems[key]
            if pageData[3]:
                if pageData[3] in self.itmDict:
                    pitm = self.itmDict[pageData[3]]  # get the parent item
                else:
                    continue
            else:
                pitm = self.configList
            self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key,
                                                      pageData[1])
            self.itmDict[key].setData(0, Qt.UserRole, key)
            if (not self.fromEric or
                displayMode != ConfigurationWidget.DefaultMode or
                    key in expandedEntries):
                self.itmDict[key].setExpanded(True)
        self.configList.sortByColumn(0, Qt.AscendingOrder)
        
        # set the initial size of the splitter
        self.configSplitter.setSizes([200, 600])
        
        self.configList.itemActivated.connect(self.__showConfigurationPage)
        self.configList.itemClicked.connect(self.__showConfigurationPage)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.rejected)
        
        if displayMode in [ConfigurationWidget.HelpBrowserMode,
                           ConfigurationWidget.TrayStarterMode,
                           ConfigurationWidget.HexEditorMode]:
            self.configListSearch.hide()
        
        if displayMode not in [ConfigurationWidget.TrayStarterMode,
                               ConfigurationWidget.HexEditorMode]:
            self.__initLexers()
        
    def accept(self):
        """
        Public slot to accept the buttonBox accept signal.
        """
        if not isMacPlatform():
            wdg = self.focusWidget()
            if wdg == self.configList:
                return
        
        self.accepted.emit()
        
    def __setupUi(self):
        """
        Private method to perform the general setup of the configuration
        widget.
        """
        self.setObjectName("ConfigurationDialog")
        self.resize(900, 650)
        self.verticalLayout_2 = QVBoxLayout(self)
        self.verticalLayout_2.setSpacing(6)
        self.verticalLayout_2.setContentsMargins(6, 6, 6, 6)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        
        self.configSplitter = QSplitter(self)
        self.configSplitter.setOrientation(Qt.Horizontal)
        self.configSplitter.setObjectName("configSplitter")
        
        self.configListWidget = QWidget(self.configSplitter)
        self.leftVBoxLayout = QVBoxLayout(self.configListWidget)
        self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0)
        self.leftVBoxLayout.setSpacing(0)
        self.leftVBoxLayout.setObjectName("leftVBoxLayout")
        self.configListSearch = E5ClearableLineEdit(
            self, self.tr("Enter search text..."))
        self.configListSearch.setObjectName("configListSearch")
        self.leftVBoxLayout.addWidget(self.configListSearch)
        self.configList = QTreeWidget()
        self.configList.setObjectName("configList")
        self.leftVBoxLayout.addWidget(self.configList)
        self.configListSearch.textChanged.connect(self.__searchTextChanged)
        
        self.scrollArea = QScrollArea(self.configSplitter)
        self.scrollArea.setFrameShape(QFrame.NoFrame)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setObjectName("scrollArea")
        
        self.configStack = QStackedWidget()
        self.configStack.setFrameShape(QFrame.Box)
        self.configStack.setFrameShadow(QFrame.Sunken)
        self.configStack.setObjectName("configStack")
        self.scrollArea.setWidget(self.configStack)
        
        self.emptyPage = QWidget()
        self.emptyPage.setGeometry(QRect(0, 0, 372, 591))
        self.emptyPage.setObjectName("emptyPage")
        self.vboxlayout = QVBoxLayout(self.emptyPage)
        self.vboxlayout.setSpacing(6)
        self.vboxlayout.setContentsMargins(6, 6, 6, 6)
        self.vboxlayout.setObjectName("vboxlayout")
        spacerItem = QSpacerItem(
            20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem)
        self.emptyPagePixmap = QLabel(self.emptyPage)
        self.emptyPagePixmap.setAlignment(Qt.AlignCenter)
        self.emptyPagePixmap.setObjectName("emptyPagePixmap")
        self.emptyPagePixmap.setPixmap(
            QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png')))
        self.vboxlayout.addWidget(self.emptyPagePixmap)
        self.textLabel1 = QLabel(self.emptyPage)
        self.textLabel1.setAlignment(Qt.AlignCenter)
        self.textLabel1.setObjectName("textLabel1")
        self.vboxlayout.addWidget(self.textLabel1)
        spacerItem1 = QSpacerItem(
            20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.vboxlayout.addItem(spacerItem1)
        self.configStack.addWidget(self.emptyPage)
        
        self.verticalLayout_2.addWidget(self.configSplitter)
        
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Apply | QDialogButtonBox.Cancel |
            QDialogButtonBox.Ok | QDialogButtonBox.Reset)
        self.buttonBox.setObjectName("buttonBox")
        if not self.fromEric and \
                self.displayMode == ConfigurationWidget.DefaultMode:
            self.buttonBox.button(QDialogButtonBox.Apply).hide()
        self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
        self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
        self.verticalLayout_2.addWidget(self.buttonBox)

        self.setWindowTitle(self.tr("Preferences"))
        
        self.configList.header().hide()
        self.configList.header().setSortIndicator(0, Qt.AscendingOrder)
        self.configList.setSortingEnabled(True)
        self.textLabel1.setText(
            self.tr("Please select an entry of the list \n"
                    "to display the configuration page."))
        
        QMetaObject.connectSlotsByName(self)
        self.setTabOrder(self.configList, self.configStack)
        
        self.configStack.setCurrentWidget(self.emptyPage)
        
        self.configList.setFocus()
    
    def __searchTextChanged(self, text):
        """
        Private slot to handle a change of the search text.
        
        @param text text to search for (string)
        """
        self.__searchChildItems(self.configList.invisibleRootItem(), text)
    
    def __searchChildItems(self, parent, text):
        """
        Private method to enable child items based on a search string.
        
        @param parent reference to the parent item (QTreeWidgetItem)
        @param text text to search for (string)
        @return flag indicating an enabled child item (boolean)
        """
        childEnabled = False
        text = text.lower()
        for index in range(parent.childCount()):
            itm = parent.child(index)
            if itm.childCount() > 0:
                enable = self.__searchChildItems(itm, text) or \
                    text == "" or text in itm.text(0).lower()
            else:
                enable = text == "" or text in itm.text(0).lower()
            if enable:
                childEnabled = True
            itm.setDisabled(not enable)
        
        return childEnabled
    
    def __initLexers(self):
        """
        Private method to initialize the dictionary of preferences lexers.
        """
        import QScintilla.Lexers
        from .PreferencesLexer import PreferencesLexer, \
            PreferencesLexerLanguageError
        
        self.lexers = {}
        for language in QScintilla.Lexers.getSupportedLanguages():
            if language not in self.lexers:
                try:
                    self.lexers[language] = PreferencesLexer(language, self)
                except PreferencesLexerLanguageError:
                    pass
        
    def __importConfigurationPage(self, name):
        """
        Private method to import a configuration page module.
        
        @param name name of the configuration page module (string)
        @return reference to the configuration page module
        """
        modName = "Preferences.ConfigurationPages.{0}".format(name)
        try:
            mod = __import__(modName)
            components = modName.split('.')
            for comp in components[1:]:
                mod = getattr(mod, comp)
            return mod
        except ImportError:
            E5MessageBox.critical(
                self,
                self.tr("Configuration Page Error"),
                self.tr("""<p>The configuration page <b>{0}</b>"""
                        """ could not be loaded.</p>""").format(name))
            return None
        
    def __showConfigurationPage(self, itm, column):
        """
        Private slot to show a selected configuration page.
        
        @param itm reference to the selected item (QTreeWidgetItem)
        @param column column that was selected (integer) (ignored)
        """
        pageName = itm.getPageName()
        self.showConfigurationPageByName(pageName, setCurrent=False)
        
    def __initPage(self, pageData):
        """
        Private method to initialize a configuration page.
        
        @param pageData data structure for the page to initialize
        @return reference to the initialized page
        """
        page = None
        if isinstance(pageData[2], types.FunctionType):
            page = pageData[2](self)
        else:
            mod = self.__importConfigurationPage(pageData[2])
            if mod:
                page = mod.create(self)
        if page is not None:
            self.configStack.addWidget(page)
            pageData[-1] = page
            try:
                page.setMode(self.displayMode)
            except AttributeError:
                pass
        return page
        
    def showConfigurationPageByName(self, pageName, setCurrent=True):
        """
        Public slot to show a named configuration page.
        
        @param pageName name of the configuration page to show (string)
        @param setCurrent flag indicating to set the current item (boolean)
        """
        if pageName == "empty" or pageName not in self.configItems:
            page = self.emptyPage
        else:
            pageData = self.configItems[pageName]
            if pageData[-1] is None and pageData[2] is not None:
                # the page was not loaded yet, create it
                page = self.__initPage(pageData)
            else:
                page = pageData[-1]
            if page is None:
                page = self.emptyPage
            elif setCurrent:
                items = self.configList.findItems(
                    pageData[0],
                    Qt.MatchFixedString | Qt.MatchRecursive)
                for item in items:
                    if item.data(0, Qt.UserRole) == pageName:
                        self.configList.setCurrentItem(item)
        self.configStack.setCurrentWidget(page)
        ssize = self.scrollArea.size()
        if self.scrollArea.horizontalScrollBar():
            ssize.setHeight(
                ssize.height() -
                self.scrollArea.horizontalScrollBar().height() - 2)
        if self.scrollArea.verticalScrollBar():
            ssize.setWidth(
                ssize.width() -
                self.scrollArea.verticalScrollBar().width() - 2)
        psize = page.minimumSizeHint()
        self.configStack.resize(max(ssize.width(), psize.width()),
                                max(ssize.height(), psize.height()))
        
        if page != self.emptyPage:
            page.polishPage()
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True)
        else:
            self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False)
            self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False)
        
        # reset scrollbars
        for sb in [self.scrollArea.horizontalScrollBar(),
                   self.scrollArea.verticalScrollBar()]:
            if sb:
                sb.setValue(0)
        
        self.__currentConfigurationPageName = pageName
        
    def getConfigurationPageName(self):
        """
        Public method to get the page name of the current page.
        
        @return page name of the current page (string)
        """
        return self.__currentConfigurationPageName
        
    def calledFromEric(self):
        """
        Public method to check, if invoked from within eric.
        
        @return flag indicating invocation from within eric (boolean)
        """
        return self.fromEric
        
    def getPage(self, pageName):
        """
        Public method to get a reference to the named page.
        
        @param pageName name of the configuration page (string)
        @return reference to the page or None, indicating page was
            not loaded yet
        """
        return self.configItems[pageName][-1]
        
    def getLexers(self):
        """
        Public method to get a reference to the lexers dictionary.
        
        @return reference to the lexers dictionary
        """
        return self.lexers
        
    def setPreferences(self):
        """
        Public method called to store the selected values into the preferences
        storage.
        """
        for key, pageData in list(self.configItems.items()):
            if pageData[-1]:
                pageData[-1].save()
                # page was loaded (and possibly modified)
                QApplication.processEvents()    # ensure HMI is responsive
        
    def on_buttonBox_clicked(self, button):
        """
        Private slot called by a button of the button box clicked.
        
        @param button button that was clicked (QAbstractButton)
        """
        if button == self.buttonBox.button(QDialogButtonBox.Apply):
            self.on_applyButton_clicked()
        elif button == self.buttonBox.button(QDialogButtonBox.Reset):
            self.on_resetButton_clicked()
        
    @pyqtSlot()
    def on_applyButton_clicked(self):
        """
        Private slot called to apply the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            page = self.configStack.currentWidget()
            savedState = page.saveState()
            page.save()
            self.preferencesChanged.emit()
            if savedState is not None:
                page.setState(savedState)
            page.polishPage()
        
    @pyqtSlot()
    def on_resetButton_clicked(self):
        """
        Private slot called to reset the settings of the current page.
        """
        if self.configStack.currentWidget() != self.emptyPage:
            currentPage = self.configStack.currentWidget()
            savedState = currentPage.saveState()
            pageName = self.configList.currentItem().getPageName()
            self.configStack.removeWidget(currentPage)
            if pageName == "editorHighlightingStylesPage":
                self.__initLexers()
            self.configItems[pageName][-1] = None
            
            self.showConfigurationPageByName(pageName)
            if savedState is not None:
                self.configStack.currentWidget().setState(savedState)
        
    def getExpandedEntries(self):
        """
        Public method to get a list of expanded entries.
        
        @return list of expanded entries (list of string)
        """
        return self.__expandedEntries
    
    @pyqtSlot(QTreeWidgetItem)
    def on_configList_itemCollapsed(self, item):
        """
        Private slot handling a list entry being collapsed.
        
        @param item reference to the collapsed item (QTreeWidgetItem)
        """
        pageName = item.data(0, Qt.UserRole)
        if pageName in self.__expandedEntries:
            self.__expandedEntries.remove(pageName)
    
    @pyqtSlot(QTreeWidgetItem)
    def on_configList_itemExpanded(self, item):
        """
        Private slot handling a list entry being expanded.
        
        @param item reference to the expanded item (QTreeWidgetItem)
        """
        pageName = item.data(0, Qt.UserRole)
        if pageName not in self.__expandedEntries:
            self.__expandedEntries.append(pageName)