示例#1
0
class AddonsPage(QWidget):
    def __init__(self, parent):
        super(AddonsPage, self).__init__()
        self.setMinimumSize(700, 500)
        self.main = parent.parent
        self.addonsManager = AddonsManager(self.main)
        self.addonsManager.loadaddons()
        self.widgets = []
        self.layoutMain = QVBoxLayout(self)
        self.scroll = QScrollArea(self)
        self.scroll.setWidgetResizable(True)
        self.title = QLabel("Addons")
        self.title.setAlignment(Qt.AlignHCenter)
        self.layoutMain.addWidget(self.title)
        self.layoutMain.addWidget(self.scroll)

        self.container = QWidget()
        self.scroll.setWidget(self.container)
        self.layout = QVBoxLayout(self.container)
        self.label = QLabel("Pas de addons")
        self.label.setAlignment(Qt.AlignHCenter)
        self.layout.addWidget(self.label)
        for i in self.addonsManager.imported:
            self.addonW = AddonWidget(self.main, self, i.replace(".", "/").split("/")[-2])
            self.widgets.append(self.addonW)
            self.layout.addWidget(self.addonW)
            self.layout.setAlignment(self.addonW, Qt.AlignTop)
            self.label.hide()

    def launchaddons(self, function, args=None):
        self.addonsManager.launchaddons(self.widgets, function, args)
示例#2
0
class DownloadPage(QWidget):
    def __init__(self, parent):
        super(DownloadPage, self).__init__()
        self.setMinimumSize(500, 300)
        self.parent = parent
        self.nbDownload = 0
        self.layoutMain = QVBoxLayout(self)
        self.scroll = QScrollArea(self)
        self.scroll.setWidgetResizable(True)
        self.title = QLabel("Téléchargements")
        self.title.setAlignment(Qt.AlignHCenter)
        self.layoutMain.addWidget(self.title)
        self.layoutMain.addWidget(self.scroll)

        self.container = QWidget()
        self.scroll.setWidget(self.container)
        self.layout = QVBoxLayout(self.container)
        self.label = QLabel("Pas de téléchargement")
        self.label.setAlignment(Qt.AlignHCenter)
        self.layout.addWidget(self.label)

    def downloadrequested(self, download):
        if download:
            if download.state() == QWebEngineDownloadItem.DownloadRequested:
                path = QFileDialog.getSaveFileName(self, "Sauver comme",
                                                   download.path())
                if path == "":
                    return
                else:
                    download.setPath(path[0])
                    download.accept()
                    self.add(
                        DownloadWidget(
                            download,
                            self.parent.parent.browserWidget.url().toString(),
                            self.parent.parent))

                    self.show()
            else:
                QMessageBox.warning(self, "ERREUR",
                                    "Le téléchargement n'a pas été demandé.")
        else:
            QMessageBox.warning(self, "ERREUR", "Le téléchargement est nul.")

    def add(self, downloadwidget):
        downloadwidget.downloadSignal.removeClicked.connect(self.remove)
        self.layout.addWidget(downloadwidget)
        self.layout.setAlignment(downloadwidget, Qt.AlignTop)
        self.nbDownload += 1
        if self.nbDownload >= 0:
            self.label.hide()

    def remove(self):
        downloadwidget = self.sender().parent
        self.layout.removeWidget(downloadwidget)
        downloadwidget.deleteLater()
        self.nbDownload -= 1
        if self.nbDownload <= 0:
            self.label.show()
示例#3
0
class MDIWidget(QMdiSubWindow):
    def __init__(self):
        super().__init__()
        self.w = 640
        self.h_scale = .75
        self.win_frame_offset = 25
        self.mdi_w = self.w
        self.mdi_h = int(self.w * self.h_scale) + self.win_frame_offset

        self.image_w = int(self.w)
        self.image_h = int(self.w * self.h_scale)

        self.image_active = None

        self.resize(self.mdi_w, self.mdi_h)
        self.mid_text = QLabel("Nothing yet...", alignment=QtCore.Qt.AlignCenter)
        self.setWidget(self.mid_text)
        self.setWindowTitle("Video")
        self.setWindowIcon(self.create_icon_by_color(QColor("transparent")))


    def display(self, image):
        image8 = image.astype(np.uint8)
        height, width, colors = image8.shape

        image = QImage(image8.data, width, height, 3 * width,
                       QImage.Format_RGB888)

        self.image_active = QPixmap.fromImage(image.rgbSwapped())
        self.rescale_active_image()

    def rescale_active_image(self):
        if self.image_active is not None:
            self.image_active = self.image_active.scaled(self.image_w, self.image_h)
            self.mid_text.setPixmap(self.image_active)

    def mousePressEvent(self, mousePressEvent):
        self.mid_text.hide()
        return super().mousePressEvent(mousePressEvent)

    def mouseReleaseEvent(self, mouseReleaseEvent):
        self.image_h = int(self.width() * self.h_scale)
        self.image_w = int(self.width())
        self.rescale_active_image()
        self.mid_text.show()
        return super().mouseReleaseEvent(mouseReleaseEvent)

    def resizeEvent(self, resizeEvent):
        self.resize(self.width(), int(self.width() * self.h_scale) + self.win_frame_offset)
        return super().resizeEvent(resizeEvent)

    def create_icon_by_color(self, color):
        pixmap = QPixmap(512, 512)
        pixmap.fill(color)
        return QIcon(pixmap)
示例#4
0
class IconStatusBar(QStatusBar):
    def __init__(self, parent):
        super().__init__(parent)

        # Icon
        self.iconWidget = QLabel(self)
        icons_base_dir = cvars.get("icons.path")
        error_icon_path = fs.path_helper(icons_base_dir) / 'error_devil2.png'
        self.error_pixmap = QPixmap(str(error_icon_path.resolve()))
        self.iconWidget.setScaledContents(True)
        self.iconWidget.setMaximumSize(self.height(), self.height())
        self.iconWidget.setPixmap(self.error_pixmap)

        # Message
        self.messageWidget = QLabel("", self)

        # Insert icon and message
        self.insertWidget(0, self.iconWidget)
        self.insertWidget(1, self.messageWidget)
        self.iconWidget.hide()

    def show_error_icon(self):
        self.iconWidget.show()

    def hide_icon(self):
        self.iconWidget.hide()

    def set_message(self, message: str):
        self.messageWidget.setText(message)

    def display_status_bar_message(self, event=None, instruction=None):
        """
        Display a message in the status bar.
        :param event:       tuple of strings, (nature, content, details)
        :param instruction: 'erase' or None
        """

        status_bar = self
        if instruction == 'erase':
            status_bar.set_message("")
            status_bar.hide_icon()
        elif event:
            nature, message, details = event
            if details:
                message += ": " + details
            if nature in ('error', 'lean_error'):
                status_bar.show_error_icon()
            else:
                status_bar.hide_icon()
            status_bar.set_message(message)
