Exemple #1
0
class YPictureBubble(QLabel):
    def __init__(self, widget):
        super().__init__(widget)
        self.parent_widget = widget
        self.setScaledContents(True)

    def setPicture(self, image_name):
        self.filename = image_name
        max_width = 300
        is_gif = False
        if image_name[-3:].lower() == 'gif':
            self.gif = QMovie(image_name)
            if self.gif.isValid():
                is_gif = True
                self.setMovie(self.gif)
                self.gif.start()
                g = self.gif.currentImage()
                w, h = (g.width(), g.height())
        if not is_gif:
            im = Image.open(image_name)
            w, h = im.size

            self.setPixmap(im.toqpixmap())

        if w >= h and w > max_width:
            ratio = max_width / w
        elif h > w and h > max_width:
            ratio = max_width / h
        else:
            ratio = 1
        w, h = int(w * ratio), int(h * ratio)
        self.resize(w, h)
Exemple #2
0
    def _load(self, path: str, keep_zoom: bool):
        """Load proper displayable QWidget for a path.

        This reads the image using QImageReader and then emits the appropriate
        *_loaded signal to tell the image to display a new object.
        """
        try:
            reader = imagereader.get_reader(path)
        except ValueError as e:
            log.error(str(e))
            return
        # SVG
        if reader.is_vectorgraphic and QtSvg is not None:
            # Do not store image and only emit with the path as the
            # VectorGraphic widget needs the path in the constructor
            api.signals.svg_loaded.emit(path, keep_zoom)
            self._edit_handler.clear()
        # Gif
        elif reader.is_animation:
            movie = QMovie(path)
            if not movie.isValid() or movie.frameCount() == 0:
                log.error("Error reading animation %s: invalid data", path)
                return
            api.signals.movie_loaded.emit(movie, keep_zoom)
            self._edit_handler.clear()
        # Regular image
        else:
            try:
                pixmap = reader.get_pixmap()
            except ValueError as e:
                log.error("%s", e)
                return
            self._edit_handler.pixmap = pixmap
            api.signals.pixmap_loaded.emit(pixmap, keep_zoom)
        self._path = path
Exemple #3
0
 def getQMovie(self):
     """
     Returns: Qmovie object containing the animation.
     """
     if not self.contents == "animation":
         return None
     if self.qdata is None and not self.error:
         root, file = self.path
         img = QMovie(os.path.join(root, file))
         if not img.isValid():
             self.error = "failed to load: " + img.lastError()
             return None
         img.setScaledSize(QSize(*self.fullsize))
         self.qdata = img
     return self.qdata
Exemple #4
0
    def _load(self, path: str, reload_only: bool):
        """Load proper displayable QWidget for a path.

        This reads the image using QImageReader and then emits the appropriate
        *_loaded signal to tell the image to display a new object.
        """
        # Pass file format explicitly as imghdr does a much better job at this than the
        # file name based approach of QImageReader
        file_format = files.imghdr.what(path)
        if file_format is None:
            log.error("%s is not a valid image", path)
            return
        reader = QImageReader(path, file_format.encode("utf-8"))
        reader.setAutoTransform(True)  # Automatically apply exif orientation
        if not reader.canRead():
            log.error("Cannot read image %s", path)
            return
        # SVG
        if file_format == "svg" and QSvgWidget:
            # Do not store image and only emit with the path as the
            # VectorGraphic widget needs the path in the constructor
            self.original = None
            api.signals.svg_loaded.emit(path, reload_only)
            self._image_type = ImageType.Svg
        # Gif
        elif reader.supportsAnimation():
            movie = QMovie(path)
            if not movie.isValid() or movie.frameCount() == 0:
                log.error("Error reading animation %s: invalid data", path)
                return
            self.original = movie
            api.signals.movie_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Movie
        # Regular image
        else:
            pixmap = QPixmap.fromImageReader(reader)
            if reader.error():
                log.error("Error reading image %s: %s", path, reader.errorString())
                return
            self.original = pixmap
            api.signals.pixmap_loaded.emit(self.current, reload_only)
            self._image_type = ImageType.Pixmap
        self._path = path
