from PyQt5 import QtWidgets as qtw from PyQt5 import QtGui as qtg from PyQt5 import QtCore as qtc from pytube import YouTube from urllib.request import urlopen import urllib.request from PyQt5.QtWidgets import QApplication, QGridLayout, QVBoxLayout, QLabel from collections import OrderedDict from functools import partial import sys class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(388, 255) self.centralwidget = qtw.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.widget = qtw.QWidget(self.centralwidget) self.widget.setGeometry(qtc.QRect(20, 10, 361, 241)) self.widget.setObjectName("widget") self.gridLayout = qtw.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.verticalLayout = qtw.QVBoxLayout(self.widget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = qtw.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.lineEdit_url = qtw.QLineEdit(self.widget) self.lineEdit_url.setObjectName("lineEdit_url") self.horizontalLayout.addWidget(self.lineEdit_url) self.insertUrl = qtw.QPushButton(self.widget) self.insertUrl.setObjectName("insertUrl") self.horizontalLayout.addWidget(self.insertUrl) self.verticalLayout.addLayout(self.horizontalLayout) self.scrollA = qtw.QScrollArea(self.widget) self.scrollA.setWidgetResizable(True) self.scrollA.setObjectName("scrollA") self.scrollAreaWidgetContents = qtw.QWidget() self.scrollAreaWidgetContents.setGeometry(qtc.QRect(0, 0, 357, 206)) self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") self.gridLayout_scroller = qtw.QGridLayout(self.scrollAreaWidgetContents) self.gridLayout_scroller.setObjectName("gridLayout_scroller") self.scrollA.setWidget(self.scrollAreaWidgetContents) self.verticalLayout.addWidget(self.scrollA) MainWindow.setCentralWidget(self.centralwidget) self.retranslateUi(MainWindow) qtc.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = qtc.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.insertUrl.setText(_translate("MainWindow", "PushButton")) class QYTVidItem(qtw.QWidget): def __init__(self, parent=None): super(QYTVidItem, self).__init__(parent) self.vid_layout = qtw.QHBoxLayout() self.vidDetailLayout = qtw.QVBoxLayout() self.vidHeaderLayout = qtw.QHBoxLayout() self.vidSpecsLayout = qtw.QHBoxLayout() self.vidStartEndLayout = qtw.QHBoxLayout() self.buttonLayout = qtw.QHBoxLayout() self.title = "" self.url = "" def setData(self,purl): self.url = purl.strip() errTxt = "OK" # load Youtube vid infos yt_vid = YouTube(url=purl) self.title = yt_vid.title ##left Side: # Thumbnail of video (or default if no thumb is found) thumbNail_url = yt_vid.thumbnail_url thumbPixmap = qtg.QPixmap() try: request = urllib.request.Request(thumbNail_url) response = urllib.request.urlopen(request) data = response.read() thumbPixmap.loadFromData(data) icoLabel = qtw.QLabel() icoLabel.setPixmap(thumbPixmap.scaled(150,150,aspectRatioMode=qtc.Qt.KeepAspectRatio)) self.vid_layout.addWidget(icoLabel) except Exception: pass ##right side # most upper row: # title title = qtw.QLabel(yt_vid.title) self.vidHeaderLayout.addWidget(title) self.btn_remove = qtw.QToolButton() self.vidHeaderLayout.addWidget(self.btn_remove) self.vidDetailLayout.addItem(self.vidHeaderLayout) # Mid row: # Video Specs dur_time = yt_vid.length duration = qtw.QLabel("Duration: {} sec".format(dur_time)) self.vidSpecsLayout.addWidget(duration) self.vidDetailLayout.addItem(self.vidSpecsLayout) # mid lower row: # Start/End Marker self.vidStartEndLayout.setContentsMargins(5,0,5,0) self.vidStartEndLayout.setSpacing(10); self.vidStartEndLayout.setAlignment(qtc.Qt.AlignLeft) vid_start_txt = qtw.QLabel("start at(sec):") vid_start_txt.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter) self.vidStartEndLayout.addWidget(vid_start_txt) lowVal = 0 self.vid_start = qtw.QLabel(str(lowVal)) self.vid_start.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter) self.vidStartEndLayout.addWidget(self.vid_start) vid_end_txt = qtw.QLabel("end at(sec):") vid_end_txt.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter) self.vidStartEndLayout.addWidget(vid_end_txt) highVal = 99 self.vid_end = qtw.QLabel(str(highVal)) self.vidStartEndLayout.addWidget(self.vid_end) self.vidStartEndLayout.setAlignment(qtc.Qt.AlignLeft|qtc.Qt.AlignVCenter) self.vidDetailLayout.addItem(self.vidStartEndLayout) # lower row: # Video specific Buttons (picograms) self.buttonLayout.setSpacing(10); self.buttonLayout.setAlignment(qtc.Qt.AlignLeft) btn_play = qtw.QToolButton() self.buttonLayout.addWidget(btn_play) btn_stop = qtw.QToolButton() self.buttonLayout.addWidget(btn_stop) btn_download = qtw.QToolButton() self.buttonLayout.addWidget(btn_download) self.vidDetailLayout.addItem(self.buttonLayout) #assamble Layouts and activate it self.vid_layout.addItem(self.vidDetailLayout) self.setLayout(self.vid_layout) return errTxt class MainWindow(qtw.QMainWindow): def __init__(self, *args, **kwargs): super().__init__(*args,**kwargs) self.main_window = Ui_MainWindow() self.main_window.setupUi(self) self.ytVidODict = OrderedDict() self.main_window.insertUrl.clicked.connect(self.insertUrl) def insertUrl(self): if (self.main_window.lineEdit_url.text() == ''): return else: newUrl = self.main_window.lineEdit_url.text() if newUrl.strip() in self.ytVidODict: return #Test URL: Rick Roll https://www.youtube.com/watch?v=Lrj2Hq7xqQ8 #Test URL2: BudS&TerH - Lala Remix: https://www.youtube.com/watch?v=lL7jwhWAU_k item = QYTVidItem(self.main_window.scrollA) returnCode = item.setData(newUrl) if (returnCode == "OK"): row = self.main_window.gridLayout_scroller.count() col = 0 self.main_window.gridLayout_scroller.addWidget(item,row,col,1,1) #save in OrderedDict: item.btn_remove.clicked.connect(partial(self.removeYTVid,newUrl)) self.ytVidODict[newUrl.strip()] = item else: self.main_window.insert_url_msg.setText(returnCode) self.main_window.lineEdit_url.setText("") def removeYTVid(self,url): #pop from ordered dict for vidItem in self.ytVidODict: if vidItem == url.strip(): self.ytVidODict.pop(url.strip()) break #clear gridlayout from remaining children for i in reversed(range(self.main_window.gridLayout_scroller.count())): widgetToRemove = self.main_window.gridLayout_scroller.itemAt( i ).widget() self.main_window.gridLayout_scroller.removeWidget( widgetToRemove ) #repopulate gridlayout for vidItem in self.ytVidODict: row = self.main_window.gridLayout_scroller.count() col = 0 self.main_window.gridLayout_scroller.addWidget(self.ytVidODict[vidItem],row,col,1,1) if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())