示例#5
0
class _SettingsPanel(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.timeAxisAttributeCB = QComboBox(self)
        self.valuesTable = SearchableAttributeTableWidget(
            self, True, False, True, [Types.Numeric, Types.Ordinal])
        self.indexTable = SearchableTableWidget(self)
        # self.meanCB = QCheckBox('Mean of selected', self)
        self.createButton = QPushButton('Create chart', self)

        sideLayout = QVBoxLayout(self)
        lab = QLabel('Select the column to use as time index')
        lab.setWordWrap(True)
        sideLayout.addWidget(lab)
        sideLayout.addWidget(self.timeAxisAttributeCB)

        lab = QLabel('Time axis format')
        self.timeAxisFormatCB = QComboBox(self)
        options = QStringListModel([
            'dd.MM.yyyy', 'yyyy-MM-dd', 'yyyy-MM', 'yyyy', 'MM', 'dd',
            'hh:mm:ss', 'hh:mm', 'hh', 'yyyy-MM-dd HH:mm:ss',
            'ddd MMM dd yyyy', 'ddd', 'MMM', 'MMM yyyy'
        ],
                                   parent=self)
        self.timeAxisFormatCB.setModel(options)
        self.timeAxisFormatCB.setCurrentIndex(0)
        sideLayout.addWidget(lab)
        sideLayout.addWidget(self.timeAxisFormatCB)

        lab = QLabel(
            'Select any number of columns to show as a function of time')
        lab.setWordWrap(True)
        sideLayout.addSpacing(30)
        sideLayout.addWidget(lab)
        sideLayout.addWidget(self.valuesTable)

        lab = QLabel(
            'Select the rows to show by index. An index attribute must be set')
        lab.setWordWrap(True)
        sideLayout.addSpacing(30)
        sideLayout.addWidget(lab)
        sideLayout.addWidget(self.indexTable)
        # sideLayout.addWidget(self.meanCB)
        sideLayout.addSpacing(30)
        sideLayout.addWidget(self.createButton)

        self.errorLabel = QLabel(self)
        self.errorLabel.setWordWrap(True)
        sideLayout.addWidget(self.errorLabel)
        self.errorLabel.hide()
示例#6
0
class QLivePreview(QWidget):
    """
    A custom class that can show an empty canvas with a message, or an image without a message.
    """
    def __init__(self,
                 placeholder: str = '(Nothing to preview)',
                 *args,
                 **kwargs):
        super().__init__(*args, **kwargs)
        self.window = QLabel()
        self.window.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.window.setLineWidth(2)

        self.placeholder_text = QLabel(parent=self.window)
        self.placeholder_text.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.placeholder_text.setAlignment(Qt.AlignCenter)
        self.placeholder_text.setText(placeholder)

        # placeholder background when nothing is shown
        self.blank_background = QPixmap(290, 290)
        self.blank_background.fill(QColor(0, 0, 0, 32))

        self.preview_layout = QVBoxLayout()
        self.preview_layout.addWidget(self.placeholder_text)
        # self.window.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.window.setLayout(self.preview_layout)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.window)
        self.setLayout(self.layout)

        self.clearImage()

    def clearImage(self):
        self.window.setPixmap(self.blank_background)
        self.placeholder_text.show()

    def setImage(self, image: QPixmap):
        self.placeholder_text.hide()
        self.window.setPixmap(image)
示例#7
0
class AccountModal(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self)
        self.account_group_box = QGroupBox("Account")
        self.modal_error_label = QLabel(
            "Wrong address, account must be written in form : '0x...'.")
        self.account_group_layout = QFormLayout()
        self.new_addr_line = QLineEdit()
        self.modal_error_label.hide()
        self.account_group_layout.addRow(self.modal_error_label)
        self.parent = parent
        self.account_group_layout.addRow(QLabel("Write your private key:"),
                                         self.new_addr_line)
        self.modal_save = QPushButton("Save")
        self.modal_save.clicked.connect(self.modal_save_func)

        self.modal_cancel = QPushButton("Cancel")
        # self.modal_cancel.clicked.connect(self.modal_cancel_func)
        self.account_group_layout.addRow(self.modal_save, self.modal_cancel)

        self.modal_cancel.clicked.connect(self.modal_cancel_func)
        self.setLayout(self.account_group_layout)

    """
    It is function to save private key for the current session
    (private key isn't stored, as it would take a lot of time to provide
    necessary security for such a task.
    """

    def modal_save_func(self):
        new_addr = self.new_addr_line.displayText()
        if re.fullmatch("[0-9a-f]{64}", new_addr):
            self.modal_error_label.hide()
            self.hide()
            self.p_key = new_addr
            self.parent.update_pkey(self.p_key)
        else:
            self.new_addr_line.setText("")
            self.modal_error_label.setText(
                "Wrong address, account must be written in form : 'e91f...'(total length is 64 characters in hexadecimal form)."
            )
            self.modal_error_label.show()

    """
    This method is for the modal window, to return to the main screen from adding private key
    """

    def modal_cancel_func(self):
        self.modal_error_label.hide()
        self.hide()
示例#8
0
class ContractModal(QDialog):

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

        # This is modal window to add new contract to work with
        self.modal_group_box = QGroupBox("Contract")
        self.modal_error_label = QLabel("Wrong address, account must be written in form : '0x...'.")
        self.modal_group_layout = QFormLayout()
        self.new_addr_line = QLineEdit()
        self.modal_error_label.hide()
        self.modal_group_layout.addRow(self.modal_error_label)

        self.modal_group_layout.addRow(QLabel("Write address of new contract:"), self.new_addr_line)
        self.modal_add = QPushButton("Add")

        self.modal_add.clicked.connect(self.modal_add_func)
        self.modal_cancel = QPushButton("Cancel")
        self.modal_cancel.clicked.connect(self.modal_cancel_func)
        self.modal_group_layout.addRow(self.modal_add, self.modal_cancel)
        self.parent = parent
        self.setLayout(self.modal_group_layout)


    """
     This method adds address from textbox(in the modal window) to the list, and checks if it satisfies needed format
    """
    def modal_add_func(self):
        new_addr = self.new_addr_line.displayText()
        if re.fullmatch("0x[0-9A-Fa-f]{40}", new_addr):
            self.modal_error_label.hide()
            self.new_addr_line.setText("")
            self.hide()
            self.parent.add_cont_address(new_addr)
        else:
            self.new_addr_line.setText("")
            self.modal_error_label.setText("Wrong address, account must be written in form : '0x...'.")
            self.modal_error_label.show()

    """
    This method is for the modal window, to return to the main screen from adding new Registry smart contract
    """
    def modal_cancel_func(self):
        self.modal_error_label.hide()
        self.hide()
示例#9
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        openmc.capi.init(['-c'])

        self.setWindowTitle('OpenMC Plot Explorer')

        self.restored = False
        self.pixmap = None
        self.zoom = 100

        self.model = PlotModel()
        self.updateRelativeBases()
        self.restoreModelSettings()

        self.cellsModel = DomainTableModel(self.model.activeView.cells)
        self.materialsModel = DomainTableModel(self.model.activeView.materials)

        # Create viewing area
        self.frame = QScrollArea(self)
        self.frame.setAlignment(QtCore.Qt.AlignCenter)
        self.frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.setCentralWidget(self.frame)

        # Create plot image
        self.plotIm = PlotImage(self.model, self.frame, self)
        self.frame.setWidget(self.plotIm)

        # Dock
        self.dock = OptionsDock(self.model, FM, self)
        self.dock.setObjectName("OptionsDock")
        self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)

        # Color Dialog
        self.colorDialog = ColorDialog(self.model, FM, self)
        self.colorDialog.hide()

        # Restore Window Settings
        self.restoreWindowSettings()

        # Create menubar
        self.createMenuBar()

        # Status Bar
        self.coord_label = QLabel()
        self.statusBar().addPermanentWidget(self.coord_label)
        self.coord_label.hide()

        # Load Plot
        self.statusBar().showMessage('Generating Plot...')
        self.dock.updateDock()
        self.colorDialog.updateDialogValues()

        if self.restored:
            self.showCurrentView()
        else:
            # Timer allows GUI to render before plot finishes loading
            QtCore.QTimer.singleShot(0, self.model.generatePlot)
            QtCore.QTimer.singleShot(0, self.showCurrentView)

    # Create and update menus:
    def createMenuBar(self):
        self.mainMenu = self.menuBar()

        # File Menu
        self.saveImageAction = QAction("&Save Image As...", self)
        self.saveImageAction.setShortcut("Ctrl+Shift+S")
        self.saveImageAction.setToolTip('Save plot image')
        self.saveImageAction.setStatusTip('Save plot image')
        self.saveImageAction.triggered.connect(self.saveImage)

        self.saveViewAction = QAction("Save &View Settings...", self)
        self.saveViewAction.setShortcut(QtGui.QKeySequence.Save)
        self.saveViewAction.setStatusTip('Save current view settings')
        self.saveViewAction.triggered.connect(self.saveView)

        self.openAction = QAction("&Open View Settings...", self)
        self.openAction.setShortcut(QtGui.QKeySequence.Open)
        self.openAction.setToolTip('Open saved view settings')
        self.openAction.setStatusTip('Open saved view settings')
        self.openAction.triggered.connect(self.openView)

        self.quitAction = QAction("&Quit", self)
        self.quitAction.setShortcut(QtGui.QKeySequence.Quit)
        self.quitAction.setToolTip('Quit OpenMC Plot Explorer')
        self.quitAction.setStatusTip('Quit OpenMC Plot Explorer')
        self.quitAction.triggered.connect(self.close)

        self.fileMenu = self.mainMenu.addMenu('&File')
        self.fileMenu.addAction(self.saveImageAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.saveViewAction)
        self.fileMenu.addAction(self.openAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.quitAction)

        # Edit Menu
        self.applyAction = QAction("&Apply Changes", self)
        self.applyAction.setShortcut("Shift+Return")
        self.applyAction.setToolTip('Generate new view with changes applied')
        self.applyAction.setStatusTip('Generate new view with changes applied')
        self.applyAction.triggered.connect(self.applyChanges)

        self.undoAction = QAction('&Undo', self)
        self.undoAction.setShortcut(QtGui.QKeySequence.Undo)
        self.undoAction.setToolTip('Undo')
        self.undoAction.setStatusTip('Undo last plot view change')
        self.undoAction.setDisabled(True)
        self.undoAction.triggered.connect(self.undo)

        self.redoAction = QAction('&Redo', self)
        self.redoAction.setDisabled(True)
        self.redoAction.setToolTip('Redo')
        self.redoAction.setStatusTip('Redo last plot view change')
        self.redoAction.setShortcut(QtGui.QKeySequence.Redo)
        self.redoAction.triggered.connect(self.redo)

        self.restoreAction = QAction("&Restore Default Plot", self)
        self.restoreAction.setShortcut("Ctrl+R")
        self.restoreAction.setToolTip('Restore to default plot view')
        self.restoreAction.setStatusTip('Restore to default plot view')
        self.restoreAction.triggered.connect(self.restoreDefault)

        self.editMenu = self.mainMenu.addMenu('&Edit')
        self.editMenu.addAction(self.applyAction)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.undoAction)
        self.editMenu.addAction(self.redoAction)
        self.editMenu.addSeparator()
        self.editMenu.addAction(self.restoreAction)
        self.editMenu.addSeparator()
        self.editMenu.aboutToShow.connect(self.updateEditMenu)

        # Edit -> Basis Menu
        self.xyAction = QAction('&xy  ', self)
        self.xyAction.setCheckable(True)
        self.xyAction.setShortcut('Alt+X')
        self.xyAction.setToolTip('Change to xy basis')
        self.xyAction.setStatusTip('Change to xy basis')
        self.xyAction.triggered.connect(
            lambda: self.editBasis('xy', apply=True))

        self.xzAction = QAction('x&z  ', self)
        self.xzAction.setCheckable(True)
        self.xzAction.setShortcut('Alt+Z')
        self.xzAction.setToolTip('Change to xz basis')
        self.xzAction.setStatusTip('Change to xz basis')
        self.xzAction.triggered.connect(
            lambda: self.editBasis('xz', apply=True))

        self.yzAction = QAction('&yz  ', self)
        self.yzAction.setCheckable(True)
        self.yzAction.setShortcut('Alt+Y')
        self.yzAction.setToolTip('Change to yz basis')
        self.yzAction.setStatusTip('Change to yz basis')
        self.yzAction.triggered.connect(
            lambda: self.editBasis('yz', apply=True))

        self.basisMenu = self.editMenu.addMenu('&Basis')
        self.basisMenu.addAction(self.xyAction)
        self.basisMenu.addAction(self.xzAction)
        self.basisMenu.addAction(self.yzAction)
        self.basisMenu.aboutToShow.connect(self.updateBasisMenu)

        # Edit -> Color By Menu
        self.cellAction = QAction('&Cell', self)
        self.cellAction.setCheckable(True)
        self.cellAction.setShortcut('Alt+C')
        self.cellAction.setToolTip('Color by cell')
        self.cellAction.setStatusTip('Color plot by cell')
        self.cellAction.triggered.connect(
            lambda: self.editColorBy('cell', apply=True))

        self.materialAction = QAction('&Material', self)
        self.materialAction.setCheckable(True)
        self.materialAction.setShortcut('Alt+M')
        self.materialAction.setToolTip('Color by material')
        self.materialAction.setStatusTip('Color plot by material')
        self.materialAction.triggered.connect(
            lambda: self.editColorBy('material', apply=True))

        self.colorbyMenu = self.editMenu.addMenu('&Color By')
        self.colorbyMenu.addAction(self.cellAction)
        self.colorbyMenu.addAction(self.materialAction)
        self.colorbyMenu.aboutToShow.connect(self.updateColorbyMenu)

        self.editMenu.addSeparator()

        self.maskingAction = QAction('Enable &Masking', self)
        self.maskingAction.setShortcut('Ctrl+M')
        self.maskingAction.setCheckable(True)
        self.maskingAction.setToolTip('Toggle masking')
        self.maskingAction.setStatusTip('Toggle whether masking is enabled')
        self.maskingAction.triggered[bool].connect(
            lambda bool=bool: self.toggleMasking(bool, apply=True))
        self.editMenu.addAction(self.maskingAction)

        self.highlightingAct = QAction('Enable High&lighting', self)
        self.highlightingAct.setShortcut('Ctrl+L')
        self.highlightingAct.setCheckable(True)
        self.highlightingAct.setToolTip('Toggle highlighting')
        self.highlightingAct.setStatusTip(
            'Toggle whether highlighting is enabled')
        self.highlightingAct.triggered[bool].connect(
            lambda bool=bool: self.toggleHighlighting(bool, apply=True))
        self.editMenu.addAction(self.highlightingAct)

        # View Menu
        self.dockAction = QAction('Hide &Dock', self)
        self.dockAction.setShortcut("Ctrl+D")
        self.dockAction.setToolTip('Toggle dock visibility')
        self.dockAction.setStatusTip('Toggle dock visibility')
        self.dockAction.triggered.connect(self.toggleDockView)

        self.zoomAction = QAction('&Zoom...', self)
        self.zoomAction.setShortcut('Alt+Shift+Z')
        self.zoomAction.setToolTip('Edit zoom factor')
        self.zoomAction.setStatusTip('Edit zoom factor')
        self.zoomAction.triggered.connect(self.editZoomAct)

        self.viewMenu = self.mainMenu.addMenu('&View')
        self.viewMenu.addAction(self.dockAction)
        self.viewMenu.addSeparator()
        self.viewMenu.addAction(self.zoomAction)
        self.viewMenu.aboutToShow.connect(self.updateViewMenu)

        # Window Menu
        self.mainWindowAction = QAction('&Main Window', self)
        self.mainWindowAction.setShortcut('Alt+W')
        self.mainWindowAction.setCheckable(True)
        self.mainWindowAction.setToolTip('Bring main window to front')
        self.mainWindowAction.setStatusTip('Bring main window to front')
        self.mainWindowAction.triggered.connect(self.showMainWindow)

        self.colorDialogAction = QAction('Color &Options', self)
        self.colorDialogAction.setShortcut('Alt+D')
        self.colorDialogAction.setCheckable(True)
        self.colorDialogAction.setToolTip('Bring Color Dialog to front')
        self.colorDialogAction.setStatusTip('Bring Color Dialog to front')
        self.colorDialogAction.triggered.connect(self.showColorDialog)

        self.windowMenu = self.mainMenu.addMenu('&Window')
        self.windowMenu.addAction(self.mainWindowAction)
        self.windowMenu.addAction(self.colorDialogAction)
        self.windowMenu.aboutToShow.connect(self.updateWindowMenu)

    def updateEditMenu(self):
        changed = self.model.currentView != self.model.defaultView
        self.restoreAction.setDisabled(not changed)

        self.maskingAction.setChecked(self.model.currentView.masking)
        self.highlightingAct.setChecked(self.model.currentView.highlighting)

        self.undoAction.setText(f'&Undo ({len(self.model.previousViews)})')
        self.redoAction.setText(f'&Redo ({len(self.model.subsequentViews)})')

    def updateBasisMenu(self):
        self.xyAction.setChecked(self.model.currentView.basis == 'xy')
        self.xzAction.setChecked(self.model.currentView.basis == 'xz')
        self.yzAction.setChecked(self.model.currentView.basis == 'yz')

    def updateColorbyMenu(self):
        cv = self.model.currentView
        self.cellAction.setChecked(cv.colorby == 'cell')
        self.materialAction.setChecked(cv.colorby == 'material')

    def updateViewMenu(self):
        if self.dock.isVisible():
            self.dockAction.setText('Hide &Dock')
        else:
            self.dockAction.setText('Show &Dock')

    def updateWindowMenu(self):
        self.colorDialogAction.setChecked(self.colorDialog.isActiveWindow())
        self.mainWindowAction.setChecked(self.isActiveWindow())

    # Menu and shared methods:

    def saveImage(self):
        filename, ext = QFileDialog.getSaveFileName(self, "Save Plot Image",
                                                    "untitled",
                                                    "Images (*.png *.ppm)")
        if filename:
            if "." not in filename:
                filename += ".png"
            self.plotIm.figure.savefig(filename, transparent=True)
            self.statusBar().showMessage('Plot Image Saved', 5000)

    def saveView(self):
        filename, ext = QFileDialog.getSaveFileName(self, "Save View Settings",
                                                    "untitled",
                                                    "View Settings (*.pltvw)")
        if filename:
            if "." not in filename:
                filename += ".pltvw"

            saved = {
                'default': self.model.defaultView,
                'current': self.model.currentView
            }

            with open(filename, 'wb') as file:
                pickle.dump(saved, file)

    def openView(self):
        filename, ext = QFileDialog.getOpenFileName(self, "Open View Settings",
                                                    ".", "*.pltvw")
        if filename:
            try:
                with open(filename, 'rb') as file:
                    saved = pickle.load(file)
            except Exception:
                message = 'Error loading plot settings'
                saved = {'default': None, 'current': None}
            if saved['default'] == self.model.defaultView:
                self.model.activeView = saved['current']
                self.dock.updateDock()
                self.applyChanges()
                message = f'{filename} settings loaded'
            else:
                message = 'Error loading plot settings. Incompatible model.'
            self.statusBar().showMessage(message, 5000)

    def applyChanges(self):
        if self.model.activeView != self.model.currentView:
            self.statusBar().showMessage('Generating Plot...')
            QApplication.processEvents()

            self.model.storeCurrent()
            self.model.subsequentViews = []
            self.model.generatePlot()
            self.resetModels()
            self.showCurrentView()

        else:
            self.statusBar().showMessage('No changes to apply.', 3000)

    def undo(self):
        self.statusBar().showMessage('Generating Plot...')
        QApplication.processEvents()

        self.model.undo()
        self.resetModels()
        self.showCurrentView()
        self.dock.updateDock()
        self.colorDialog.updateDialogValues()

        if not self.model.previousViews:
            self.undoAction.setDisabled(True)
        self.redoAction.setDisabled(False)

    def redo(self):
        self.statusBar().showMessage('Generating Plot...')
        QApplication.processEvents()

        self.model.redo()
        self.resetModels()
        self.showCurrentView()
        self.dock.updateDock()
        self.colorDialog.updateDialogValues()

        if not self.model.subsequentViews:
            self.redoAction.setDisabled(True)
        self.undoAction.setDisabled(False)

    def restoreDefault(self):
        if self.model.currentView != self.model.defaultView:

            self.statusBar().showMessage('Generating Plot...')
            QApplication.processEvents()

            self.model.storeCurrent()
            self.model.activeView = copy.deepcopy(self.model.defaultView)
            self.model.generatePlot()
            self.resetModels()
            self.showCurrentView()
            self.dock.updateDock()
            self.colorDialog.updateDialogValues()

            self.model.subsequentViews = []

    def editBasis(self, basis, apply=False):
        self.model.activeView.basis = basis
        self.dock.updateBasis()
        if apply:
            self.applyChanges()

    def editColorBy(self, domain_kind, apply=False):
        self.model.activeView.colorby = domain_kind
        self.dock.updateColorBy()
        self.colorDialog.updateColorBy()
        if apply:
            self.applyChanges()

    def toggleMasking(self, state, apply=False):
        self.model.activeView.masking = bool(state)
        self.colorDialog.updateMasking()
        if apply:
            self.applyChanges()

    def toggleHighlighting(self, state, apply=False):
        self.model.activeView.highlighting = bool(state)
        self.colorDialog.updateHighlighting()
        if apply:
            self.applyChanges()

    def toggleDockView(self):
        if self.dock.isVisible():
            self.dock.hide()
            if not self.isMaximized() and not self.dock.isFloating():
                self.resize(self.width() - self.dock.width(), self.height())
        else:
            self.dock.setVisible(True)
            if not self.isMaximized() and not self.dock.isFloating():
                self.resize(self.width() + self.dock.width(), self.height())
        self.resizePixmap()
        self.showMainWindow()

    def editZoomAct(self):
        percent, ok = QInputDialog.getInt(self, "Edit Zoom", "Zoom Percent:",
                                          self.dock.zoomBox.value(), 25, 2000)
        if ok:
            self.dock.zoomBox.setValue(percent)

    def editZoom(self, value):
        self.zoom = value
        self.resizePixmap()
        self.dock.zoomBox.setValue(value)

    def showMainWindow(self):
        self.raise_()
        self.activateWindow()

    def showColorDialog(self):
        self.colorDialog.show()
        self.colorDialog.raise_()
        self.colorDialog.activateWindow()

    # Dock methods:

    def editSingleOrigin(self, value, dimension):
        self.model.activeView.origin[dimension] = value

    def editPlotAlpha(self, value):
        self.model.activeView.plotAlpha = value
        self.dock.updatePlotAlpha()

    def editWidth(self, value):
        self.model.activeView.width = value
        self.onRatioChange()
        self.dock.updateWidth()

    def editHeight(self, value):
        self.model.activeView.height = value
        self.onRatioChange()
        self.dock.updateHeight()

    def toggleAspectLock(self, state):
        self.model.activeView.aspectLock = bool(state)
        self.onRatioChange()
        self.dock.updateAspectLock()

    def editVRes(self, value):
        self.model.activeView.v_res = value
        self.dock.updateVRes()

    def editHRes(self, value):
        self.model.activeView.h_res = value
        self.onRatioChange()
        self.dock.updateHRes()

    # Color dialog methods:

    def editMaskingColor(self):
        current_color = self.model.activeView.maskBackground
        dlg = QColorDialog(self)

        dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
        if dlg.exec_():
            new_color = dlg.currentColor().getRgb()[:3]
            self.model.activeView.maskBackground = new_color
            self.colorDialog.updateMaskingColor()

    def editHighlightColor(self):
        current_color = self.model.activeView.highlightBackground
        dlg = QColorDialog(self)

        dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
        if dlg.exec_():
            new_color = dlg.currentColor().getRgb()[:3]
            self.model.activeView.highlightBackground = new_color
            self.colorDialog.updateHighlightColor()

    def editAlpha(self, value):
        self.model.activeView.highlightAlpha = value

    def editSeed(self, value):
        self.model.activeView.highlightSeed = value

    def editBackgroundColor(self, apply=False):
        current_color = self.model.activeView.plotBackground
        dlg = QColorDialog(self)

        dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
        if dlg.exec_():
            new_color = dlg.currentColor().getRgb()[:3]
            self.model.activeView.plotBackground = new_color
            self.colorDialog.updateBackgroundColor()

        if apply:
            self.applyChanges()

    # Plot image methods

    def editPlotOrigin(self, xOr, yOr, zOr=None, apply=False):
        if zOr != None:
            self.model.activeView.origin = [xOr, yOr, zOr]
        else:
            origin = [None, None, None]
            origin[self.xBasis] = xOr
            origin[self.yBasis] = yOr
            origin[self.zBasis] = self.model.activeView.origin[self.zBasis]
            self.model.activeView.origin = origin

        self.dock.updateOrigin()

        if apply:
            self.applyChanges()

    def revertDockControls(self):
        self.dock.revertToCurrent()

    def editDomainColor(self, kind, id):
        if kind == 'Cell':
            domain = self.model.activeView.cells
        else:
            domain = self.model.activeView.materials

        current_color = domain[id].color
        dlg = QColorDialog(self)

        if isinstance(current_color, tuple):
            dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
        elif isinstance(current_color, str):
            current_color = openmc.plots._SVG_COLORS[current_color]
            dlg.setCurrentColor(QtGui.QColor.fromRgb(*current_color))
        if dlg.exec_():
            new_color = dlg.currentColor().getRgb()[:3]
            domain[id].color = new_color

        self.applyChanges()

    def toggleDomainMask(self, state, kind, id):
        if kind == 'Cell':
            domain = self.model.activeView.cells
        else:
            domain = self.model.activeView.materials

        domain[id].masked = bool(state)
        self.applyChanges()

    def toggleDomainHighlight(self, state, kind, id):
        if kind == 'Cell':
            domain = self.model.activeView.cells
        else:
            domain = self.model.activeView.materials

        domain[id].highlighted = bool(state)
        self.applyChanges()

    # Helper methods:

    def restoreWindowSettings(self):
        settings = QtCore.QSettings()

        self.resize(settings.value("mainWindow/Size", QtCore.QSize(800, 600)))
        self.move(
            settings.value("mainWindow/Position", QtCore.QPoint(100, 100)))
        self.restoreState(settings.value("mainWindow/State"))

        self.colorDialog.resize(
            settings.value("colorDialog/Size", QtCore.QSize(400, 500)))
        self.colorDialog.move(
            settings.value("colorDialog/Position", QtCore.QPoint(600, 200)))
        self.colorDialog.setVisible(
            bool(settings.value("colorDialog/Visible", 0)))

    def restoreModelSettings(self):
        if os.path.isfile("plot_settings.pkl"):

            with open('plot_settings.pkl', 'rb') as file:
                model = pickle.load(file)

            if model.defaultView == self.model.defaultView:
                self.model.currentView = model.currentView
                self.model.activeView = copy.deepcopy(model.currentView)
                self.model.previousViews = model.previousViews
                self.model.subsequentViews = model.subsequentViews
                if os.path.isfile('plot_ids.binary') \
                    and os.path.isfile('plot.ppm'):
                    self.restored = True

    def resetModels(self):
        self.cellsModel = DomainTableModel(self.model.activeView.cells)
        self.materialsModel = DomainTableModel(self.model.activeView.materials)
        self.cellsModel.beginResetModel()
        self.cellsModel.endResetModel()
        self.materialsModel.beginResetModel()
        self.materialsModel.endResetModel()
        self.colorDialog.updateDomainTabs()

    def showCurrentView(self):
        self.resizePixmap()
        self.updateScale()
        self.updateRelativeBases()

        if self.model.previousViews:
            self.undoAction.setDisabled(False)
        if self.model.subsequentViews:
            self.redoAction.setDisabled(False)
        else:
            self.redoAction.setDisabled(True)

        self.statusBar().showMessage('Done', 1000)
        self.adjustWindow()

    def updateScale(self):
        cv = self.model.currentView
        self.scale = (cv.h_res / cv.width, cv.v_res / cv.height)

    def updateRelativeBases(self):
        cv = self.model.currentView
        self.xBasis = 0 if cv.basis[0] == 'x' else 1
        self.yBasis = 1 if cv.basis[1] == 'y' else 2
        self.zBasis = 3 - (self.xBasis + self.yBasis)

    def adjustWindow(self):
        self.screen = app.desktop().screenGeometry()
        self.setMaximumSize(self.screen.width(), self.screen.height())

    def onRatioChange(self):
        av = self.model.activeView
        if av.aspectLock:
            ratio = av.width / max(av.height, .001)
            av.v_res = int(av.h_res / ratio)
            self.dock.updateVRes()

    def showCoords(self, xPlotPos, yPlotPos):
        cv = self.model.currentView
        if cv.basis == 'xy':
            coords = (f"({round(xPlotPos, 2)}, {round(yPlotPos, 2)}, "
                      f"{round(cv.origin[2], 2)})")
        elif cv.basis == 'xz':
            coords = (f"({round(xPlotPos, 2)}, {round(cv.origin[1], 2)}, "
                      f"{round(yPlotPos, 2)})")
        else:
            coords = (f"({round(cv.origin[0], 2)}, {round(xPlotPos, 2)}, "
                      f"{round(yPlotPos, 2)})")
        self.coord_label.setText(f'{coords}')

    def resizePixmap(self):
        z = self.zoom / 100.
        self.plotIm.setPixmap(self.frame.width() * z, self.frame.height() * z)
        self.plotIm.adjustSize()

    def moveEvent(self, event):
        self.adjustWindow()

    def resizeEvent(self, event):
        if self.pixmap:
            self.adjustWindow()
            self.updateScale()

    def closeEvent(self, event):
        settings = QtCore.QSettings()
        settings.setValue("mainWindow/Size", self.size())
        settings.setValue("mainWindow/Position", self.pos())
        settings.setValue("mainWindow/State", self.saveState())

        settings.setValue("colorDialog/Size", self.colorDialog.size())
        settings.setValue("colorDialog/Position", self.colorDialog.pos())
        visible = int(self.colorDialog.isVisible())
        settings.setValue("colorDialog/Visible", visible)

        if len(self.model.previousViews) > 10:
            self.model.previousViews = self.model.previousViews[-10:]
        if len(self.model.subsequentViews) > 10:
            self.model.subsequentViews = self.model.subsequentViews[-10:]

        with open('plot_settings.pkl', 'wb') as file:
            pickle.dump(self.model, file)