class MoviePlayer(QWidget):
    def __init__(self, parent=None):
        super(MoviePlayer, self).__init__(parent)

        self.movie = QMovie(self)
        self.movie.setCacheMode(QMovie.CacheAll)

        self.movieLabel = QLabel("No movie loaded")
        self.movieLabel.setAlignment(Qt.AlignCenter)
        self.movieLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.movieLabel.setBackgroundRole(QPalette.Dark)
        self.movieLabel.setAutoFillBackground(True)

        self.currentMovieDirectory = ''

        self.createControls()
        self.createButtons()

        self.movie.frameChanged.connect(self.updateFrameSlider)
        self.movie.stateChanged.connect(self.updateButtons)
        self.fitCheckBox.clicked.connect(self.fitToWindow)
        self.frameSlider.valueChanged.connect(self.goToFrame)
        self.speedSpinBox.valueChanged.connect(self.movie.setSpeed)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.movieLabel)
        mainLayout.addLayout(self.controlsLayout)
        mainLayout.addLayout(self.buttonsLayout)
        self.setLayout(mainLayout)

        self.updateFrameSlider()
        self.updateButtons()

        self.setWindowTitle("Movie Player")
        self.resize(400, 400)

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open a Movie",
                                                  self.currentMovieDirectory)

        if fileName:
            self.openFile(fileName)

    def openFile(self, fileName):
        self.currentMovieDirectory = QFileInfo(fileName).path()

        self.movie.stop()
        self.movieLabel.setMovie(self.movie)
        self.movie.setFileName(fileName)
        self.movie.start()

        self.updateFrameSlider()
        self.updateButtons()

    def goToFrame(self, frame):
        self.movie.jumpToFrame(frame)

    def fitToWindow(self):
        self.movieLabel.setScaledContents(self.fitCheckBox.isChecked())

    def updateFrameSlider(self):
        hasFrames = (self.movie.currentFrameNumber() >= 0)

        if hasFrames:
            if self.movie.frameCount() > 0:
                self.frameSlider.setMaximum(self.movie.frameCount() - 1)
            elif self.movie.currentFrameNumber() > self.frameSlider.maximum():
                self.frameSlider.setMaximum(self.movie.currentFrameNumber())

            self.frameSlider.setValue(self.movie.currentFrameNumber())
        else:
            self.frameSlider.setMaximum(0)

        self.frameLabel.setEnabled(hasFrames)
        self.frameSlider.setEnabled(hasFrames)

    def updateButtons(self):
        state = self.movie.state()

        self.playButton.setEnabled(self.movie.isValid()
                                   and self.movie.frameCount() != 1
                                   and state == QMovie.NotRunning)
        self.pauseButton.setEnabled(state != QMovie.NotRunning)
        self.pauseButton.setChecked(state == QMovie.Paused)
        self.stopButton.setEnabled(state != QMovie.NotRunning)

    def createControls(self):
        self.fitCheckBox = QCheckBox("Fit to Window")

        self.frameLabel = QLabel("Current frame:")

        self.frameSlider = QSlider(Qt.Horizontal)
        self.frameSlider.setTickPosition(QSlider.TicksBelow)
        self.frameSlider.setTickInterval(10)

        speedLabel = QLabel("Speed:")

        self.speedSpinBox = QSpinBox()
        self.speedSpinBox.setRange(1, 9999)
        self.speedSpinBox.setValue(100)
        self.speedSpinBox.setSuffix("%")

        self.controlsLayout = QGridLayout()
        self.controlsLayout.addWidget(self.fitCheckBox, 0, 0, 1, 2)
        self.controlsLayout.addWidget(self.frameLabel, 1, 0)
        self.controlsLayout.addWidget(self.frameSlider, 1, 1, 1, 2)
        self.controlsLayout.addWidget(speedLabel, 2, 0)
        self.controlsLayout.addWidget(self.speedSpinBox, 2, 1)

    def createButtons(self):
        iconSize = QSize(36, 36)

        openButton = QToolButton()
        openButton.setIcon(self.style().standardIcon(
            QStyle.SP_DialogOpenButton))
        openButton.setIconSize(iconSize)
        openButton.setToolTip("Open File")
        openButton.clicked.connect(self.open)

        self.playButton = QToolButton()
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.setIconSize(iconSize)
        self.playButton.setToolTip("Play")
        self.playButton.clicked.connect(self.movie.start)

        self.pauseButton = QToolButton()
        self.pauseButton.setCheckable(True)
        self.pauseButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaPause))
        self.pauseButton.setIconSize(iconSize)
        self.pauseButton.setToolTip("Pause")
        self.pauseButton.clicked.connect(self.movie.setPaused)

        self.stopButton = QToolButton()
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setIconSize(iconSize)
        self.stopButton.setToolTip("Stop")
        self.stopButton.clicked.connect(self.movie.stop)

        quitButton = QToolButton()
        quitButton.setIcon(self.style().standardIcon(
            QStyle.SP_DialogCloseButton))
        quitButton.setIconSize(iconSize)
        quitButton.setToolTip("Quit")
        quitButton.clicked.connect(self.close)

        self.buttonsLayout = QHBoxLayout()
        self.buttonsLayout.addStretch()
        self.buttonsLayout.addWidget(openButton)
        self.buttonsLayout.addWidget(self.playButton)
        self.buttonsLayout.addWidget(self.pauseButton)
        self.buttonsLayout.addWidget(self.stopButton)
        self.buttonsLayout.addWidget(quitButton)
        self.buttonsLayout.addStretch()
