Esempio n. 1
0
class AddUserFace(QDialog):
    def __init__(self, image):
        super(AddUserFace, self).__init__()
        self.setFixedSize(300, 275)
        self.setWindowIcon(QIcon('icons/add.png'))
        self.setWindowTitle('添加')

        self.rb_select = QRadioButton("选择", self)
        self.rb_select.setGeometry(70, 20, 50, 26)
        self.rb_select.toggled.connect(self.toggle)

        self.rb_new = QRadioButton('新建', self)
        self.rb_new.setGeometry(120, 20, 50, 26)
        self.rb_new.toggled.connect(self.toggle)

        lbl_name = QLabel('名称', self)
        lbl_name.setGeometry(10, 70, 50, 26)
        lbl_name.setAlignment(Qt.AlignCenter)

        users = DbHelper.query_users()

        self.cb_user = QComboBox(self)
        self.cb_user.setGeometry(70, 70, 200, 26)
        self.le_user = QLineEdit(self)
        self.le_user.setGeometry(70, 70, 200, 26)

        if users is not None and len(users) > 0:
            self.rb_select.setChecked(True)
            for user in users:
                self.cb_user.addItem(user[1], userData=user)
        else:
            self.rb_select.setDisabled(True)
            self.rb_new.setChecked(True)

        lbl_face = QLabel('人脸', self)
        lbl_face.setGeometry(10, 140, 50, 26)
        lbl_face.setAlignment(Qt.AlignCenter)

        self.btn_save = QPushButton(self)
        self.btn_save.setText('保存')
        self.btn_save.setGeometry(10, 234, 280, 30)
        self.btn_save.clicked.connect(self.save)

        self.cache_faces = {}
        self.face = None

        faces = HaarcascadeDetective.get_faces(image)
        index = 0
        for face in faces:
            viewer_face = QPushButton(self)
            viewer_face.setGeometry(70 * (index + 1), 120, 60, 60)
            viewer_face.setIconSize(QSize(56, 56))
            img = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
            image = QImage(img, img.shape[1], img.shape[0], img.shape[1] * 3,
                           QImage.Format_RGB888)
            pix_map = QPixmap.fromImage(image)
            viewer_face.setIcon(QIcon(pix_map))
            viewer_face.clicked.connect(self.select_face)
            self.cache_faces[viewer_face] = face
            if index == 0:
                self.face = face
                viewer_face.setStyleSheet(
                    'border-color: rgb(255, 0, 0);border-style: outset;border-width: 2px;'
                )
            index += 1
            if index > 3:
                break

        if index == 0:
            Tool.show_msg_box("未检测到人脸信息")

    def select_face(self):
        sender = self.sender()
        for btn in self.cache_faces:
            btn.setStyleSheet('border-style: none')
        sender.setStyleSheet(
            "border-color: rgb(255, 0, 0);border-style: outset;border-width: 2px;"
        )
        self.face = self.cache_faces[btn]

    def toggle(self):
        if self.rb_new.isChecked():
            self.cb_user.hide()
            self.le_user.show()
        elif self.rb_select.isChecked():
            self.le_user.hide()
            self.cb_user.show()

    def save(self):
        if self.face is None:
            return
        self.btn_save.setDisabled(True)
        if self.rb_new.isChecked():
            user_name = self.le_user.text().strip(' ')
            if not user_name.replace(' ', '').encode("utf-8").isalpha():
                Tool.show_msg_box('只支持英文字母和空格~')
                self.le_name.setFocus()
                return
            user_id = DbHelper.insert_user(user_name)
        else:
            user_id = self.cb_user.currentData()[0]
        if not os.path.exists("faces"):
            os.mkdir("faces")
        if not os.path.exists('faces/{}'.format(user_id)):
            os.mkdir('faces/{}'.format(user_id))
        face = 'faces/{}/{}.png'.format(user_id, time.time())
        cv2.imwrite(face, self.face)
        self.close()