示例#10
0
class App(QWidget):
    def __init__(self, bk, prefs):
        super().__init__()

        self.bk = bk
        self.prefs = prefs
        self.update = False

        # Install translator for the DOCXImport plugin dialog.
        # Use the Sigil language setting unless manually overridden.
        plugin_translator = QTranslator()
        if prefs['language_override'] is not None:
            print('Plugin preferences language override in effect')
            qmf = '{}_{}'.format(bk._w.plugin_name.lower(),
                                 prefs['language_override'])
        else:
            qmf = '{}_{}'.format(bk._w.plugin_name.lower(), bk.sigil_ui_lang)
        print(
            qmf,
            os.path.join(bk._w.plugin_dir, bk._w.plugin_name, 'translations'))
        plugin_translator.load(
            qmf,
            os.path.join(bk._w.plugin_dir, bk._w.plugin_name, 'translations'))
        print(QCoreApplication.instance().installTranslator(plugin_translator))

        self._ok_to_close = False

        self.FTYPE_MAP = {
            'smap': {
                'title': _translate('App', 'Select custom style-map file'),
                'defaultextension': '.txt',
                'filetypes': 'Text Files (*.txt);;All files (*.*)',
            },
            'css': {
                'title': _translate('App', 'Select custom CSS file'),
                'defaultextension': '.css',
                'filetypes': 'CSS Files (*.css)',
            },
            'docx': {
                'title': _translate('App', 'Select DOCX file'),
                'defaultextension': '.docx',
                'filetypes': 'DOCX Files (*.docx)',
            },
        }

        # Check online github files for newer version
        if self.prefs['check_for_updates']:
            self.update, self.newversion = self.check_for_update()
        self.initUI()

    def initUI(self):
        main_layout = QVBoxLayout(self)

        self.setWindowTitle('DOCXImport')
        self.upd_layout = QVBoxLayout()
        self.update_label = QLabel()
        self.update_label.setAlignment(Qt.AlignCenter)
        self.upd_layout.addWidget(self.update_label)
        self.get_update_button = QPushButton()
        self.get_update_button.clicked.connect(self.get_update)
        self.upd_layout.addWidget(self.get_update_button)
        main_layout.addLayout(self.upd_layout)
        if not self.update:
            self.update_label.hide()
            self.get_update_button.hide()

        self.details_grid = QGridLayout()
        self.epub2_select = QRadioButton()
        self.epub2_select.setText('EPUB2')
        self.epubType = QButtonGroup()
        self.epubType.addButton(self.epub2_select)
        self.details_grid.addWidget(self.epub2_select, 0, 0, 1, 1)
        self.checkbox_get_updates = QCheckBox()
        self.details_grid.addWidget(self.checkbox_get_updates, 0, 1, 1, 1)
        self.epub3_select = QRadioButton()
        self.epub3_select.setText('EPUB3')
        self.epubType.addButton(self.epub3_select)
        self.details_grid.addWidget(self.epub3_select, 1, 0, 1, 1)
        main_layout.addLayout(self.details_grid)
        self.checkbox_get_updates.setChecked(self.prefs['check_for_updates'])
        if self.prefs['epub_version'] == '2.0':
            self.epub2_select.setChecked(True)
        elif self.prefs['epub_version'] == '3.0':
            self.epub3_select.setChecked(True)
        else:
            self.epub2_select.setChecked(True)

        self.groupBox = QGroupBox()
        self.groupBox.setTitle('')
        self.verticalLayout_2 = QVBoxLayout(self.groupBox)
        self.docx_grid = QGridLayout()
        self.docx_label = QLabel()
        self.docx_grid.addWidget(self.docx_label, 0, 0, 1, 1)
        self.docx_path = QLineEdit()
        self.docx_grid.addWidget(self.docx_path, 1, 0, 1, 1)
        self.choose_docx_button = QPushButton()
        self.choose_docx_button.setText('...')
        self.docx_grid.addWidget(self.choose_docx_button, 1, 1, 1, 1)
        self.verticalLayout_2.addLayout(self.docx_grid)
        self.choose_docx_button.clicked.connect(
            lambda: self.fileChooser('docx', self.docx_path))
        if len(self.prefs['lastDocxPath']):
            self.docx_path.setText(self.prefs['lastDocxPath'])
        self.docx_path.setEnabled(False)

        self.smap_grid = QGridLayout()
        self.checkbox_smap = QCheckBox(self.groupBox)
        self.smap_grid.addWidget(self.checkbox_smap, 0, 0, 1, 1)
        self.cust_smap_path = QLineEdit(self.groupBox)
        self.smap_grid.addWidget(self.cust_smap_path, 1, 0, 1, 1)
        self.choose_smap_button = QPushButton(self.groupBox)
        self.choose_smap_button.setText('...')
        self.smap_grid.addWidget(self.choose_smap_button, 1, 1, 1, 1)
        self.verticalLayout_2.addLayout(self.smap_grid)
        self.checkbox_smap.setChecked(self.prefs['useSmap'])
        self.checkbox_smap.stateChanged.connect(lambda: self.chkBoxActions(
            self.checkbox_smap, self.choose_smap_button))
        self.choose_smap_button.clicked.connect(
            lambda: self.fileChooser('smap', self.cust_smap_path, self.
                                     checkbox_smap, self.choose_smap_button))
        if len(self.prefs['useSmapPath']):
            self.cust_smap_path.setText(self.prefs['useSmapPath'])
        self.cust_smap_path.setEnabled(False)
        self.chkBoxActions(self.checkbox_smap, self.choose_smap_button)

        self.css_grid = QGridLayout()
        self.checkbox_css = QCheckBox(self.groupBox)
        self.css_grid.addWidget(self.checkbox_css, 0, 0, 1, 1)
        self.cust_css_path = QLineEdit(self.groupBox)
        self.css_grid.addWidget(self.cust_css_path, 1, 0, 1, 1)
        self.choose_css_button = QPushButton(self.groupBox)
        self.choose_css_button.setText('...')
        self.css_grid.addWidget(self.choose_css_button, 1, 1, 1, 1)
        self.verticalLayout_2.addLayout(self.css_grid)
        self.checkbox_css.setChecked(self.prefs['useCss'])
        self.checkbox_css.stateChanged.connect(lambda: self.chkBoxActions(
            self.checkbox_css, self.choose_css_button))
        self.choose_css_button.clicked.connect(
            lambda: self.fileChooser('css', self.cust_css_path, self.
                                     checkbox_css, self.choose_css_button))
        if len(self.prefs['useCssPath']):
            self.cust_css_path.setText(self.prefs['useCssPath'])
        self.cust_css_path.setEnabled(False)
        self.chkBoxActions(self.checkbox_css, self.choose_css_button)

        main_layout.addWidget(self.groupBox)
        self.checkbox_debug = QCheckBox()
        main_layout.addWidget(self.checkbox_debug)
        self.checkbox_debug.setChecked(self.prefs['debug'])

        spacerItem = QSpacerItem(20, 15, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        main_layout.addItem(spacerItem)

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._ok_clicked)
        button_box.rejected.connect(self._cancel_clicked)
        main_layout.addWidget(button_box)
        self.retranslateUi(self)
        if self.prefs['qt_geometry'] is not None:
            try:
                self.restoreGeometry(
                    QByteArray.fromHex(
                        self.prefs['qt_geometry'].encode('ascii')))
            except:
                pass
        self.show()

    def retranslateUi(self, App):
        self.update_label.setText(_translate('App', 'Plugin Update Available'))
        self.get_update_button.setText(_translate('App',
                                                  'Go to download page'))
        self.checkbox_get_updates.setText(
            _translate('App', 'Check for plugin updates'))
        self.docx_label.setText(_translate('App', 'DOCX File to import'))
        self.checkbox_smap.setText(_translate('App', 'Use Custom Style Map'))
        self.checkbox_css.setText(_translate('App', 'Use Custom CSS'))
        self.checkbox_debug.setText(
            _translate('App',
                       'Debug Mode (change takes effect next plugin run)'))

    def fileChooser(self, ftype, qlineedit, qcheck=None, qbutton=None):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        title = self.FTYPE_MAP[ftype]['title']
        startfolder = self.prefs['lastDir'][ftype]
        ffilter = self.FTYPE_MAP[ftype]['filetypes']
        inpath, _ = QFileDialog.getOpenFileName(self,
                                                title,
                                                startfolder,
                                                ffilter,
                                                options=options)
        if len(inpath):
            qlineedit.setEnabled(True)
            qlineedit.setText(os.path.normpath(inpath))
            self.prefs['lastDir'][ftype] = os.path.dirname(inpath)
            qlineedit.setEnabled(False)
        else:
            if qcheck is not None:
                qcheck.setChecked(False)
            if qbutton is not None:
                qbutton.setEnabled(False)

    def chkBoxActions(self, chk, btn):
        btn.setEnabled(chk.isChecked())

    def cmdDo(self):
        global _DETAILS
        self.prefs['qt_geometry'] = self.saveGeometry().toHex().data().decode(
            'ascii')
        self.prefs['check_for_updates'] = self.checkbox_get_updates.isChecked()
        self.prefs['epub_version'] = self.epubType.checkedButton().text(
        )[-1] + '.0'
        self.prefs['debug'] = self.checkbox_debug.isChecked()
        _DETAILS['vers'] = self.epubType.checkedButton().text()[-1] + '.0'
        self.prefs['useSmap'] = self.checkbox_smap.isChecked()
        if self.checkbox_smap.isChecked():
            if len(self.cust_smap_path.text()):
                self.prefs['useSmapPath'] = self.cust_smap_path.text()
                _DETAILS['smap'] = (self.checkbox_smap.isChecked(),
                                    self.cust_smap_path.text())
            else:
                # Message box that no file is selected
                return
        self.prefs['useCss'] = self.checkbox_css.isChecked()
        if self.checkbox_css.isChecked():
            if len(self.cust_css_path.text()):
                self.prefs['useCssPath'] = self.cust_css_path.text()
                _DETAILS['css'] = (self.checkbox_css.isChecked(),
                                   self.cust_css_path.text())
            else:
                # Message box that no file is selected
                return
        if len(self.docx_path.text()):
            self.prefs['lastDocxPath'] = self.docx_path.text()
            _DETAILS['docx'] = self.docx_path.text()
        else:
            # Message box that no file is selected
            return

    def check_for_update(self):
        '''Use updatecheck.py to check for newer versions of the plugin'''
        chk = UpdateChecker(self.prefs['last_time_checked'], self.bk._w)
        update_available, online_version, time = chk.update_info()
        # update preferences with latest date/time/version
        self.prefs['last_time_checked'] = time
        if online_version is not None:
            self.prefs['last_online_version'] = online_version
        if update_available:
            return (True, online_version)
        return (False, online_version)

    def get_update(self):
        url = DOWNLOAD_PAGE
        if self.update:
            latest = '/tag/v{}'.format(self.newversion)
            url = url + latest
        webbrowser.open_new_tab(url)

    def _ok_clicked(self):
        self._ok_to_close = True
        self.cmdDo()
        self.bk.savePrefs(self.prefs)
        QCoreApplication.instance().quit()

    def _cancel_clicked(self):
        self._ok_to_close = True
        '''Close aborting any changes'''
        self.prefs['qt_geometry'] = self.saveGeometry().toHex().data().decode(
            'ascii')
        self.prefs['check_for_updates'] = self.checkbox_get_updates.isChecked()
        self.prefs['debug'] = self.checkbox_debug.isChecked()
        self.bk.savePrefs(self.prefs)
        QCoreApplication.instance().quit()

    def closeEvent(self, event):
        if self._ok_to_close:
            event.accept()  # let the window close
        else:
            self._cancel_clicked()
示例#11
0
class QWidget_PlaceholderText(QWidget):
    """QTableView or Tree with palceholder text if empty.

    This class extends the `QWidget` class.
    """
    __placeholder_text = "The table is empty."

    def __init__(self, placeholder_text: str = None):
        """
        Args:
            placeholder_text (str): Placeholder text..  Defaults to None.
        """
        self._placeholder_text = placeholder_text if placeholder_text else self.__placeholder_text

        self._placeholder_label = QLabel(self._placeholder_text, self)
        self.setup_placeholder_label()

    def setup_placeholder_label(self):
        """QComponents will be displayed here when you create them."""
        self.update_placeholder_text()

        if not self.layout():
            layout = QVBoxLayout()
            self.setLayout(layout)

        self.layout().addWidget(self._placeholder_label)

    def update_placeholder_text(self, text=None):
        """Update the placeholder text to the given string.

        Args:
            text (str): New placeholder text..  Defaults to None.
        """
        if text:
            self._placeholder_text = text

        label = self._placeholder_label
        label.setText(self._placeholder_text)

        # Text
        label.setWordWrap(True)
        label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

        # transperant
        label.setAutoFillBackground(False)
        label.setAttribute(Qt.WA_TranslucentBackground)

        # color PlaceholderText
        palette = self.palette()
        # This enum value has been introduced in Qt 5.12
        if hasattr(palette, 'PlaceholderText'):
            placeholder_color = palette.PlaceholderText
        else:
            placeholder_color = palette.WindowText
        color = palette.color(placeholder_color)
        palette.setColor(palette.Text, color)
        palette.setColor(palette.Text, color)
        label.setPalette(palette)

    def show_placeholder_text(self):
        """Show the placeholder text."""
        self._placeholder_label.show()

    def hide_placeholder_text(self):
        """Hide the placeholder text."""
        self._placeholder_label.hide()
示例#12
0
class SequenceEditor(SchemeEditor):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._sequences = []
        """All sequences as a list of tuples (seq_as_graph, seq_as_list, radio_button)"""

        self.selector_placeholder = QLabel("(none)")
        self.selector_placeholder.setAlignment(Qt.AlignCenter)

        self.selector = None
        self.selector_button_group = None

        self.selector_scroll_area = QScrollArea()
        self.selector_dock = QDockWidget("Active Sequence", self)
        self.selector_dock.setWidget(self.selector_scroll_area)
        self.selector_dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
        self.selector_dock.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
        self.addDockWidget(Qt.LeftDockWidgetArea, self.selector_dock)

    def setScheme(self, scheme):
        super().setScheme(scheme)
        self.scheme().graphChanged.connect(self._updateSelector)
        self._updateSelector()

    def sequences(self):
        """Return a list of tuples (sequence_as_graph, sequence_as_list, sequence_button)."""
        return self._sequences
    
    def selectedSequence(self):
        """Return a tuple (sequence_as_graph, sequence_as_list, sequence_button) of the selected sequence."""
        checked = [s for s in self.sequences() if s[2].isChecked()]
        
        assert len(checked) <= 1
        if len(checked) == 1:
            return checked[0]
        return None

    def _updateSelector(self):
        sequences = list(self._possibleSequences())
        
        # Build a new widget with all the new options
        selector = QWidget()
        layout = QVBoxLayout()
        layout.setSizeConstraint(layout.SetMinAndMaxSize)
        layout.addWidget(self.selector_placeholder)
        selector.setLayout(layout)
        self.selector_scroll_area.setWidget(selector)
        self.selector_button_group = QButtonGroup()
        self.selector = selector
        
        if len(sequences) == 0:
            self.selector_placeholder.show()
            return
        self.selector_placeholder.hide()

        # Some black magic because of problems with scopes
        def selectSequence(seq):
            self.scheme().clearSelection()
            seq[0].selectAll()

        def makeSelectSequence(seq):
            return lambda: selectSequence(seq)
        # End of black magic

        self._sequences = []
        for sgraph, slist in sequences:
            label = " → ".join([node.title() for node in slist])

            button = QRadioButton(label)
            button.clicked.connect(makeSelectSequence((sgraph, slist)))

            self.selector_button_group.addButton(button)
            layout.addWidget(button)
            self._sequences.append((sgraph, slist, button))
        
        # Now that the new widget was built, determine which point should be selected considering previous selection
        selected = self.selectedSequence()

        if selected is None:
            # If no previous selection, select the first one
            self._sequences[0][2].setChecked(True)
            return

        candidates = []
        for sgraph, slist, button in self._sequences:
            # Analyze every new option
            if selected[0] <= sgraph:
                # If old selection is a subset of a new option, that means a new node was attached and current selection
                # should be expanded
                button.setChecked(True)
                return
            
            if sgraph <= selected[0]:
                # This option is a subset of previous option, which means that something was deleted. If an edge was
                # removed, there may be other parts of previous options, add them all to candidates for new selection.
                candidates.append((sgraph, slist, button))

        if len(candidates) == 0:
            # If there are no candidates, select the first option.
            self._sequences[0][2].setChecked(True)
            return

        for node in selected[1]:
            # For each node in order in prev. selection, see if any candidates have it. Select the first mathcing one.
            for sgraph, slist, button in candidates:
                if node in sgraph:
                    button.setChecked(True)
                    return

    def _possibleSequences(self):
        """Return a list of tuples, where each tuple represents a possible experiment sequence.
        Tuple contains 2 items: a graph-view of the sequence, and a list of nodes of that sequence in order.
        """
        g = self.scheme().graph

        for node in g.nodes:
            if len(node.inputs) == 0 or len(list(node.inputs[0].edges)) == 0:
                for sequence in self._possibleSequencesFrom(node):
                    yield sequence

    def _possibleSequencesFrom(self, node):
        """Return a list of tuples, where each tuple represents a possible experiment sequence starting from this node.
        Tuple contains 2 items: a graph-view of the sequence, and a list of nodes of that sequence in order.
        """
        has_sequences = False

        for out in node.outputs:
            for edge in out.edges:
                connected = edge.targetNode()

                if connected is None:
                    # Filter for edges with no target nodes. These are usually fake edges that the user drags.
                    # When they drop and become real, they will have a node.
                    continue

                for sequence_graph, sequence_list in self._possibleSequencesFrom(connected):
                    sequence_graph.add(node)
                    sequence_graph.add(edge)
                    sequence_list.insert(0, node)
                    
                    yield (sequence_graph, sequence_list)
                    has_sequences = True
        
        if not has_sequences:
            # If no sequences could be built, this node is the final node.
            # In this case, just yield itself.
            result = (Graph(), list())
            result[0].add(node)
            result[1].append(node)
            yield result
class ExerciseStatusBar(QStatusBar):
    # TODO: Docstring me and all methods

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

        # Icon
        self.iconWidget = QLabel(self)
        icons_base_dir = cvars.get("icons.path")
        error_icon_path = fs.path_helper(icons_base_dir) / 'cancel.png'
        success_icon_path = fs.path_helper(icons_base_dir) / 'checked.png'
        self.error_pixmap = QPixmap(str(error_icon_path.resolve()))
        self.success_pixmap = QPixmap(str(success_icon_path.resolve()))
        self.iconWidget.setScaledContents(True)
        self.iconWidget.setMaximumSize(self.height(), self.height())

        # Message
        self.messageWidget = QLabel("", self)

        # Insert icon and message
        self.insertWidget(0, self.iconWidget)
        self.insertWidget(1, self.messageWidget)
        self.show_success_icon()  # Trick: the status bar adapts its height
        self.hide_icon()

        # Verbose mode
        self.display_success_msgs = cvars.get(
            'display.display_success_messages', True)

    def show_error_icon(self):
        self.iconWidget.setPixmap(self.error_pixmap)
        self.iconWidget.show()

    def show_success_icon(self):
        self.iconWidget.setPixmap(self.success_pixmap)
        self.iconWidget.show()

    def hide_icon(self):
        self.iconWidget.hide()

    def set_message(self, msg: str):
        self.messageWidget.setText(msg)

    def erase(self):
        self.set_message("")
        self.hide_icon()

    @Slot()
    def show_normal_msg(self, msg):
        log.debug("StatusBar: show " + msg)
        self.hide_icon()
        self.set_message(msg)

    def manage_msgs(self, proof_step):
        """
        Display a message in the status bar. Three kinds of messages are
        considered: new goal, error or success.
        - New goal msgs are normal msgs, i.e. they will remain in the status
        bar unless they are hidden temporarily by a temporary msg.
        e.g. "First case: we assume a in A".
        - success and error msgs are temporary msgs.
        """

        #log.debug(f"Display msg: "
        #          f"{proof_step.error_msg, proof_step.success_msg}")
        if proof_step.is_error():
            tmp_msg = proof_step.error_msg
        else:
            tmp_msg = proof_step.success_msg
        # Capitalize first char but do not un-capitalize the remaining
        if tmp_msg:  # Fixme: remove and capitalize msgs correctly!
            tmp_msg = tmp_msg[0].capitalize() + tmp_msg[1:]

        if proof_step.is_error():
            log.debug("StatusBar: " + tmp_msg)
            self.show_error_icon()
            self.set_message(tmp_msg)
        elif proof_step.success_msg and self.display_success_msgs:
            log.debug("StatusBar: " + tmp_msg)
            self.show_success_icon()
            self.set_message(tmp_msg)
        else:
            self.hide_icon()
            tmp_msg = ""

        if proof_step.new_goals:
            new_goal = proof_step.new_goals[-1]
            if new_goal:
                # Set QTimer for normal msg
                if tmp_msg:
                    log.debug("StatusBar timer " + new_goal.msg)
                    timer = QTimer(self)
                    func = partial(self.show_normal_msg, new_goal.msg)
                    timer.singleShot(3000, func)  # 3000 = 3sec
                else:  # Show immediately
                    self.show_normal_msg(new_goal.msg)
