def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.fnames = [] # list of file names to be converted self.office_listener_started = False self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents')] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout( 'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action( self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.add_files ) convertAction = utils.create_action( self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion ) quitAction = utils.create_action( self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close ) edit_presetsAction = utils.create_action( self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.open_dialog_presets ) importAction = utils.create_action( self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets ) exportAction = utils.create_action( self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets ) resetAction = utils.create_action( self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets ) syncAction = utils.create_action( self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets ) removeoldAction = utils.create_action( self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets ) clearallAction = utils.create_action( self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all ) preferencesAction = utils.create_action( self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.open_dialog_preferences ) trackerAction = utils.create_action( self, 'Issue tracker', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/issues") ) wikiAction = utils.create_action( self, 'Wiki', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/wiki") ) ffmpegdocAction = utils.create_action( self, 'FFmpeg ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "https://www.ffmpeg.org/documentation.html") ) imagemagickdocAction = utils.create_action( self, 'ImageMagick ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "http://www.imagemagick.org/script/convert.php") ) aboutAction = utils.create_action( self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.open_dialog_about ) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions( fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions( presetsMenu, [edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction] ) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions( helpMenu, [trackerAction, wikiAction, None, ffmpegdocAction, imagemagickdocAction, None, aboutAction] ) self.filesList.dropped.connect(self.add_files_dropped) addQPB.clicked.connect(self.add_files) delQPB.clicked.connect(self.delete_files) clearQPB.clicked.connect(self.clear_fileslist) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.toggled.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.open_dir) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.delete_files) self.setWindowTitle('FF Multi Converter') QTimer.singleShot(0, self.check_for_dependencies) QTimer.singleShot(0, self.load_settings) QTimer.singleShot(0, self.audiovideo_tab.set_default_command) QTimer.singleShot(0, self.update_filesList)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.fnames = [] # list of file names to be converted self.office_listener_started = False self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents')] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout( 'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action( self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.add_files ) convertAction = utils.create_action( self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion ) quitAction = utils.create_action( self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close ) edit_presetsAction = utils.create_action( self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.open_dialog_presets ) importAction = utils.create_action( self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets ) exportAction = utils.create_action( self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets ) resetAction = utils.create_action( self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets ) syncAction = utils.create_action( self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets ) removeoldAction = utils.create_action( self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets ) clearallAction = utils.create_action( self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all ) preferencesAction = utils.create_action( self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.open_dialog_preferences ) trackerAction = utils.create_action( self, 'Issue tracker', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/issues") ) wikiAction = utils.create_action( self, 'Wiki', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/wiki") ) ffmpegdocAction = utils.create_action( self, 'FFmpeg ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "https://www.ffmpeg.org/documentation.html") ) imagemagickdocAction = utils.create_action( self, 'ImageMagick ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "http://www.imagemagick.org/script/convert.php") ) aboutAction = utils.create_action( self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.open_dialog_about ) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions( fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions( presetsMenu, [edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction] ) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions( helpMenu, [trackerAction, wikiAction, None, ffmpegdocAction, imagemagickdocAction, None, aboutAction] ) self.filesList.dropped.connect(self.add_files_dropped) addQPB.clicked.connect(self.add_files) delQPB.clicked.connect(self.delete_files) clearQPB.clicked.connect(self.clear_fileslist) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.toggled.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.open_dir) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.delete_files) self.setWindowTitle('FF Multi Converter') QTimer.singleShot(0, self.check_for_dependencies) QTimer.singleShot(0, self.load_settings) QTimer.singleShot(0, self.audiovideo_tab.set_default_command) QTimer.singleShot(0, self.update_filesList) def parse_cla(self): """Parse command line arguments.""" for i in QCoreApplication.argv()[1:]: i = os.path.abspath(i) if os.path.isfile(i): self.fnames.append(i) else: print("ffmulticonverter: {0}: Not a file".format(i)) def check_for_dependencies(self): """ Check if each one of the program dependencies are installed and update self.dependenciesQL with the appropriate message. """ self.vidconverter = None if utils.is_installed('ffmpeg'): self.vidconverter = 'ffmpeg' elif utils.is_installed('avconv'): self.vidconverter = 'avconv' self.unoconv = utils.is_installed('unoconv') self.imagemagick = utils.is_installed('convert') missing = [] if self.vidconverter is None: missing.append('ffmpeg/avconv') if not self.unoconv: missing.append('unoconv') if not self.imagemagick: missing.append('imagemagick') if missing: missing = ', '.join(missing) status = self.tr('Missing dependencies:') + ' ' + missing self.dependenciesQL.setText(status) def load_settings(self, onstart=True): """ Load settings values. onstart -- True means that this is the first time the method called, usually when program beggins """ def get_str_value(settings, name): value = settings.value(name) if value is not None: return value return '' settings = QSettings() self.overwrite_existing = utils.str_to_bool( get_str_value(settings, 'overwrite_existing')) self.default_output = get_str_value(settings, 'default_output') self.prefix = get_str_value(settings, 'prefix') self.suffix = get_str_value(settings, 'suffix') defcmd = get_str_value(settings, 'default_command') extraformats = get_str_value(settings, 'extraformats') videocodecs = settings.value('videocodecs') audiocodecs = settings.value('audiocodecs') if videocodecs is None: videocodecs = "\n".join(config.video_codecs) settings.setValue('videocodecs', videocodecs) if audiocodecs is None: audiocodecs = "\n".join(config.audio_codecs) settings.setValue('audiocodecs', audiocodecs) if defcmd: self.default_command = defcmd else: self.default_command = config.default_ffmpeg_cmd self.audiovideo_tab.fill_video_comboboxes( videocodecs, audiocodecs, extraformats) if onstart: self.toQLE.setText(self.default_output) def current_tab(self): """Return the corresponding object of the selected tab.""" for i in self.tabs: if self.tabs.index(i) == self.tabWidget.currentIndex(): return i def update_filesList(self): """Clear self.filesList and add to it all items of self.fname.""" self.filesList.clear() for i in self.fnames: self.filesList.addItem(i) def add_files(self): """ Get file names using a standard Qt dialog. Append to self.fnames each file name that not already exists and update self.filesList. """ # Create lists holding file formats extension. # To be passed in QFileDialog.getOpenFileNames(). all_files = '*' audiovideo_files = ' '.join( ['*.'+i for i in self.audiovideo_tab.formats]) img_formats = self.image_tab.formats[:] img_formats.extend(self.image_tab.extra_img) image_files = ' '.join(['*.'+i for i in img_formats]) document_files = ' '.join(['*.'+i for i in self.document_tab.formats]) formats = [all_files, audiovideo_files, image_files, document_files] strings = [self.tr('All Files'), self.tr('Audio/Video Files'), self.tr('Image Files'), self.tr('Document Files')] filters = '' for string, extensions in zip(strings, formats): filters += string + ' ({0});;'.format(extensions) filters = filters[:-2] # remove last ';;' fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' + self.tr('Choose File'), config.home, filters) if fnames: for i in fnames: if not i in self.fnames: self.fnames.append(i) self.update_filesList() def add_files_dropped(self, links): """ Append to self.fnames each file name that not already exists and update self.filesList. """ for path in links: if os.path.isfile(path) and not path in self.fnames: self.fnames.append(path) self.update_filesList() def delete_files(self): """ Get selectedItems of self.filesList, remove them from self.fnames and update the filesList. """ items = self.filesList.selectedItems() if items: for i in items: self.fnames.remove(i.text()) self.update_filesList() def clear_fileslist(self): """Make self.fnames empty and update self.filesList.""" self.fnames = [] self.update_filesList() def clear_all(self): """Clear all values of graphical widgets.""" self.toQLE.clear() self.origQCB.setChecked(False) self.deleteQCB.setChecked(False) self.clear_fileslist() self.audiovideo_tab.clear() self.image_tab.clear() def open_dir(self): """ Get a directory name using a standard QtDialog and update self.toQLE with dir's name. """ if self.toQLE.isEnabled(): output = QFileDialog.getExistingDirectory( self, 'FF Multi Converter - ' + self.tr('Choose output destination'), config.home) if output: self.toQLE.setText(output) def import_presets(self): presets_dlgs.ShowPresets().import_presets() def export_presets(self): presets_dlgs.ShowPresets().export_presets() def reset_presets(self): presets_dlgs.ShowPresets().reset() def sync_presets(self): presets_dlgs.ShowPresets().synchronize() def removeold_presets(self): presets_dlgs.ShowPresets().remove_old() def ok_to_continue(self): """ Check if everything is ok to continue with conversion. Check if: - At least one file has given for conversion. - An output folder has given. - Output folder exists. Return False if an error arises, else True. """ try: if not self.fnames: raise ValidationError( self.tr('You must add at least one file to convert!')) elif not self.origQCB.isChecked() and not self.toQLE.text(): raise ValidationError( self.tr('You must choose an output folder!')) elif (not self.origQCB.isChecked() and not os.path.exists(self.toQLE.text())): raise ValidationError(self.tr('Output folder does not exists!')) if not self.current_tab().ok_to_continue(): return False return True except ValidationError as e: QMessageBox.warning( self, 'FF Multi Converter - ' + self.tr('Error!'), str(e)) return False def get_output_extension(self): """Extract the desired output file extension from GUI and return it.""" tab = self.current_tab() if tab.name == 'AudioVideo': ext_to = self.audiovideo_tab.extQCB.currentText() elif tab.name == 'Images': ext_to = tab.extQCB.currentText() else: ext_to = tab.convertQCB.currentText().split()[-1] return '.' + ext_to def start_conversion(self): """ Extract the appropriate information from GUI and call the Progress dialog with the suitable argumens. """ if not self.ok_to_continue(): return tab = self.current_tab() if tab.name == 'Documents' and not self.office_listener_started: utils.start_office_listener() self.office_listener_started = True ext_to = self.get_output_extension() _list = utils.create_paths_list( self.fnames, ext_to, self.prefix, self.suffix, self.toQLE.text(), self.origQCB.isChecked(), self.overwrite_existing ) dialog = progress.Progress( _list, tab, self.deleteQCB.isChecked(), self) dialog.show() def open_dialog_preferences(self): """Open the preferences dialog.""" dialog = preferences_dlg.Preferences(self) if dialog.exec_(): self.load_settings(onstart=False) def open_dialog_presets(self): """Open the presets dialog.""" dialog = presets_dlgs.ShowPresets(self) dialog.exec_() def open_dialog_about(self): """Call the about dialog with the appropriate values.""" msg = self.tr('Convert among several file types to other formats') msg = textwrap.fill(msg, 54).replace('\n', '<br>') text = '''<b> FF Multi Converter {0} </b> <p>{1} <p><a href="{2}">FF Multi Converter - Home Page</a> <p>Copyright © 2011-2015 {3} <br>License: {4} <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\ .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__, ffmc.__license__, platform.python_version()[:5], QT_VERSION_STR, PYQT_VERSION_STR, platform.system()) image = ':/ffmulticonverter.png' authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__) authors += 'Contributors:\nPanagiotis Mavrogiorgos' translators = [] for i in config.translators: translators.append('{0}\n {1}'.format(i[0], i[1])) translators = '\n\n'.join(translators) dialog = about_dlg.AboutDialog(text, image, authors, translators, self) dialog.exec_()
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # main window dimensions self.main_width = 780 self.main_height = 510 self.main_fixed_height = 684 self.default_command = config.default_ffmpeg_cmd self.fnames = list() # list of file names to be converted self.docconv = False # True when a documents conversion is running self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents')] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout( 'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action( self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.add_files ) convertAction = utils.create_action( self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion ) quitAction = utils.create_action( self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close ) edit_presetsAction = utils.create_action( self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.presets ) importAction = utils.create_action( self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets ) exportAction = utils.create_action( self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets ) resetAction = utils.create_action( self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets ) syncAction = utils.create_action( self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets ) removeoldAction = utils.create_action( self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets ) clearallAction = utils.create_action( self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all ) preferencesAction = utils.create_action( self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.preferences ) aboutAction = utils.create_action( self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.about ) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions( fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions( presetsMenu, [edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction] ) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions(helpMenu, [aboutAction]) self.filesList.dropped.connect(self.url_dropped) addQPB.clicked.connect(self.add_files) delQPB.clicked.connect(self.delete_files) clearQPB.clicked.connect(self.clear_fileslist) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.clicked.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.open_dir) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.delete_files) self.resize(self.main_width, self.main_height) self.setWindowTitle('FF Multi Converter') QTimer.singleShot(0, self.check_for_dependencies) QTimer.singleShot(0, self.load_settings) QTimer.singleShot(0, self.audiovideo_tab.set_default_command) QTimer.singleShot(0, self.update_filesList)
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) # main window dimensions self.main_width = 780 self.main_height = 510 self.main_fixed_height = 684 self.default_command = config.default_ffmpeg_cmd self.fnames = list() # list of file names to be converted self.docconv = False # True when a documents conversion is running self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents')] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout( 'v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action( self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.add_files ) convertAction = utils.create_action( self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion ) quitAction = utils.create_action( self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close ) edit_presetsAction = utils.create_action( self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.presets ) importAction = utils.create_action( self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets ) exportAction = utils.create_action( self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets ) resetAction = utils.create_action( self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets ) syncAction = utils.create_action( self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets ) removeoldAction = utils.create_action( self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets ) clearallAction = utils.create_action( self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all ) preferencesAction = utils.create_action( self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.preferences ) aboutAction = utils.create_action( self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.about ) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions( fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions( presetsMenu, [edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction] ) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions(helpMenu, [aboutAction]) self.filesList.dropped.connect(self.url_dropped) addQPB.clicked.connect(self.add_files) delQPB.clicked.connect(self.delete_files) clearQPB.clicked.connect(self.clear_fileslist) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.clicked.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.open_dir) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.delete_files) self.resize(self.main_width, self.main_height) self.setWindowTitle('FF Multi Converter') QTimer.singleShot(0, self.check_for_dependencies) QTimer.singleShot(0, self.load_settings) QTimer.singleShot(0, self.audiovideo_tab.set_default_command) QTimer.singleShot(0, self.update_filesList) def parse_cla(self): """Parse command line arguments.""" for i in QCoreApplication.argv()[1:]: i = os.path.abspath(i) if os.path.isfile(i): self.fnames.append(i) else: print("ffmulticonverter: {0}: Not a file".format(i)) def load_settings(self): """Load settings values.""" def get_str_value(settings, name): value = settings.value(name) if value is not None: return value return '' settings = QSettings() self.overwrite_existing = utils.str_to_bool( get_str_value(settings, 'overwrite_existing')) self.avconv_prefered = utils.str_to_bool( get_str_value(settings, 'avconv_prefered')) self.default_output = get_str_value(settings, 'default_output') self.prefix = get_str_value(settings, 'prefix') self.suffix = get_str_value(settings, 'suffix') defcmd = get_str_value(settings, 'default_command') videocodecs = get_str_value(settings, 'videocodecs') audiocodecs = get_str_value(settings, 'audiocodecs') extraformats = get_str_value(settings, 'extraformats') if defcmd: self.default_command = defcmd self.toQLE.setText(self.default_output) self.audiovideo_tab.fill_video_comboboxes( videocodecs, audiocodecs, extraformats) def current_tab(self): """Return the corresponding object of the selected tab.""" for i in self.tabs: if self.tabs.index(i) == self.tabWidget.currentIndex(): return i def update_filesList(self): """Clear self.filesList and add to it all items of self.fname.""" self.filesList.clear() for i in self.fnames: self.filesList.addItem(i) def url_dropped(self, links): """ Append to self.fnames each file name that not already exists and update self.filesList. """ for url in links: if os.path.isfile(url) and not url in self.fnames: self.fnames.append(url) self.update_filesList() def add_files(self): """ Get file names using a standard Qt dialog. Append to self.fnames each file name that not already exists and update self.filesList. """ # Create lists holding file formats extension. # To be passed in QFileDialog.getOpenFileNames(). all_files = '*' audiovideo_files = ' '.join( ['*.'+i for i in self.audiovideo_tab.formats]) img_formats = self.image_tab.formats[:] img_formats.extend(self.image_tab.extra_img) image_files = ' '.join(['*.'+i for i in img_formats]) document_files = ' '.join(['*.'+i for i in self.document_tab.formats]) formats = [all_files, audiovideo_files, image_files, document_files] strings = [self.tr('All Files'), self.tr('Audio/Video Files'), self.tr('Image Files'), self.tr('Document Files')] filters = '' for string, extensions in zip(strings, formats): filters += string + ' ({0});;'.format(extensions) filters = filters[:-2] # remove last ';;' fnames = QFileDialog.getOpenFileNames(self, 'FF Multi Converter - ' + self.tr('Choose File'), config.home, filters) if fnames: for i in fnames: if not i in self.fnames: self.fnames.append(i) self.update_filesList() def delete_files(self): """ Get selectedItems of self.filesList, remove them from self.fnames and update the filesList. """ items = self.filesList.selectedItems() if items: for i in items: self.fnames.remove(i.text()) self.update_filesList() def clear_fileslist(self): """Make self.fnames empty and update self.filesList.""" self.fnames = [] self.update_filesList() def clear_all(self): """Clear all values of graphical widgets.""" self.toQLE.clear() self.origQCB.setChecked(False) self.deleteQCB.setChecked(False) self.clear_fileslist() self.audiovideo_tab.clear() self.image_tab.clear() def open_dir(self): """ Get a directory name using a standard QtDialog and update self.toQLE with dir's name. """ if self.toQLE.isEnabled(): output = QFileDialog.getExistingDirectory( self, 'FF Multi Converter - ' + self.tr('Choose output destination'), config.home) if output: self.toQLE.setText(output) def preferences(self): """Open the preferences dialog.""" dialog = preferences_dlg.Preferences(self) if dialog.exec_(): self.load_settings() def presets(self): """Open the presets dialog.""" dialog = presets_dlgs.ShowPresets(self) dialog.exec_() def import_presets(self): presets_dlgs.ShowPresets().import_presets() def export_presets(self): presets_dlgs.ShowPresets().export_presets() def reset_presets(self): presets_dlgs.ShowPresets().reset() def sync_presets(self): presets_dlgs.ShowPresets().synchronize() def removeold_presets(self): presets_dlgs.ShowPresets().remove_old() def ok_to_continue(self): """ Check if everything is ok to continue with conversion. Check if: - At least one file has given for conversion. - An output folder has given. - Output folder exists. Return False if an error arises, else True. """ try: if not self.fnames: raise ValidationError( self.tr('You must add at least one file to convert!')) elif not self.origQCB.isChecked() and not self.toQLE.text(): raise ValidationError( self.tr('You must choose an output folder!')) elif (not self.origQCB.isChecked() and not os.path.exists(self.toQLE.text())): raise ValidationError(self.tr('Output folder does not exists!')) if not self.current_tab().ok_to_continue(): return False return True except ValidationError as e: QMessageBox.warning( self, 'FF Multi Converter - ' + self.tr('Error!'), str(e)) return False def output_ext(self): """Extract the desired output file extension from GUI and return it.""" tab = self.current_tab() if tab.name == 'AudioVideo': ext_to = self.audiovideo_tab.extQCB.currentText() elif tab.name == 'Images': ext_to = tab.extQCB.currentText() else: ext_to = tab.convertQCB.currentText().split()[-1] return '.' + ext_to def start_conversion(self): """ Extract the appropriate information from GUI and call the Progress dialog with the suitable argumens. """ if not self.ok_to_continue(): return ext_to = self.output_ext() _list = utils.create_paths_list( self.fnames, ext_to, self.prefix, self.suffix, self.toQLE.text(), self.origQCB.isChecked(), self.overwrite_existing ) tab = self.current_tab() if tab.name == 'Documents': self.docconv = True dialog = progress.Progress( _list, tab, self.deleteQCB.isChecked(), self) dialog.show() def check_for_dependencies(self): """ Check if each one of the program dependencies are installed and update self.dependenciesQL with the appropriate message. """ self.ffmpeg = utils.is_installed('ffmpeg') self.avconv = utils.is_installed('avconv') self.unoconv = utils.is_installed('unoconv') self.imagemagick = utils.is_installed('convert') missing = [] if not self.ffmpeg and not self.avconv: missing.append('ffmpeg/avconv') if not self.unoconv: missing.append('unoconv') if not self.imagemagick: missing.append('imagemagick') if missing: missing = ', '.join(missing) status = self.tr('Missing dependencies:') + ' ' + missing self.dependenciesQL.setText(status) def about(self): """Call the about dialog with the appropriate values.""" msg = self.tr('Convert among several file types to other extensions') msg = textwrap.fill(msg, 54).replace('\n', '<br>') text = '''<b> FF Multi Converter {0} </b> <p>{1} <p><a href="{2}">FF Multi Converter - Home Page</a> <p>Copyright © 2011-2014 {3} <br>License: {4} <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\ .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__, ffmc.__license__, platform.python_version()[:5], QT_VERSION_STR, PYQT_VERSION_STR, platform.system()) image = ':/ffmulticonverter.png' authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__) authors += 'Contributors:\nPanagiotis Mavrogiorgos' transl_list = [['[bg] Bulgarian', 'Vasil Blagoev'], ['[cs] Czech', 'Petr Simacek'], ['[de_DE] German (Germany)', 'Stefan Wilhelm'], ['[el] Greek', 'Ilias Stamatis'], ['[es] Spanish', 'Miguel Ángel Rodríguez Muíños'], ['[fr] French', 'Rémi Mercier' '\n Lebarhon'], ['[gl] Galician', 'Miguel Anxo Bouzada'], ['[gl_ES] Galician (Spain)', 'Miguel Anxo Bouzada'], ['[hu] Hungarian', 'Farkas Norbert'], ['[it] Italian', 'Fabio Boccaletti'], ['[ms_MY] Malay (Malaysia)', 'abuyop'], ['[pl_PL] Polish (Poland)', 'Lukasz Koszy' '\n Piotr Surdacki'], ['[pt] Portuguese', 'Sérgio Marques'], ['[pt_BR] Portuguese (Brasil)', 'José Humberto A Melo'], ['[ro_RO] Romanian (Romania)', 'Angelescu Constantin'], ['[ru] Russian', 'Andrew Lapshin'], ['[tu] Turkish', 'Tayfun Kayha'], ['[vi] Vietnamese', 'Anh Phan'], ['[zh_CN] Chinese (China)', 'Dianjin Wang'], ['[zh_TW] Chinese (Taiwan)', 'Taijuin Lee'], ] translators = [] for i in transl_list: translators.append('{0}\n {1}'.format(i[0], i[1])) translators = '\n\n'.join(translators) dialog = about_dlg.AboutDialog(text, image, authors, translators, self) dialog.exec_()
def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.fnames = [] # list of file names to be converted self.office_listener_started = False self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [ self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents') ] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout('v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action(self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.filesList_add) convertAction = utils.create_action(self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion) quitAction = utils.create_action(self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close) edit_presetsAction = utils.create_action(self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.open_dialog_presets) importAction = utils.create_action(self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets) exportAction = utils.create_action(self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets) resetAction = utils.create_action(self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets) syncAction = utils.create_action(self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets) removeoldAction = utils.create_action(self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets) clearallAction = utils.create_action(self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all) preferencesAction = utils.create_action(self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.open_dialog_preferences) trackerAction = utils.create_action( self, 'Issue tracker', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/issues")) wikiAction = utils.create_action( self, 'Wiki', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/wiki")) ffmpegdocAction = utils.create_action( self, 'FFmpeg ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open("https://www.ffmpeg.org/documentation.html" )) imagemagickdocAction = utils.create_action( self, 'ImageMagick ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "http://www.imagemagick.org/script/convert.php")) aboutAction = utils.create_action(self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.open_dialog_about) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions(fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions(presetsMenu, [ edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction ]) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions(helpMenu, [ trackerAction, wikiAction, None, ffmpegdocAction, imagemagickdocAction, None, aboutAction ]) self.filesList.dropped.connect(self.filesList_add_dragged) addQPB.clicked.connect(self.filesList_add) delQPB.clicked.connect(self.filesList_delete) clearQPB.clicked.connect(self.filesList_clear) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.toggled.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.get_output_folder) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.filesList_delete) self.setWindowTitle('FF Multi Converter') self.load_settings() self.check_for_dependencies() self.audiovideo_tab.set_default_command() self.image_tab.set_default_command() self.toQLE.setText(self.default_output) self.filesList_update()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.fnames = [] # list of file names to be converted self.office_listener_started = False self.parse_cla() addQPB = QPushButton(self.tr('Add')) delQPB = QPushButton(self.tr('Delete')) clearQPB = QPushButton(self.tr('Clear')) vlayout1 = utils.add_to_layout('v', addQPB, delQPB, clearQPB, None) self.filesList = utils.FilesList() self.filesList.setSelectionMode(QAbstractItemView.ExtendedSelection) hlayout1 = utils.add_to_layout('h', self.filesList, vlayout1) outputQL = QLabel(self.tr('Output folder:')) self.toQLE = QLineEdit() self.toQLE.setReadOnly(True) self.toQTB = QToolButton() self.toQTB.setText('...') hlayout2 = utils.add_to_layout('h', outputQL, self.toQLE, self.toQTB) self.audiovideo_tab = AudioVideoTab(self) self.image_tab = ImageTab(self) self.document_tab = DocumentTab(self) self.tabs = [self.audiovideo_tab, self.image_tab, self.document_tab] tab_names = [ self.tr('Audio/Video'), self.tr('Images'), self.tr('Documents') ] self.tabWidget = QTabWidget() for num, tab in enumerate(tab_names): self.tabWidget.addTab(self.tabs[num], tab) self.tabWidget.setCurrentIndex(0) self.origQCB = QCheckBox( self.tr('Save each file in the same\nfolder as input file')) self.deleteQCB = QCheckBox(self.tr('Delete original')) convertQPB = QPushButton(self.tr('&Convert')) hlayout3 = utils.add_to_layout('h', self.origQCB, self.deleteQCB, None) hlayout4 = utils.add_to_layout('h', None, convertQPB) final_layout = utils.add_to_layout('v', hlayout1, self.tabWidget, hlayout2, hlayout3, hlayout4) self.dependenciesQL = QLabel() self.statusBar().addPermanentWidget(self.dependenciesQL, stretch=1) widget = QWidget() widget.setLayout(final_layout) self.setCentralWidget(widget) openAction = utils.create_action(self, self.tr('Open'), QKeySequence.Open, None, self.tr('Open a file'), self.filesList_add) convertAction = utils.create_action(self, self.tr('Convert'), 'Ctrl+C', None, self.tr('Convert files'), self.start_conversion) quitAction = utils.create_action(self, self.tr('Quit'), 'Ctrl+Q', None, self.tr('Quit'), self.close) edit_presetsAction = utils.create_action(self, self.tr('Edit Presets'), 'Ctrl+P', None, self.tr('Edit Presets'), self.open_dialog_presets) importAction = utils.create_action(self, self.tr('Import'), None, None, self.tr('Import presets'), self.import_presets) exportAction = utils.create_action(self, self.tr('Export'), None, None, self.tr('Export presets'), self.export_presets) resetAction = utils.create_action(self, self.tr('Reset'), None, None, self.tr('Reset presets'), self.reset_presets) syncAction = utils.create_action(self, self.tr('Synchronize'), None, None, self.tr('Synchronize presets'), self.sync_presets) removeoldAction = utils.create_action(self, self.tr('Remove old'), None, None, self.tr('Remove old presets'), self.removeold_presets) clearallAction = utils.create_action(self, self.tr('Clear All'), None, None, self.tr('Clear form'), self.clear_all) preferencesAction = utils.create_action(self, self.tr('Preferences'), 'Alt+Ctrl+P', None, self.tr('Preferences'), self.open_dialog_preferences) trackerAction = utils.create_action( self, 'Issue tracker', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/issues")) wikiAction = utils.create_action( self, 'Wiki', None, None, None, lambda: webbrowser.open( "https://github.com/Ilias95/FF-Multi-Converter/wiki")) ffmpegdocAction = utils.create_action( self, 'FFmpeg ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open("https://www.ffmpeg.org/documentation.html" )) imagemagickdocAction = utils.create_action( self, 'ImageMagick ' + self.tr('documentation'), None, None, None, lambda: webbrowser.open( "http://www.imagemagick.org/script/convert.php")) aboutAction = utils.create_action(self, self.tr('About'), 'Ctrl+?', None, self.tr('About'), self.open_dialog_about) fileMenu = self.menuBar().addMenu(self.tr('File')) editMenu = self.menuBar().addMenu(self.tr('Edit')) presetsMenu = self.menuBar().addMenu(self.tr('Presets')) helpMenu = self.menuBar().addMenu(self.tr('Help')) utils.add_actions(fileMenu, [openAction, convertAction, None, quitAction]) utils.add_actions(presetsMenu, [ edit_presetsAction, importAction, exportAction, resetAction, None, syncAction, removeoldAction ]) utils.add_actions(editMenu, [clearallAction, None, preferencesAction]) utils.add_actions(helpMenu, [ trackerAction, wikiAction, None, ffmpegdocAction, imagemagickdocAction, None, aboutAction ]) self.filesList.dropped.connect(self.filesList_add_dragged) addQPB.clicked.connect(self.filesList_add) delQPB.clicked.connect(self.filesList_delete) clearQPB.clicked.connect(self.filesList_clear) self.tabWidget.currentChanged.connect( lambda: self.tabs[0].moreQPB.setChecked(False)) self.origQCB.toggled.connect( lambda: self.toQLE.setEnabled(not self.origQCB.isChecked())) self.toQTB.clicked.connect(self.get_output_folder) convertQPB.clicked.connect(convertAction.triggered) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.filesList_delete) self.setWindowTitle('FF Multi Converter') self.load_settings() self.check_for_dependencies() self.audiovideo_tab.set_default_command() self.image_tab.set_default_command() self.toQLE.setText(self.default_output) self.filesList_update() def parse_cla(self): """Parse command line arguments.""" for i in QCoreApplication.arguments()[1:]: i = os.path.abspath(i) if os.path.isfile(i): self.fnames.append(i) else: print("ffmulticonverter: {0}: Not a file".format(i)) def check_for_dependencies(self): """ Check if each one of the program dependencies are installed and update self.dependenciesQL with the appropriate message. """ if not utils.is_installed(self.ffmpeg_path): self.ffmpeg_path = utils.is_installed('ffmpeg') QSettings().setValue('ffmpeg_path', self.ffmpeg_path) self.unoconv = utils.is_installed('unoconv') self.imagemagick = utils.is_installed('convert') missing = [] if not self.ffmpeg_path: missing.append('ffmpeg') if not self.unoconv: missing.append('unoconv') if not self.imagemagick: missing.append('imagemagick') if missing: missing = ', '.join(missing) status = self.tr('Missing dependencies:') + ' ' + missing self.dependenciesQL.setText(status) def load_settings(self): settings = QSettings() self.overwrite_existing = settings.value('overwrite_existing', type=bool) self.default_output = settings.value('default_output', type=str) self.prefix = settings.value('prefix', type=str) self.suffix = settings.value('suffix', type=str) self.ffmpeg_path = settings.value('ffmpeg_path', type=str) self.default_command = (settings.value('default_command', type=str) or config.default_ffmpeg_cmd) # type=list won't work for some reason extraformats_video = (settings.value('extraformats_video') or []) videocodecs = (settings.value('videocodecs') or config.video_codecs) audiocodecs = (settings.value('audiocodecs') or config.audio_codecs) self.default_command_image = (settings.value('default_command_image', type=str) or config.default_imagemagick_cmd) extraformats_image = (settings.value('extraformats_image') or []) extraformats_document = (settings.value('extraformats_document') or []) self.audiovideo_tab.fill_video_comboboxes(videocodecs, audiocodecs, extraformats_video) self.image_tab.fill_extension_combobox(extraformats_image) self.document_tab.fill_extension_combobox(extraformats_document) def get_current_tab(self): for i in self.tabs: if self.tabs.index(i) == self.tabWidget.currentIndex(): return i def filesList_update(self): self.filesList.clear() for i in self.fnames: self.filesList.addItem(i) def filesList_add(self): filters = 'All Files (*);;' filters += 'Audio/Video Files (*.{});;'.format(' *.'.join( self.audiovideo_tab.formats)) filters += 'Image Files (*.{});;'.format( ' *.'.join(self.image_tab.formats + self.image_tab.extra_img)) filters += 'Document Files (*.{})'.format(' *.'.join( self.document_tab.formats)) fnames = QFileDialog.getOpenFileNames( self, 'FF Multi Converter - ' + self.tr('Choose File'), config.home, filters, options=QFileDialog.HideNameFilterDetails)[0] if fnames: for i in fnames: if not i in self.fnames: self.fnames.append(i) self.filesList_update() def filesList_add_dragged(self, links): for path in links: if os.path.isfile(path) and not path in self.fnames: self.fnames.append(path) self.filesList_update() def filesList_delete(self): items = self.filesList.selectedItems() if items: for i in items: self.fnames.remove(i.text()) self.filesList_update() def filesList_clear(self): self.fnames = [] self.filesList_update() def clear_all(self): """Clears or sets to default the values of all graphical widgets.""" self.toQLE.clear() self.origQCB.setChecked(False) self.deleteQCB.setChecked(False) self.filesList_clear() self.audiovideo_tab.clear() self.image_tab.clear() def get_output_folder(self): if self.toQLE.isEnabled(): output = QFileDialog.getExistingDirectory( self, 'FF Multi Converter - ' + self.tr('Choose output destination'), config.home) if output: self.toQLE.setText(output) def import_presets(self): presets_dlgs.ShowPresets().import_presets() def export_presets(self): presets_dlgs.ShowPresets().export_presets() def reset_presets(self): presets_dlgs.ShowPresets().reset() def sync_presets(self): presets_dlgs.ShowPresets().synchronize() def removeold_presets(self): presets_dlgs.ShowPresets().remove_old() def ok_to_continue(self): """ Check if everything is ok to continue with conversion. Check if: - At least one file has given for conversion. - An output folder has given. - Output folder exists. Return False if an error arises, else True. """ try: if not self.fnames: raise ValidationError( self.tr('You must add at least one file to convert!')) elif not self.origQCB.isChecked() and not self.toQLE.text(): raise ValidationError( self.tr('You must choose an output folder!')) elif (not self.origQCB.isChecked() and not os.path.exists(self.toQLE.text())): raise ValidationError( self.tr('Output folder does not exists!')) if not self.get_current_tab().ok_to_continue(): return False return True except ValidationError as e: QMessageBox.warning(self, 'FF Multi Converter - ' + self.tr('Error!'), str(e)) return False def start_conversion(self): """ Extract the appropriate information from GUI and call the Progress dialog with the suitable argumens. """ if not self.ok_to_continue(): return tab = self.get_current_tab() ext_to = '.' + tab.extQCB.currentText() if tab.name == 'Documents' and not self.office_listener_started: utils.start_office_listener() self.office_listener_started = True _list = utils.create_paths_list(self.fnames, ext_to, self.prefix, self.suffix, self.toQLE.text(), self.origQCB.isChecked(), self.overwrite_existing) dialog = progress.Progress(_list, tab, self.deleteQCB.isChecked(), self) dialog.show() def open_dialog_preferences(self): """Open the preferences dialog.""" dialog = preferences_dlg.Preferences(self) if dialog.exec_(): self.load_settings() def open_dialog_presets(self): """Open the presets dialog.""" dialog = presets_dlgs.ShowPresets(self) dialog.exec_() def open_dialog_about(self): """Call the about dialog with the appropriate values.""" msg = self.tr('Convert among several file types to other formats') msg = textwrap.fill(msg, 54).replace('\n', '<br>') text = '''<b> FF Multi Converter {0} </b> <p>{1} <p><a href="{2}">FF Multi Converter - Home Page</a> <p>Copyright © 2011-2016 {3} <br>License: {4} <p>Python {5} - Qt {6} - PyQt {7} on {8}'''\ .format(ffmc.__version__, msg, ffmc.__url__, ffmc.__author__, ffmc.__license__, platform.python_version()[:5], QT_VERSION_STR, PYQT_VERSION_STR, platform.system()) image = ':/ffmulticonverter.png' authors = '{0} <{1}>\n\n'.format(ffmc.__author__, ffmc.__author_email__) authors += 'Contributors:\nPanagiotis Mavrogiorgos' translators = [] for i in config.translators: translators.append('{0}\n {1}'.format(i[0], i[1])) translators = '\n\n'.join(translators) dialog = about_dlg.AboutDialog(text, image, authors, translators, self) dialog.exec_()