Esempio n. 2
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()
Esempio n. 3
0
class DictWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__()

        self.view = QTableView()
        self.model = DictModel()
        self.proxy_model = QSortFilterProxyModel()
        self.search_bar = QLineEdit()
        self._show_loading = False

        self.proxy_model.setSourceModel(self.model)

        self.view.setModel(self.proxy_model)
        self.view.setAlternatingRowColors(True)
        self.view.horizontalHeader().setStretchLastSection(True)
        self.view.setSelectionMode(QAbstractItemView.SingleSelection)
        self.view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.view.setSortingEnabled(True)
        self.view.verticalHeader().hide()

        self.search_bar.textChanged.connect(
            self.proxy_model.setFilterRegularExpression)
        self.search_bar.setVisible(False)

        self._show_search_action = QAction("show search bar")
        self._show_search_action.setCheckable(True)
        self._show_search_action.setShortcutContext(Qt.WidgetShortcut)
        self._show_search_action.setShortcut(QKeySequence.Find)
        self._show_search_action.triggered.connect(self._on_show_search)

        self._close_search_action = QAction()
        self._close_search_action.setShortcut(QKeySequence(Qt.Key_Escape))
        self._close_search_action.setShortcutContext(Qt.WidgetShortcut)
        self._close_search_action.triggered.connect(self._on_close_search)

        self.view.addAction(self._show_search_action)
        self.search_bar.addAction(self._close_search_action)

        _layout = QVBoxLayout()
        _layout.addWidget(self.view)
        _layout.addWidget(self.search_bar)
        _layout.setContentsMargins(0, 0, 0, 0)

        self.setLayout(_layout)
        print("init")

    def set_dict(self, data: dict):

        self.model.set_dict(data)

    def _on_show_search(self):
        self.search_bar.setVisible(True)
        self.search_bar.setFocus(Qt.ShortcutFocusReason)

    def _on_close_search(self):
        self.search_bar.hide()
        self.search_bar.clear()
        self.view.setFocus(Qt.ShortcutFocusReason)

    def set_header_visible(self, visible=True):
        self.view.horizontalHeader().setVisible(visible)

    def clear(self):
        self.model.clear()

    def paintEvent(self, event: QPaintEvent):

        if self._show_loading:
            painter = QPainter(self)
            painter.drawText(self.rect(), Qt.AlignCenter,
                             self.tr("Loading ..."))
        else:
            super().paintEvent(event)

    def set_loading(self, show=True):
        self._show_loading = True
        self.view.setVisible(not show)
        self.update()