示例#14
0
class fontWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.fontName = '微软雅黑'
        self.fontSize = 60
        self.fontBold = True
        self.fontItalic = False
        self.fontUnderline = False
        self.fontStrikeout = False
        fontBold = '粗体' if self.fontBold else ''
        fontItalic = '斜体' if self.fontItalic else ''
        fontUnderline = '下划线' if self.fontUnderline else ''
        fontStrikeOut = '删除线' if self.fontStrikeout else ''
        self.fontColor = '#ffffff'
        self.secondColor = '#000000'
        self.outlineColor = '#000000'
        self.shadowColor = '#696969'

        self.optionLayout = QGridLayout()
        self.setLayout(self.optionLayout)
        self.fontSelect = QPushButton(
            '%s%s号%s%s%s%s' % (self.fontName, self.fontSize, fontBold,
                               fontItalic, fontUnderline, fontStrikeOut))
        self.fontSelect.setFixedWidth(150)
        self.fontSelect.clicked.connect(self.getFont)
        self.optionLayout.addWidget(self.fontSelect, 0, 0, 1, 2)
        self.optionLayout.addWidget(QLabel(''), 0, 2, 1, 1)
        self.fontColorSelect = label()
        self.fontColorSelect.setAlignment(Qt.AlignCenter)
        self.fontColorSelect.setText(self.fontColor)
        self.fontColorSelect.setStyleSheet(
            'background-color:%s;color:%s' %
            (self.fontColor, self.colorReverse(self.fontColor)))
        self.fontColorSelect.clicked.connect(self.getFontColor)
        self.optionLayout.addWidget(self.fontColorSelect, 0, 3, 1, 1)
        self.fontColorLabel = QLabel('字体颜色')
        self.optionLayout.addWidget(self.fontColorLabel, 0, 4, 1, 1)
        self.karaoke = QPushButton('卡拉OK模式')
        self.karaoke.setFixedWidth(150)
        self.karaokeStatus = False
        self.karaoke.clicked.connect(self.setKaraoke)
        self.optionLayout.addWidget(self.karaoke, 1, 0, 1, 2)
        self.secondColorSelect = label()
        self.secondColorSelect.setAlignment(Qt.AlignCenter)
        self.secondColorSelect.setText(self.secondColor)
        self.secondColorSelect.setStyleSheet(
            'background-color:%s;color:%s' %
            (self.secondColor, self.colorReverse(self.secondColor)))
        self.secondColorSelect.clicked.connect(self.getSecondFontColor)
        self.secondColorSelect.hide()
        self.optionLayout.addWidget(self.secondColorSelect, 1, 3, 1, 1)
        self.secondColorLabel = QLabel('次要颜色')
        self.secondColorLabel.hide()
        self.optionLayout.addWidget(self.secondColorLabel, 1, 4, 1, 1)

        self.outlineSizeBox = QComboBox()
        self.outlineSizeBox.addItems(['0', '1', '2', '3', '4'])
        self.outlineSizeBox.setCurrentIndex(1)
        self.outlineSizeBox.setFixedWidth(100)
        self.optionLayout.addWidget(self.outlineSizeBox, 2, 0, 1, 1)
        self.outlineSizeLabel = QLabel('描边大小')
        self.optionLayout.addWidget(self.outlineSizeLabel, 2, 1, 1, 1)
        self.outlineColorSelect = label()
        self.outlineColorSelect.setAlignment(Qt.AlignCenter)
        self.outlineColorSelect.setText(self.outlineColor)
        self.outlineColorSelect.setStyleSheet(
            'background-color:%s;color:%s' %
            (self.outlineColor, self.colorReverse(self.outlineColor)))
        self.outlineColorSelect.clicked.connect(self.getOutlineColor)
        self.optionLayout.addWidget(self.outlineColorSelect, 2, 3, 1, 1)
        self.outlineColorLabel = QLabel('描边颜色')
        self.optionLayout.addWidget(self.outlineColorLabel, 2, 4, 1, 1)
        self.shadowSizeBox = QComboBox()
        self.shadowSizeBox.addItems(['0', '1', '2', '3', '4'])
        self.shadowSizeBox.setCurrentIndex(1)
        self.shadowSizeBox.setFixedWidth(100)
        self.optionLayout.addWidget(self.shadowSizeBox, 3, 0, 1, 1)
        self.shadowSizeLabel = QLabel('阴影大小')
        self.optionLayout.addWidget(self.shadowSizeLabel, 3, 1, 1, 1)
        self.shadowColorSelect = label()
        self.shadowColorSelect.setAlignment(Qt.AlignCenter)
        self.shadowColorSelect.setText(self.shadowColor)
        self.shadowColorSelect.setStyleSheet(
            'background-color:%s;color:%s' %
            (self.shadowColor, self.colorReverse(self.shadowColor)))
        self.shadowColorSelect.clicked.connect(self.getShadowColor)
        self.optionLayout.addWidget(self.shadowColorSelect, 3, 3, 1, 1)
        self.shadowColorLabel = QLabel('阴影颜色')
        self.optionLayout.addWidget(self.shadowColorLabel, 3, 4, 1, 1)
        self.align = QComboBox()
        self.align.addItems([
            '1: 左下', '2: 中下', '3: 右下', '4: 中左', '5: 中间', '6: 中右', '7: 左上',
            '8: 中上', '9: 右上'
        ])
        self.align.setCurrentIndex(1)
        self.align.setFixedWidth(100)
        self.optionLayout.addWidget(self.align, 4, 0, 1, 1)
        self.alignLabel = QLabel('对齐方式')
        self.optionLayout.addWidget(self.alignLabel, 4, 1, 1, 1)
        self.VAlignSlider = QSlider()
        self.VAlignSlider.setFixedWidth(100)
        self.VAlignSlider.setTickPosition(QSlider.TicksAbove)
        self.VAlignSlider.setSingleStep(10)
        self.VAlignSlider.setTickInterval(20)
        self.optionLayout.addWidget(self.VAlignSlider, 4, 3, 1, 1)
        self.VAlignSlider.setOrientation(Qt.Horizontal)
        self.VAlignLabel = QLabel('垂直边距')
        self.optionLayout.addWidget(self.VAlignLabel, 4, 4, 1, 1)

        self.LAlignSlider = QSlider()
        self.LAlignSlider.setFixedWidth(100)
        self.LAlignSlider.setTickPosition(QSlider.TicksAbove)
        self.LAlignSlider.setSingleStep(10)
        self.LAlignSlider.setTickInterval(20)
        self.optionLayout.addWidget(self.LAlignSlider, 5, 0, 1, 1)
        self.LAlignSlider.setOrientation(Qt.Horizontal)
        self.LAlignLabel = QLabel('左边距')
        self.optionLayout.addWidget(self.LAlignLabel, 5, 1, 1, 1)
        self.RAlignSlider = QSlider()
        self.RAlignSlider.setFixedWidth(100)
        self.RAlignSlider.setTickPosition(QSlider.TicksAbove)
        self.RAlignSlider.setSingleStep(10)
        self.RAlignSlider.setTickInterval(20)
        self.optionLayout.addWidget(self.RAlignSlider, 5, 3, 1, 1)
        self.RAlignSlider.setOrientation(Qt.Horizontal)
        self.RAlignLabel = QLabel('右边距')
        self.optionLayout.addWidget(self.RAlignLabel, 5, 4, 1, 1)

    def getFont(self):
        status, font = QFontDialog.getFont()
        if status:
            self.font = QFontInfo(font)
            self.fontName = self.font.family()
            self.fontSize = self.font.pointSize()
            self.fontBold = self.font.bold()
            self.fontItalic = self.font.italic()
            self.fontUnderline = self.font.underline()
            self.fontStrikeout = self.font.strikeOut()
            fontBold = '粗体' if self.fontBold else ''
            fontItalic = '斜体' if self.fontItalic else ''
            fontUnderline = '下划线' if self.fontUnderline else ''
            fontStrikeOut = '删除线' if self.fontStrikeout else ''
            self.fontSelect.setText('%s%s号%s%s%s%s' %
                                    (self.fontName, self.fontSize, fontBold,
                                     fontItalic, fontUnderline, fontStrikeOut))

    def setKaraoke(self):
        self.karaokeStatus = not self.karaokeStatus
        if self.karaokeStatus:
            self.secondColorSelect.show()
            self.secondColorLabel.show()
            self.karaoke.setStyleSheet('background-color:#3daee9')
        else:
            self.secondColorSelect.hide()
            self.secondColorLabel.hide()
            self.karaoke.setStyleSheet('background-color:#31363b')

    def getFontColor(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.fontColor = color.name()
            self.fontColorSelect.setText(self.fontColor)
            self.fontColorSelect.setStyleSheet(
                'background-color:%s;color:%s' %
                (self.fontColor, self.colorReverse(self.fontColor)))

    def getSecondFontColor(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.secondColor = color.name()
            self.secondColorSelect.setText(self.fontColor)
            self.secondColorSelect.setStyleSheet(
                'background-color:%s;color:%s' %
                (self.secondColor, self.colorReverse(self.secondColor)))

    def getOutlineColor(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.outlineColor = color.name()
            self.outlineColorSelect.setText(self.outlineColor)
            self.outlineColorSelect.setStyleSheet(
                'background-color:%s;color:%s' %
                (self.outlineColor, self.colorReverse(self.outlineColor)))

    def getShadowColor(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.shadowColor = color.name()
            self.shadowColorSelect.setText(self.shadowColor)
            self.shadowColorSelect.setStyleSheet(
                'background-color:%s;color:%s' %
                (self.shadowColor, self.colorReverse(self.shadowColor)))

    def colorReverse(self, color):
        r = 255 - int(color[1:3], 16)
        g = 255 - int(color[3:5], 16)
        b = 255 - int(color[5:7], 16)
        return '#%s%s%s' % (hex(r)[2:], hex(g)[2:], hex(b)[2:])
示例#15
0
文件: ui.py 项目: ramesharun/caribou
class ResultWidget(QWidget):
    def __init__(self, route=None):
        super().__init__()

        layout = QVBoxLayout()
        self.route = route

        self.thread_pool = QThreadPool()

        layout_send = QHBoxLayout()
        self.send_button = QPushButton('Send')
        self.send_button.clicked.connect(self.make_request)

        self.search_line = QLineEdit()
        self.search_line.setPlaceholderText('Search')
        self.search_line.textChanged.connect(self.search_result_reset)
        self.search_line.returnPressed.connect(self.search_result)

        self.response_status_label = QLabel()
        self.response_status_label.setFont(FONT_ROUTE)
        self.response_status_label.hide()

        self.elapsed_time_label = QLabel()
        self.elapsed_time_label.setFont(FONT_ROUTE)
        self.elapsed_time_label.hide()

        self.search_summary_label = QLabel()
        self.search_summary_label.setFont(FONT_ROUTE)
        self.search_summary_label.hide()

        if route is not None:
            layout_send.addWidget(self.send_button)

        layout_send.addWidget(self.response_status_label)
        layout_send.addWidget(self.elapsed_time_label)
        layout_send.addStretch(1)

        layout_send.addWidget(self.search_summary_label)
        layout_send.addWidget(self.search_line)

        layout.addLayout(layout_send)

        self.result_text_edit = ResultTextEdit()
        self.result_text_edit.setReadOnly(True)
        self.result_text_edit.setFont(TEXT_FONT)
        self.result_text_edit.setContextMenuPolicy(Qt.NoContextMenu)

        self.result_text_edit.search.connect(self.focus)

        self.shortcut = QShortcut(QKeySequence("Ctrl+Return"), self,
                                  self.make_request)

        self.result_text_edit.setUndoRedoEnabled(False)

        self.highlighter = TextHighlighter(self.result_text_edit.document())

        layout.addWidget(self.result_text_edit)

        if route is not None:
            saved_result = load_request_result(route)
            self.result_text_edit.setPlainText(saved_result)

        self.setLayout(layout)

    def goto(self, to):
        c = self.result_text_edit.textCursor()
        c.movePosition(to, QTextCursor.MoveAnchor, 1)
        self.result_text_edit.setTextCursor(c)

    def search_result_reset(self):
        self.goto(QTextCursor.Start)

        string_format = QTextCharFormat()
        string_format.setBackground(QColor('#668B8B'))

        extras = []
        self.search_positions = []
        while True:
            extra = QTextEdit.ExtraSelection()
            found = self.result_text_edit.find(self.search_line.text())

            if not found:
                break

            extra.cursor = self.result_text_edit.textCursor()
            extra.format = string_format

            self.search_positions.append(extra.cursor.position())
            extras.append(extra)

        self.result_text_edit.setExtraSelections(extras)
        self.goto(QTextCursor.Start)
        self.search_result()

    def search_result(self):
        p = self.result_text_edit.palette()
        p.setColor(QPalette.Highlight, QColor("#ee799f"))
        self.result_text_edit.setPalette(p)

        search_settings = QTextDocument.FindFlags()

        mod = QApplication.keyboardModifiers()
        if (mod & Qt.ShiftModifier) != 0:
            search_settings |= QTextDocument.FindBackward

        r = self.result_text_edit.find(self.search_line.text(),
                                       search_settings)
        if not r:
            if (mod & Qt.ShiftModifier) != 0:
                self.goto(QTextCursor.End)
            else:
                self.goto(QTextCursor.Start)
            self.result_text_edit.find(self.search_line.text(),
                                       search_settings)

        if self.search_line.text() == '':
            self.search_summary_label.hide()
            return

        current_position = self.result_text_edit.textCursor().position()
        try:
            current_index = self.search_positions.index(current_position)
        except ValueError:
            current_index = -1

        self.search_summary_label.show()
        self.search_summary_label.setText(
            '%s/%s' % (current_index + 1, len(self.search_positions)))

    def focus(self):
        self.search_line.setFocus()
        self.search_line.selectAll()

    def make_request(self):
        self.response_status_label.hide()
        self.elapsed_time_label.hide()
        self.result_text_edit.setPlainText('Loading..')
        try:
            group_values, route_values = get_parameter_values_for_route(
                self.route)
            request = self.route.get_request(group_values, route_values)
            worker = RequestWorker(
                request.method,
                request.url,
                params=request.params,
                headers=request.headers,
                json=request.json,
            )
            worker.signals.result.connect(self.set_result)
            self.thread_pool.start(worker)
        except CaribouException as e:
            self.result_text_edit.setPlainText(str(e))
        except Exception:
            self.result_text_edit.setPlainText(traceback.format_exc())

    def set_result(self, text, status_code, elapsed_time):
        if status_code == 0:
            self.response_status_label.hide()
            self.elapsed_time_label.hide()
        else:
            p = self.response_status_label.palette()
            if status_code == 200:
                self.response_status_label.setText(str(status_code) + ' OK')
                p.setColor(QPalette.WindowText, QColor('#1FDA9A'))
            else:
                self.response_status_label.setText(str(status_code) + ' ERROR')
                p.setColor(QPalette.WindowText, QColor('#DB3340'))

            self.response_status_label.setPalette(p)
            self.response_status_label.show()

            self.elapsed_time_label.setText('%s ms' % int(elapsed_time * 1000))
            self.elapsed_time_label.show()

        self.result_text_edit.setUpdatesEnabled(False)
        self.result_text_edit.setPlainText(text)
        self.result_text_edit.setUpdatesEnabled(True)

        save_request_result(self.route, text)
        persist_storage()
示例#16
0
class VqlEditorWidget(plugin.PluginWidget):
    """Exposed class to manage VQL/SQL queries from the mainwindow"""

    LOCATION = plugin.FOOTER_LOCATION
    ENABLE = True

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle(self.tr("VQL Editor"))

        # Top toolbar
        self.top_bar = QToolBar()
        self.top_bar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.run_action = self.top_bar.addAction(FIcon(0xF040A),
                                                 self.tr("Run"), self.run_vql)
        self.run_action.setShortcuts(
            [Qt.CTRL + Qt.Key_R, QKeySequence.Refresh])
        self.run_action.setToolTip(
            self.tr("Run VQL query (%s)" %
                    self.run_action.shortcut().toString()))

        # Syntax highlighter and autocompletion
        self.text_edit = CodeEdit()
        # Error handling
        self.log_edit = QLabel()
        self.log_edit.setMinimumHeight(40)
        self.log_edit.setStyleSheet(
            "QWidget{{background-color:'{}'; color:'{}'}}".format(
                style.WARNING_BACKGROUND_COLOR, style.WARNING_TEXT_COLOR))
        self.log_edit.hide()
        self.log_edit.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.top_bar)
        main_layout.addWidget(self.text_edit)
        main_layout.addWidget(self.log_edit)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)
        self.setLayout(main_layout)

    def on_open_project(self, conn: sqlite3.Connection):
        """overrided from PluginWidget : Do not call this methods

        Args:
            conn (sqlite3.Connection): sqlite3 connection
        """
        self.conn = conn
        self._fill_completer()

        self.on_refresh()

    def on_refresh(self):
        """overrided from PluginWidget"""

        vql_query = build_vql_query(
            self.mainwindow.state.fields,
            self.mainwindow.state.source,
            self.mainwindow.state.filters,
            self.mainwindow.state.group_by,
            self.mainwindow.state.having,
        )

        self.set_vql(vql_query)

    def set_vql(self, text: str):
        """Set vql source code without executed

        Args:
            text (str): VQL query
        """
        self.text_edit.blockSignals(True)
        self.text_edit.setPlainText(text)
        self.text_edit.blockSignals(False)

    def _fill_completer(self):
        """Create Completer with his model

        Fill the model with the SQL keywords and database fields
        """
        # preload samples , selection and wordset
        samples = [i["name"] for i in sql.get_samples(self.conn)]
        selections = [i["name"] for i in sql.get_selections(self.conn)]
        wordsets = [i["name"] for i in sql.get_wordsets(self.conn)]

        # keywords = []
        self.text_edit.completer.model.clear()
        self.text_edit.completer.model.beginResetModel()

        # register keywords
        for keyword in self.text_edit.syntax.sql_keywords:
            self.text_edit.completer.model.add_item(keyword, "VQL keywords",
                                                    FIcon(0xF0169), "#f6ecf0")

        for selection in selections:
            self.text_edit.completer.model.add_item(selection, "Source table",
                                                    FIcon(0xF04EB), "#f6ecf0")

        for wordset in wordsets:
            self.text_edit.completer.model.add_item(f"WORDSET['{wordset}']",
                                                    "WORDSET", FIcon(0xF04EB),
                                                    "#f6ecf0")

        for field in sql.get_fields(self.conn):
            name = field["name"]
            description = "<b>{}</b> ({}) from {} <br/><br/> {}".format(
                field["name"], field["type"], field["category"],
                field["description"])
            color = style.FIELD_TYPE.get(field["type"], "str")["color"]
            icon = FIcon(
                style.FIELD_TYPE.get(field["type"], "str")["icon"], "white")

            if field["category"] == "variants" or field[
                    "category"] == "annotations":
                self.text_edit.completer.model.add_item(
                    name, description, icon, color)

            if field["category"] == "samples":
                # Overwrite name
                for sample in samples:
                    name = "sample['{}'].{}".format(sample, field["name"])
                    description = "<b>{}</b> ({}) from {} {} <br/><br/> {}".format(
                        field["name"],
                        field["type"],
                        field["category"],
                        sample,
                        field["description"],
                    )
                    self.text_edit.completer.model.add_item(
                        name, description, icon, color)

        self.text_edit.completer.model.endResetModel()

        # if field["category"] == "samples":
        #     for sample in samples:
        #         keywords.append("sample['{}'].{}".format(sample, field["name"]))
        # else:
        #     keywords.append(field["name"])

    def check_vql(self) -> bool:
        """Check VQL statement; return True if OK, False when an error occurs

        Notes:
            This function also sets the error message to the bottom of the view.

        Returns:
            bool: Status of VQL query (True if valid, False otherwise).
        """
        try:
            self.log_edit.hide()
            _ = [i for i in vql.parse_vql(self.text_edit.toPlainText())]
        except (TextXSyntaxError, VQLSyntaxError) as e:
            # Show the error message on the ui
            # Available attributes: e.message, e.line, e.col
            self.set_message("%s: %s, col: %d" %
                             (e.__class__.__name__, e.message, e.col))
            return False
        return True

    def run_vql(self):
        """Execute VQL code

        Suported commands and the plugins that need to be refreshed in consequence:
            - select_cmd: main ui (all plugins in fact)
            - count_cmd: *not supported*
            - drop_cmd: selections & wordsets
            - create_cmd: selections
            - set_cmd: selections
            - bed_cmd: selections
            - show_cmd: *not supported*
            - import_cmd: wordsets
        """
        # Check VQL syntax first
        if not self.check_vql():
            return

        for cmd in vql.parse_vql(self.text_edit.toPlainText()):

            LOGGER.debug("VQL command %s", cmd)
            cmd_type = cmd["cmd"]

            # If command is a select kind
            if cmd_type == "select_cmd":
                # => Command will be executed in different widgets (variant_view)
                # /!\ VQL Editor will not check SQL validity of the command
                # columns from variant table
                self.mainwindow.state.fields = cmd["fields"]
                # name of the variant selection
                self.mainwindow.state.source = cmd["source"]
                self.mainwindow.state.filters = cmd["filters"]
                self.mainwindow.state.group_by = cmd["group_by"]
                self.mainwindow.state.having = cmd["having"]
                # Refresh all plugins
                self.mainwindow.refresh_plugins(sender=self)
                continue

            try:
                # Check SQL validity of selections related commands
                command.create_command_from_obj(self.conn, cmd)()
            except (sqlite3.DatabaseError, VQLSyntaxError) as e:
                # Display errors in VQL editor
                self.set_message(str(e))
                LOGGER.exception(e)
                continue

            # Selections related commands
            if cmd_type in ("create_cmd", "set_cmd", "bed_cmd"):
                # refresh source editor plugin for selections
                self.mainwindow.refresh_plugin("source_editor")
                continue

            if cmd_type == "drop_cmd":
                # refresh source editor plugin for selections
                self.mainwindow.refresh_plugin("source_editor")
                # refresh wordset plugin
                self.mainwindow.refresh_plugin("word_set")

            if cmd_type == "import_cmd":
                # refresh wordset plugin
                self.mainwindow.refresh_plugin("word_set")

    def set_message(self, message: str):
        """Show message error at the bottom of the view

        Args:
            message (str): Error message
        """
        if self.log_edit.isHidden():
            self.log_edit.show()

        icon_64 = FIcon(0xF0027, style.WARNING_TEXT_COLOR).to_base64(18, 18)

        self.log_edit.setText("""<div height=100%>
            <img src="data:image/png;base64,{}" align="left"/>
             <span> {} </span>
            </div>""".format(icon_64, message))
示例#17
0
class Title(StyleWindow):
    class TitleControl(IntEnum):
        TitleLog = 1 << 1,
        TitleText = 1 << 2,
        TitleMinimized = 1 << 3,
        TitleMaximized = 1 << 4,
        TitleClose = 1 << 5

    def __init__(self, parent=None):
        super(Title, self).__init__(parent)
        self._layout = None
        self._enabled_movie = False  # 是否支持拖动
        self._left_button_pressed = False
        self._pressed_pos = QPoint()
        self._log = None
        self._title = None
        self._maximize_btn = None
        self._minimize_btn = None
        self._close_btn = None
        self.mouse_drag_enabled = False
        self._init_def_layout()
        self.set_show_title_ctrls(self.TitleControl.TitleText
                                  | self.TitleControl.TitleMinimized
                                  | self.TitleControl.TitleMaximized
                                  | self.TitleControl.TitleClose)

    close = Signal()
    show_minimized = Signal()
    show_maximized = Signal()

    def _init_def_layout(self):
        self._layout = QHBoxLayout()
        self.set_layout(self._layout)
        self._layout.setContentsMargins(5, 0, 10, 5)
        self._layout.setSpacing(10)
        #
        self._log = QLabel()
        self._log.setObjectName("Title_LogLabel")
        self._layout.addWidget(self._log)
        self._log.hide()
        self._title = QLabel()
        self._title.setObjectName("Title_TitleLabel")
        self._layout.addWidget(self._title)
        # self._title.hide()
        self._layout.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed))
        # close button
        self._close_btn = DImageButton()
        self._close_btn.setObjectName("Title_CloseButton")
        self._maximize_btn = DImageButton()
        self._maximize_btn.setObjectName("Title_MaximizeButton")
        self._minimize_btn = DImageButton()
        self._minimize_btn.setObjectName("Title_MinimizeButton")
        self._layout.addWidget(self._minimize_btn, 0, Qt.AlignRight)
        self._layout.addWidget(self._maximize_btn, 0, Qt.AlignRight)
        self._layout.addWidget(self._close_btn, 0, Qt.AlignRight)

        #self._close_btn.hide()
        self._maximize_btn.hide()
        # self._minimize_btn.hide()

        self._close_btn.clicked.connect(self.close)
        self._minimize_btn.clicked.connect(self.show_minimized)
        self._maximize_btn.clicked.connect(self.show_maximized)

    def log(self):
        return self._log

    def set_log(self, pix: QPixmap):
        self._log_label.setPixmap(pix)

    log_ = Property(QPixmap, fget=log, fset=set_log)

    @property
    def enabled_movie(self):
        return self._enabled_movie

    @enabled_movie.setter
    def enabled_movie(self, enabled):
        self._enabled_movie = enabled

    def mousePressEvent(self, event):
        self.set_calc_mouse_type(
            self._calc_cursor_pos(event.pos(),
                                  self._calc_cursor_col(event.pos())))
        if self._mouse_drag_is_center_type():
            if Qt.LeftButton == event.button() and self.parent() is not None:
                self._left_button_pressed = True
                self._pressed_pos = event.globalPos() - self.parent().pos()
        super(Title, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        self._left_button_pressed = False
        super(Title, self).mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):
        if self._mouse_drag_is_center_type():
            if self._left_button_pressed and self.parent() is not None:
                self.parent().move(event.globalPos() - self._pressed_pos)
        super(Title, self).mouseMoveEvent(event)

    @property
    def title_text(self):
        return self._title.text()

    @title_text.setter
    def title_text(self, text):
        self._title.setText(text)

    def set_show_title_ctrls(self, ctrls):
        """设置标题需要显示的控件"""
        self._log.setVisible(ctrls & self.TitleControl.TitleLog)
        self._title.setVisible(ctrls & self.TitleControl.TitleText)
        self._minimize_btn.setVisible(ctrls & self.TitleControl.TitleMinimized)
        self._maximize_btn.setVisible(ctrls & self.TitleControl.TitleMaximized)
        self._close_btn.setVisible(ctrls & self.TitleControl.TitleClose)
