diff options
author | Jesús <heckyel@hyperbola.info> | 2019-12-11 19:56:15 -0500 |
---|---|---|
committer | Jesús <heckyel@hyperbola.info> | 2019-12-11 19:56:15 -0500 |
commit | dae3d5063652967bd8dcc9c769240b43ac3e8384 (patch) | |
tree | a80e7d1236f5e1594c24141f1793168e34070304 /hypervideo_gui.py | |
parent | deb5c7cd1300138f9e4dc08a0d9071e4032111c5 (diff) | |
download | hypervideo-gui-dae3d5063652967bd8dcc9c769240b43ac3e8384.tar.lz hypervideo-gui-dae3d5063652967bd8dcc9c769240b43ac3e8384.tar.xz hypervideo-gui-dae3d5063652967bd8dcc9c769240b43ac3e8384.zip |
pep8
Diffstat (limited to 'hypervideo_gui.py')
-rw-r--r-- | hypervideo_gui.py | 198 |
1 files changed, 106 insertions, 92 deletions
diff --git a/hypervideo_gui.py b/hypervideo_gui.py index f2e832d..23ff0df 100644 --- a/hypervideo_gui.py +++ b/hypervideo_gui.py @@ -46,9 +46,12 @@ class App(QMainWindow): def __init__(self): super().__init__() - gui_state = self.loadGUIState() # load GUI state from file, load default state if save file not found + # load GUI state from file, load default state if save file not found + gui_state = self.load_gui_state() self.download_folder_list = gui_state['DownloadFolderList'] - self.default_video_formats_menu_items = ['Video/Audio - Best Quality', 'Audio Only - Best Quality', 'Detect All Available Formats'] + self.default_formats_menu_items = ['Video/Audio - Best Quality', + 'Audio Only - Best Quality', + 'Detect All Available Formats'] # initialize window dimensions self.left = 100 @@ -57,73 +60,76 @@ class App(QMainWindow): self.height = 200 self.setFixedSize(self.width, self.height) - self.initUI() + self._init_ui() - def initUI(self): + def _init_ui(self): + ''' Initial UI ''' self.setWindowTitle('Simple Hypervideo Downloader GUI') self.setGeometry(self.left, self.top, self.width, self.height) # Initialize status bar self.statusBar().showMessage('Welcome to Simple Hypervideo Downloader GUI!') # Menu - mainMenu = self.menuBar() - fileMenu = mainMenu.addMenu('File') - helpMenu = mainMenu.addMenu('Help') + main_menu = self.menuBar() + file_menu = main_menu.addMenu('File') + help_menu = main_menu.addMenu('Help') # Exit button - exitButton = QAction('Exit', self) - exitButton.setShortcut('Ctrl+Q') - exitButton.setStatusTip('Exit application') - exitButton.triggered.connect(self.close) + exit_button = QAction('Exit', self) + exit_button.setShortcut('Ctrl+Q') + exit_button.setStatusTip('Exit application') + exit_button.triggered.connect(self.close) # About button - aboutButton = QAction('About', self) - aboutButton.triggered.connect(self.on_button_clicked) + about_button = QAction('About', self) + about_button.triggered.connect(self.on_button_clicked) # Adding buttons to Menu - helpMenu.addAction(aboutButton) - fileMenu.addAction(exitButton) + help_menu.addAction(about_button) + file_menu.addAction(exit_button) # Create URL entry buttons and entry textbox - urlEntryLabel = QLabel('Enter URL:') - self.urlEntryText = QLineEdit() - self.urlEntryText.setPlaceholderText('https://invidio.us/watch?v=8SdPLG-_wtA') + url_entry_label = QLabel('Enter URL:') + self.url_entry_text = QLineEdit() + self.url_entry_text.setPlaceholderText('https://invidio.us/watch?v=8SdPLG-_wtA') # set up callback to update video formats when URL is changed - self.urlEntryText.textChanged.connect(self.resetVideoFormats) + self.url_entry_text.textChanged.connect(self.reset_video_formats) # create output folder button and entry textbox - outputFolderButton = QPushButton('Select Output Folder') - outputFolderButton.setToolTip('Select output folder') - outputFolderButton.clicked.connect(self.updateOutputFolder) - self.outputEntryCombobox = QComboBox() - self.outputEntryCombobox.setEditable(True) + output_folder_button = QPushButton('Select Output Folder') + output_folder_button.setToolTip('Select output folder') + output_folder_button.clicked.connect(self.update_output_folder) + self.output_entry_combobox = QComboBox() + self.output_entry_combobox.setEditable(True) for item in self.download_folder_list: - self.outputEntryCombobox.addItem(item) # set default output folder to be downloads folder - # self.outputEntryCombobox.editTextChanged[str].connect(self.downloadTextChanged) + # set default output folder to be downloads folder + self.output_entry_combobox.addItem(item) + # self.output_entry_combobox.editTextChanged[str].connect(self.download_text_changed) # add combobox for video download format and detect formats button - detectFormatsLabel = QLabel('Download Format:') + detect_formats_label = QLabel('Download Format:') - self.videoFormatCombobox = QComboBox() - self.populateVideoFormatCombobox(self.default_video_formats_menu_items) # set default values for format select combobox - self.videoFormatCombobox.activated[str].connect(self.videoFormatChange) + self.video_format_combobox = QComboBox() + # set default values for format select combobox + self.populate_video_format_combobox(self.default_formats_menu_items) + self.video_format_combobox.activated[str].connect(self.video_format_change) # add download button - downloadButton = QPushButton('Download') - downloadButton.clicked.connect(self.downloadVideo_callback) + download_button = QPushButton('Download') + download_button.clicked.connect(self.download_video_callback) # create grid layout layout = QGridLayout() # add widgets to the layout - layout.addWidget(urlEntryLabel, 1, 0) - layout.addWidget(self.urlEntryText, 1, 1) - layout.addWidget(outputFolderButton, 2, 0) - layout.addWidget(self.outputEntryCombobox, 2, 1) - layout.addWidget(detectFormatsLabel, 3, 0) - layout.addWidget(self.videoFormatCombobox, 3, 1) - layout.addWidget(downloadButton, 5, 0) + layout.addWidget(url_entry_label, 1, 0) + layout.addWidget(self.url_entry_text, 1, 1) + layout.addWidget(output_folder_button, 2, 0) + layout.addWidget(self.output_entry_combobox, 2, 1) + layout.addWidget(detect_formats_label, 3, 0) + layout.addWidget(self.video_format_combobox, 3, 1) + layout.addWidget(download_button, 5, 0) # add grid layout as central widget for main window main_widget = QWidget() @@ -144,52 +150,52 @@ class App(QMainWindow): msg.exec_() - def url_entry(self): + def url_catch(self): ''' Return URL EntryText''' - url = self.urlEntryText.text() + url = self.url_entry_text.text() url = str(url.strip()) return url - def url_check(self): + def url_check_valid(self): ''' Check valid URL ''' - if re.match(self._VALID_URL, self.url_entry()) is None: + if re.match(self._VALID_URL, self.url_catch()) is None: check = False else: check = True return check - def downloadVideo_callback(self): + def download_video_callback(self): ''' Callback for the "Download Video" button ''' - def downloadVideo_thread_helper(self, ydl_opts): + def download_video_thread_helper(self, ydl_opts): '''Download the video. Meant to be called in a background daemon thread ''' with hypervideo.YoutubeDL(ydl_opts) as ydl: - ydl.download([self.urlEntryText.text()]) + ydl.download([self.url_catch()]) self.statusBar().showMessage('Downloading Video... Done!', msecs=0) # make sure a valid output directory was entered - if not os.path.isdir(self.outputEntryCombobox.currentText()): + if not os.path.isdir(self.output_entry_combobox.currentText()): self.statusBar().showMessage('Invalid download directory!') return # make sure the Download Folder List combobox is populated with the latest entry # this covers the case where the user uses the edittext portion of the combobox - self.addItemToDownloadsCombobox(self.outputEntryCombobox.currentText()) + self.add_item_to_downloads_combobox(self.output_entry_combobox.currentText()) # set output path/format - outtmpl = os.path.join(self.outputEntryCombobox.currentText(), r'%(title)s.%(ext)s') + outtmpl = os.path.join(self.output_entry_combobox.currentText(), r'%(title)s.%(ext)s') # create the youtube downloader options based on video format combobox selection - if self.videoFormatCombobox.currentText() == self.default_video_formats_menu_items[0]: + if self.video_format_combobox.currentText() == self.default_formats_menu_items[0]: # download best video quality ydl_opts = { 'format': 'bestvideo+bestaudio/best', 'outtmpl': outtmpl, } - elif self.videoFormatCombobox.currentText() == self.default_video_formats_menu_items[1]: + elif self.video_format_combobox.currentText() == self.default_formats_menu_items[1]: # for downloading best audio and converting to mp3 ydl_opts = { 'format': 'bestaudio/best', @@ -201,10 +207,11 @@ class App(QMainWindow): }], } else: - # grab video format from the dropdown string: ie. "135 - some video metadata here" -> "135" - video_format = self.videoFormatCombobox.currentText()[0:self.videoFormatCombobox.currentText().find('-')-1] + # grab video format from the dropdown string: + # ie. "135 - some video metadata here" -> "135" + video_format = self.video_format_combobox.currentText()[0:self.video_format_combobox.currentText().find('-')-1] # set output path/format - outformat = os.path.join(self.outputEntryCombobox.currentText(), + outformat = os.path.join(self.output_entry_combobox.currentText(), r'%(title)s.f%(format_id)s.%(ext)s') ydl_opts = { 'format': video_format, @@ -212,20 +219,20 @@ class App(QMainWindow): } # download the video in daemon thread - if self.url_check() is False: + if self.url_check_valid() is False: self.statusBar().showMessage('Please add a URL...') else: self.statusBar().showMessage('Downloading Video...') - thread = threading.Thread(target=downloadVideo_thread_helper, args=(self, ydl_opts, )) + thread = threading.Thread(target=download_video_thread_helper, args=(self, ydl_opts, )) thread.daemon = True thread.start() - def updateVideoFormats(self): + def update_video_formats(self): '''Grabs the list of available video formats in background thread and populates video format combobox with results when complete. ''' - def getVideoFormats_thread_helper(self, url): + def get_video_formats_thread_helper(self, url): ''' Grabs the available video formats. Intended to be run as background thread. ''' self.options = { @@ -234,7 +241,7 @@ class App(QMainWindow): 'noplaylist': True, # only download single song, not playlist } - if self.url_check() is True: + if self.url_check_valid() is True: try: with hypervideo.YoutubeDL(self.options) as ydl: meta = ydl.extract_info(url, download=False) @@ -247,56 +254,58 @@ class App(QMainWindow): if formats is None: self.statusBar().showMessage('Formats not found') else: - item_list = self.default_video_formats_menu_items[0:2] + item_list = self.default_formats_menu_items[0:2] data_list = [f['format_id'] + ' - ' + f['ext'] for f in formats] item_list.extend(data_list) - self.populateVideoFormatCombobox(item_list) + self.populate_video_format_combobox(item_list) self.statusBar().showMessage('Finished Downloading Video Formats', msecs=0) - self.videoFormatCombobox.setCurrentIndex(0) + self.video_format_combobox.setCurrentIndex(0) # check if is valid url # should probably be reworked to be compatible with non-YouTube websites - if self.url_check() is False: - self.populateVideoFormatCombobox(self.default_video_formats_menu_items) + if self.url_check_valid() is False: + self.populate_video_format_combobox(self.default_formats_menu_items) return else: # valid url - fetch the video formats in background daemon thread self.statusBar().showMessage('Downloading Video Formats') - thread = threading.Thread(target=getVideoFormats_thread_helper, args=(self, self.url_entry(), )) + thread = threading.Thread(target=get_video_formats_thread_helper, args=(self, self.url_catch(), )) thread.daemon = True thread.start() - def videoFormatChange(self, text): - if text == self.default_video_formats_menu_items[2]: + def video_format_change(self, text): + ''' Video Format Change ''' + if text == self.default_formats_menu_items[2]: # detect video formats was selected # update statusbar to let user know something is happening - if self.url_check() is False: + if self.url_check_valid() is False: self.statusBar().showMessage('Please add a URL...') else: # update video formats - self.updateVideoFormats() + self.update_video_formats() - def populateVideoFormatCombobox(self, labels): + def populate_video_format_combobox(self, labels): '''Populate the video format combobox with video formats. Clear the previous labels. labels {list} -- list of strings representing the video format combobox options ''' - self.videoFormatCombobox.clear() + self.video_format_combobox.clear() for label in labels: - self.videoFormatCombobox.addItem(label) + self.video_format_combobox.addItem(label) - def resetVideoFormats(self): - idx = self.videoFormatCombobox.currentIndex() + def reset_video_formats(self): + ''' Clean video formast ''' + idx = self.video_format_combobox.currentIndex() - self.populateVideoFormatCombobox(self.default_video_formats_menu_items) + self.populate_video_format_combobox(self.default_formats_menu_items) # preserve combobox index if possible if idx > 1: - self.videoFormatCombobox.setCurrentIndex(0) + self.video_format_combobox.setCurrentIndex(0) else: - self.videoFormatCombobox.setCurrentIndex(idx) + self.video_format_combobox.setCurrentIndex(idx) @pyqtSlot() - def updateOutputFolder(self): + def update_output_folder(self): ''' Callback for "Update Output Folder" button. Allows user to select output directory via standard UI. https://stackoverflow.com/questions/43121340/why-is-the-use-of-lensequence-in-condition-values-considered-incorrect-by-pyli @@ -304,16 +313,18 @@ class App(QMainWindow): file = str(QFileDialog.getExistingDirectory(self, "Select Directory")) if file: - self.addItemToDownloadsCombobox(file) + self.add_item_to_downloads_combobox(file) else: self.statusBar().showMessage('Select a folder!') - def downloadTextChanged(self, text): + def download_text_changed(self, text): + ''' download text changed ''' # function not used right now if text not in self.download_folder_list and os.path.isdir(text): - self.addItemToDownloadsCombobox(text) + self.add_item_to_downloads_combobox(text) - def addItemToDownloadsCombobox(self, text): + def add_item_to_downloads_combobox(self, text): + ''' Add item to download comboboc ''' if text not in self.download_folder_list: # if it's not in the list, add it to the list self.download_folder_list = [text]+self.download_folder_list @@ -326,13 +337,14 @@ class App(QMainWindow): self.download_folder_list = self.download_folder_list[0:6] # update the combobox - self.outputEntryCombobox.clear() + self.output_entry_combobox.clear() for item in self.download_folder_list: - self.outputEntryCombobox.addItem(item) + self.output_entry_combobox.addItem(item) - self.outputEntryCombobox.setCurrentIndex(0) # reset index - just in case + self.output_entry_combobox.setCurrentIndex(0) # reset index - just in case - def saveGUIState(self): + def save_gui_state(self): + ''' Save GUI State ''' save_dict = {'DownloadFolderList': self.download_folder_list, } if not GUI_STATE_JSON_FILE: @@ -342,7 +354,8 @@ class App(QMainWindow): with open(GUI_STATE_JSON_FILE, 'w') as file: json.dump(save_dict, file) - def loadGUIState(self): + def load_gui_state(self): + ''' Load GUI state ''' if os.path.isfile(GUI_STATE_JSON_FILE): with open(GUI_STATE_JSON_FILE, 'r') as file: save_data = json.load(file) @@ -357,11 +370,12 @@ class App(QMainWindow): return save_data def closeEvent(self, event): - '''This function gets called when the user closes the GUI. + '''Protected Function for PyQt5 + gets called when the user closes the GUI. It saves the GUI state to the json file GUI_STATE_JSON_FILE. ''' - self.saveGUIState() + self.save_gui_state() close = QMessageBox() close.setIcon(QMessageBox.Question) @@ -388,7 +402,7 @@ def get_default_download_path(): return os.path.join(dpath) if __name__ == '__main__': - app = QApplication(sys.argv) - app.setStyle('Fusion') + APP = QApplication(sys.argv) + APP.setStyle('Fusion') ex = App() - sys.exit(app.exec_()) + sys.exit(APP.exec_()) |