def showFullImage(self, p): fullImage = QtGui.QDialog(self) fullImage.setWindowModality(QtCore.Qt.ApplicationModal) fullImage.resize(self.pixmap.size()) label = QClickLabel(fullImage) label.setPixmap(self.pixmap) label.clicked.connect(fullImage.accept) fullImage.exec_()
def __init__(self, cue, **kwargs): super().__init__(**kwargs) self.cue = None self._selected = False self._accurate_timing = False self._show_dbmeter = False self._countdown_mode = True self._dbmeter_element = None self._fade_element = None self.setAttribute(Qt.WA_TranslucentBackground) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(2) self.layout().setColumnStretch(0, 6) self.layout().setRowStretch(0, 4) self.nameButton = QClickLabel(self) self.nameButton.setObjectName('ButtonCueWidget') self.nameButton.setWordWrap(True) self.nameButton.setAlignment(Qt.AlignCenter) self.nameButton.setFocusPolicy(Qt.NoFocus) self.nameButton.clicked.connect(self._clicked) self.nameButton.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.layout().addWidget(self.nameButton, 0, 0) self.statusIcon = QLabel(self.nameButton) self.statusIcon.setStyleSheet('background-color: transparent') self.statusIcon.setPixmap(CueWidget.STOP.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) self.seekSlider = QClickSlider(self.nameButton) self.seekSlider.setOrientation(Qt.Horizontal) self.seekSlider.setFocusPolicy(Qt.NoFocus) self.seekSlider.setVisible(False) self.dbMeter = QDbMeter(self) self.dbMeter.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.dbMeter.setVisible(False) self.timeBar = QProgressBar(self) self.timeBar.setTextVisible(False) self.timeBar.setLayout(QHBoxLayout()) self.timeBar.layout().setContentsMargins(0, 0, 0, 0) self.timeDisplay = QLCDNumber(self.timeBar) self.timeDisplay.setStyleSheet('background-color: transparent') self.timeDisplay.setSegmentStyle(QLCDNumber.Flat) self.timeDisplay.setDigitCount(8) self.timeDisplay.display('00:00:00') self.timeBar.layout().addWidget(self.timeDisplay) self.timeBar.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.timeBar.setVisible(False) self._set_cue(cue)
def __init__(self, parent=None): super(MediaWidget, self).__init__(parent) self.setStyleSheet('background: rgba(0,0,0,0);') self.totalTime = QtCore.QTime(0, 0, 0) self.dragPos = QtCore.QPoint(0, 0) self.position = (-1, -1, -1) self.current = 0 self.selected = False self.media = None self.actionsList = [] self.actionIndex = -1 self.countdownMode = True self.levelVisible = False self.button = QClickLabel(self) self.button.setWordWrap(True) self.button.setAlignment(QtCore.Qt.AlignCenter) self.button.setFocusPolicy(QtCore.Qt.NoFocus) self.button.setText('Empty\nMedia') self.button.setStyleSheet( 'background-color: ' + Media.MEDIA_DEFAULT_CONF['color'] + ';\ color: ' + Media.MEDIA_DEFAULT_CONF['font-color'] + ';\ border: 1 solid rgb(0,0,0);\ border-radius: 6;') self.button.contextMenuEvent = lambda e: self.onContextAction.emit(self, e.globalPos()) self.button.clicked.connect(self.onClick) self.button.mouseMoveEvent = self.mouseMoveEvent self.slider = QClickSlider(self) self.slider.setOrientation(QtCore.Qt.Horizontal) self.slider.setFocusPolicy(QtCore.Qt.NoFocus) self.slider.setVisible(False) self.level = QLevelPlotter(self) self.level.setVisible(False) self.slider.setMinimum(0) self.countBar = QtGui.QProgressBar(self) self.countBar.setTextVisible(False) self.count = QtGui.QLCDNumber(self.countBar) self.count.setDigitCount(8) self.count.setSegmentStyle(QtGui.QLCDNumber.Flat) self.count.enterEvent = self.enterEvent #self.count.setStyleSheet('background: rgba(0,0,0,0);') self.count.display('00:00:00') self.countBar.resizeEvent = lambda e: self.count.resize(e.size()) self.resizer = AutoResizer(self) self.installEventFilter(self.resizer)
class CueWidget(QWidget): STOP = QIcon.fromTheme('led-off') START = QIcon.fromTheme('led-running') PAUSE = QIcon.fromTheme('led-pause') ERROR = QIcon.fromTheme('led-error') ICON_SIZE = 14 context_menu_request = pyqtSignal(object, QPoint) edit_request = pyqtSignal(object) cue_executed = pyqtSignal(object) def __init__(self, cue, **kwargs): super().__init__(**kwargs) self.cue = None self._selected = False self._accurate_timing = False self._show_dbmeter = False self._countdown_mode = True self._dbmeter_element = None self._fade_element = None self.setAttribute(Qt.WA_TranslucentBackground) self.setLayout(QGridLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(2) self.layout().setColumnStretch(0, 6) self.layout().setRowStretch(0, 4) self.nameButton = QClickLabel(self) self.nameButton.setObjectName('ButtonCueWidget') self.nameButton.setWordWrap(True) self.nameButton.setAlignment(Qt.AlignCenter) self.nameButton.setFocusPolicy(Qt.NoFocus) self.nameButton.clicked.connect(self._clicked) self.nameButton.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.layout().addWidget(self.nameButton, 0, 0) self.statusIcon = QLabel(self.nameButton) self.statusIcon.setStyleSheet('background-color: transparent') self.statusIcon.setPixmap(CueWidget.STOP.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) self.seekSlider = QClickSlider(self.nameButton) self.seekSlider.setOrientation(Qt.Horizontal) self.seekSlider.setFocusPolicy(Qt.NoFocus) self.seekSlider.setVisible(False) self.dbMeter = QDbMeter(self) self.dbMeter.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.dbMeter.setVisible(False) self.timeBar = QProgressBar(self) self.timeBar.setTextVisible(False) self.timeBar.setLayout(QHBoxLayout()) self.timeBar.layout().setContentsMargins(0, 0, 0, 0) self.timeDisplay = QLCDNumber(self.timeBar) self.timeDisplay.setStyleSheet('background-color: transparent') self.timeDisplay.setSegmentStyle(QLCDNumber.Flat) self.timeDisplay.setDigitCount(8) self.timeDisplay.display('00:00:00') self.timeBar.layout().addWidget(self.timeDisplay) self.timeBar.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.timeBar.setVisible(False) self._set_cue(cue) @property def selected(self): return self._selected @selected.setter def selected(self, value): self._selected = value self._update_style(self.cue.stylesheet) def contextMenuEvent(self, event): self.context_menu_request.emit(self, event.globalPos()) def mouseMoveEvent(self, event): if (event.buttons() == Qt.LeftButton and (event.modifiers() == Qt.ControlModifier or event.modifiers() == Qt.ShiftModifier)): mime_data = QMimeData() mime_data.setText(PageWidget.DRAG_MAGIC) drag = QDrag(self) drag.setMimeData(mime_data) drag.setPixmap(self.grab(self.rect())) if event.modifiers() == Qt.ControlModifier: drag.exec_(Qt.MoveAction) else: drag.exec_(Qt.CopyAction) event.accept() else: event.ignore() def set_countdown_mode(self, mode): self._countdown_mode = mode self._update_time(self.cue.current_time()) def set_accurate_timing(self, enable): self._accurate_timing = enable if self.cue.state == CueState.Pause: self._update_time(self.cue.current_time(), True) elif self.cue.state != CueState.Running: self._update_duration(self.cue.duration) def show_seek_slider(self, visible): self.seekSlider.setVisible(visible) self.update() def show_dbmeters(self, visible): if isinstance(self.cue, MediaCue): self._show_dbmeter = visible if self._dbmeter_element is not None: self._dbmeter_element.level_ready.disconnect(self.dbMeter.plot) self._dbmeter_element = None if visible: self._dbmeter_element = self.cue.media.element('DbMeter') if self._dbmeter_element is not None: self._dbmeter_element.level_ready.connect(self.dbMeter.plot) self.layout().addWidget(self.dbMeter, 0, 1) self.layout().setColumnStretch(1, 1) self.dbMeter.show() else: self.dbMeter.hide() self.layout().setColumnStretch(1, 0) self.update() def _set_cue(self, cue): self.cue = cue self.cue.changed('name').connect(self._update_name, Connection.QtQueued) self.cue.changed('stylesheet').connect(self._update_style, Connection.QtQueued) self.cue.changed('duration').connect(self._update_duration, Connection.QtQueued) self.cue.changed('description').connect(self._update_description, Connection.QtQueued) if isinstance(cue, MediaCue): self.cue.media.changed('pipe').connect(self._media_updated) self.cue.paused.connect(self.dbMeter.reset, Connection.QtQueued) self.cue.stopped.connect(self.dbMeter.reset, Connection.QtQueued) self.cue.end.connect(self.dbMeter.reset, Connection.QtQueued) self.cue.error.connect(self.dbMeter.reset, Connection.QtQueued) self.seekSlider.sliderMoved.connect(self.cue.media.seek) self.seekSlider.sliderJumped.connect(self.cue.media.seek) # Cue status changed self.cue.started.connect(self._status_playing, Connection.QtQueued) self.cue.stopped.connect(self._status_stopped, Connection.QtQueued) self.cue.paused.connect(self._status_paused, Connection.QtQueued) self.cue.error.connect(self._status_error, Connection.QtQueued) self.cue.end.connect(self._status_stopped, Connection.QtQueued) self._cue_time = CueTime(self.cue) self._cue_time.notify.connect(self._update_time) self._update_name(cue.name) self._update_style(cue.stylesheet) self._update_duration(self.cue.duration) def _media_updated(self): self.show_dbmeters(self._show_dbmeter) new_fade = self.cue.media.element('Fade') if new_fade is not self._fade_element: if self._fade_element is not None: self._fade_element.enter_fadein.disconnect(self._enter_fadein) self._fade_element.enter_fadeout.disconnect(self._enter_fadeout) self._fade_element.exit_fadein.disconnect(self._exit_fade) self._fade_element.exit_fadeout.disconnect(self._exit_fade) if new_fade is not None: self._fade_element = new_fade self._fade_element.enter_fadein.connect(self._enter_fadein) self._fade_element.enter_fadeout.connect(self._enter_fadeout) self._fade_element.exit_fadein.connect(self._exit_fade) self._fade_element.exit_fadeout.connect(self._exit_fade) def _update_name(self, name): self.nameButton.setText(name) def _update_description(self, description): self.nameButton.setToolTip(description) def _clicked(self, event): if not self.seekSlider.geometry().contains(event.pos()): if event.button() != Qt.RightButton: if event.modifiers() == Qt.ShiftModifier: self.edit_request.emit(self.cue) elif event.modifiers() == Qt.ControlModifier: self.selected = not self.selected else: self.cue_executed.emit(self.cue) self.cue.execute() def _update_style(self, stylesheet): stylesheet += 'text-decoration: underline;' if self.selected else '' self.nameButton.setStyleSheet(stylesheet) def _enter_fadein(self): p = self.timeDisplay.palette() p.setColor(p.WindowText, QColor(0, 255, 0)) self.timeDisplay.setPalette(p) def _enter_fadeout(self): p = self.timeDisplay.palette() p.setColor(p.WindowText, QColor(255, 50, 50)) self.timeDisplay.setPalette(p) def _exit_fade(self): self.timeDisplay.setPalette(self.timeBar.palette()) def _status_stopped(self): self.statusIcon.setPixmap(CueWidget.STOP.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) self._update_time(0, True) def _status_playing(self): self.statusIcon.setPixmap(CueWidget.START.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) def _status_paused(self): self.statusIcon.setPixmap(CueWidget.PAUSE.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) def _status_error(self, cue, error, details): self.statusIcon.setPixmap(CueWidget.ERROR.pixmap(CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)) QDetailedMessageBox.dcritical(self.cue.name, error, details) def _update_duration(self, duration): # Update the maximum values of seek-slider and time progress-bar if duration > 0: if not self.timeBar.isVisible(): self.layout().addWidget(self.timeBar, 1, 0, 1, 2) self.layout().setRowStretch(1, 1) self.timeBar.show() self.timeBar.setMaximum(duration) self.seekSlider.setMaximum(duration) else: self.timeBar.hide() self.layout().setRowStretch(1, 0) # If not in playing or paused update the widget showed time if self.cue.state != CueState.Running or self.cue.state != CueState.Running: self._update_time(duration, True) def _update_time(self, time, ignore_visibility=False): if ignore_visibility or not self.visibleRegion().isEmpty(): # If the given value is the duration or < 0 set the time to 0 if time == self.cue.duration or time < 0: time = 0 # Set the value the seek slider self.seekSlider.setValue(time) # If in count-down mode the widget will show the remaining time if self._countdown_mode: time = self.cue.duration - time # Set the value of the timer progress-bar if self.cue.duration > 0: self.timeBar.setValue(time) # Show the time in the widget self.timeDisplay.display(strtime(time, accurate=self._accurate_timing)) def resizeEvent(self, event): self.update() def update(self): super().update() self.layout().activate() xdim = self.nameButton.width() ydim = self.nameButton.height() / 5 ypos = self.nameButton.height() - ydim self.seekSlider.setGeometry(0, ypos, xdim, ydim) self.statusIcon.setGeometry(4, 4, CueWidget.ICON_SIZE, CueWidget.ICON_SIZE)
class MediaWidget(QtGui.QWidget): UNDERLINE_CSS = 'text-decoration: underline;' onFocus = QtCore.pyqtSignal(object) onContextAction = QtCore.pyqtSignal(object, QtCore.QPoint) onEditAction = QtCore.pyqtSignal(object) def __init__(self, parent=None): super(MediaWidget, self).__init__(parent) self.setStyleSheet('background: rgba(0,0,0,0);') self.totalTime = QtCore.QTime(0, 0, 0) self.dragPos = QtCore.QPoint(0, 0) self.position = (-1, -1, -1) self.current = 0 self.selected = False self.media = None self.actionsList = [] self.actionIndex = -1 self.countdownMode = True self.levelVisible = False self.button = QClickLabel(self) self.button.setWordWrap(True) self.button.setAlignment(QtCore.Qt.AlignCenter) self.button.setFocusPolicy(QtCore.Qt.NoFocus) self.button.setText('Empty\nMedia') self.button.setStyleSheet( 'background-color: ' + Media.MEDIA_DEFAULT_CONF['color'] + ';\ color: ' + Media.MEDIA_DEFAULT_CONF['font-color'] + ';\ border: 1 solid rgb(0,0,0);\ border-radius: 6;') self.button.contextMenuEvent = lambda e: self.onContextAction.emit(self, e.globalPos()) self.button.clicked.connect(self.onClick) self.button.mouseMoveEvent = self.mouseMoveEvent self.slider = QClickSlider(self) self.slider.setOrientation(QtCore.Qt.Horizontal) self.slider.setFocusPolicy(QtCore.Qt.NoFocus) self.slider.setVisible(False) self.level = QLevelPlotter(self) self.level.setVisible(False) self.slider.setMinimum(0) self.countBar = QtGui.QProgressBar(self) self.countBar.setTextVisible(False) self.count = QtGui.QLCDNumber(self.countBar) self.count.setDigitCount(8) self.count.setSegmentStyle(QtGui.QLCDNumber.Flat) self.count.enterEvent = self.enterEvent #self.count.setStyleSheet('background: rgba(0,0,0,0);') self.count.display('00:00:00') self.countBar.resizeEvent = lambda e: self.count.resize(e.size()) self.resizer = AutoResizer(self) self.installEventFilter(self.resizer) def mouseMoveEvent(self, e): if(e.buttons() == QtCore.Qt.LeftButton and (e.modifiers() == QtCore.Qt.ControlModifier or e.modifiers() == QtCore.Qt.ShiftModifier)): mimeData = QtCore.QMimeData() mimeData.setText('GridLayout_Drag&Drop') drag = QtGui.QDrag(self) drag.setMimeData(mimeData) drag.setPixmap(QtGui.QPixmap.grabWidget(self, self.rect())) self.dragPos = e.pos() self.preDragPos = self.pos() if(e.modifiers() == QtCore.Qt.ControlModifier): drag.start(QtCore.Qt.MoveAction) else: drag.start(QtCore.Qt.CopyAction) def setMedia(self, media): if(self.media is not None): raise Exception('Media is assigned yet') self.media = media self.setPos(self.position) def reset(): self.actionIndex = -1 self.media.onStop.connect(reset) self.media.onEndOfStream.connect(reset) self.media.onError.connect(reset) self.media.mediaTime.progress.connect(self.updateCount) self.media.onDuration.connect(self.onDuration, QtCore.Qt.QueuedConnection) self.media.onConfigurationChanged.connect(self.updateConf, QtCore.Qt.QueuedConnection) self.media.onFadeIn.connect(self.fadeInIndicator, QtCore.Qt.QueuedConnection) self.media.onFadeOut.connect(self.fadeOutIndicator, QtCore.Qt.QueuedConnection) self.media.onEndOfStream.connect(self.updateConf, QtCore.Qt.QueuedConnection) self.media.onEndOfStream.connect(self.level.reset) self.media.onLevel.connect(self.level.plot) self.media.onStopped.connect(self.level.reset) self.slider.sliderMoved.connect(self.seek) self.slider.sliderJumped.connect(self.media.seek) self.updateConf() self.onDuration() def setPos(self, pos): self.position = pos if(self.media is not None): self.media.conf['pos'] = pos def select(self): self.selected = not self.selected self.selectionIndicator() def onClick(self, e): if(e.modifiers() == QtCore.Qt.ShiftModifier): self.onEditAction.emit(self.media) elif(e.modifiers() == QtCore.Qt.ControlModifier): self.select() else: self.performAction() def seek(self, time_ms): if(self.media.state != Media.NONE): self.media.seek(time_ms) def performAction(self): if(len(self.actionsList) == 0): self.playback() elif(self.actionIndex == -1): self.playback() self.actionIndex += 1 elif(self.actionIndex == len(self.actionsList)): self.playback() else: self.actionsList[self.actionIndex].exec_() self.actionIndex += 1 def playback(self): if(self.media.state == Media.PLAYING): if(self.media.conf['pause']): self.media.pause() else: self.media.stop() self.actionIndex = -1 elif(self.media.state == Media.PAUSED or self.media.state == Media.STOPPED): self.media.play() def fadeOutIndicator(self, fade): if(fade): self.button.setStyleSheet(self.widgetColor() + '\ border: 2 solid rgba(160,0,0,255);\ border-radius: 6px;\ color:' + self.media.conf['font-color'] + ';\ font-size: ' + str(self.media.conf['font-size']) + 'pt;') else: self.button.setStyleSheet(self.widgetColor() + '\ border: 1 solid rgb(0,0,0);\ border-radius: 6px;\ color:' + self.media.conf['font-color'] + ';\ font-size: ' + str(self.media.conf['font-size']) + 'pt;') def fadeInIndicator(self, fade): if(fade): self.button.setStyleSheet(self.widgetColor() + '\ border: 2 solid rgba(0,100,0,255);\ border-radius: 6px;\ color:' + self.media.conf['font-color'] + ';\ font-size: ' + str(self.media.conf['font-size']) + 'pt;') else: self.button.setStyleSheet(self.widgetColor() + '\ border: 1 solid rgb(0,0,0);\ border-radius: 6px;\ color:' + self.media.conf['font-color'] + ';\ font-size: ' + str(self.media.conf['font-size']) + 'pt;') def selectionIndicator(self): if(not self.selected): self.button.setStyleSheet(self.button.styleSheet().replace(self.UNDERLINE_CSS, '')) else: self.button.setStyleSheet(self.button.styleSheet() + self.UNDERLINE_CSS) def updateConf(self): self.media.conf['pos'] = self.position self.button.setText(self.media.conf['name']) self.button.setStyleSheet(self.widgetColor() + '\ border: 1 solid rgb(0,0,0);\ border-radius: 6px;\ color:' + self.media.conf['font-color'] + ';\ font-size: ' + str(self.media.conf['font-size']) + 'pt;') self.selectionIndicator() def widgetColor(self): return 'background-color: ' + self.media.conf['color'] + ';' def updateCount(self, time, ignoreVisibility=False): if(not (not ignoreVisibility and self.visibleRegion().isEmpty())): if(self.media.conf['duration'] != -1): duration = self.media.conf['duration'] / self.media.conf['pitch']['tempo'] if(time == duration): time = 0 if(time < 0): time = 0 self.slider.setValue(time) if(self.countdownMode): time = duration - time self.countBar.setValue(time) displayTime = QtCore.QTime(0, (time / 60000) % 60, second=(time / 1000) % 60, msec=time % 1000) if(self.countdownMode and time / 1000 < 60): self.count.display(displayTime.toString('mm:ss:zzz')[:-2] + '0') else: self.count.display(displayTime.toString('mm:ss') + ':00') def onDuration(self): duration = self.media.conf['duration'] / self.media.conf['pitch']['tempo'] self.slider.setMaximum(duration) self.countBar.setMaximum(duration) if(self.media.state != Media.PLAYING): self.updateCount(duration, True) def showLevels(self, visible): self.level.setVisible(visible) self.levelVisible = visible self.update() def setCountdownMode(self, mode): self.countdownMode = mode self.updateCount(self.media.currentTime()) def update(self): super(MediaWidget, self).update() xdim = self.geometry().width() ydim = self.geometry().height() / 5 ypos = self.geometry().height() - ydim self.countBar.setGeometry(0, ypos, xdim, ydim) ydim2 = self.geometry().height() / 5 ypos = self.geometry().height() - (ydim + ydim2) ydim = self.geometry().height() - ydim if(self.levelVisible): xdim -= self.geometry().width() / 6 self.button.setGeometry(0, 0, xdim, ydim - 1) self.slider.setGeometry(0, ypos, xdim, ydim2 - 4) if(self.levelVisible): xpos = xdim xdim = self.geometry().width() / 6 self.level.setGeometry(xpos + 2, 0, xdim - 4, ydim)