Refactoring the project. Adding some improvements. Add QRangeSlider slider to set the scope of the podcast preview. Interface improvements to the podcast view. Update .gitignore.

This commit is contained in:
Jarosław Wieczorek 2021-01-18 11:07:12 +01:00
parent 0efb96fef6
commit cce2fb47dc
11 changed files with 477 additions and 213 deletions

2
.gitignore vendored
View File

@ -54,7 +54,7 @@ cover/
# Translations # Translations
*.mo *.mo
*.pot *.pot
demuxer.txt
# Django stuff: # Django stuff:
*.log *.log
local_settings.py local_settings.py

View File

@ -0,0 +1,3 @@
<component name="ProjectDictionaryState">
<dictionary name="afar" />
</component>

View File

@ -11,6 +11,7 @@ pylama = "*"
ffmpeg = "*" ffmpeg = "*"
pip = "*" pip = "*"
ffmpeg-python = "*" ffmpeg-python = "*"
pydub = "*"
[dev-packages] [dev-packages]

10
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "6c12b28b456a859b8139dd5175876beeec58f47abcfbcb6d98dbfdc3a955320d" "sha256": "b9153460b4a961fc9063b87ddac6e4c7bf8748bfaefcefc26f2401e340ae7b1e"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -148,6 +148,14 @@
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==5.1.1" "version": "==5.1.1"
}, },
"pydub": {
"hashes": [
"sha256:25fdfbbfd4c69363006a27c7bd2346c4b886a0dd3da264c14d858b71a9593284",
"sha256:630c68bfff9bb27cbc5e1f02923f717c3bc5f4d73fd685fda08b6ce90f76dc69"
],
"index": "pypi",
"version": "==0.24.1"
},
"pyflakes": { "pyflakes": {
"hashes": [ "hashes": [
"sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92",

BIN
src/gui/fonts/Raleway.zip Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 840 B

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>dialog</class> <class>PreviewDialog</class>
<widget class="QDialog" name="dialog"> <widget class="QDialog" name="PreviewDialog">
<property name="windowModality"> <property name="windowModality">
<enum>Qt::NonModal</enum> <enum>Qt::NonModal</enum>
</property> </property>
@ -18,85 +18,68 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QVBoxLayout" name="vertical_layout"> <layout class="QVBoxLayout" name="v_layout_1"/>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="h_layout_range_values">
<item> <item>
<widget class="QGraphicsView" name="graphics_view"/> <widget class="QLabel" name="left_label">
</item> <property name="text">
<item> <string>Czas rozpoczęcia:</string>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QSlider" name="range_silder"> <widget class="QLineEdit" name="left_range"/>
<property name="orientation"> </item>
<enum>Qt::Horizontal</enum> <item>
</property> <widget class="QLabel" name="right_label">
<property name="tickPosition"> <property name="text">
<enum>QSlider::TicksBothSides</enum> <string>Czas zakończenia:</string>
</property>
<property name="tickInterval">
<number>1</number>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Line" name="line_2"> <widget class="QLineEdit" name="right_range"/>
<property name="orientation"> </item>
<enum>Qt::Horizontal</enum> <item>
<widget class="QPushButton" name="create_preview_button">
<property name="text">
<string>utwórz podgląd</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="play_button">
<property name="text">
<string>start</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontal_layout_2"> <widget class="QPushButton" name="stop_button">
<item> <property name="text">
<widget class="QLabel" name="label"> <string>stop</string>
<property name="text"> </property>
<string>Początek fragmentu</string> </widget>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_edit"/>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Koniec fragemntu</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="line_edit_2"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontal_layout_3">
<item>
<widget class="QPushButton" name="push_button">
<property name="text">
<string>start</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="push_button_2">
<property name="text">
<string>stop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="push_button_3">
<property name="text">
<string>zakończ</string>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>

View File

@ -2,6 +2,8 @@ import os
import shutil import shutil
import subprocess import subprocess
import tempfile import tempfile
from pathlib import Path
from pydub.utils import mediainfo
# import resources_rc # import resources_rc
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
@ -10,12 +12,18 @@ from PyQt5.QtWidgets import QMainWindow, QLabel, QFileDialog, QDialog, QDialogBu
from src.python.classes.settings_dialog import SettingsDialog from src.python.classes.settings_dialog import SettingsDialog
from src.python.ui.mainwindow_ui import Ui_MainWindow from src.python.ui.mainwindow_ui import Ui_MainWindow
from src.python.classes.translate import Translator from src.python.classes.translate import Translator
from src.python.classes.preview_dialog import PreviewDialog
import generate_demuxer import generate_demuxer
class MainWindow(QMainWindow, QApplication, Ui_MainWindow): class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
"""
MainWindow Class
"""
def __init__(self, parent=None): def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent) super(MainWindow, self).__init__(parent=parent)
self.translator = Translator() self.translator = Translator()
@ -29,9 +37,14 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.aresample = "8000" self.aresample = "8000"
self.test_data() self.test_data()
self.image_extensions = ['.jpg', '.png']
self.audio_extensions = ['.mp3', '.wav']
def setup_logic(self): def setup_logic(self):
"""Connect ui elements with methods."""
self.action_settings.triggered.connect(self.open_setting_dialog) self.action_settings.triggered.connect(self.open_setting_dialog)
self.button_generate.clicked.connect(self.generate_video_podcast) self.button_generate.clicked.connect(self.generate_video_podcast)
self.button_preview.clicked.connect(self.preview_video_podcast)
self.button_audio_1.clicked.connect(lambda: self.open_audio_import(audio_number=1)) self.button_audio_1.clicked.connect(lambda: self.open_audio_import(audio_number=1))
self.button_audio_2.clicked.connect(lambda: self.open_audio_import(audio_number=2)) self.button_audio_2.clicked.connect(lambda: self.open_audio_import(audio_number=2))
self.button_select_avatar_1.clicked.connect(lambda: self.open_image_import(image_number=1)) self.button_select_avatar_1.clicked.connect(lambda: self.open_image_import(image_number=1))
@ -42,6 +55,7 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.check_box_connected_channels.stateChanged.connect(self.channels_connected) self.check_box_connected_channels.stateChanged.connect(self.channels_connected)
def change_language(self): def change_language(self):
"""Retranslate user interface."""
self.translator.load_lang(self.lang) self.translator.load_lang(self.lang)
self.retranslateUi(self.window()) self.retranslateUi(self.window())
@ -49,25 +63,12 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.test_data() self.test_data()
def setup_detail(self): def setup_detail(self):
"""TODO: add names to images"""
self.line_edit_name_1.setDisabled(True) self.line_edit_name_1.setDisabled(True)
self.line_edit_name_2.setDisabled(True) self.line_edit_name_2.setDisabled(True)
@staticmethod
def create_custom_dialog(title: str, msg: str):
dialog = QDialog()
label = QLabel()
label.setText(msg)
label.setObjectName('message_box')
buttons = QDialogButtonBox.Ok
button_box = QDialogButtonBox(buttons)
button_box.accepted.connect(dialog.accept)
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(button_box)
dialog.setLayout(layout)
return dialog
def test_data(self): def test_data(self):
"""Test data."""
self.line_edit_audio_1.setText('./src/sounds/oba_kanały.mp3') self.line_edit_audio_1.setText('./src/sounds/oba_kanały.mp3')
pixmap1 = QPixmap('./src/gui/images/both.png') pixmap1 = QPixmap('./src/gui/images/both.png')
scaled_pixmap1 = pixmap1.scaled(pixmap1.size(), Qt.KeepAspectRatio) scaled_pixmap1 = pixmap1.scaled(pixmap1.size(), Qt.KeepAspectRatio)
@ -89,83 +90,122 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.preview_label_avatar_4.setPixmap(scaled_pixmap4) self.preview_label_avatar_4.setPixmap(scaled_pixmap4)
self.preview_label_avatar_4.setProperty('path', './src/gui/images/right.png') self.preview_label_avatar_4.setProperty('path', './src/gui/images/right.png')
def open_setting_dialog(self): def check_file(self, file, extensions):
old_lang = self.lang """Check file exist and have good extension."""
settings = SettingsDialog(parent=self)
settings.exec_()
if old_lang != self.lang:
print(old_lang, self.lang)
self.change_language()
def open_image_import(self, image_number: int):
dialog = QFileDialog()
dialog.setOption(dialog.DontUseNativeDialog, True)
dialog.setFileMode(QFileDialog.ExistingFile)
file_formats = "All Files (*);;JPG (*.jpg);;PNG (*.png)"
file, _ = dialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "", file_formats, options=dialog.options())
if not file:
title = 'Ostrzeżenie'
msg = "[!] Nie wybrano żadnego pliku."
dialog = self.create_custom_dialog(title=title, msg=msg)
dialog.exec_()
if file and not file.lower().endswith('.jpg') and not file.lower().endswith('.png'):
title = 'Błąd'
msg = F"[!] Plik {file} nie jest plikiem jpg/png."
dialog = self.create_custom_dialog(title=title, msg=msg)
dialog.exec_()
else:
if file:
pixmap = QPixmap(file)
scaled_pixmap = pixmap.scaled(pixmap.size(), Qt.KeepAspectRatio)
if image_number == 1:
self.preview_label_avatar_1.setProperty('path', file)
self.preview_label_avatar_1.setPixmap(scaled_pixmap)
elif image_number == 2:
self.preview_label_avatar_2.setProperty('path', file)
self.preview_label_avatar_2.setPixmap(scaled_pixmap)
elif image_number == 3:
self.preview_label_avatar_3.setProperty('path', file)
self.preview_label_avatar_3.setPixmap(scaled_pixmap)
elif image_number == 4:
self.preview_label_avatar_4.setProperty('path', file)
self.preview_label_avatar_4.setPixmap(scaled_pixmap)
print(F"[*] Zaimportowano garfikę {image_number} z pliku: '{file}'.")
print(F"[*] Rodzielczość grafiki: {pixmap.width()}x{pixmap.height()}")
def open_audio_import(self, audio_number: int):
dialog = QFileDialog()
dialog.setOption(dialog.DontUseNativeDialog, True)
dialog.setFileMode(QFileDialog.ExistingFile)
file_formats = "All Files (*);;mp3 (*.mp3);;wav (*.wav)"
file, _ = dialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "", file_formats, options=dialog.options())
if not file: if not file:
msg = "[!] Nie wybrano żadnego pliku." msg = "[!] Nie wybrano żadnego pliku."
dialog = self.create_custom_dialog(title='Ostrzeżenie', msg=msg) dialog = self.create_custom_dialog(title='Ostrzeżenie', msg=msg)
dialog.exec_() dialog.exec_()
return False
elif not file.lower().endswith('.mp3') and not file.lower().endswith('.wav'): elif not Path(file).is_file():
msg = F"[!] Plik {file} nie jest plikiem mp3/wav." msg = f"[!] Wybrany plik: {file} - nie istnieje."
dialog = self.create_custom_dialog(title='Błąd', msg=msg) dialog = self.create_custom_dialog(title='Ostrzeżenie', msg=msg)
dialog.exec_() dialog.exec_()
return False
elif not any(file.lower().endswith(x) for x in extensions):
dialog = self.create_custom_dialog(
title='Błąd',
msg=F"[!] Wybrany plik: {file.rsplit('/')[-1]} - nie jest plikiem o rozszerzeniu {extensions}.")
dialog.exec_()
return False
return True
def create_custom_dialog(self, title: str, msg: str):
"""Create custom dialog."""
dialog = QDialog(parent=self)
dialog.setWindowTitle(title)
label = QLabel()
label.setText(msg)
label.setObjectName('message_box')
buttons = QDialogButtonBox.Ok
button_box = QDialogButtonBox(buttons)
button_box.accepted.connect(dialog.accept)
layout = QVBoxLayout()
layout.addWidget(label)
layout.addWidget(button_box)
dialog.setLayout(layout)
return dialog
def open_image_import(self, image_number: int):
""""Import images."""
dialog: QFileDialog = QFileDialog()
dialog.setOption(dialog.DontUseNativeDialog, False)
dialog.setFileMode(QFileDialog.ExistingFile)
title = f"Import image file {image_number}:"
# TODO: dynamic create formats filter based on list self.image_extensions
formats_filter = "All Files (*);;JPG (*.jpg);;PNG (*.png)"
file, _ = dialog.getOpenFileName(
self, caption=title, filter=formats_filter, options=dialog.options()
)
if not self.check_file(file, self.image_extensions):
return -1
else:
pixmap = QPixmap(file)
scaled_pixmap = pixmap.scaled(pixmap.size(), Qt.KeepAspectRatio)
if image_number == 1:
self.preview_label_avatar_1.setProperty('path', file)
self.preview_label_avatar_1.setPixmap(scaled_pixmap)
elif image_number == 2:
self.preview_label_avatar_2.setProperty('path', file)
self.preview_label_avatar_2.setPixmap(scaled_pixmap)
elif image_number == 3:
self.preview_label_avatar_3.setProperty('path', file)
self.preview_label_avatar_3.setPixmap(scaled_pixmap)
elif image_number == 4:
self.preview_label_avatar_4.setProperty('path', file)
self.preview_label_avatar_4.setPixmap(scaled_pixmap)
print(F"[*] Zaimportowano garfikę {image_number} z pliku: '{file}'.")
print(F"[*] Rodzielczość grafiki: {pixmap.width()}x{pixmap.height()}")
def open_audio_import(self, audio_number: int):
"""Method to import audio."""
dialog = QFileDialog()
dialog.setOption(dialog.DontUseNativeDialog, True)
dialog.setFileMode(QFileDialog.ExistingFile)
file_formats = "All Files (*);;mp3 (*.mp3);;wav (*.wav)"
title = f"Import audio file {audio_number}:"
file, _ = dialog.getOpenFileName(
self, caption=title, filter=file_formats, options=dialog.options()
)
if not self.check_file(file, self.audio_extensions):
return -1
else: else:
if audio_number == 1: if audio_number == 1:
self.line_edit_audio_1.setText(file) self.line_edit_audio_1.setText(file)
self.line_edit_audio_1.setProperty('duration', mediainfo(file)['duration'])
print(f"[*] Audio 1: {file} duration: {mediainfo(file)['duration']}")
elif audio_number == 2: elif audio_number == 2:
self.line_edit_audio_2.setText(file) self.line_edit_audio_2.setText(file)
self.line_edit_audio_2.setProperty('duration', mediainfo(file)['duration'])
print(f"[*] Audio 2: {file} duration: {mediainfo(file)['duration']}")
print(F"[*] Zaimportowano ścieżkę {audio_number} pliku: '{file}'.") print(F"[*] Zaimportowano ścieżkę {audio_number} pliku: '{file}'.")
def open_setting_dialog(self):
"""Open settings dialog."""
old_lang = self.lang
settings = SettingsDialog(parent=self)
settings.exec_()
if old_lang != self.lang:
print(old_lang, self.lang)
self.change_language()
return True
def channels_connected(self, checked): def channels_connected(self, checked):
"""Change information id channels connected."""
print(checked) print(checked)
if checked: if checked:
self.button_audio_2.setDisabled(True) self.button_audio_2.setDisabled(True)
@ -177,10 +217,15 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
self.line_edit_audio_2.setDisabled(False) self.line_edit_audio_2.setDisabled(False)
self.line_edit_audio_1.setPlaceholderText("Plik audio 1 rozmówcy") self.line_edit_audio_1.setPlaceholderText("Plik audio 1 rozmówcy")
def generate_video_podcast(self): def preview_video_podcast(self):
# TODO: Change to pure python """Preview Video Podcast"""
preview_dialog = PreviewDialog(parent=self)
preview_dialog.exec_()
def generate_video_podcast(self, start=None, end=None):
"""Generate podcast based on values from UI.""" """Generate podcast based on values from UI."""
connected_channels = self.check_box_connected_channels.isChecked() connected_channels = self.check_box_connected_channels.isChecked()
# Setup images # Setup images
image_files = { image_files = {
'both': self.preview_label_avatar_1.property('path'), 'both': self.preview_label_avatar_1.property('path'),
@ -188,7 +233,12 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
'left': self.preview_label_avatar_3.property('path'), 'left': self.preview_label_avatar_3.property('path'),
'right': self.preview_label_avatar_4.property('path') 'right': self.preview_label_avatar_4.property('path')
} }
audio_files = [] audio_files = []
for image_path in image_files.values():
if not self.check_file(image_path, self.image_extensions):
self.create_custom_dialog(title='Błąd!', msg=f"Tworzenie podcastu zostało przerwane.")
return -1
if not connected_channels: if not connected_channels:
audio_files.append({'file': self.line_edit_audio_1.text()}) audio_files.append({'file': self.line_edit_audio_1.text()})
@ -197,6 +247,12 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
else: else:
audio_files.append({'file': self.line_edit_audio_1.text()}) audio_files.append({'file': self.line_edit_audio_1.text()})
for audio_path in audio_files:
if not Path(audio_path['file']).is_file():
if not self.check_file(audio_path['file'], self.audio_extensions):
self.create_custom_dialog(title='Błąd!', msg=f"Tworzenie podcastu zostało przerwane.")
return -1
# Split name and extension of the file # Split name and extension of the file
for dictionary in audio_files: for dictionary in audio_files:
dictionary['ext'] = dictionary['file'].rsplit('.')[-1] dictionary['ext'] = dictionary['file'].rsplit('.')[-1]

View File

@ -0,0 +1,72 @@
from PyQt5.QtMultimedia import QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from src.python.classes.range_slider import QRangeSlider
from src.python.ui.preview_dialog_ui import Ui_PreviewDialog
from PyQt5.QtWidgets import QDialog, QLabel, QStyle
class PreviewDialog(QDialog, Ui_PreviewDialog):
"""
Dialog to show preview of podcast.
"""
def __init__(self, parent=None, start_time=0, end_time=15):
super(PreviewDialog, self).__init__(parent=parent)
self.setupUi(self)
self.mediaPlayer = QMediaPlayer(parent=self, flags=QMediaPlayer.VideoSurface)
self.video_widget = QVideoWidget()
self.range_slider = QRangeSlider()
self.v_layout_1.addWidget(self.video_widget)
self.v_layout_1.addWidget(self.range_slider)
self.range_slider.setRange(start=int(start_time), end=int(end_time))
def setup_video_logic(self):
"""
Setup connections to events
"""
self.mediaPlayer.setVideoOutput(self.video_widget)
self.mediaPlayer.stateChanged.connect(self.media_state_changed)
self.mediaPlayer.positionChanged.connect(self.position_changed)
self.mediaPlayer.durationChanged.connect(self.duration_changed)
self.create_preview_button.connect(self.generate_podcast_preview)
def media_state_changed(self, state):
"""
:param 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 position_changed(self):
"""
Position Changed
"""
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def play(self):
"""
Play
"""
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def duration_changed(self, duration):
"""
:param duration:
:return:
"""
self.positionSlider.setRange(0, duration)

View File

@ -0,0 +1,150 @@
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class QRangeSlider(QAbstractSlider):
"""
QRangeSlider
"""
def __init__(self, parent=None):
super().__init__(parent)
self.first_position = 1
self.second_position = 8
self.opt = QStyleOptionSlider()
self.opt.minimum = 0
self.opt.maximum = 100
self.setTickPosition(QSlider.TicksAbove)
self.setTickInterval(1)
self.setSizePolicy(
QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.Slider)
)
def setRangeLimit(self, minimum: int, maximum: int):
self.opt.minimum = minimum
self.opt.maximum = maximum
def setRange(self, start: int, end: int):
self.first_position = start
self.second_position = end
def getRange(self):
return self.first_position, self.second_position
def setTickPosition(self, position: QSlider.TickPosition):
self.opt.tickPosition = position
def setTickInterval(self, ti: int):
self.opt.tickInterval = ti
def paintEvent(self, event: QPaintEvent):
painter = QPainter(self)
# Draw rule
self.opt.initFrom(self)
self.opt.rect = self.rect()
self.opt.sliderPosition = 0
self.opt.subControls = QStyle.SC_SliderGroove | QStyle.SC_SliderTickmarks
# Draw GROOVE
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
# Draw INTERVAL
color = self.palette().color(QPalette.Highlight)
color.setAlpha(160)
painter.setBrush(QBrush(color))
painter.setPen(Qt.NoPen)
self.opt.sliderPosition = self.first_position
x_left_handle = (
self.style()
.subControlRect(QStyle.CC_Slider, self.opt, QStyle.SC_SliderHandle)
.right()
)
self.opt.sliderPosition = self.second_position
x_right_handle = (
self.style()
.subControlRect(QStyle.CC_Slider, self.opt, QStyle.SC_SliderHandle)
.left()
)
groove_rect = self.style().subControlRect(
QStyle.CC_Slider, self.opt, QStyle.SC_SliderGroove
)
selection = QRect(
x_left_handle,
groove_rect.y(),
x_right_handle - x_left_handle,
groove_rect.height(),
).adjusted(-1, 1, 1, -1)
painter.drawRect(selection)
# Draw first handle
self.opt.subControls = QStyle.SC_SliderHandle
self.opt.sliderPosition = self.first_position
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
# Draw second handle
self.opt.sliderPosition = self.second_position
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
def mousePressEvent(self, event: QMouseEvent):
self.opt.sliderPosition = self.first_position
self._first_sc = self.style().hitTestComplexControl(
QStyle.CC_Slider, self.opt, event.pos(), self
)
self.opt.sliderPosition = self.second_position
self._second_sc = self.style().hitTestComplexControl(
QStyle.CC_Slider, self.opt, event.pos(), self
)
def mouseMoveEvent(self, event: QMouseEvent):
distance = self.opt.maximum - self.opt.minimum
pos = self.style().sliderValueFromPosition(
0, distance, event.pos().x(), self.rect().width()
)
if self._first_sc == QStyle.SC_SliderHandle:
if pos <= self.second_position:
self.first_position = pos
self.update()
return
if self._second_sc == QStyle.SC_SliderHandle:
if pos >= self.first_position:
self.second_position = pos
self.update()
def sizeHint(self):
""" override """
SliderLength = 84
TickSpace = 5
w = SliderLength
h = self.style().pixelMetric(QStyle.PM_SliderThickness, self.opt, self)
if (
self.opt.tickPosition & QSlider.TicksAbove
or self.opt.tickPosition & QSlider.TicksBelow
):
h += TickSpace
return (
self.style()
.sizeFromContents(QStyle.CT_Slider, self.opt, QSize(w, h), self)
.expandedTo(QApplication.globalStrut())
)

View File

@ -11,81 +11,72 @@
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_dialog(object): class Ui_PreviewDialog(object):
def setupUi(self, dialog): def setupUi(self, PreviewDialog):
dialog.setObjectName("dialog") PreviewDialog.setObjectName("PreviewDialog")
dialog.setWindowModality(QtCore.Qt.NonModal) PreviewDialog.setWindowModality(QtCore.Qt.NonModal)
dialog.resize(782, 356) PreviewDialog.resize(782, 356)
self.verticalLayout = QtWidgets.QVBoxLayout(dialog) self.verticalLayout = QtWidgets.QVBoxLayout(PreviewDialog)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.vertical_layout = QtWidgets.QVBoxLayout() self.v_layout_1 = QtWidgets.QVBoxLayout()
self.vertical_layout.setObjectName("vertical_layout") self.v_layout_1.setObjectName("v_layout_1")
self.graphics_view = QtWidgets.QGraphicsView(dialog) self.verticalLayout.addLayout(self.v_layout_1)
self.graphics_view.setObjectName("graphics_view") self.line_2 = QtWidgets.QFrame(PreviewDialog)
self.vertical_layout.addWidget(self.graphics_view)
self.line = QtWidgets.QFrame(dialog)
self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.vertical_layout.addWidget(self.line)
self.range_silder = QtWidgets.QSlider(dialog)
self.range_silder.setOrientation(QtCore.Qt.Horizontal)
self.range_silder.setTickPosition(QtWidgets.QSlider.TicksBothSides)
self.range_silder.setTickInterval(1)
self.range_silder.setObjectName("range_silder")
self.vertical_layout.addWidget(self.range_silder)
self.line_2 = QtWidgets.QFrame(dialog)
self.line_2.setFrameShape(QtWidgets.QFrame.HLine) self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setObjectName("line_2") self.line_2.setObjectName("line_2")
self.vertical_layout.addWidget(self.line_2) self.verticalLayout.addWidget(self.line_2)
self.horizontal_layout_2 = QtWidgets.QHBoxLayout() self.h_layout_range_values = QtWidgets.QHBoxLayout()
self.horizontal_layout_2.setObjectName("horizontal_layout_2") self.h_layout_range_values.setObjectName("h_layout_range_values")
self.label = QtWidgets.QLabel(dialog) self.left_label = QtWidgets.QLabel(PreviewDialog)
self.label.setObjectName("label") self.left_label.setObjectName("left_label")
self.horizontal_layout_2.addWidget(self.label) self.h_layout_range_values.addWidget(self.left_label)
self.line_edit = QtWidgets.QLineEdit(dialog) self.left_range = QtWidgets.QLineEdit(PreviewDialog)
self.line_edit.setObjectName("line_edit") self.left_range.setObjectName("left_range")
self.horizontal_layout_2.addWidget(self.line_edit) self.h_layout_range_values.addWidget(self.left_range)
self.label_2 = QtWidgets.QLabel(dialog) self.right_label = QtWidgets.QLabel(PreviewDialog)
self.label_2.setObjectName("label_2") self.right_label.setObjectName("right_label")
self.horizontal_layout_2.addWidget(self.label_2) self.h_layout_range_values.addWidget(self.right_label)
self.line_edit_2 = QtWidgets.QLineEdit(dialog) self.right_range = QtWidgets.QLineEdit(PreviewDialog)
self.line_edit_2.setObjectName("line_edit_2") self.right_range.setObjectName("right_range")
self.horizontal_layout_2.addWidget(self.line_edit_2) self.h_layout_range_values.addWidget(self.right_range)
self.vertical_layout.addLayout(self.horizontal_layout_2) self.create_preview_button = QtWidgets.QPushButton(PreviewDialog)
self.horizontal_layout_3 = QtWidgets.QHBoxLayout() self.create_preview_button.setObjectName("create_preview_button")
self.horizontal_layout_3.setObjectName("horizontal_layout_3") self.h_layout_range_values.addWidget(self.create_preview_button)
self.push_button = QtWidgets.QPushButton(dialog) self.verticalLayout.addLayout(self.h_layout_range_values)
self.push_button.setObjectName("push_button") self.line = QtWidgets.QFrame(PreviewDialog)
self.horizontal_layout_3.addWidget(self.push_button) self.line.setFrameShape(QtWidgets.QFrame.HLine)
self.push_button_2 = QtWidgets.QPushButton(dialog) self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.push_button_2.setObjectName("push_button_2") self.line.setObjectName("line")
self.horizontal_layout_3.addWidget(self.push_button_2) self.verticalLayout.addWidget(self.line)
self.push_button_3 = QtWidgets.QPushButton(dialog) self.horizontalLayout = QtWidgets.QHBoxLayout()
self.push_button_3.setObjectName("push_button_3") self.horizontalLayout.setObjectName("horizontalLayout")
self.horizontal_layout_3.addWidget(self.push_button_3) self.play_button = QtWidgets.QPushButton(PreviewDialog)
self.vertical_layout.addLayout(self.horizontal_layout_3) self.play_button.setObjectName("play_button")
self.verticalLayout.addLayout(self.vertical_layout) self.horizontalLayout.addWidget(self.play_button)
self.stop_button = QtWidgets.QPushButton(PreviewDialog)
self.stop_button.setObjectName("stop_button")
self.horizontalLayout.addWidget(self.stop_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.retranslateUi(dialog) self.retranslateUi(PreviewDialog)
QtCore.QMetaObject.connectSlotsByName(dialog) QtCore.QMetaObject.connectSlotsByName(PreviewDialog)
def retranslateUi(self, dialog): def retranslateUi(self, PreviewDialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
dialog.setWindowTitle(_translate("dialog", "Dialog")) PreviewDialog.setWindowTitle(_translate("PreviewDialog", "Dialog"))
self.label.setText(_translate("dialog", "Początek fragmentu")) self.left_label.setText(_translate("PreviewDialog", "Czas rozpoczęcia:"))
self.label_2.setText(_translate("dialog", "Koniec fragemntu")) self.right_label.setText(_translate("PreviewDialog", "Czas zakończenia:"))
self.push_button.setText(_translate("dialog", "start")) self.create_preview_button.setText(_translate("PreviewDialog", "utwórz podgląd"))
self.push_button_2.setText(_translate("dialog", "stop")) self.play_button.setText(_translate("PreviewDialog", "start"))
self.push_button_3.setText(_translate("dialog", "zakończ")) self.stop_button.setText(_translate("PreviewDialog", "stop"))
if __name__ == "__main__": if __name__ == "__main__":
import sys import sys
app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog() PreviewDialog = QtWidgets.QDialog()
ui = Ui_dialog() ui = Ui_PreviewDialog()
ui.setupUi(dialog) ui.setupUi(PreviewDialog)
dialog.show() PreviewDialog.show()
sys.exit(app.exec_()) sys.exit(app.exec_())