示例#18
0
class _RotorsHandlerWidget(QFrame):
    """Coordinates all rotors and the settings button"""
    def __init__(
        self,
        master,
        position_plug,
        rotate_plug,
        rotate_ref_plug,
        enigma_api,
        refresh_plug,
        reflector_pos_plug,
    ):
        """
        :param master: {Qt} Master qt object
        :param position_plug: {callable} Callable method for getting rotor
                                         positions
        :param rotate_plug: {callable} Temporary callable for getting
                                      rotor offset handlers
        :param rotate_ref_plug: {callable} Callable to change reflector position
        :param enigma_api: {EnigmaAPI} Shared EnigmaAPI instance
        :param refresh_plug: {callable} Used to refresh the GUI based on new rotor positions
        :param reflector_pos_plug: {callable} Used to get reflector position
        """
        super().__init__(master)

        # QT WINDOW SETTINGS ==================================================

        self.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.__layout = QHBoxLayout(self)
        self.__layout.setAlignment(Qt.AlignCenter)
        self.__rotor_indicators = []
        self.__reflector_indicator = None

        # ATTRIBUTES ==========================================================

        self.__enigma_api = enigma_api
        self.__rotate_plug = rotate_plug
        self.__position_plug = position_plug
        self.__refresh_plug = refresh_plug
        self.__reflector_pos_plug = reflector_pos_plug

        # SETTINGS ICON =======================================================

        self.__settings_button = QPushButton(QIcon(BASE_DIR + "settings.png"),
                                             "", self)
        self.__settings_button.setIconSize(QSize(50, 50))
        self.__settings_button.setToolTip(
            "Edit Enigma rotor and reflector settings")
        self.__settings_button.setSizePolicy(QSizePolicy.Fixed,
                                             QSizePolicy.Expanding)
        self.__settings_button.clicked.connect(self.__open_settings)

        # GENERATE ROTORS AND REFLECTOR =======================================

        self.__ukwd_indicator = QLabel("D")
        self.__ukwd_indicator.setStyleSheet(
            "QLabel{font-size: 20px; text-align: center; background-color: white; color: red}"
        )
        self.__ukwd_indicator.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.__ukwd_indicator.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
        self.__ukwd_indicator.setLineWidth(2)
        self.__ukwd_indicator.setFixedSize(40, 40)
        self.__ukwd_indicator.hide()

        self.__reflector_indicator = _RotorHandlerWidget(
            self,
            rotate_ref_plug(1, True),
            rotate_ref_plug(-1, True),
            self.set_positions,
        )
        self.__reflector_indicator.setToolTip("Reflector position indicator")
        self.__reflector_indicator.hide()

        self._left_spacer = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
        self._right_spacer = QSpacerItem(0, 0, QSizePolicy.Expanding,
                                         QSizePolicy.Expanding)

        # REGENERATE ===============================================

        self.generate_rotors()
        self.set_positions()

    def generate_rotors(self):
        """Regenerates rotor and reflector views (with position indicators and
        and buttons to rotate them according to new EnigmaAPI settings"""
        self.__layout.removeItem(self._left_spacer)
        self.__layout.removeItem(self._right_spacer)
        self.__layout.removeWidget(self.__settings_button)
        self.__layout.removeWidget(self.__ukwd_indicator)
        self.__ukwd_indicator.hide()
        self.__reflector_indicator.hide()
        self.__layout.removeWidget(self.__reflector_indicator)
        self.__reflector_indicator.hide()

        for indicator in self.__rotor_indicators:
            indicator.deleteLater()

        self.__layout.addItem(self._left_spacer)

        self.__rotor_indicators = []

        if self.__enigma_api.reflector() == "UKW-D":
            logging.info("UKW-D reflector detected, showing indicator...")
            self.__layout.addWidget(self.__ukwd_indicator)
            self.__ukwd_indicator.show()
        elif self.__enigma_api.reflector_rotatable():
            logging.info("Rotatable reflector detected, showing indicator...")
            self.__layout.addWidget(self.__reflector_indicator)
            self.__reflector_indicator.show()

        # Create
        for i in range(len(self.__position_plug())):  # Rotor controls
            indicator = _RotorHandlerWidget(
                self,
                self.__rotate_plug(i, 1),
                self.__rotate_plug(i, -1),
                self.set_positions,
            )
            self.__layout.addWidget(indicator, alignment=Qt.AlignLeft)
            self.__rotor_indicators.append(indicator)

        self.__layout.addItem(self._right_spacer)
        self.__layout.addWidget(self.__settings_button)

    def __open_settings(self):
        """Opens settings and reloads indicators afterwards if changes are
        detected"""
        logging.info("Opening settings menu...")
        old_cfg = self.__enigma_api.get_config()
        settings = SettingsWindow(self, self.__enigma_api)
        settings.exec()  # Exec gives focus to top window, unlike .show
        if old_cfg != self.__enigma_api.get_config():
            logging.info("Settings changed, reloading GUI...")
            del settings
            self.generate_rotors()
            self.__refresh_plug()
            self.set_positions()
        else:
            logging.info("No changes to settings made...")

    def set_positions(self):
        """Refreshes position indicators to show new positions from EnigmaAPI"""
        if (self.__enigma_api.reflector_rotatable()
                and self.__enigma_api.reflector() != "UKW-D"):
            logging.info('Reflector indicator set to position "%s"',
                         self.__reflector_pos_plug())
            self.__reflector_indicator.set(self.__reflector_pos_plug())

        logging.info('Rotor indicators set to positions "%s"',
                     str(self.__position_plug()))
        for rotor, position in zip(self.__rotor_indicators,
                                   self.__position_plug()):
            rotor.set(position)
class ProgressUpdater(QWidget):
    def __init__(self,
                 parent: QtCore.QObject = None,
                 window: QtWidgets.QMainWindow = None,
                 processingText: str = "Compressing...",
                 clickToStartText: str = "Click compress to start.") -> None:
        super().__init__(parent=parent)
        self.parentWindow: QtWidgets.QMainWindow = window
        self.processingText = processingText
        self.clickToStartText = clickToStartText
        self.isLoading = True
        #self.setFixedHeight(30)
        self.setUpWidgets()

    def setUpWidgets(self) -> None:
        self.wheelLabel = QLabel(self)
        self.progressBar = QProgressBar(self)
        self.progressBar.setAlignment(QtCore.Qt.AlignHCenter
                                      | QtCore.Qt.AlignVCenter)
        self.progressBar.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                       QtWidgets.QSizePolicy.Expanding)
        self.infoLabel = QLabel(self)
        self.infoLabel.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
                                     QtWidgets.QSizePolicy.Ignored)

        self.mainLayout = QHBoxLayout()
        self.mainLayout.addWidget(self.wheelLabel)
        self.mainLayout.addWidget(self.progressBar)
        self.mainLayout.addWidget(self.infoLabel, stretch=1)

        self.wheelMovie = QtGui.QMovie(self)
        self.wheelMovie.setFileName(getPath("load.gif"))
        self.wheelMovie.setScaledSize(QtCore.QSize(20, 20))
        self.wheelMovie.start()

        self.wheelLabel.setMovie(self.wheelMovie)
        self.wheelLabel.hide()
        self.progressBar.setRange(0, 100)
        #self.progressBar.setFixedHeight(30)
        if (_platform == "win32"):
            self.parentWindow.taskbprogress.setRange(0, 100)
        self.progressBar.setValue(0)
        if (_platform == "win32"): self.parentWindow.taskbprogress.setValue(0)
        self.progressBar.setFixedSize(400, 20)
        self.progressBar.setFormat("Ready")
        self.infoLabel.setText(self.clickToStartText)

        self.mainLayout.setMargin(0)

        self.setLayout(self.mainLayout)

    def startLoading(self) -> None:
        self.isLoading = True
        if (_platform == "win32"): self.parentWindow.taskbprogress.show()
        if (_platform == "win32"): self.parentWindow.taskbprogress.setValue(0)
        self.progressBar.setValue(0)
        if (_platform == "win32"):
            self.parentWindow.taskbprogress.setRange(0, 0)
        self.progressBar.setRange(0, 0)
        self.infoLabel.setText(self.processingText)
        self.progressBar.setFormat("%p%")
        self.wheelLabel.show()

    def stopLoading(self) -> None:
        self.isLoading = False
        self.wheelLabel.hide()
        if (_platform == "win32"): self.parentWindow.taskbprogress.hide()
        if (_platform == "win32"):
            self.parentWindow.taskbprogress.setRange(0, 100)
        self.progressBar.setRange(0, 100)
        if (_platform == "win32"): self.parentWindow.taskbprogress.setValue(0)
        self.progressBar.setValue(0)
        self.progressBar.setFormat("Ready")
        self.infoLabel.setText(self.clickToStartText)

    def setText(self, text: str) -> None:
        self.infoLabel.setText(text)
        self.infoLabel.setToolTip(text)

    def setRange(self, min: int, max: int) -> None:
        self.progressBar.setRange(min, max)
        if (_platform == "win32"):
            self.parentWindow.taskbprogress.setRange(min, max)

    def setValue(self, value: int) -> None:
        self.progressBar.setValue(value)
        if (_platform == "win32"):
            self.parentWindow.taskbprogress.setValue(value)