Esempio n. 4
0
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setFixedWidth(70)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))
        self.lbl.selectionChanged.connect(lambda: self.lbl.setSelection(0, 0))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))
        self.elbl.selectionChanged.connect(
            lambda: self.elbl.setSelection(0, 0))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
                "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
                "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)

        self.shortcut = QShortcut(QKeySequence("y"), self)
        self.shortcut.activated.connect(self.getYTUrl)

        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        print("QT5 Player started")
        print("press 'o' to open file (see context menu for more)")
        self.suspend_screensaver()

    def mouseDoubleClickEvent(self, event):
        self.handleFullscreen()

    def playFromURL(self):
        self.mediaPlayer.pause()
        self.myurl = self.clip.text()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(self.myurl)

    def getYTUrl(self):
        cmd = "youtube-dl -g -f best " + self.clip.text()
        print("grabbing YouTube URL")
        self.process.start(cmd)

    def dataReady(self):
        self.myurl = str(self.process.readAll(), encoding='utf8').rstrip()  ###
        self.myurl = self.myurl.partition("\n")[0]
        print(self.myurl)
        self.clip.setText(self.myurl)
        self.playFromURL()

    def suspend_screensaver(self):
        'suspend linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false',
            shell=True)
        proc.wait()

    def resume_screensaver(self):
        'resume linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true',
            shell=True)
        proc.wait()

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Open Movie",
            QDir.homePath() + "/Videos",
            "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)"
        )

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(mtime.toString())

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: ", self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        self.resume_screensaver()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"),
                                    "open File (o)")
        actionclipboard = menu.addSeparator()
        actionURL = menu.addAction(QIcon.fromTheme("browser"),
                                   "URL from Clipboard (u)")
        actionclipboard = menu.addSeparator()
        actionYTurl = menu.addAction(QIcon.fromTheme("youtube"),
                                     "URL from YouTube (y)")
        actionclipboard = menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"),
                                      "show / hide Slider (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"),
                                    "Fullscreen (f)")
        action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9")
        action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)")
        action5 = menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"),
                                    "Exit (q)")

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        actionYTurl.triggered.connect(self.getYTUrl)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             round((mwidth + mscale) / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             round((mwidth + mscale) / 1.33))
        #elif self.positionSlider.hasFocus():
        #    self.positionSlider.value = self.positionSlider.value + 5

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio))

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, round(mwidth / mratio))

    def handleFullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def handleInfo(self):
        msg = QMessageBox.about(self, "QT5 Player", self.myinfo)

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33))

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.55))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(mwidth / 1.33))

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mousePressEvent(self, evt):
        self.oldPos = evt.globalPos()

    def mouseMoveEvent(self, evt):
        delta = QPoint(evt.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = evt.globalPos()

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

    def dropEvent(self, event):
        print("drop")
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            ### YouTube url
            if "youtube" in mydrop:
                print("is YouTube", mydrop)
                self.clip.setText(mydrop)
                self.getYTUrl()
            else:
                ### normal url
                print("generic url = ", mydrop)
                self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
                self.playButton.setEnabled(True)
                self.mediaPlayer.play()
                self.hideSlider()

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()

    def printMediaData(self):
        if self.mediaPlayer.mediaStatus() == 6:
            if self.mediaPlayer.isMetaDataAvailable():
                res = str(self.mediaPlayer.metaData("Resolution")).partition(
                    "PyQt5.QtCore.QSize(")[2].replace(", ",
                                                      "x").replace(")", "")
                print("%s%s" % ("Video Resolution = ", res))
                if int(res.partition("x")[0]) / int(
                        res.partition("x")[2]) < 1.5:
                    self.screen43()
                else:
                    self.screen169()
            else:
                print("no metaData available")

    def openFileAtStart(self, filelist):
        matching = [s for s in filelist if ".myformat" in s]
        if len(matching) > 0:
            self.loadFilm(matching)
class QtOpticalflowInterfaceCloud(QWidget):
    PREVIEW = [
        "no preview", "print fps", "image (default)", "image+fps",
        "print+image+fps", "print+image"
    ]

    MODE = [
        "stream",
        "video",
    ]

    ESTIMATION = [
        "no computing estimation",
        "simple estimate",
        "complete estimation (video mode only)",
    ]

    os.chdir("../modules")
    VISION_MODULES = glob.glob("*.py")
    os.chdir("../solutions")

    def __init__(self):
        QWidget.__init__(self)

        self.salutation_lbl = QLabel(
            'Welcome to Opticalflow utilise Graphic interface', self)

        self.compute_location_text = QLabel("compute location:", self)
        self.compute_location = QComboBox(self)

        self.setMinimumSize(400, 400)
        self.setWindowTitle('GUI opticalflow utilities')

        self.ip_text = QLabel("ip:", self)
        self.ip = QLineEdit(self)

        self.port_text = QLabel("port:", self)
        self.port = QLineEdit(self)

        self.width_text = QLabel("width:", self)
        self.width = QLineEdit(self)

        self.height_text = QLabel("height:", self)
        self.height = QLineEdit(self)

        self.save_text = QLabel("save:", self)
        self.save = QCheckBox(self)

        self.save_extension = QLabel("", self)

        self.name_save = QLineEdit(self)

        self.fps_text = QLabel("fps:", self)
        self.fps = QLineEdit(self)

        self.preview_text = QLabel("preview:", self)
        self.preview = QComboBox(self)

        self.mode_text = QLabel("mode:", self)
        self.mode = QComboBox(self)

        self.video_file = QLineEdit(self)

        self.estimation_text = QLabel("estimation:", self)
        self.estimation = QComboBox(self)

        self.module_vision_text = QLabel("vision module:", self)
        self.module_vision = QComboBox(self)

        self.validation_button = QPushButton(self)

        self.set_buttons()

    def set_buttons(self):
        self.salutation_lbl.move(50, 5)  # offset the first control 5px

        self.compute_location_text.move(5, 35)
        self.compute_location.move(120, 30)
        self.compute_location.addItems(["local", "cloud"])
        self.compute_location.currentIndexChanged.connect(self.cloud_ip)

        self.ip_text.move(5, 70)
        self.ip.setText("localhost")
        self.ip.move(110, 70)
        self.ip.hide()
        self.ip_text.hide()

        self.port_text.move(5, 105)
        self.port.setText("10000")
        self.port.move(110, 105)
        self.port.hide()
        self.port_text.hide()

        self.width_text.move(5, 140)
        self.width.setText("320")
        self.width.move(110, 140)

        self.height_text.move(5, 175)
        self.height.setText("240")
        self.height.move(110, 175)

        self.save_text.move(5, 205)
        self.save.move(110, 205)
        self.save.clicked.connect(self.fps_show)

        self.name_save.move(130, 200)
        self.name_save.setText("file")
        self.name_save.hide()

        self.save_extension.move(260, 205)
        self.save_extension.hide()

        self.fps_text.move(5, 240)
        self.fps.move(110, 240)
        self.fps.setText("20")

        self.fps_text.hide()
        self.fps.hide()

        self.preview.addItems(self.PREVIEW)
        self.preview.move(110, 275)
        self.preview_text.move(5, 275)

        self.mode.addItems(self.MODE)
        self.mode.move(110, 310)
        self.mode_text.move(5, 310)
        self.mode.currentIndexChanged.connect(self.video_mode)

        self.video_file.move(190, 310)
        self.video_file.setText("videos_to_computed_videos/video_list_example")
        self.video_file.hide()

        self.estimation.addItems(self.ESTIMATION)
        self.estimation.move(110, 345)
        self.estimation_text.move(5, 345)

        self.module_vision.addItems(self.VISION_MODULES)
        self.module_vision.move(110, 375)
        self.module_vision_text.move(5, 375)

        self.validation_button.move(5, 400)
        self.validation_button.setText("clicked")
        self.validation_button.clicked.connect(self.reset_window)

    def get_value(self):
        return self

    def reset_window(self):
        copyfile("../modules/" + self.module_vision.currentText(),
                 "./realtime/vision_module.py")

        if self.compute_location.currentText() == "cloud":
            self.streaming = Streaming(FieldValue(self))
        elif self.mode.currentIndex() == 0:
            self.streaming = OpticalRealtime(FieldValue(self))
        elif self.mode.currentIndex() == 1:
            self.streaming = VideoList(FieldValue(self))

        self.streaming.run()

    def fps_show(self):
        if self.save.isChecked():
            self.fps_text.show()
            self.fps.show()
            self.name_save.show()
            self.save_extension.show()
        else:
            self.fps_text.hide()
            self.fps.hide()
            self.name_save.hide()
            self.save_extension.hide()

    def cloud_ip(self):
        if self.compute_location.currentText() == "local":
            self.ip.hide()
            self.ip_text.hide()
            self.port.hide()
            self.port_text.hide()
        else:
            self.ip.show()
            self.ip_text.show()
            self.port.show()
            self.port_text.show()

    def video_mode(self):
        if self.mode.currentText() == "video":
            self.video_file.show()
        else:
            self.video_file.hide()

    def __delete__(self):
        pass
Esempio n. 6
0
class ParametersWindow(QWidget):
    """
    Créer la fenêtre des paramètres
    """
    def __init__(self, settings):
        QWidget.__init__(self)
        self.settings = settings

        self.setWindowTitle('PARAMETERS')
        self.setFixedSize(360, 500)

        self.main_layout = QGridLayout()
        self.main_layout.setAlignment(Qt.AlignTop)
        self.setLayout(self.main_layout)

        calculous_parameters_label = QLabel('CALCULOUS PARAMETERS')
        calculous_parameters_label.setAlignment(Qt.AlignCenter)
        calculous_parameters_label.setFixedHeight(58)
        calculous_parameters_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        self.main_layout.addWidget(calculous_parameters_label, 0, 0, 1, 2)

        object_mass_label = QLabel('Object mass (kg)')
        object_mass_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        object_mass_label.setFixedHeight(32)
        self.main_layout.addWidget(object_mass_label, 1, 0, 1, 1)

        self.object_mass_input = QLineEdit()
        self.object_mass_input.setAlignment(Qt.AlignRight)
        self.object_mass_input.setText(str(self.settings.object_mass))
        self.object_mass_input.textChanged.connect(self.updateObjectMass)
        self.main_layout.addWidget(self.object_mass_input, 1, 1, 1, 1)

        dichotomy_precision_label = QLabel('Dichotomy precision')
        dichotomy_precision_label.setFixedHeight(32)
        dichotomy_precision_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        self.main_layout.addWidget(dichotomy_precision_label, 2, 0, 1, 1)

        self.dichotomy_precision_input = QLineEdit()
        self.dichotomy_precision_input.setAlignment(Qt.AlignRight)
        self.dichotomy_precision_input.setText(
            str(self.settings.dichotomy_precision))
        self.dichotomy_precision_input.textChanged.connect(
            self.updateDichotomyPrecision)
        self.main_layout.addWidget(self.dichotomy_precision_input, 2, 1, 1, 1)

        fluid_density_label = QLabel('Fluid density (kg/m3)')
        fluid_density_label.setFixedHeight(32)
        fluid_density_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        self.main_layout.addWidget(fluid_density_label, 3, 0, 1, 1)

        self.fluid_density_options = QComboBox()
        if self.settings.fluid_density == SALTWATER_DENSITY:
            self.fluid_density_options.addItem('saltwater (' +
                                               str(SALTWATER_DENSITY) +
                                               ' kg/m3)')
            self.fluid_density_options.addItem('freshwater (' +
                                               str(FRESHWATER_DENSITY) +
                                               ' kg/m3)')
        else:
            self.fluid_density_options.addItem('freshwater (' +
                                               str(FRESHWATER_DENSITY) +
                                               ' kg/m3)')
            self.fluid_density_options.addItem('saltwater (' +
                                               str(SALTWATER_DENSITY) +
                                               ' kg/m3)')
        self.fluid_density_options.addItem('Other')
        self.fluid_density_options.activated.connect(
            self.updateFluidDensityWithOption)
        self.main_layout.addWidget(self.fluid_density_options, 3, 1, 1, 1)

        self.fluid_density_input = QLineEdit()
        self.fluid_density_input.setAlignment(Qt.AlignRight)
        self.fluid_density_input.textChanged.connect(
            self.updateFluidDensityWithInput)
        if self.settings.fluid_density in [
                FRESHWATER_DENSITY, SALTWATER_DENSITY
        ]:
            self.fluid_density_input.hide()
        else:
            self.fluid_density_input.setText(str(self.settings.fluid_density))
        self.main_layout.addWidget(self.fluid_density_input, 4, 1, 1, 1)

        display_parameters_label = QLabel('DISPLAY PARAMETERS')
        display_parameters_label.setAlignment(Qt.AlignCenter)
        display_parameters_label.setFixedHeight(58)
        display_parameters_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        self.main_layout.addWidget(display_parameters_label, 5, 0, 1, 2)

        show_draught_label = QLabel('Show draught')
        show_draught_label.setFixedHeight(32)
        show_draught_label.setStyleSheet(
            'font-family: Calibri; font-size : 10pt; color: #2C3E50;')
        self.main_layout.addWidget(show_draught_label, 6, 0, 1, 1)
        self.show_draught_checkbox = QCheckBox()
        self.show_draught_checkbox.stateChanged.connect(self.updateShowDraught)
        self.show_draught_checkbox.setCheckState(
            Qt.CheckState.Checked if self.settings.show_draught else Qt.
            CheckState.Unchecked)
        self.main_layout.addWidget(self.show_draught_checkbox, 6, 1, 1, 1)

        self.show()

    def updateObjectMass(self):
        """
        Mettre à jour la masse entrée par l'utilisateur
        """
        try:
            if float(self.object_mass_input.text()
                     ) != self.settings.object_mass:
                self.settings.object_mass = float(
                    self.object_mass_input.text())
                self.lockSimulationButtons()
                self.settings.term.addSuccessMessage(
                    'The mass you entered is in a valid format')
        except Exception:
            self.settings.term.addErrorMessage(
                'The mass you entered is not in a valid format')
        finally:
            pass

    def updateDichotomyPrecision(self):
        """
        Mettre à jour la précision entrée par l'utilisateur
        """
        try:
            if float(self.dichotomy_precision_input.text()
                     ) != self.settings.dichotomy_precision:
                self.settings.dichotomy_precision = float(
                    self.dichotomy_precision_input.text())
                self.lockSimulationButtons()
                self.settings.term.addSuccessMessage(
                    'The dichotomy_precision you entered is in a valid format')
        except Exception:
            self.settings.term.addErrorMessage(
                'The dichotomy_precision you entered is not in a valid format')
        finally:
            pass

    def updateFluidDensityWithOption(self):
        """
        Mettre à jour la densité sélectionnée par l'utilisateur
        """
        option = self.fluid_density_options.currentText()
        if option == 'Other':
            self.fluid_density_input.show()
        else:
            self.fluid_density_input.hide()
            if option == 'freshwater (' + str(FRESHWATER_DENSITY) + ' kg/m3)':
                if self.settings.fluid_density != FRESHWATER_DENSITY:
                    self.settings.fluid_density = FRESHWATER_DENSITY
                    self.lockSimulationButtons()
            else:
                if self.settings.fluid_density != SALTWATER_DENSITY:
                    self.settings.fluid_density = SALTWATER_DENSITY
                    self.lockSimulationButtons()
            self.settings.term.addSuccessMessage(
                'The density of the fluid has correctly been changed')

    def updateFluidDensityWithInput(self):
        """
        Permettre à l'utilisateur d'entrer une densité de lui-même
        """
        try:
            if float(self.fluid_density_input.text()
                     ) != self.settings.fluid_density:
                self.settings.fluid_density = float(
                    self.fluid_density_input.text())
                self.lockSimulationButtons()
                self.settings.term.addSuccessMessage(
                    'The fluid density you entered is in a valid format')
        except Exception:
            self.settings.term.addErrorMessage(
                'The fluid density entered is not in a valid format')
        finally:
            pass

    def updateShowDraught(self):
        """
        Afficher le tirant d'eau si l'utilisateur le désire
        """
        if self.show_draught_checkbox.isChecked(
        ) != self.settings.show_draught:
            self.settings.show_draught = self.show_draught_checkbox.isChecked()
            self.lockSimulationButtons()
            if self.settings.show_draught:
                self.settings.draught_legend.show()
            else:
                self.settings.draught_legend.hide()
            self.settings.term.addSuccessMessage(
                'Show draught has correctly changed')

            self.settings.updatePreview(self.settings.show_draught)

    def lockSimulationButtons(self):
        """
        Désactiver certains boutons lors de la modification des paramètres
        """
        for i in range(3, 7):
            self.settings.buttons[i].setDisabled(True)
        self.settings.buttons[2].setDisabled(False)
Esempio n. 7
0
class MainWindow(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.setWindowTitle('MASK标注工具')
        self.setFixedSize(1000, 650)
        self.move_to_center()

        #
        self.mask_img_size = QSize(512, 512)
        self.brush_color = QColor(255, 255, 0)
        self.eraser_color = QColor(0, 0, 0)
        self.label_img = ImageLabel(self, self.mask_img_size, self.brush_color,
                                    self.eraser_color)
        self.label_img.setAlignment(Qt.AlignCenter)
        self.label_img.setText('没有选择任何图片')
        self.label_img.setFixedWidth(700)
        self.label_img.setFixedHeight(600)

        #
        self.btn_select_dir = QPushButton(self)
        self.btn_select_dir.setText('选择目录...')
        self.btn_select_dir.clicked.connect(self.on_btn_select_dir)

        self.btn_prev_img = QPushButton(self)
        self.btn_prev_img.setText('上一张')
        self.btn_prev_img.clicked.connect(self.on_btn_prev_img)
        self.connect(QShortcut(QKeySequence(Qt.Key_Left), self),
                     QtCore.SIGNAL('activated()'), self.btn_prev_img.click)

        self.btn_next_img = QPushButton(self)
        self.btn_next_img.setText('下一张')
        self.btn_next_img.clicked.connect(self.on_btn_next_img)
        self.connect(QShortcut(QKeySequence(Qt.Key_Right), self),
                     QtCore.SIGNAL('activated()'), self.btn_next_img.click)

        self.btn_select_brush_color = QPushButton(self)
        self.btn_select_brush_color.setText('修改画笔颜色')
        self.btn_select_brush_color.clicked.connect(
            self.on_btn_select_brush_color)

        self.label_brush_color = QLabel(self)
        self.label_brush_color.setFixedWidth(50)

        pe = QPalette()
        pe.setColor(QPalette.Window, self.brush_color)
        self.label_brush_color.setPalette(pe)
        self.label_brush_color.setAutoFillBackground(True)

        self.defalut_brush_pixle_size = 5
        self.min_brush_pixle_size = 1
        self.max_brush_pixle_size = 50
        self.label_brush_pixle_size = QLabel('画笔像素大小:')
        self.label_brush_pixle_size.setFixedWidth(110)
        self.edit_brush_pixle_size_validator = QIntValidator()
        self.edit_brush_pixle_size_validator.setRange(
            self.min_brush_pixle_size, self.max_brush_pixle_size)
        self.edit_brush_pixle_size = QLineEdit(self)
        self.edit_brush_pixle_size.setText(f'{self.defalut_brush_pixle_size}')
        self.edit_brush_pixle_size.setValidator(
            self.edit_brush_pixle_size_validator)
        self.edit_brush_pixle_size.textChanged.connect(
            self.on_edit_brush_pixle_size_change)

        self.label_img.update_brush_pixle_size(self.defalut_brush_pixle_size)

        self.defalut_eraser_pixle_size = 50
        self.min_eraser_pixle_size = 5
        self.max_eraser_pixle_size = 50
        self.label_eraser_pixle_size = QLabel('橡皮擦像素大小:')
        self.label_eraser_pixle_size.setFixedWidth(110)
        self.edit_eraser_pixle_size_validator = QIntValidator()
        self.edit_eraser_pixle_size_validator.setRange(
            self.min_eraser_pixle_size, self.max_eraser_pixle_size)
        self.edit_eraser_pixle_size = QLineEdit(self)
        self.edit_eraser_pixle_size.setText(
            f'{self.defalut_eraser_pixle_size}')
        self.edit_eraser_pixle_size.setValidator(
            self.edit_eraser_pixle_size_validator)
        self.edit_eraser_pixle_size.textChanged.connect(
            self.on_edit_eraser_pixle_size_change)

        self.label_img.update_eraser_pixle_size(self.defalut_eraser_pixle_size)

        self.btn_clear_mask = QPushButton(self)
        self.btn_clear_mask.setText('全部擦除')
        self.btn_clear_mask.clicked.connect(self.on_btn_clear_mask)

        self.btn_roate = QPushButton(self)
        self.btn_roate.setText('旋转')
        self.btn_roate.clicked.connect(self.on_btn_roate)

        self.btn_roate_img = QPushButton(self)
        self.btn_roate_img.setText('旋转原图')
        self.btn_roate_img.clicked.connect(self.on_btn_roate_img)
        self.connect(QShortcut(QKeySequence(Qt.Key_Up), self),
                     QtCore.SIGNAL('activated()'), self.btn_roate_img.click)

        self.btn_roate_mask = QPushButton(self)
        self.btn_roate_mask.setText('旋转标注图')
        self.btn_roate_mask.clicked.connect(self.on_btn_roate_mask)

        self.label_lable_docs = QLabel(self)
        self.label_lable_docs.setAlignment(Qt.AlignLeft)
        self.label_lable_docs.setText(r'''
- 鼠标左键拖动,绘制标注内容
- ALT+鼠标左键拖动,擦除标注内容

- CTRL+鼠标滚轮,调整画笔像素大小
- ALT+鼠标滚轮,调整橡皮擦像素大小

- 键盘左方向键切换到上一张图片
- 键盘右方向键切换到下一张图片

- 输入张数加回车跳转到指定张数
        ''')

        self.label_status_running1 = QLabel(self)
        self.label_status_running1.setAlignment(Qt.AlignLeft)
        self.label_status_running1.setText('请选择需要标注的目录')

        self.label_status_page_number_validator = QIntValidator()
        self.label_status_page_number = QLineEdit(self)
        self.label_status_page_number.setMaximumWidth(50)
        self.label_status_page_number.setValidator(
            self.label_status_page_number_validator)
        self.label_status_page_number.hide()
        self.label_status_page_number.returnPressed.connect(self.on_page_jump)

        self.label_status_running2 = QLabel(self)
        self.label_status_running2.setAlignment(Qt.AlignLeft)
        self.label_status_running2.setText('张')
        self.label_status_running2.hide()

        # 布局
        layout_root = QVBoxLayout()

        layout_root2 = QHBoxLayout()
        layout_col1 = QVBoxLayout()
        layout_col2 = QVBoxLayout()
        layout_root2.addLayout(layout_col1)
        layout_root2.addLayout(layout_col2)
        layout_root_row2 = QHBoxLayout()

        layout_root.addLayout(layout_root2)
        layout_root.addLayout(layout_root_row2)

        layout_root_row2.addWidget(self.label_status_running1)
        layout_root_row2.addWidget(self.label_status_page_number)
        layout_root_row2.addWidget(self.label_status_running2)

        layout_col1.addWidget(self.label_img)

        layout_col2_row1 = QHBoxLayout()
        layout_col2_row1.addWidget(self.btn_select_dir)

        layout_col2_row2 = QHBoxLayout()
        layout_col2_row2.addWidget(self.btn_prev_img)
        layout_col2_row2.addWidget(self.btn_next_img)

        layout_col2_row3 = QHBoxLayout()
        layout_col2_row3.addWidget(self.label_brush_pixle_size)
        layout_col2_row3.addWidget(self.edit_brush_pixle_size)

        layout_col2_row4 = QHBoxLayout()
        layout_col2_row4.addWidget(self.label_eraser_pixle_size)
        layout_col2_row4.addWidget(self.edit_eraser_pixle_size)

        layout_col2_row5 = QHBoxLayout()
        layout_col2_row5.addWidget(self.btn_select_brush_color)
        layout_col2_row5.addWidget(self.label_brush_color)

        layout_col2.addLayout(layout_col2_row1)
        layout_col2.addLayout(layout_col2_row2)
        layout_col2.addLayout(layout_col2_row5)
        layout_col2.addLayout(layout_col2_row3)
        layout_col2.addLayout(layout_col2_row4)
        layout_col2.addWidget(self.btn_clear_mask)
        layout_col2.addWidget(self.btn_roate)
        layout_col2.addWidget(self.btn_roate_img)
        layout_col2.addWidget(self.btn_roate_mask)
        layout_col2.addWidget(self.label_lable_docs)
        layout_col2.addStretch()

        self.setLayout(layout_root)

        # 其他数据
        self.directory = None
        self.all_img_file = []
        self.all_img_file_index = 0

        self.update_btn_status()

    def move_to_center(self):
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)

    def on_btn_select_dir(self):
        try:
            self.directory = QFileDialog.getExistingDirectory(self, '选择图片目录')

            all_img_file = sorted([
                x for x in Path(self.directory).iterdir() if x.is_file()
                and x.suffix.upper() in ['.JPG', '.JPEG', '.BMP', '.PNG']
            ])

            if len(all_img_file) <= 0:
                QMessageBox.information(self, '<提示>',
                                        f'{self.directory}\n目录下没有找到图片文件',
                                        QMessageBox.Ok)
                return

            self.setWindowTitle(f'MASK标注工具: {self.directory}')
            self.all_img_file = all_img_file
            self.all_img_file_index = 0
            self.show_label_img()
        finally:
            self.update_btn_status()

    def on_btn_next_img(self):
        try:
            self.all_img_file_index += 1
            self.show_label_img()
        finally:
            self.update_btn_status()

    def on_btn_prev_img(self):
        try:
            self.all_img_file_index -= 1
            self.show_label_img()
        finally:
            self.update_btn_status()

    def on_btn_select_brush_color(self):
        self.brush_color = QColorDialog.getColor()
        self.label_img.update_brush_color(self.brush_color)

        pe = QPalette()
        pe.setColor(QPalette.Window, self.brush_color)
        self.label_brush_color.setPalette(pe)
        self.label_brush_color.setAutoFillBackground(True)

    def on_btn_clear_mask(self):
        self.show_label_img(do_clear=True)

    def on_btn_roate(self):
        self.show_label_img(do_roate=True)

    def on_btn_roate_img(self):
        self.show_label_img(do_roate_img=True)

    def on_btn_roate_mask(self):
        self.show_label_img(do_roate_mask=True)

    def on_page_jump(self):
        try:
            page_num = int(self.label_status_page_number.text())
            if page_num >= 1 and page_num <= len(self.all_img_file):
                self.all_img_file_index = page_num - 1
            self.show_label_img()
            self.setFocus()
        finally:
            self.update_btn_status()

    def wheelEvent(self, event):
        if QApplication.keyboardModifiers() == QtCore.Qt.ControlModifier:
            brush_pixle_size = int(self.edit_brush_pixle_size.text())
            delta = event.delta()
            if delta > 0:
                brush_pixle_size += 1
            elif delta < 0:
                brush_pixle_size -= 1

            if brush_pixle_size >= self.min_brush_pixle_size and brush_pixle_size <= self.max_brush_pixle_size:
                self.edit_brush_pixle_size.setText(f'{brush_pixle_size}')
        elif QApplication.keyboardModifiers() == QtCore.Qt.AltModifier:
            eraser_pixle_size = int(self.edit_eraser_pixle_size.text())
            delta = event.delta()
            if delta > 0:
                eraser_pixle_size += 1
            elif delta < 0:
                eraser_pixle_size -= 1

            if eraser_pixle_size >= self.min_eraser_pixle_size and eraser_pixle_size <= self.max_eraser_pixle_size:
                self.edit_eraser_pixle_size.setText(f'{eraser_pixle_size}')

    def on_edit_brush_pixle_size_change(self):
        if self.edit_brush_pixle_size.text():
            brush_pixle_size = int(self.edit_brush_pixle_size.text())
            self.label_img.update_brush_pixle_size(brush_pixle_size)

    def on_edit_eraser_pixle_size_change(self):
        if self.edit_eraser_pixle_size.text():
            eraser_pixle_size = int(self.edit_eraser_pixle_size.text())
            self.label_img.update_eraser_pixle_size(eraser_pixle_size)

    def update_btn_status(self):
        try:
            self.btn_next_img.setEnabled(False)
            self.btn_prev_img.setEnabled(False)
            self.btn_roate.setEnabled(False)
            self.btn_roate_img.setEnabled(False)
            self.btn_roate_mask.setEnabled(False)
            self.btn_clear_mask.setEnabled(False)

            if not self.all_img_file:
                self.label_status_running1.setText('请选择需要标注的目录')
                self.label_status_page_number.hide()
                self.label_status_running2.hide()
            else:
                img_name = self.all_img_file[self.all_img_file_index]

                # self.label_status_page_number.show()
                # self.label_status_running2.show()
                self.label_status_page_number_validator.setRange(
                    1, len(self.all_img_file))
                self.label_status_page_number.setText(
                    f'{self.all_img_file_index+1}')
                self.label_status_running1.setText(
                    f'当前图片: {img_name} ({self.all_img_file_index + 1}/{len(self.all_img_file)}) 跳转到'
                )
                self.label_status_running2.setText(f'张')

                if self.all_img_file_index == 0:
                    self.btn_prev_img.setEnabled(False)
                else:
                    self.btn_prev_img.setEnabled(True)

                if self.all_img_file_index == len(self.all_img_file) - 1:
                    self.btn_next_img.setEnabled(False)
                else:
                    self.btn_next_img.setEnabled(True)

                self.btn_roate.setEnabled(True)
                self.btn_roate_img.setEnabled(True)
                self.btn_roate_mask.setEnabled(True)
                self.btn_clear_mask.setEnabled(True)
        except:
            logging.exception('update_btn_status exception')

    def show_label_img(self,
                       do_roate=False,
                       do_roate_img=False,
                       do_roate_mask=False,
                       do_clear=False):
        if not self.all_img_file:
            return

        img_path = self.all_img_file[self.all_img_file_index]
        img = QPixmap(str(img_path))

        img_mask_path = img_path.parent.joinpath(f'mask/{img_path.stem}.bmp')
        img_mask_path.parent.mkdir(parents=True, exist_ok=True)

        if img_mask_path.is_dir():
            QMessageBox.warning(
                self, '<致命错误>',
                f'标注文件<{img_mask_path}>是一个目录, 请把它拷贝到别的地方, 然后重新打开标注工具!!!',
                QMessageBox.Ok)
            sys.exit(-1)

        if img_mask_path.exists():
            img_mask = QPixmap(str(img_mask_path))
            if img_mask.size() != self.mask_img_size:
                os.remove(str(img_mask_path))

        if not img_mask_path.exists() or do_clear:
            img_mask = QPixmap(self.mask_img_size)
            img_mask.fill(QColor(0, 0, 0))
            img_mask.save(str(img_mask_path))

        if do_roate:
            rm = QMatrix()
            rm.rotate(90)
            img = img.transformed(rm)
            img.save(str(img_path))
            img_mask = img_mask.transformed(rm)
            img_mask.save(str(img_mask_path))

        if do_roate_img:
            rm = QMatrix()
            rm.rotate(90)
            img = img.transformed(rm)
            img.save(str(img_path))

        if do_roate_mask:
            rm = QMatrix()
            rm.rotate(90)
            img_mask = img_mask.transformed(rm)
            img_mask.save(str(img_mask_path))

        self.label_img.update_label_img(img, img_mask, str(img_mask_path))