class LoginDialog(QDialog):
    login_signal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setFixedSize(350, 250)
        self.setWindowIcon(QIcon('app.ico'))
        self.setWindowTitle('登录')
        self.setWindowFlags(Qt.FramelessWindowHint)

        self.picLabel = QLabel('', self)
        self.picLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken)
        self.picLabel.setGeometry(0, 0, 350, 140)
        self.movie = QMovie('杜甫.gif')
        if self.movie.isValid():
            self.picLabel.setMovie(self.movie)
            self.picLabel.setScaledContents(True)
            self.movie.start()
        else:
            self.picLabel.setPixmap(QPixmap('.\CDUT_pic_1.jpeg'))

        self.pwdEdit = QLineEdit(self)
        self.pwdEdit.setGeometry(90, 160, 200, 30)
        self.pwdEdit.setPlaceholderText('请输入密钥')
        self.pwdEdit.setEchoMode(QLineEdit.Password)

        self.submitBtn = QPushButton('登录', self)
        self.submitBtn.setGeometry(106, 210, 60, 30)
        self.submitBtn.setStyleSheet("QPushButton{color:black}"
                                     "QPushButton:hover{color:red}"
                                     "QPushButton{background-color:lightgreen}"
                                     "QPushButton{border:2px}"
                                     "QPushButton{border-radius:15px}"
                                     "QPushButton{padding:2px 4px}")

        self.closeBtn = QPushButton('关闭', self)
        self.closeBtn.setGeometry(215, 210, 60, 30)
        self.closeBtn.setStyleSheet("QPushButton{color:black}"
                                    "QPushButton:hover{color:red}"
                                    "QPushButton{background-color:lightgreen}"
                                    "QPushButton{border:2px}"
                                    "QPushButton{border-radius:15px}"
                                    "QPushButton{padding:2px 4px}")

        self.submitBtn.clicked.connect(self.submitLogin)
        self.closeBtn.clicked.connect(self.closeLogin)

        self.show()

    def submitLogin(self):
        self.text = self.pwdEdit.text()

        if self.text not in LOGIN_PWDS:
            msgBox = QMessageBox()
            msgBox.setWindowOpacity(0.8)
            msgBox.setWindowTitle('错误')
            msgBox.setWindowIcon(QIcon('app.ico'))
            msgBox.setIcon(QMessageBox.Critical)
            msgBox.setText('密钥输入错误!')
            msgBox.setInformativeText(
                '请联系QQ:<span style="color: red">1792575431</span>')
            msgBox.addButton('确定', QMessageBox.AcceptRole)
            msgBox.exec_()
            self.pwdEdit.clear()
            self.login_signal.emit('fail')

        else:
            self.login_signal.emit('success')
            self.close()

    def closeLogin(self):
        self.close()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()
            event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