class TreeWidget(QTreeWidget):
    def __init__(self, parent=None, emptyText="Hint"):
        super().__init__(parent=parent)
        self.backgroundLabel = QLabel(self)
        self.backgroundLabel.setAttribute(
            QtCore.Qt.WA_TransparentForMouseEvents)
        self.backgroundLabel.setWordWrap(True)
        self.backgroundLabel.show()
        self.openFileAction = self.doNothing
        self.backgroundLabel.setAlignment(QtCore.Qt.AlignCenter)
        self.backgroundLabel.setText(emptyText)
        self.backgroundLabel.resize(400, 200)
        self.opacity = QtWidgets.QGraphicsOpacityEffect(self)
        self.opacity.setOpacity(0.5)
        self.backgroundLabel.setGraphicsEffect(self.opacity)
        self.backgroundLabel.setStyleSheet(
            "background-color: transparent; font-size: 15pt; font-weight: light;"
        )
        self.setColumnCount(5)
        self.setIconSize(QtCore.QSize(32, 32))
        self.setAutoScroll(True)
        self.setVerticalScrollMode(QtWidgets.QTreeWidget.ScrollPerPixel)
        self.setHorizontalScrollMode(QtWidgets.QTreeWidget.ScrollPerPixel)
        self.setColumnWidth(0, 300)
        self.setSelectionMode(
            QtWidgets.QTreeView.SelectionMode.ContiguousSelection)
        self.setColumnWidth(3, 200)
        self.setHeaderLabels(
            ["File name", "Size", "Status", "File location", "Relative path"])
        self.setDropIndicatorShown(True)
        self.setAcceptDrops(True)
        self.setSupportedDropActions = QtCore.Qt.CopyAction | QtCore.Qt.MoveAction

    def dragEnterEvent(self, e):
        e.accept()

    def dragMoveEvent(self, e):
        e.accept()

    def dropEvent(self, e):
        self.openFileAction(str(e.mimeData().text().replace("file://", "")))

    def resizeEvent(self, event) -> None:
        eventResult = super().resizeEvent(event)
        w, h = self.width(), self.height()
        diffW = w - self.backgroundLabel.width()
        diffH = h - self.backgroundLabel.height()
        self.backgroundLabel.move(diffW // 2, diffH // 2)
        return eventResult

    def setEmptyText(self, text: str) -> None:
        self.backgroundLabel.setText(text)

    def connectFileDragEvent(self, func) -> None:
        self.openFileAction = func

    def doNothing(self, f: str) -> None:
        log("[  WARN  ] File {f} dragged, but no actoin was defined for this event"
            )

    def showHideLabel(self) -> None:
        if (self.topLevelItemCount() > 0):
            self.backgroundLabel.hide()
        else:
            self.backgroundLabel.show()

    def addTopLevelItem(self, item: QtWidgets.QTreeWidgetItem) -> None:
        super().addTopLevelItem(item)
        self.showHideLabel()

    def addTopLevelItems(self, items: typing.Sequence) -> None:
        super().addTopLevelItems(items)
        self.showHideLabel()

    def clear(self) -> None:
        super().clear()
        self.showHideLabel()

    def takeTopLevelItem(self, index: int) -> QtWidgets.QTreeWidgetItem:
        w = super().takeTopLevelItem(index)
        self.showHideLabel()
        return w

    def insertTopLevelItem(self, index: int,
                           item: QtWidgets.QTreeWidgetItem) -> None:
        super().insertTopLevelItem(index, item)
        self.showHideLabel()

    def insertTopLevelItems(self, index: int, items: typing.Sequence) -> None:
        super().insertTopLevelItems(index, items)
        self.showHideLabel()
示例#21
0
class Form(QDialog):
    def __init__(self, parent=None):
        self.round = 0
        self.lcd = QLCDNumber(5)
        self.lcd2 = QLCDNumber(5)
        self.clock = QLCDNumber(5)
        super(Form, self).__init__(parent)
        self.setWindowTitle("Pomodoro")
        # Create widgets
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(1, 99)
        self.slider.setValue(25)
        self.slider2 = QSlider(Qt.Horizontal)
        self.slider2.setRange(1, 99)
        self.slider2.setValue(5)
        self.count = self.slider.value() * 60
        self.rest = self.slider2.value() * 60
        self.taskbar_count = 0
        self.taskbar2_count = 0
        self.text = QLabel("How long should the work period be?")
        self.text2 = QLabel("How long should the rest period be?")
        self.work = QLabel("WORK")
        self.pause = QLabel("REST")
        self.rounds = QLabel("Number of rounds: " + str(self.round))
        self.work.setAlignment(Qt.AlignHCenter)
        self.work.setFont(QFont("Times", 18, QFont.Bold))
        self.pause.setAlignment(Qt.AlignHCenter)
        self.pause.setFont(QFont("Times", 18, QFont.Bold))
        self.button = QPushButton("Start timer")
        self.button2 = QPushButton("Stop timer")
        self.reset = QPushButton("Reset rounds")
        self.lcd.display("25:00")
        self.lcd2.display("05:00")
        mins = 25
        secs = "00"
        self.clock.display(f"{mins}:{secs}")
        self.slider.valueChanged.connect(self.first_display)
        self.slider2.valueChanged.connect(self.second_display)
        self.slider.valueChanged.connect(self.clock_display)
        self.button2.hide()
        self.work.hide()
        self.pause.hide()
        self.clock.hide()
        # Create layout and add widgets
        layout = QVBoxLayout()
        layout.addWidget(self.text)
        layout.addWidget(self.lcd)
        layout.addWidget(self.slider)
        layout.addWidget(self.text2)
        layout.addWidget(self.lcd2)
        layout.addWidget(self.slider2)
        layout.addWidget(self.button)
        layout.addWidget(self.button2)
        layout.addWidget(self.work)
        layout.addWidget(self.pause)
        layout.addWidget(self.clock)
        layout.addWidget(self.rounds)
        layout.addWidget(self.reset)
        # Set dialog layout
        self.setLayout(layout)
        self.systemtray_icon = QSystemTrayIcon(QIcon("snake.png"))
        self.systemtray_icon.show()
        self.systemtray_icon.activated.connect(self.icon_activated)
        self.menu = QMenu(parent)
        self.exit_action = self.menu.addAction("Exit")
        self.systemtray_icon.setContextMenu(self.menu)
        self.exit_action.triggered.connect(self.slot_exit)
        # Add signals
        self.slider.valueChanged.connect(self.count_func)
        self.slider2.valueChanged.connect(self.count_func)
        self.button.clicked.connect(self.button_update)
        self.button.clicked.connect(self.timer_func)
        self.button.clicked.connect(self.round_count)
        self.button2.clicked.connect(self.stop)
        self.reset.clicked.connect(self.reset_rounds)

    def reset_rounds(self):
        self.round = 0
        self.rounds.setText("Number of rounds: " + str(self.round))

    def round_count(self):
        self.round += 1
        self.rounds.setText("Number of rounds: " + str(self.round))

    def icon_activated(self, reason):
        if reason in (QSystemTrayIcon.Trigger, QSystemTrayIcon.DoubleClick):
            self.show()

    def closeEvent(self, event):
        self.hide()
        event.ignore()

    def slot_exit(self):
        QApplication.exit(0)

    def first_display(self):
        minute = str(self.slider.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider.sliderPosition() >= 10:
            self.lcd.display(minute + second)
        else:
            self.lcd.display(leading_zero + minute + second)

    def second_display(self):
        minute = str(self.slider2.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider2.sliderPosition() >= 10:
            self.lcd2.display(minute + second)
        else:
            self.lcd2.display(leading_zero + minute + second)

    def clock_display(self):
        minute = str(self.slider.sliderPosition())
        second = ":00"
        leading_zero = "0"
        if self.slider.sliderPosition() >= 10:
            self.clock.display(minute + second)
        else:
            self.clock.display(leading_zero + minute + second)

    def count_func(self):
        self.count = self.slider.sliderPosition() * 60
        self.rest = self.slider2.sliderPosition() * 60

    def countdown(self):
        minute, second = divmod(self.count, 60)
        zero = "0"
        show = self.work.show()
        if second < 10 and minute < 10:
            self.clock.display(zero + str(minute) + ":" + zero + str(second))
        elif second < 10:
            self.clock.display(str(minute) + ":" + zero + str(second))
        elif minute < 10:
            self.clock.display(zero + str(minute) + ":" + str(second))
        else:
            self.clock.display(str(minute) + ":" + str(second))
        self.count -= 1
        if self.count < -1:
            self.work.hide()
            self.taskbar_rest()
            show = self.pause.show()
            minute, second = divmod(self.rest, 60)
            zero = "0"
            if self.rest == self.slider2.value() * 60:
                self.show()
            if second < 10 and minute < 10:
                self.clock.display(zero + str(minute) + ":" + zero +
                                   str(second))
            elif second < 10:
                self.clock.display(str(minute) + ":" + zero + str(second))
            elif minute < 10:
                self.clock.display(zero + str(minute) + ":" + str(second))
            else:
                self.clock.display(str(minute) + ":" + str(second))
            self.rest -= 1
            if self.rest < -1:
                self.clock.display("00:00")
                self.taskbar_work()
                self.timer.stop()
                self.stop()
        show

    def timer_func(self):
        timer = QTimer()
        self.timer = timer
        self.timer.timeout.connect(self.countdown)
        self.timer.start(1000)

    def button_update(self):
        self.button.hide()
        self.text.hide()
        self.lcd.hide()
        self.slider.hide()
        self.text2.hide()
        self.lcd2.hide()
        self.slider2.hide()
        self.reset.hide()
        self.clock.show()
        self.button2.show()
        self.work.show()

    def taskbar_rest(self):
        if self.taskbar_count == 0:
            self.systemtray_icon.showMessage("PAUSE", "Time to rest!",
                                             QSystemTrayIcon.Information,
                                             500000)
            self.taskbar_count = 1

    def taskbar_work(self):
        if self.taskbar2_count == 0:
            self.systemtray_icon.showMessage("WORK", "Break over!",
                                             QSystemTrayIcon.Information,
                                             500000)
            self.taskbar2_count = 1

    def stop(self):
        self.timer.stop()
        self.button2.hide()
        self.work.hide()
        self.pause.hide()
        self.clock.hide()
        self.count = self.slider.value() * 60
        self.rest = self.slider2.value() * 60
        self.clock.display(str(self.slider.value()) + ":00")
        self.button.show()
        self.text.show()
        self.lcd.show()
        self.slider.show()
        self.text2.show()
        self.lcd2.show()
        self.slider2.show()
        self.reset.show()
        self.show()
        self.taskbar_count = 0
        self.taskbar2_count = 0
示例#22
0
class Changewall(QDialog):
    """ Parent of all the widgets """
    def __init__(self, parent=None):
        super().__init__(parent)

        self.screen_width, self.screen_height = get_screen_res(screen)
        self.screen_res: str = f'{self.screen_width}x{self.screen_height}'
        self.payload: Dict[str, str] = {
            'sorting': 'random',
            'categories': '100',
            'atleast': self.screen_res
        }

        self.sw = StackedWidget()

        self.progressbar = ProgressBar()
        self.progressbar.hide()

        self.prev_btn = Button('angle-left.svg', key='left')
        self.next_btn = Button('angle-right.svg', key='right')
        self.update_btn = Button('sync-alt.svg', ' Update', key='r')
        self.apply_btn = Button('check.svg', 'Apply')
        self.save_btn = Button('save.svg', 'Save')

        self.prev_btn.clicked.connect(self.prev)
        self.next_btn.clicked.connect(self.next)
        self.apply_btn.clicked.connect(self.apply)
        self.update_btn.clicked.connect(self.update_)
        self.save_btn.clicked.connect(self.save)

        self.saved_msg = QLabel('Saved')
        self.image_count = QLabel()
        self.image_res = QLabel()
        self.saved_msg.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_count.setStyleSheet(f'color: {INFO_COLOR}')
        self.image_res.setStyleSheet(f'color: {INFO_COLOR}')

        self.info_layout = QHBoxLayout()
        self.info_layout.addWidget(self.progressbar)
        self.info_layout.addStretch()
        self.info_layout.addWidget(self.image_count)
        self.info_layout.addWidget(self.image_res)

        button_layout = QHBoxLayout()
        button_layout.addWidget(self.prev_btn)
        button_layout.addWidget(self.next_btn)
        button_layout.addWidget(self.update_btn)
        button_layout.addWidget(self.apply_btn)
        button_layout.addWidget(self.save_btn)

        self.main_layout = QVBoxLayout()
        self.main_layout.addLayout(self.info_layout)
        self.main_layout.addWidget(self.sw)
        self.main_layout.addLayout(button_layout)
        self.setLayout(self.main_layout)

        self.sw.added.connect(self.change_image_count)

    def prev(self) -> None:
        """ Show previous image in stacked widget """
        current_index: int = self.sw.currentIndex()
        if current_index > 0:
            self.sw.setCurrentIndex(current_index - 1)
        logger.debug(
            f"Stacked widget's current index is {self.sw.currentIndex()}")
        self.change_info()

    def next(self) -> None:
        """ Show next image in stacked widget """
        current_index: int = self.sw.currentIndex()
        self.sw.setCurrentIndex(current_index + 1)
        logger.debug(
            f"Stacked widget's current index is {self.sw.currentIndex()}")
        self.change_info()

    def update_(self) -> None:
        """
        Download new json, new thumbnails and delete old ones
        with clearing stacked widget
        """
        for file in THUMBS_DIR.iterdir():
            logger.debug(f'Deleting {short_path(file)}')
            file.unlink()

        # Clear stacked widget
        for _ in range(self.sw.count()):
            widget = self.sw.widget(0)
            self.sw.removeWidget(widget)
            del widget

        download = Download(JSON_FILE,
                            APP_DIR,
                            SEARCH_URL,
                            payload=self.payload)
        download.save()

        self.progressbar.show()
        self.download_thumbs()

    def apply(self) -> None:
        """ Set current image as wallpaper """
        for file in CURRENT_DIR.iterdir():
            file.unlink()
            logger.debug(f'Deleted {short_path(file)}')

        image_id: str = self.sw.current_image_id()
        info: Dict[str, str] = image_info(image_id)
        image: Path = Path(info['image_id'] + info['extension'])

        self.progressbar.show()
        download = Download(image,
                            CURRENT_DIR,
                            info['full_image_url'],
                            stream=True)
        download.finished_chunk.connect(self.set_progressbar)
        download.finished_file.connect(set_wall)
        download.save()

    def save(self) -> None:
        """
        Save image to CURRENT_DIR
        When image is saved, show Saved label
        """
        image_id: str = self.sw.current_image_id()
        info: Dict[str, str] = image_info(image_id)
        image: Path = Path(info['image_id'] + info['extension'])

        self.progressbar.show()
        download = Download(image,
                            SAVED_DIR,
                            info['full_image_url'],
                            stream=True)
        download.finished_chunk.connect(self.set_progressbar)
        download.save()

        # Show message "Saved" for 3 seconds in info layout
        self.info_layout.insertWidget(2, self.saved_msg)
        self.saved_msg.show()
        QTimer.singleShot(3000, self.hide_msg)

        save_msg: bool = config.getboolean('Program', 'show_save_message')

        def disable_save_msg():
            config['Program']['show_save_message'] = 'no'
            config_save()
            logger.debug('Save message is now disabled')

        # Create and show "save message box" if it is set to True
        if save_msg:
            msgBox = QMessageBox(self)
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setText('Saved')
            msgBox.setInformativeText(
                f'The image has been saved to \n{str(SAVED_DIR)}')
            msgBox.setStandardButtons(QMessageBox.Ok)
            dontshow_btn = msgBox.addButton("Don't show again",
                                            QMessageBox.ActionRole)
            dontshow_btn.clicked.connect(disable_save_msg)
            msgBox.exec_()

    def hide_msg(self) -> None:
        """ Remove save label from info layout and hide it """
        self.info_layout.removeWidget(self.saved_msg)
        self.saved_msg.hide()

    def download_thumbs(self) -> None:
        """
        Parse JSON_FILE then download thumbnails asynchronously.

        Each time thumbnail is downloaded, signals are emitted to
        stacked widget and progressbar
        """
        with open(JSON_FILE, 'r') as f:
            data: Dict = json.load(f)
            for item in data['data']:
                url: str = item['thumbs']['large']
                name: Path = Path(item['id'] + '.' + url[-3:])
                dt = DownloadThread(name, THUMBS_DIR, url)
                dt.finished_file.connect(self.sw.add)
                dt.finished_file.connect(self.set_progressbar)
                QThreadPool.globalInstance().start(dt)

    def change_image_count(self) -> None:
        """
        Update info of current image position in stacked widget
        and total number of images
        """
        self.image_count.setText(self.sw.count_info())

    def change_info(self) -> None:
        """
        Everytime change_info is called
        it get info of current image to
        update label 'image_res' with
        image resolution and image
        position in stacked widget
        """
        info: Dict[str, str] = image_info(self.sw.current_image_id())
        self.change_image_count()
        if len(info) > 0:
            self.image_res.setText(info['resolution'])
        else:
            self.image_res.setText('Image info not found')

    def set_progressbar(self, _) -> None:
        """
        Update progressbar and hide it
        when it reaches its maximum
        """
        current: int = self.progressbar.value()
        self.progressbar.setValue(current + 1)
        if current == self.progressbar.maximum():
            self.progressbar.hide()
            self.progressbar.setValue(0)

    def load(self) -> None:
        """
        Download thumbnails if THUMBS_DIR is empty
        or JSON_FILE don't exist.
        Otherwise fill stacked widget with existing thumbnails
        """
        create_dirs(THUMBS_DIR, CURRENT_DIR, SAVED_DIR)

        if JSON_FILE.exists():
            if not is_dir_contains_images(THUMBS_DIR):
                logger.debug(
                    f"{short_path(THUMBS_DIR)} is empty. Downloading new thumbnails"
                )
                self.progressbar.show()
                self.download_thumbs()
            else:
                logger.debug('Filling stacked widget')
                self.sw.fill()
                self.change_info()
        else:
            logger.debug(f"{short_path(JSON_FILE)} doesn't exist. Updating")
            self.update_()

    def resize_move(self) -> None:
        """ Resize and move window using parameters from settings """
        try:
            self.resize(*win_size)
            logger.debug(f'Resized window to {win_size}')
        except:
            logger.warning('Could not resize window')

        if win_pos:
            try:
                self.move(*win_pos)
                logger.debug(f'Moved window to {win_pos}')
            except:
                logger.warning('Could not move window to a new position')

    def closeEvent(self, event) -> None:
        """ Save window size and position before closing the window"""
        config['Program']['window_size'] = f'{self.width()}, {self.height()}'
        config['Program']['window_position'] = f'{self.x()}, {self.y()}'
        config_save()
示例#23
0
class CameraPanel(QWidget):
    __obj = None

    def __init__(self, n_camera, app: QApplication, *args, **kwargs):
        if CameraPanel.__obj is not None:
            raise type(
                'InstanceExists', (Exception, ),
                {})('A CameraPanel instance has already been constructed.')
        CameraPanel.__obj = self
        super().__init__(*args, **kwargs)
        self.cameras = []
        self.box = QVBoxLayout()
        self.setLayout(self.box)

        Configuration(n_camera, self)
        TrafficMonitor(n_camera)
        FrameRateMonitor(n_camera)
        FrameDropMonitor(n_camera)

        self.connectButton = QPushButton("Connect")
        self.connectButton.clicked.connect(self.connectRemote)
        self.reconnecting = QLabel("Disconnected. Trying to reconnect")
        self.reconnecting.setWordWrap(True)
        self.total_traffic = QLabel("0.000 KB/s")
        self.restart_remote = QPushButton("Restart Remote")
        self.restart_remote.setSizePolicy(QSizePolicy.Maximum,
                                          QSizePolicy.Expanding)
        self.restart_remote.clicked.connect(self.restartRemote)
        self.scan = QPushButton("Scan")
        self.scan.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding)
        self.scan.clicked.connect(Configuration().scan)

        self.top_frame = QFrame()
        self.top_frame.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum)
        self.top_grid = QGridLayout()
        self.top_grid.setContentsMargins(0, 0, 0, 0)
        self.top_frame.setLayout(self.top_grid)

        self.top_grid.addWidget(self.connectButton, 0, 1)
        self.top_grid.addWidget(self.reconnecting, 0, 1)
        self.top_grid.addWidget(self.total_traffic, 0, 1)
        self.top_grid.addWidget(self.restart_remote, 0, 2)
        self.top_grid.addWidget(self.scan, 0, 0)

        self.total_traffic.hide()
        self.reconnecting.hide()

        self.box.addWidget(self.top_frame)

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

        for i in range(n_camera):
            self.cameras.append(Camera(i, app))

        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.addWidget(self.cameras[0])
        if n_camera == 2:
            main_splitter.addWidget(self.cameras[1])
        elif n_camera == 3:
            sub_splitter = QSplitter(Qt.Horizontal)
            sub_splitter.addWidget(self.cameras[1])
            sub_splitter.addWidget(self.cameras[2])
            main_splitter.addWidget(sub_splitter)
        elif n_camera == 4:
            sub_splitter = QSplitter(Qt.Horizontal)
            sub_sub_splitter = QSplitter(Qt.Horizontal)
            sub_splitter.addWidget(sub_sub_splitter)
            sub_sub_splitter.addWidget(self.cameras[1])
            sub_sub_splitter.addWidget(self.cameras[2])
            sub_splitter.addWidget(self.cameras[3])
            main_splitter.addWidget(sub_splitter)

        self.box.addWidget(main_splitter)

    def connectRemote(self):
        """
        This function blocks until TCP connection succeeds.
        Call with caution
        """
        if Configuration().connect():
            self.connectButton.hide()
            self.total_traffic.show()
            for cam in self.cameras:
                cam.startReceiving()
                cam.mode_selection.setEnabled(True)
                cam.updateMode(cam.mode_selection.currentIndex())

    def restartRemote(self):
        os.system(
            f'ssh root@{REMOTE_IP_ADDR} systemctl restart vision-server.service'
        )
        if self.connectButton.isVisible():
            self.connectRemote()
        else:
            Configuration().reconnect()

    def updateTraffic(self):
        self.total_traffic.setText('{:<4} KB/s'.format(
            round(TrafficMonitor().total / 1024, 2)))
示例#24
0
class Game(QOpenGLWidget):
    selectedCoordinates: List[Positions] = []
    SCREEN = 1
    gameTitle = None
    playButtonLabel = None

    def __init__(self, QOpenGLWidget):
        super().__init__()
        '''
        if turn equals to false, then cirlcle will be marked
        and if its equals to true, then X will be marked 
        '''
        self.turn = False
        self.initializeHomeScreen()
        self.matrix_game = [[0 for _ in range(3)] for _ in range(3)]
        self.players = ['X', 'O']

    def initializeGL(self):
        self.resize(env.VIEW_WIDTH, env.VIEW_HEIGHT)
        glViewport(0, 0, env.VIEW_WIDTH, env.VIEW_HEIGHT)

    def resizeEvent(self, e: PySide2.QtGui.QResizeEvent):
        super().resizeEvent(e)
        width = self.SCREEN == 1 and 220 or 400
        if self.gameTitle is not None:
            x = e.size().width() / 3
            y = e.size().height() / 2
            self.gameTitle.setGeometry(int(x), int(y) - 100, width, 50)

        if self.playButtonLabel is not None:
            x = e.size().width() / 3
            y = e.size().height() / 3
            self.playButtonLabel.setGeometry(int(x), int(y) + 50, width, 50)

    def initializeHomeScreen(self):
        self.gameTitle = QLabel("Tic Tac Toe", self)
        self.playButtonLabel = QLabel("Jogar", self)
        self.gameTitle.setStyleSheet(env.titleLabelProps)
        self.playButtonLabel.setStyleSheet(env.btnLabelProps)

    def initializeEndScreen(self, victoryMsg):
        self.gameTitle = QLabel(victoryMsg, self)
        self.playButtonLabel = QLabel("Jogar Novamente", self)
        self.gameTitle.setStyleSheet(env.titleLabelProps)
        self.playButtonLabel.setStyleSheet(env.btnLabelProps)
        print(self.geometry().x(), self.geometry().y())
        self.gameTitle.setGeometry(int(self.geometry().x() * 9),
                                   int(self.geometry().y() * 9) - 100, 420, 50)
        self.playButtonLabel.setGeometry(int(self.geometry().x() * 9),
                                         int(self.geometry().y() * 10) + 50,
                                         400, 50)

    def calculateCoordinates(self, x, y):
        coordinates = Positions()
        # get width and height in case of resizes
        # divides by 3 due to 9x9 matrix of tic tac toe
        w1 = self.geometry().width() / 3
        w2 = w1 * 2
        h1 = self.geometry().height() / 3
        h2 = h1 * 2

        # identifying x index
        if 0 <= x < w1:
            coordinates.x = 0
        elif w1 <= x < w2:
            coordinates.x = 1
        else:
            coordinates.x = 2

        # identifying y index
        if 0 <= y < h1:
            coordinates.y = 0
        elif h1 <= y < h2:
            coordinates.y = 1
        else:
            coordinates.y = 2

        return coordinates

    def switchButtonsState(self, activate):
        if activate:
            self.playButtonLabel.show()
            self.gameTitle.show()
        else:
            self.playButtonLabel.hide()
            self.gameTitle.hide()

    def calculateCoordinatesHome(self, x, y):
        print(x, y, 215 <= x < 426, 204 <= y < 280)
        btnGeometry = self.playButtonLabel.geometry()
        print(self.playButtonLabel.geometry().x(),
              self.playButtonLabel.geometry().width())
        if btnGeometry.x() <= x < btnGeometry.x() + btnGeometry.width(
        ) and btnGeometry.y() <= y < btnGeometry.y() + btnGeometry.height():
            self.switchButtonsState(False)
            return 2
        return 1

    def clearBoard(self):
        self.selectedCoordinates: List[Positions] = []
        self.matrix_game = [[0 for _ in range(3)] for _ in range(3)]

    def checkPlayPosition(self, x, y):
        for coordinate in self.selectedCoordinates:
            if coordinate.x == x and coordinate.y == y:
                print("Esse campo já foi escolhido")
                return False

        return True

    def mouseReleaseEvent(self, QMouseEvent):
        if self.SCREEN == 1:
            self.SCREEN = self.calculateCoordinatesHome(
                QMouseEvent.x(), QMouseEvent.y())
        elif self.SCREEN == 2:
            positions = self.calculateCoordinates(QMouseEvent.x(),
                                                  QMouseEvent.y())
            print("x: " + str(positions.x) + " Y: " + str(positions.y))
            if self.checkPlayPosition(positions.x, positions.y):
                self.selectedCoordinates.append(positions)
                self.repaint()
                if self.turn:
                    player = 'O'
                else:
                    player = 'X'

                self.matrix_game[positions.x][positions.y] = player

                if self.hasFinished(positions.x, positions.y):
                    self.initializeEndScreen("O Jogador '" + player +
                                             "' Ganhou!")
                    print(player + ' Won!')
                    self.clearBoard()
                    self.SCREEN = 1
                    self.repaint()
                else:
                    draw = True
                    for line in range(3):
                        for column in range(3):
                            if self.matrix_game[line][
                                    column] != 'X' and self.matrix_game[line][
                                        column] != 'O':
                                draw = False
                    if draw:
                        self.initializeEndScreen("Deu velha")
                        print('Deu velha')
                        self.clearBoard()
                        self.SCREEN = 1
                        self.repaint()

    def repaint(self):
        if self.SCREEN == 1:
            self.switchButtonsState(True)

        elif self.SCREEN == 2:
            DRAWER.draw_grid()
            for coordinate in self.selectedCoordinates:
                if coordinate.turn == 0:
                    if self.turn:
                        DRAWER.draw_x(coordinate.x, coordinate.y)
                        coordinate.turn = 1
                    else:
                        DRAWER.draw_circle(coordinate.x, coordinate.y)
                        coordinate.turn = 2
                    self.turn = not self.turn
                elif coordinate.turn == 1:
                    DRAWER.draw_x(coordinate.x, coordinate.y)
                    coordinate.turn = 1
                elif coordinate.turn == 2:
                    DRAWER.draw_circle(coordinate.x, coordinate.y)
                    coordinate.turn = 2
        self.update()

    def paintGL(self):
        glClear(GL_COLOR_BUFFER_BIT)
        glClearColor(5 / 255, 102 / 255, 141 / 255, 1.0)
        glPointSize(10)
        self.repaint()

    def hasFinished(self, x, y):
        # check if is vertical line
        if (self.matrix_game[0][y] in self.players) and self.matrix_game[0][y] == self.matrix_game[1][y] == \
                self.matrix_game[2][y]:
            return True

        # check if is horizontal line
        if (self.matrix_game[x][0] in self.players) and self.matrix_game[x][0] == self.matrix_game[x][1] == \
                self.matrix_game[x][2]:
            return True

        # check if is in first diagonal
        if (self.matrix_game[0][0] in self.players) and self.matrix_game[0][0] == self.matrix_game[1][1] == \
                self.matrix_game[2][2]:
            return True

        # check if is in second diagonal
        if (self.matrix_game[0][2] in self.players) and self.matrix_game[0][2] == self.matrix_game[1][1] == \
                self.matrix_game[2][0]:
            return True

        return False
示例#25
0
class CamView(AbstractView):
    def __init__(self,
                 name: str = "CAM_NONE",
                 log_handlers: [StreamHandler] = None):
        self._logger = getLogger(__name__)
        if log_handlers:
            for h in log_handlers:
                self._logger.addHandler(h)
        self._logger.debug("Initializing")
        super().__init__(name)
        """ Min size for cam window """
        self._subwindow_height = 222
        self._subwindow_width = 518

        self._initialization_bar_frame = EasyFrame()
        self._initialization_bar_frame.setMouseTracking(True)
        self._initialization_bar_frame.setMaximumHeight(70)
        self._initialization_bar_layout = QVBoxLayout(
            self._initialization_bar_frame)

        self._initialization_bar_label = QLabel(self._initialization_bar_frame)
        self._initialization_bar_label.setMouseTracking(True)
        self._initialization_bar = QProgressBar(self._initialization_bar_frame)
        self._initialization_bar.setMouseTracking(True)
        self._initialization_bar.setMaximumHeight(15)
        self._initialization_bar.setTextVisible(True)
        self._initialization_bar.setAlignment(Qt.AlignHCenter)

        self._initialization_bar_layout.addWidget(
            self._initialization_bar_label)
        self._initialization_bar_layout.addWidget(self._initialization_bar)

        self._cam_settings_frame = EasyFrame()
        self._cam_settings_layout = QGridLayout(self._cam_settings_frame)

        self._resolution_selector_label = QLabel(self._cam_settings_frame)
        self._resolution_selector_label.setAlignment(Qt.AlignLeft)

        self._resolution_selector = QComboBox(self._cam_settings_frame)
        self._resolution_selector.setMaximumHeight(22)

        self._cam_settings_layout.addWidget(self._resolution_selector_label, 0,
                                            0)
        self._cam_settings_layout.addWidget(self._resolution_selector, 0, 1)

        self._fps_selector_label = QLabel(self._cam_settings_frame)
        self._fps_selector_label.setAlignment(Qt.AlignLeft)

        self._fps_selector = QComboBox(self._cam_settings_frame)
        self._fps_selector.setMaximumHeight(22)

        self._cam_settings_layout.addWidget(self._fps_selector_label, 1, 0)
        self._cam_settings_layout.addWidget(self._fps_selector, 1, 1)

        self._show_feed_checkbox_label = QLabel(self._cam_settings_frame)
        self._show_feed_checkbox_label.setAlignment(Qt.AlignLeft)

        self._show_feed_checkbox = QCheckBox()
        self._show_feed_checkbox.setChecked(True)
        self._show_feed_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._show_feed_checkbox_label, 2,
                                            0)
        self._cam_settings_layout.addWidget(self._show_feed_checkbox, 2, 1)

        self._use_cam_checkbox_label = QLabel(self._cam_settings_frame)
        self._use_cam_checkbox_label.setAlignment(Qt.AlignLeft)

        self._use_cam_checkbox = QCheckBox()
        self._use_cam_checkbox.setChecked(True)
        self._use_cam_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._use_cam_checkbox_label, 3, 0)
        self._cam_settings_layout.addWidget(self._use_cam_checkbox, 3, 1)

        self._use_overlay_checkbox_label = QLabel(self._cam_settings_frame)
        self._use_overlay_checkbox_label.setAlignment(Qt.AlignLeft)

        self._use_overlay_checkbox = QCheckBox()
        self._use_overlay_checkbox.setChecked(True)
        self._use_overlay_checkbox.setLayoutDirection(Qt.RightToLeft)

        self._cam_settings_layout.addWidget(self._use_overlay_checkbox_label,
                                            4, 0)
        self._cam_settings_layout.addWidget(self._use_overlay_checkbox, 4, 1)

        self._image_display_frame = EasyFrame()
        self._image_display_layout = QVBoxLayout(self._image_display_frame)

        self._image_display_label = QLabel(self._image_display_frame)
        self._image_display_label.setAlignment(Qt.AlignHCenter)
        self._image_display = QLabel(self._image_display_frame)
        self._image_display.setAlignment(Qt.AlignCenter)
        self._image_display.setMouseTracking(True)
        self._image_display_layout.addWidget(self._image_display_label)
        self._image_display_layout.addWidget(self._image_display)

        spacer = QSpacerItem(1, 1, vData=QSizePolicy.Expanding)

        self._dev_sets_frame = EasyFrame()
        self._dev_sets_layout = QVBoxLayout(self._dev_sets_frame)

        self.config_button = ClickAnimationButton()
        self.config_button.clicked.connect(self._config_button_handler)

        self.layout().addWidget(self.config_button, 0, 0,
                                Qt.AlignTop | Qt.AlignRight)
        self.config_button.setFixedSize(30, 25)
        self.config_button.setStyleSheet(
            "background-color: rgba(200, 200, 200, 50%)")

        self._dev_sets_layout.addWidget(self._cam_settings_frame)
        self._dev_sets_layout.addItem(spacer)
        self.layout().addWidget(self._image_display, 0, 0)
        self.layout().addWidget(self._initialization_bar_frame, 0, 0)

        self._config_items = [
            self._resolution_selector,
            self._fps_selector,
            self._use_cam_checkbox,
            self._show_feed_checkbox,
            self._use_overlay_checkbox,
        ]

        config_win_w = 350
        config_win_h = len(self._config_items) * 30

        self.config_button.raise_()

        self._config_win = ConfigPopUp()
        self._config_win.setLayout(self._dev_sets_layout)
        self._config_win.setFixedSize(config_win_w, config_win_h)

        self._rec_label = QLabel()
        self._rec_label.setStyleSheet(
            "background-color: rgba(0, 0, 0, 0%); color: red; font: 20px")
        self._rec_label.hide()

        self.layout().addWidget(self._rec_label, 0, 0,
                                Qt.AlignBottom | Qt.AlignRight)

        self.layout().setMargin(0)

        self._window_changing = False
        self._showing_images = False
        self._hidden = False
        w = 320
        self._aspect_ratio = 9 / 16
        self.resize(w, self.heightForWidth(w))
        self._strings = dict()
        self._lang_enum = LangEnum.ENG
        self.setMinimumSize(self._subwindow_width, self._subwindow_height)
        self.old_size = QSize(self.width(), self.height())

        self._logger.debug("Initialized")

    def set_show_feed_button_handler(self, func) -> None:
        """
        Add handler for show camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._show_feed_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def set_resolution_selector_handler(self, func) -> None:
        """
        Add handler for resolution selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector.activated.connect(func)
        self._logger.debug("done")

    def set_fps_selector_handler(self, func) -> None:
        """
        Add handler for resolution selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.activated.connect(func)
        self._logger.debug("done")

    def set_use_cam_button_handler(self, func) -> None:
        """
        Add handler for use camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._use_cam_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def set_use_overlay_button_handler(self, func) -> None:
        """
        Add handler for use camera selector.
        :param func: The handler.
        :return None:
        """
        self._logger.debug("running")
        self._use_overlay_checkbox.toggled.connect(func)
        self._logger.debug("done")

    def _config_button_handler(self) -> None:
        """
        Show config pop up.
        :return None:
        """
        self._logger.debug("running")
        self.config_button.setStyleSheet(
            "background-color: rgba(200, 200, 200, 50%)")
        self._config_win.exec_()
        self._logger.debug("done")

    @property
    def language(self) -> LangEnum:
        """
        :return: The current lang enum being used.
        """
        return self._lang_enum

    @language.setter
    def language(self, lang: LangEnum) -> None:
        """
        Set the language for this view object.
        :param lang: The language to use.
        :return None:
        """
        self._logger.debug("running")
        self._lang_enum = lang
        self._strings = strings[lang]
        self._set_texts()
        self._set_tooltips()
        self._logger.debug("done")

    @property
    def resolution_list(self) -> list:
        """
        Get list of resolutions.
        :return list: The list of resolutions.
        """
        ret = list()
        return ret

    @resolution_list.setter
    def resolution_list(self, res_list: list) -> None:
        """
        Set list of resolutions available to res_list.
        :param res_list: The list of available resolutions.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector.clear()
        for item in res_list:
            self._resolution_selector.addItem(str(item))
        self._logger.debug("done")

    @property
    def resolution(self) -> str:
        """
        Get the current resolution selection.
        :return str: The current resolution.
        """
        return self._resolution_selector.currentText()

    @resolution.setter
    def resolution(self, res: str) -> None:
        """
        Set the current resolution selection.
        :param res: The resolution to set to.
        :return None:
        """
        self._resolution_selector.setCurrentIndex(
            self._resolution_selector.findText(res))

    @property
    def fps_list(self) -> list:
        """
        Get list of fps options.
        :return list: The list of fps options.
        """
        ret = list()
        return ret

    @fps_list.setter
    def fps_list(self, fps_list: list) -> None:
        """
        Set list of available fps to fps_list.
        :param fps_list:
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.clear()
        for item in fps_list:
            self._fps_selector.addItem(str(item))
        self._logger.debug("done")

    @property
    def fps(self) -> str:
        """
        Get the current fps selection.
        :return str: The current fps selection.
        """
        return self._fps_selector.currentText()

    @fps.setter
    def fps(self, fps: str) -> None:
        """
        Set the current fps selection.
        :param fps: The fps to set to.
        :return None:
        """
        self._logger.debug("running")
        self._fps_selector.setCurrentIndex(self._fps_selector.findText(fps))
        self._logger.debug("done")

    @property
    def use_feed(self) -> bool:
        """
        Get the current use_cam setting.
        :return bool: User selection for using cam.
        """
        return self._show_feed_checkbox.isChecked()

    @use_feed.setter
    def use_feed(self, useable: bool) -> None:
        """
        Set use_cam setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._show_feed_checkbox.setChecked(useable)
        self._logger.debug("Done")

    @property
    def use_cam(self) -> bool:
        """
        Get the current use_cam setting.
        :return bool: User selection for using cam.
        """
        return self._use_cam_checkbox.isChecked()

    @use_cam.setter
    def use_cam(self, useable: bool) -> None:
        """
        Set use_cam setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._use_cam_checkbox.setChecked(useable)
        self._logger.debug("Done")

    @property
    def use_overlay(self) -> bool:
        """
        Get the current use_overlay setting.
        :return bool: User selection for using overlay.
        """
        return self._use_overlay_checkbox.isChecked()

    @use_overlay.setter
    def use_overlay(self, useable: bool) -> None:
        """
        Set use_overlay setting.
        :param useable: The setting to set to.
        :return None:
        """
        self._logger.debug("running")
        self._use_overlay_checkbox.setChecked(useable)
        self._logger.debug("Done")

    def heightForWidth(self, w: int) -> int:
        return int(w * self._aspect_ratio)

    def widthForHeight(self, h: int) -> int:
        return int(h / self._aspect_ratio)

    def hideEvent(self, hideEvent: QHideEvent):
        """
        Track minimize event.
        :param hideEvent:
        :return None:
        """
        self._hidden = True

    def showEvent(self, showEvent: QShowEvent):
        """
        Track restore event.
        :param showEvent:
        :return None:
        """
        self._hidden = False

    def update_image(self, image: QPixmap = None, msg: str = None) -> None:
        """
        Update image viewer with new image.
        :param image: The new image to show.
        :param msg: The text to show if no image.
        :return None:
        """
        self._logger.debug("running")
        if not self._window_changing:
            if image is not None:
                temp_image_w = image.scaledToWidth(self.width() - 15)
                temp_image_h = image.scaledToHeight(self.height() - 35)
                if temp_image_w.height() > self.height() - 35:
                    self._image_display.setPixmap(temp_image_h)
                else:
                    self._image_display.setPixmap(temp_image_w)
            elif msg is not None:
                self._image_display.setText(msg)
        self._logger.debug("done")

    def show_images(self) -> None:
        """
        Show image display and hide initialization bar.
        :return None:
        """
        self._logger.debug("running")
        geo = self.geometry()
        self._showing_images = True
        self._initialization_bar_frame.hide()
        self._image_display.show()
        self.config_button.show()
        self.setStyleSheet("background-color: black")
        self.setGeometry(geo)
        self._logger.debug("done")

    def show_initialization(self) -> None:
        """
        Show initialization bar and hide image display.
        :return None:
        """
        self._logger.debug("running")
        self._showing_images = False
        self._image_display.hide()
        self.config_button.hide()
        self._initialization_bar_frame.show()
        self._logger.debug("done")

    def update_init_bar(self, progress: int) -> None:
        """
        set progress bar value to progress.
        :param progress: The value to set progress bar to.
        :return None:
        """
        self._logger.debug("running")
        if progress > 100:
            progress = 100
        elif progress < 0:
            progress = 0
        self._initialization_bar.setValue(progress)
        self._logger.debug("done")

    def set_config_active(self, is_active: bool) -> None:
        """
        Set whether this camera config options are usable.
        :param is_active: Usable.
        :return None:
        """
        self._logger.debug("running")
        if self._showing_images:
            if is_active:
                self._rec_label.hide()
            elif self.use_cam:
                self._rec_label.show()
        for item in self._config_items:
            item.setEnabled(is_active)
        self._logger.debug("done")

    def _set_texts(self) -> None:
        """
        Set the texts in this view object.
        :return None:
        """
        self._logger.debug("running")
        self._initialization_bar_label.setText(
            self._strings[StringsEnum.INITIALIZATION_BAR_LABEL])
        self._initialization_bar.setValue(0)
        self._image_display_label.setText(
            self._strings[StringsEnum.IMAGE_DISPLAY_LABEL])
        self._image_display.setText(self._strings[StringsEnum.IMAGE_DISPLAY])
        self._show_feed_checkbox_label.setText(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_LABEL])
        self._use_cam_checkbox_label.setText(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_LABEL])
        self._use_overlay_checkbox_label.setText(
            self._strings[StringsEnum.USE_OVERLAY_CHECKBOX_LABEL])
        self._resolution_selector_label.setText(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_LABEL])
        self._fps_selector_label.setText(
            self._strings[StringsEnum.FPS_SELECTOR_LABEL])
        self._config_win.setWindowTitle(
            self.get_name() + " " +
            self._strings[StringsEnum.CONFIG_TAB_LABEL])
        self.config_button.setText("...")
        self._rec_label.setText("rec ●")
        self._logger.debug("done")

    def _set_tooltips(self) -> None:
        """
        Set the tooltips in this view object.
        :return None:
        """
        self._logger.debug("running")
        self._resolution_selector_label.setToolTip(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_TOOLTIP])
        self._resolution_selector.setToolTip(
            self._strings[StringsEnum.RESOLUTION_SELECTOR_TOOLTIP])
        self._fps_selector_label.setToolTip(
            self._strings[StringsEnum.FPS_SELECTOR_TOOLTIP])
        self._fps_selector.setToolTip(
            self._strings[StringsEnum.FPS_SELECTOR_TOOLTIP])
        self._show_feed_checkbox_label.setToolTip(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_TOOLTIP])
        self._show_feed_checkbox.setToolTip(
            self._strings[StringsEnum.SHOW_FEED_CHECKBOX_TOOLTIP])
        self._use_cam_checkbox_label.setToolTip(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_TOOLTIP])
        self._use_cam_checkbox.setToolTip(
            self._strings[StringsEnum.USE_CAM_CHECKBOX_TOOLTIP])
        self._use_overlay_checkbox_label.setToolTip(
            self._strings[StringsEnum.USE_OVERLAY_TOOLTIP])
        self._use_overlay_checkbox.setToolTip(
            self._strings[StringsEnum.USE_OVERLAY_TOOLTIP])
        self._image_display.setToolTip(
            self._strings[StringsEnum.IMAGE_DISPLAY_TOOLTIP])
        self._logger.debug("done")
示例#26
0
        class MyWidget(QWidget):
            def __init__(self, parent):
                super().__init__(parent)
                self.buttons_id_value = {
                    1: ('comma', ','),
                    2: ('space', '\b'),
                    3: ('tab', '\t'),
                    4: ('semicolon', ';')
                }
                self.separator = QButtonGroup()
                lab = QLabel()
                lab.setText('Choose a separator:')
                for bid, value in self.buttons_id_value.items():
                    self.separator.addButton(QRadioButton(value[0]), id=bid)
                self.separator.setExclusive(True)
                self.default_button = self.separator.button(1)
                button_layout = QHBoxLayout()
                for button in self.separator.buttons():
                    button_layout.addWidget(button)
                self.default_button.click()

                openFileChooser = QPushButton('Choose')
                fileChooser = QFileDialog(self, 'Open csv', str(os.getcwd()),
                                          'Csv (*.csv *.tsv *.dat)')
                fileChooser.setFileMode(QFileDialog.ExistingFile)
                self.filePath = QLineEdit()
                openFileChooser.released.connect(fileChooser.show)
                fileChooser.fileSelected.connect(self.filePath.setText)
                self.filePath.textChanged.connect(self.checkFileExists)
                nameLabel = QLabel('Select a name:', self)
                self.nameField = QLineEdit(self)
                self.nameErrorLabel = QLabel(self)

                self.file_layout = QVBoxLayout()
                fileChooserLayout = QHBoxLayout()
                nameRowLayout = QHBoxLayout()
                fileChooserLayout.addWidget(openFileChooser)
                fileChooserLayout.addWidget(self.filePath)
                nameRowLayout.addWidget(nameLabel)
                nameRowLayout.addWidget(self.nameField)
                self.fileErrorLabel = QLabel(self)
                self.file_layout.addLayout(fileChooserLayout)
                self.file_layout.addWidget(self.fileErrorLabel)
                self.file_layout.addLayout(nameRowLayout)
                self.file_layout.addWidget(self.nameErrorLabel)
                self.fileErrorLabel.hide()
                self.nameErrorLabel.hide()
                self.tablePreview = SearchableAttributeTableWidget(self, True)
                self.tableSpinner = QtWaitingSpinner(
                    self.tablePreview,
                    centerOnParent=True,
                    disableParentWhenSpinning=True)
                self.nameField.textEdited.connect(self.nameErrorLabel.hide)

                # Split file by row
                splitRowLayout = QHBoxLayout()
                self.checkSplit = QCheckBox('Split file by rows', self)
                self.numberRowsChunk = QLineEdit(self)
                self.numberRowsChunk.setPlaceholderText(
                    'Number of rows per chunk')
                self.numberRowsChunk.setValidator(QIntValidator(self))
                splitRowLayout.addWidget(self.checkSplit)
                splitRowLayout.addWidget(self.numberRowsChunk)
                self.checkSplit.stateChanged.connect(self.toggleSplitRows)

                layout = QVBoxLayout()
                layout.addLayout(self.file_layout)
                layout.addWidget(lab)
                layout.addLayout(button_layout)
                layout.addLayout(splitRowLayout)
                layout.addWidget(QLabel('Preview'))
                layout.addWidget(self.tablePreview)
                self.setLayout(layout)

                self.filePath.textChanged.connect(self.loadPreview)
                self.separator.buttonClicked.connect(self.loadPreview)

            @Slot(object)
            def loadPreview(self) -> None:
                if not os.path.isfile(self.filePath.text()):
                    return

                class WorkerThread(QThread):
                    resultReady = Signal(Frame)

                    def __init__(self, path: str, separ: str, parent=None):
                        super().__init__(parent)
                        self.__path = path
                        self.__sep = separ

                    def run(self):
                        header = pd.read_csv(self.__path,
                                             sep=self.__sep,
                                             index_col=False,
                                             nrows=0)
                        self.resultReady.emit(Frame(header))

                sep: int = self.separator.checkedId()
                sep_s: str = self.buttons_id_value[sep][
                    1] if sep != -1 else None
                assert sep_s is not None

                # Async call to load header
                worker = WorkerThread(path=self.filePath.text(),
                                      separ=sep_s,
                                      parent=self)
                worker.resultReady.connect(self.onPreviewComputed)
                worker.finished.connect(worker.deleteLater)
                self.tableSpinner.start()
                worker.start()

            @Slot(Frame)
            def onPreviewComputed(self, header: Frame):
                self.tablePreview.setSourceFrameModel(FrameModel(self, header))
                self.tablePreview.model().setAllChecked(True)
                self.tableSpinner.stop()

            @Slot(str)
            def checkFileExists(self, path: str) -> None:
                file_exists = os.path.isfile(path)
                if not file_exists:
                    self.fileErrorLabel.setText('File does not exists!')
                    self.fileErrorLabel.setStyleSheet('color: red')
                    self.filePath.setToolTip('File does not exists!')
                    self.filePath.setStyleSheet('border: 1px solid red')
                    # self.file_layout.addWidget(self.fileErrorLabel)
                    self.parentWidget().disableOkButton()
                    self.fileErrorLabel.show()
                else:
                    # self.file_layout.removeWidget(self.fileErrorLabel)
                    self.fileErrorLabel.hide()
                    self.filePath.setStyleSheet('')
                    self.parentWidget().enableOkButton()
                    if not self.nameField.text():
                        name: str = os.path.splitext(os.path.basename(path))[0]
                        self.nameField.setText(name)

            @Slot(Qt.CheckState)
            def toggleSplitRows(self, state: Qt.CheckState) -> None:
                if state == Qt.Checked:
                    self.numberRowsChunk.setEnabled(True)
                else:
                    self.numberRowsChunk.setDisabled(True)

            def showNameError(self, msg: str) -> None:
                self.nameErrorLabel.setText(msg)
                self.nameErrorLabel.setStyleSheet('color: red')
                self.nameErrorLabel.show()