Exemple #7
0
class CAvatar(QWidget):

    Circle = 0  # 圆圈
    Rectangle = 1  # 圆角矩形
    SizeLarge = QSize(128, 128)
    SizeMedium = QSize(64, 64)
    SizeSmall = QSize(32, 32)
    StartAngle = 0  # 起始旋转角度
    EndAngle = 360  # 结束旋转角度

    def __init__(self,
                 *args,
                 shape=0,
                 url='',
                 cacheDir=False,
                 size=QSize(64, 64),
                 animation=False,
                 **kwargs):
        super(CAvatar, self).__init__(*args, **kwargs)
        self.url = ''
        self._angle = 0  # 角度
        self.pradius = 0  # 加载进度条半径
        self.animation = animation  # 是否使用动画
        self._movie = None  # 动态图
        self._pixmap = QPixmap()  # 图片对象
        self.pixmap = QPixmap()  # 被绘制的对象
        self.isGif = url.endswith('.gif')
        # 进度动画定时器
        self.loadingTimer = QTimer(self, timeout=self.onLoading)
        # 旋转动画
        self.rotateAnimation = QPropertyAnimation(self,
                                                  b'angle',
                                                  self,
                                                  loopCount=1)
        self.setShape(shape)
        self.setCacheDir(cacheDir)
        self.setSize(size)
        self.setUrl(url)

    def paintEvent(self, event):
        super(CAvatar, self).paintEvent(event)
        # 画笔
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        # 绘制
        path = QPainterPath()
        diameter = min(self.width(), self.height())
        if self.shape == self.Circle:
            radius = int(diameter / 2)
        elif self.shape == self.Rectangle:
            radius = 4
        halfW = self.width() / 2
        halfH = self.height() / 2
        painter.translate(halfW, halfH)
        path.addRoundedRect(QRectF(-halfW, -halfH, diameter, diameter), radius,
                            radius)
        painter.setClipPath(path)
        # 如果是动画效果
        if self.rotateAnimation.state() == QPropertyAnimation.Running:
            painter.rotate(self._angle)  # 旋转
            painter.drawPixmap(
                QPointF(-self.pixmap.width() / 2, -self.pixmap.height() / 2),
                self.pixmap)
        else:
            painter.drawPixmap(-int(halfW), -int(halfH), self.pixmap)
        # 如果在加载
        if self.loadingTimer.isActive():
            diameter = 2 * self.pradius
            painter.setBrush(
                QColor(45, 140, 240, (1 - self.pradius / 10) * 255))
            painter.setPen(Qt.NoPen)
            painter.drawRoundedRect(
                QRectF(-self.pradius, -self.pradius, diameter, diameter),
                self.pradius, self.pradius)

    def enterEvent(self, event):
        """鼠标进入动画
        :param event:
        """
        if not (self.animation and not self.isGif):
            return
        self.rotateAnimation.stop()
        cv = self.rotateAnimation.currentValue() or self.StartAngle
        self.rotateAnimation.setDuration(540 if cv ==
                                         0 else int(cv / self.EndAngle * 540))
        self.rotateAnimation.setStartValue(cv)
        self.rotateAnimation.setEndValue(self.EndAngle)
        self.rotateAnimation.start()

    def leaveEvent(self, event):
        """鼠标离开动画
        :param event:
        """
        if not (self.animation and not self.isGif):
            return
        self.rotateAnimation.stop()
        cv = self.rotateAnimation.currentValue() or self.EndAngle
        self.rotateAnimation.setDuration(int(cv / self.EndAngle * 540))
        self.rotateAnimation.setStartValue(cv)
        self.rotateAnimation.setEndValue(self.StartAngle)
        self.rotateAnimation.start()

    def onLoading(self):
        """更新进度动画
        """
        if self.loadingTimer.isActive():
            if self.pradius > 9:
                self.pradius = 0
            self.pradius += 1
        else:
            self.pradius = 0
        self.update()

    def onFinished(self):
        """图片下载完成
        """
        self.loadingTimer.stop()
        self.pradius = 0
        reply = self.sender()

        if self.isGif:
            self._movie = QMovie(reply, b'gif', self)
            if self._movie.isValid():
                self._movie.frameChanged.connect(self._resizeGifPixmap)
                self._movie.start()
        else:
            data = reply.readAll().data()
            reply.deleteLater()
            del reply
            self._pixmap.loadFromData(data)
            if self._pixmap.isNull():
                self._pixmap = QPixmap(self.size())
                self._pixmap.fill(QColor(204, 204, 204))
            self._resizePixmap()

    def onError(self, code):
        """下载出错了
        :param code:
        """
        self._pixmap = QPixmap(self.size())
        self._pixmap.fill(QColor(204, 204, 204))
        self._resizePixmap()

    def refresh(self):
        """强制刷新
        """
        self._get(self.url)

    def isLoading(self):
        """判断是否正在加载
        """
        return self.loadingTimer.isActive()

    def setShape(self, shape):
        """设置形状
        :param shape:        0=圆形, 1=圆角矩形
        """
        self.shape = shape

    def setUrl(self, url):
        """设置url,可以是本地路径,也可以是网络地址
        :param url:
        """
        self.url = url
        self._get(url)

    def setCacheDir(self, cacheDir=''):
        """设置本地缓存路径
        :param cacheDir:
        """
        self.cacheDir = cacheDir
        self._initNetWork()

    def setSize(self, size):
        """设置固定尺寸
        :param size:
        """
        if not isinstance(size, QSize):
            size = self.SizeMedium
        self.setMinimumSize(size)
        self.setMaximumSize(size)
        self._resizePixmap()

    @pyqtProperty(int)
    def angle(self):
        return self._angle

    @angle.setter
    def angle(self, value):
        self._angle = value
        self.update()

    def _resizePixmap(self):
        """缩放图片
        """
        if not self._pixmap.isNull():
            self.pixmap = self._pixmap.scaled(self.width(), self.height(),
                                              Qt.IgnoreAspectRatio,
                                              Qt.SmoothTransformation)
        self.update()

    def _resizeGifPixmap(self, _):
        """缩放动画图片
        """
        if self._movie:
            self.pixmap = self._movie.currentPixmap().scaled(
                self.width(), self.height(), Qt.IgnoreAspectRatio,
                Qt.SmoothTransformation)
        self.update()

    def _initNetWork(self):
        """初始化异步网络库
        """
        if not hasattr(qApp, '_network'):
            network = QNetworkAccessManager(self.window())
            setattr(qApp, '_network', network)
        # 是否需要设置缓存
        if self.cacheDir and not qApp._network.cache():
            cache = QNetworkDiskCache(self.window())
            cache.setCacheDirectory(self.cacheDir)
            qApp._network.setCache(cache)

    def _get(self, url):
        """设置图片或者请求网络图片
        :param url:
        """
        if not url:
            self.onError('')
            return
        if url.startswith('http') and not self.loadingTimer.isActive():
            url = QUrl(url)
            request = QNetworkRequest(url)
            request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar')
            request.setRawHeader(b'Author', b'Irony')
            request.setAttribute(QNetworkRequest.FollowRedirectsAttribute,
                                 True)
            if qApp._network.cache():
                request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                                     QNetworkRequest.PreferNetwork)
                request.setAttribute(QNetworkRequest.CacheSaveControlAttribute,
                                     True)
            reply = qApp._network.get(request)
            self.pradius = 0
            self.loadingTimer.start(50)  # 显示进度动画
            reply.finished.connect(self.onFinished)
            reply.error.connect(self.onError)
            return
        self.pradius = 0
        if os.path.exists(url) and os.path.isfile(url):
            if self.isGif:
                self._movie = QMovie(url, parent=self)
                if self._movie.isValid():
                    self._movie.frameChanged.connect(self._resizeGifPixmap)
                    self._movie.start()
            else:
                self._pixmap = QPixmap(url)
                self._resizePixmap()
        else:
            self.onError('')
Exemple #8
0
class MoviePlayer(QWidget):
    def __init__(self, parent=None):
        super(MoviePlayer, self).__init__(parent)

        self.movie = QMovie(self)
        self.movie.setCacheMode(QMovie.CacheAll)

        self.movieLabel = QLabel("No movie loaded")
        self.movieLabel.setAlignment(Qt.AlignCenter)
        self.movieLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.movieLabel.setBackgroundRole(QPalette.Dark)
        self.movieLabel.setAutoFillBackground(True)

        self.currentMovieDirectory = ''

        self.createControls()
        self.createButtons()

        self.movie.frameChanged.connect(self.updateFrameSlider)
        self.movie.stateChanged.connect(self.updateButtons)
        self.fitCheckBox.clicked.connect(self.fitToWindow)
        self.frameSlider.valueChanged.connect(self.goToFrame)
        self.speedSpinBox.valueChanged.connect(self.movie.setSpeed)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.movieLabel)
        mainLayout.addLayout(self.controlsLayout)
        mainLayout.addLayout(self.buttonsLayout)
        self.setLayout(mainLayout)

        self.updateFrameSlider()
        self.updateButtons()

        self.setWindowTitle("Movie Player")
        self.resize(400, 400)

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open a Movie",
                self.currentMovieDirectory)

        if fileName:
            self.openFile(fileName)

    def openFile(self, fileName):
        self.currentMovieDirectory = QFileInfo(fileName).path()

        self.movie.stop()
        self.movieLabel.setMovie(self.movie)
        self.movie.setFileName(fileName)
        self.movie.start()

        self.updateFrameSlider();
        self.updateButtons();

    def goToFrame(self, frame):
        self.movie.jumpToFrame(frame)

    def fitToWindow(self):
        self.movieLabel.setScaledContents(self.fitCheckBox.isChecked())

    def updateFrameSlider(self):
        hasFrames = (self.movie.currentFrameNumber() >= 0)

        if hasFrames:
            if self.movie.frameCount() > 0:
                self.frameSlider.setMaximum(self.movie.frameCount() - 1)
            elif self.movie.currentFrameNumber() > self.frameSlider.maximum():
                self.frameSlider.setMaximum(self.movie.currentFrameNumber())

            self.frameSlider.setValue(self.movie.currentFrameNumber())
        else:
            self.frameSlider.setMaximum(0)

        self.frameLabel.setEnabled(hasFrames)
        self.frameSlider.setEnabled(hasFrames)

    def updateButtons(self):
        state = self.movie.state()

        self.playButton.setEnabled(self.movie.isValid() and
                self.movie.frameCount() != 1 and state == QMovie.NotRunning)
        self.pauseButton.setEnabled(state != QMovie.NotRunning)
        self.pauseButton.setChecked(state == QMovie.Paused)
        self.stopButton.setEnabled(state != QMovie.NotRunning)

    def createControls(self):
        self.fitCheckBox = QCheckBox("Fit to Window")

        self.frameLabel = QLabel("Current frame:")

        self.frameSlider = QSlider(Qt.Horizontal)
        self.frameSlider.setTickPosition(QSlider.TicksBelow)
        self.frameSlider.setTickInterval(10)

        speedLabel = QLabel("Speed:")

        self.speedSpinBox = QSpinBox()
        self.speedSpinBox.setRange(1, 9999)
        self.speedSpinBox.setValue(100)
        self.speedSpinBox.setSuffix("%")

        self.controlsLayout = QGridLayout()
        self.controlsLayout.addWidget(self.fitCheckBox, 0, 0, 1, 2)
        self.controlsLayout.addWidget(self.frameLabel, 1, 0)
        self.controlsLayout.addWidget(self.frameSlider, 1, 1, 1, 2)
        self.controlsLayout.addWidget(speedLabel, 2, 0)
        self.controlsLayout.addWidget(self.speedSpinBox, 2, 1)

    def createButtons(self):
        iconSize = QSize(36, 36)

        openButton = QToolButton()
        openButton.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
        openButton.setIconSize(iconSize)
        openButton.setToolTip("Open File")
        openButton.clicked.connect(self.open)

        self.playButton = QToolButton()
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.setIconSize(iconSize)
        self.playButton.setToolTip("Play")
        self.playButton.clicked.connect(self.movie.start)

        self.pauseButton = QToolButton()
        self.pauseButton.setCheckable(True)
        self.pauseButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
        self.pauseButton.setIconSize(iconSize)
        self.pauseButton.setToolTip("Pause")
        self.pauseButton.clicked.connect(self.movie.setPaused)

        self.stopButton = QToolButton()
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setIconSize(iconSize)
        self.stopButton.setToolTip("Stop")
        self.stopButton.clicked.connect(self.movie.stop)

        quitButton = QToolButton()
        quitButton.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        quitButton.setIconSize(iconSize)
        quitButton.setToolTip("Quit")
        quitButton.clicked.connect(self.close)

        self.buttonsLayout = QHBoxLayout()
        self.buttonsLayout.addStretch()
        self.buttonsLayout.addWidget(openButton)
        self.buttonsLayout.addWidget(self.playButton)
        self.buttonsLayout.addWidget(self.pauseButton)
        self.buttonsLayout.addWidget(self.stopButton)
        self.buttonsLayout.addWidget(quitButton)
        self.buttonsLayout.addStretch()