class PropertyTreeDelegateEditor(QFrame):
    """A special editor that handles renaming blocks and groups."""
    sizeHintChanged = Signal(object)
    """Emitted when the widget changes sizeHint. Delegate should update it's geometry."""

    def __init__(self, parent=None):
        super().__init__(parent)
        layout = QVBoxLayout()
        self.setLayout(layout)            
        self.setContentsMargins(0, 0, 0, 0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        self.setAutoFillBackground(True)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setFrameStyle(QFrame.Panel | QFrame.Plain)

        self._fallback_text = None
        self._experiment = None

        self.line_edit = QLineEdit()
        self.line_edit.setFrame(False)
        self.message_label = QLabel()
        self.message_label.hide()

        # Divider line
        self.divider_line = QFrame()
        self.divider_line.setFrameShape(QFrame.HLine)
        self.divider_line.setFrameShadow(QFrame.Plain)
        self.divider_line.setLineWidth(1)

        layout.addWidget(self.line_edit)
        layout.addWidget(self.divider_line)
        layout.addWidget(self.message_label)

        self.line_edit.textChanged.connect(self._updateMessage)
    
    def experiment(self):
        return self._experiment

    def setExperiment(self, ex):
        self._experiment = ex

    def fallbackText(self):
        return self._fallback_text

    def text(self):
        """Get the current text value of the editor widget.
        If editing has not been finished succesfully, returns fallbackText().
        """
        (text_ok, _) = self.experiment().checkName(self.line_edit.text())
        if text_ok:
            return self.line_edit.text()
        else:
            return self.fallbackText()
    
    def setFallbackText(self, text):
        """Set the fallback text value to be used if the editing was not succesfully finished.
        The text() method returns this value or the line_edit text.
        """
        self._fallback_text = text

    def setText(self, text):
        """Set currently editable text. Equivalent to self.line_edit.setText."""
        self.line_edit.setText(text)
    
    def _updateMessage(self):
        """Update the displayed message in response to changed text."""
        if self.line_edit.text() == self.fallbackText():
            # Perform no check
            text_ok = True
        else:
            (text_ok, reason) = self.experiment().checkName(self.line_edit.text())
        
        if text_ok:
            self.message_label.hide()
            self.divider_line.hide()
        else:
            self.message_label.setText(reason)
            self.message_label.show()
            self.divider_line.show()
        
        self.sizeHintChanged.emit(self)
    
    def focusInEvent(self, event):
        super().focusInEvent(event)
        self.line_edit.setFocus()
示例#28
0
文件: update.py 项目: zizle/ADSYSTEM
class UpdateDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(UpdateDialog, self).__init__(*args, **kwargs)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.setWindowTitle("版本检查")
        self.setFixedSize(240, 120)
        layout = QVBoxLayout()
        self.current_version_message = QLabel("当前版本:", self)
        self.current_version_message.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.current_version_message)

        self.last_version_message = QLabel("最新版本:检查中...", self)
        self.last_version_message.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.last_version_message)

        #  启动更新的信息提示
        self.run_message = QLabel("", self)
        self.run_message.setWordWrap(True)
        self.run_message.hide()
        self.run_message.setAlignment(Qt.AlignCenter)
        self.run_message.setStyleSheet("color:rgb(200,50,50)")
        layout.addWidget(self.run_message)

        opts_layout = QHBoxLayout()
        self.update_button = QPushButton("立即更新")
        self.update_button.clicked.connect(self.exit_for_updating)
        self.close_button = QPushButton("下次更新")
        self.close_button.clicked.connect(self.close)
        opts_layout.addWidget(self.update_button)
        opts_layout.addWidget(self.close_button)
        layout.addLayout(opts_layout)
        self.update_button.hide()
        self.setLayout(layout)

        # 检测最新版本
        app = QApplication.instance()
        self.network_manager = getattr(app, "_network")

        self._get_last_version()

    def _get_last_version(self):
        """ 获取最新版本号 """
        # 获取当前版本号
        json_file = os.path.join(BASE_DIR, "classini/update_{}.json".format(SYS_BIT))
        if not os.path.exists(json_file):
            self.current_version_message.setText("当前版本:检测失败.")
            self.last_version_message.setText("最新版本:检测失败.")
            self.close_button.setText("关闭")
            return

        with open(json_file, "r", encoding="utf-8") as jf:
            update_json = json.load(jf)

        self.current_version_message.setText("当前版本:{}".format(update_json["VERSION"]))

        url = SERVER + "check_version/?version={}&sys_bit={}".format(update_json["VERSION"], SYS_BIT)
        request = QNetworkRequest(url=QUrl(url))

        reply = self.network_manager.get(request)
        reply.finished.connect(self.last_version_back)

    def last_version_back(self):
        """ 检测版本结果 """
        reply = self.sender()
        if reply.error():
            reply.deleteLater()
            self.last_version_message.setText("最新版本:检测失败.")
            return
        data = reply.readAll().data()
        u_data = json.loads(data.decode("utf-8"))
        if u_data["update_needed"]:
            for_update_file = os.path.join(BASE_DIR, "classini/for_update_{}.json".format(SYS_BIT))
            # 写入待更新信息
            f_data = {
                "VERSION": u_data["last_version"],
                "SERVER": u_data["file_server"],
                "FILES": u_data["update_files"]
            }
            with open(for_update_file, "w", encoding="utf-8") as f:
                json.dump(f_data, f, indent=4, ensure_ascii=False)
            self.update_button.show()
        else:
            self.update_button.hide()
            self.close_button.setText("关闭")
        self.last_version_message.setText("最新版本:{}".format(u_data["last_version"]))
        reply.deleteLater()

    def exit_for_updating(self):
        """ 退出当前程序,启动更新更新 """
        script_file = os.path.join(BASE_DIR, "AutoUpdate.exe")
        if SYS_BIT == "admin":
            script_file = os.path.join(BASE_DIR, "AutoAdminUpdate.exe")
        is_close = True
        if os.path.exists(script_file):
            try:
                Popen(script_file, shell=False)
            except OSError as e:
                self.run_message.setText(str(e))
                is_close = False
        else:
            self.run_message.setText("更新程序丢失...")
            is_close = False
        self.run_message.show()
        if is_close:
            sys.exit()

    def closeEvent(self, event):
        """ 下次更新 """
        for_update_file = os.path.join(BASE_DIR, "classini/for_update_{}.json".format(SYS_BIT))
        if os.path.exists(for_update_file):
            os.remove(for_update_file)
        super(UpdateDialog, self).closeEvent(event)
class OutputLayout(QGridLayout):
    ga_result = Signal(
        str
    )  # a signal that is emited so it can transfer resulting string to the output_layout class

    def __init__(self):
        super(OutputLayout, self).__init__()
        self.run_section = QWidget()
        self.run_section.setMaximumHeight(100)
        self.run_layout = QVBoxLayout()
        self.header_run = QLabel()
        self.run_comment = QLabel()
        self.btn_run = QPushButton("Run")
        self.btn_run.clicked.connect(self.run_button_clicked)

        self.progress = QProgressBar()
        self.console = QTextEdit()
        self.console.setText("This is output")
        self.init_console()
        self.init_run_section()

        self.addWidget(self.console, 1, 1, 1, 1)

    def print_output(self, output_text):
        self.console.setText(output_text)

    def append_output(self, text):
        self.console.append(text)

    def init_console(self):
        # new_font = QFont('courier new', 8)
        # self.console.setFont(new_font)
        self.console.setReadOnly(True)
        self.console.horizontalScrollBar().setEnabled(True)
        self.console.setLineWrapMode(QTextEdit.NoWrap)

    def init_run_section(self):
        font14 = QFont()
        font14.setPointSizeF(12)
        self.header_run.setFont(font14)
        self.header_run.setText("RUN")
        self.run_comment.setText("Iteration stopped in 128 iteration")
        self.run_comment.hide()
        font10 = QFont()
        font10.setPointSizeF(10)
        self.run_comment.setFont(font10)
        self.run_comment.setAlignment(Qt.AlignCenter)
        self.progress.show()

        self.addWidget(self.header_run, 2, 1, 1, 1)
        self.addWidget(self.run_comment, 3, 1, 1, 1)
        self.addWidget(self.progress, 4, 1, 1, 1)
        self.addWidget(self.btn_run, 5, 1, 1, 1)

    def run_button_clicked(self):
        self.clear_console()
        options = QApplication.instance().main_window.centerWidget.layout(
        ).inputs_layout.get_options()
        controller = QApplication.instance().controller
        self.progress.show()
        function = options["function"]
        num_var = options["num_var"]

        ga(function, int(num_var), options, controller)

    def set_progress_bar(self, value):
        self.progress.setValue(value)

    def set_status_text(self, text):
        self.run_comment.setText(text)

    def clear_console(self):
        self.console.clear()

    def set_run_comment(self, text):
        self.run_comment.setText(text)
        self.run_comment.show()
示例#30
0
class UserSelect(QWidget):
    def __init__(self, kernel, parent=None):
        super(UserSelect, self).__init__(parent)
        self.kernel = kernel
        self.parent = parent
        self.initUI()

    def initUI(self):
        self.createElements()
        self.createLayout()
        self.createActions()
        self.hideNewUserForm()
        self.hideLoginForm()

    def createElements(self):
        self.userButtons = [
            UserTile(u, self) for u in self.kernel.getAllUsers()
        ]
        for b, u in zip(self.userButtons, self.kernel.getAllUsers()):
            b.setProfilePicture(self.kernel.getUsersDir() + u +
                                '/profile/profile_pic.png')
            b.createLayout()

        self.newUserButton = QPushButton('New User')
        self.nevermindButton = QPushButton("Nevermind")
        self.newUserNameField = QLineEdit("Username")
        self.newUserPasswordField = QLineEdit("Password")
        self.newUserPasswordField.setEchoMode(QLineEdit.Password)
        self.newUserConfirmPasswordField = QLineEdit("Confirm Password")
        self.newUserConfirmPasswordField.setEchoMode(QLineEdit.Password)
        self.submitNewUserButton = QPushButton('submit')
        self.newUserNameErrorLabel = QLabel('')
        self.newPasswordErrorLabel = QLabel('')
        self.existingUserLoginField = QLineEdit('Password')
        self.existingUserLoginField.setEchoMode(QLineEdit.Password)
        self.existingUserLoginButton = QPushButton('Login')
        self.existingUserLoginErrorLabel = QLabel('')
        self.selectedUser = None

    def createLayout(self):
        self.existingUsersLayout = QHBoxLayout()
        self.existingUsersLayout.addStretch()
        for ub in self.userButtons:
            ub.resize(100, 120)
            self.existingUsersLayout.addWidget(ub)
            self.existingUsersLayout.addStretch()

        self.formLayout = QVBoxLayout()
        self.formLayout.addStretch()
        self.formLayout.addWidget(self.newUserButton)
        self.formLayout.addWidget(self.nevermindButton)
        self.formLayout.addWidget(self.newUserNameField)
        self.formLayout.addWidget(self.newUserNameErrorLabel)
        self.formLayout.addWidget(self.newUserPasswordField)
        self.formLayout.addWidget(self.newUserConfirmPasswordField)
        self.formLayout.addWidget(self.newPasswordErrorLabel)
        self.formLayout.addWidget(self.submitNewUserButton)
        self.formLayout.addWidget(self.existingUserLoginField)
        self.formLayout.addWidget(self.existingUserLoginErrorLabel)
        self.formLayout.addWidget(self.existingUserLoginButton)
        self.formLayout.addStretch()

        self.lowLayout = QHBoxLayout()
        self.lowLayout.addStretch()
        self.lowLayout.addLayout(self.formLayout)
        self.lowLayout.addStretch()

        self.layout = QVBoxLayout(self)
        self.layout.addStretch()
        self.layout.addLayout(self.existingUsersLayout)
        self.layout.addLayout(self.lowLayout)
        self.layout.addStretch()

    def createActions(self):
        self.newUserButton.clicked.connect(self.revealNewUserForm)
        self.nevermindButton.clicked.connect(self.hideNewUserForm)
        self.submitNewUserButton.clicked.connect(self.submitNewUserRequest)
        self.existingUserLoginButton.clicked.connect(self.login)
        for btn in self.userButtons:
            btn.nameButton.clicked.connect(
                lambda: self.revealLoginForm(btn.nameButton.text()))

    def revealNewUserForm(self):
        self.hideLoginForm()
        self.newUserButton.hide()
        self.newUserNameField.show()
        self.newUserPasswordField.show()
        self.newUserConfirmPasswordField.show()
        self.submitNewUserButton.show()
        self.nevermindButton.show()

    def hideNewUserForm(self):
        self.newUserButton.show()
        self.newUserNameErrorLabel.hide()
        self.newPasswordErrorLabel.hide()
        self.newUserNameField.hide()
        self.newUserPasswordField.hide()
        self.newUserConfirmPasswordField.hide()
        self.submitNewUserButton.hide()
        self.nevermindButton.hide()

    def revealLoginForm(self, user):
        self.hideNewUserForm()
        self.selectedUser = user
        self.existingUserLoginButton.show()
        self.existingUserLoginErrorLabel.show()
        self.existingUserLoginField.show()

    def hideLoginForm(self):
        self.selectedUser = None
        self.existingUserLoginButton.hide()
        self.existingUserLoginErrorLabel.hide()
        self.existingUserLoginField.hide()

    def submitNewUserRequest(self):
        userName = self.newUserNameField.text()
        pwd = self.newUserPasswordField.text()
        conf_pwd = self.newUserConfirmPasswordField.text()

        err_msg = ''
        if pwd != conf_pwd:
            err_msg = 'Error: passwords do not match'
            self.newPasswordErrorLabel.setText(err_msg)
            self.newPasswordErrorLabel.show()
        else:
            self.newPasswordErrorLabel.hide()

        if self.kernel.userExists(userName):
            err_msg = 'Error: Username is already taken. Choose something else'
            self.newUserNameErrorLabel.setText(err_msg)
            self.newUserNameErrorLabel.show()
        else:
            self.newUserNameErrorLabel.hide()

        if err_msg != '':
            return

        if self.kernel.addUser(userName, pwd):
            self.parent.loadApplication()
        else:
            err = "Error: User Creation failed.\nPlease use your Robinhood Credentials"
            self.newPasswordErrorLabel.setText(err)
            self.newPasswordErrorLabel.show()

    def login(self):
        assert (self.selectedUser != None)
        pwd = self.existingUserLoginField.text()
        if not self.kernel.switchUser(self.selectedUser, pwd):
            self.existingUserLoginErrorLabel.setText(err)
            self.existingUserLoginErrorLabel.show()
        else:
            self.parent.loadApplication()