Exemple #9
0
class SlideshowMediaWindow(QDialog):
    def __init__(self, parent, area=None, *args, **kwargs):
        "parent: parent widget"
        "area: top-left-x(to screen), top-left-y(to screen), width, height"
        super(SlideshowMediaWindow, self).__init__(parent, *args, **kwargs)
        self.setWindowTitle("Slideshow External Media Window")
        sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.setSizePolicy(sizePolicy)
        self.setAttribute(Qt.WA_DeleteOnClose, on=True)
        self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
        self.setSizeGripEnabled(True)

        self.layout = QVBoxLayout()
        self.media_container = QLabel(self)
        self.media_container.setAttribute(Qt.WA_NativeWindow, on=True)
        # self.media_container.setFrameShape(QFrame.NoFrame)
        sizePolicy = QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        sizePolicy.setHeightForWidth(
            self.media_container.sizePolicy().hasHeightForWidth())
        self.media_container.setSizePolicy(sizePolicy)
        self.media_container.setAlignment(Qt.AlignCenter)
        self.media_container.setStyleSheet("background-color: black;")

        self.layout.addWidget(self.media_container)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.setLayout(self.layout)
        self.area = area
        if any(area):
            self.resize(area[2], area[3])
            self.move(area[0], area[1])
        else:
            self.resize(400, 300)
        self.mouse_pos = [0, 0]
        self.allow_resize_mouse_press = False

        self.pic_image = None
        self.media_container.setScaledContents(False)
        self.media_container.original_resizeEvent = self.media_container.resizeEvent

        def media_container_resizeEvent(event):
            if self.pic_image and isinstance(self.pic_image, QPixmap):
                if self.pic_image.width() > self.media_container.width() - 2 \
                   and self.pic_image.height() > self.media_container.height() - 2:
                    target_width = self.media_container.width() - 2
                    target_height = self.media_container.height() - 2
                else:
                    target_width = self.pic_image.width()
                    target_height = self.pic_image.height()
                scaled_image = self.pic_image.scaled(
                    target_width,
                    target_height,
                    aspectRatioMode=Qt.KeepAspectRatio,
                    transformMode=Qt.FastTransformation)
                self.media_container.setPixmap(scaled_image)
            elif self.pic_image and isinstance(self.pic_image, QMovie):
                if self.pic_image.original_size.width() > self.media_container.width() - 2 \
                   and self.pic_image.original_size.height() > self.media_container.height() - 2:
                    target_width = self.media_container.width() - 2
                    target_height = self.media_container.height() - 2
                else:
                    target_width = self.pic_image.original_size.width()
                    target_height = self.pic_image.original_size.height()
                scaled_size = self.pic_image.original_size.scaled(
                    target_width, target_height, Qt.KeepAspectRatio)
                self.pic_image.setScaledSize(scaled_size)
            else:
                self.media_container.original_resizeEvent(event)

        self.media_container.resizeEvent = media_container_resizeEvent

        self.show()

        self.last_media_path = ""
        self.media_show_completed_notice = None
        # this should be a function to be called like self.stop_media_show()
        self.stop_media_show = lambda: None

        self.gif_completed_notice = threading.Event()

    def show_video(self, path):
        self.stop_media_show()
        self.media_container.clear()
        # some say the winId change all the time...so...
        mplayer_extended.setup(int(self.media_container.winId()))
        self.media_show_completed_notice = mplayer_extended.play(path)
        logger.debug("ext-media-win showed video: %s" % path)
        self.last_media_path = path
        self.stop_media_show = mplayer_extended.stop

    def show_pic(self, path):
        self.stop_media_show()
        self.media_container.clear()
        if not path.lower().endswith(".gif"):
            self.pic_image = QPixmap(path)
            if self.pic_image.width() > self.media_container.width() - 2 \
               and self.pic_image.height() > self.media_container.height() - 2:
                target_width = self.media_container.width() - 2
                target_height = self.media_container.height() - 2
            else:
                target_width = self.pic_image.width()
                target_height = self.pic_image.height()
            scaled_image = self.pic_image.scaled(
                target_width,
                target_height,
                aspectRatioMode=Qt.KeepAspectRatio,
                transformMode=Qt.SmoothTransformation)
            self.media_container.setPixmap(scaled_image)
            logger.debug("ext-media-win showed pic: %s" % path)
            self.stop_media_show = lambda: None
            self.media_show_completed_notice = None
        else:
            self.last_media_path = path
            self.pic_image = QMovie(path, QByteArray(), self)
            if not self.pic_image.isValid():
                self.media_show_completed_notice = None
                return
            self.pic_image.setCacheMode(QMovie.CacheAll)
            self.pic_image.jumpToNextFrame()
            self.pic_image.original_size = self.pic_image.currentPixmap().size(
            )
            if self.pic_image.original_size.width() > self.media_container.width() - 2 \
               and self.pic_image.original_size.height() > self.media_container.height() - 2:
                target_width = self.media_container.width() - 2
                target_height = self.media_container.height() - 2
            else:
                target_width = self.pic_image.original_size.width()
                target_height = self.pic_image.original_size.height()
            scaled_size = self.pic_image.original_size.scaled(
                target_width, target_height, Qt.KeepAspectRatio)
            self.pic_image.setScaledSize(scaled_size)
            self.pic_image.setSpeed(100)
            self.media_container.setMovie(self.pic_image)

            self.media_show_completed_notice = self.gif_completed_notice
            self.media_show_completed_notice.clear()

            def frameChanged_Handler(frameNumber):
                if frameNumber >= self.pic_image.frameCount() - 1:
                    self.pic_image.stop()
                    self.media_show_completed_notice.set()

            self.pic_image.frameChanged.connect(frameChanged_Handler)
            self.pic_image.start()
            logger.debug("ext-media-win showed gif: %s" % path)

            def stop_gif():
                try:
                    self.pic_image.stop()
                    self.media_show_completed_notice.set()
                except Exception:
                    pass

            self.stop_media_show = stop_gif

    def contextMenuEvent(self, event):
        m = QMenu(self)
        item = m.addAction("Stop Media")
        item.triggered.connect(self.stop_media_show)
        item = m.addAction("Exit Media Window")
        item.triggered.connect(self.close)
        m.popup(QCursor.pos())

    def mousePressEvent(self, event):
        self.mouse_pos[0] = event.x()
        self.mouse_pos[1] = event.y()
        if event.globalX() < self.x() + self.frameGeometry().width() - 20 \
           or event.globalY() < self.y() + self.frameGeometry().height() - 20:
            self.allow_resize_mouse_press = True
        else:
            self.allow_resize_mouse_press = True
        super().mousePressEvent(event)

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

    def mouseMoveEvent(self, event):
        if self.allow_resize_mouse_press:
            self.move(event.globalX() - self.mouse_pos[0],
                      event.globalY() - self.mouse_pos[1])
        super().mouseMoveEvent(event)

    def mouseDoubleClickEvent(self, event):
        self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)
        super().mouseDoubleClickEvent(event)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_F11:
            self.setWindowState(self.windowState() ^ Qt.WindowFullScreen)
        else:
            super().keyPressEvent(event)

    def closeEvent(self, event):
        self.stop_media_show()
        self.area[0] = self.x()
        self.area[1] = self.y()
        self.area[2] = self.width()
        self.area[3] = self.height()
        event.accept()