class GCWii(Ui_MainWindow): def __init__(self, source='', destination='', clear_destination=False): super(GCWii, self).__init__() self.export_in_progress = False app = QtWidgets.QApplication(sys.argv) self.MainWindow = QtWidgets.QMainWindow() self.max_treads = QThread.idealThreadCount() self.setupUi(self.MainWindow) self.msg = MessageBox() self.manager = GCWiiManager() self.default_box_artwork = str(os.path.join('images', 'blanc-case.png')) self.default_disc_artwork = str( os.path.join('images', 'blanc-disc.png')) self.source_directory = source self.source_game_collection = {} self.destination_directory = destination self.clear_destination = clear_destination self.destination_game_collection = {} self.box_artwork_path = os.path.join(os.getcwd(), 'images', 'cover3D') self.disc_artwork_path = os.path.join(os.getcwd(), 'images', 'disc') self.current_selection = {} self.games_to_export = {} self.setup_widgets() self.setup_actions() self.MainWindow.show() if self.source_directory: self.update_source_list() if self.destination_directory: self.update_destination_list() sys.exit(app.exec_()) def setup_widgets(self): self.source_btn.clicked.connect(lambda: self.update_source_list(True)) self.destination_btn.clicked.connect( lambda: self.update_destination_list(True)) self.export_btn.clicked.connect(self.export_all) self.listView_source.clicked.connect( lambda: self.update_art_work('source')) self.listView_destination.clicked.connect( lambda: self.update_art_work('destination')) self.listView_destination.addAction(self.action_reload_destination) self.listView_destination.addAction( self.action_select_folder_destination) self.listView_destination.addAction( self.action_delete_selected_in_destination) self.listView_destination.addAction( self.action_delete_all_items_in_destination) self.listView_source.addAction(self.action_reload_source) self.listView_source.addAction(self.action_select_folder_source) self.listView_source.addAction(self.action_export_selected) self.exit_btn.clicked.connect(self.quit) self.exportSelected_btn.clicked.connect(self.export_selection) self.cancel_btn.setEnabled(False) self.cancel_btn.clicked.connect(self.cancel_copy) self.label_box.setPixmap(QtGui.QPixmap(self.default_box_artwork)) self.label_disc.setPixmap(QtGui.QPixmap(self.default_disc_artwork)) self.progressBar_fileProgress.setVisible(False) self.progressBar_destination.setVisible(False) def setup_actions(self): # Source self.action_reload_source.triggered.connect(self.update_source_list) self.action_select_folder_source.triggered.connect( lambda: self.update_source_list(True)) self.action_export_selected.triggered.connect(self.export_selection) # Destination self.action_reload_destination.triggered.connect( self.update_destination_list) self.action_select_folder_destination.triggered.connect( lambda: self.update_destination_list(True)) self.action_delete_selected_in_destination.triggered.connect( self.delete_selected_in_destination) self.action_delete_all_items_in_destination.triggered.connect( self.delete_all_in_destination) def delete_all_in_destination(self): self.manager.delete_all_files_in_directory(self.destination_directory) self.update_destination_list() def delete_selected_in_destination(self): for item in self.listView_destination.selectedIndexes(): title = item.data() game = self.manager.get_game_from_collection_by_title( title, self.destination_game_collection) if game: self.manager.delete_all_files_in_directory(game["path"]) self.update_destination_list() def export_selection(self): """ Export games marked on the source list_name """ results = dict() for index in self.listView_source.selectedIndexes(): title = QModelIndex.data(index) for key in self.source_game_collection.keys(): if self.source_game_collection[key]["title"] == title: results[key] = self.source_game_collection[key] self.games_to_export = results self.export() def export_all(self): self.games_to_export = self.manager.get_collection_diff( self.source_game_collection, self.destination_game_collection) if not self.games_to_export: return self.msg.info("Nothing to export") self.export() def update_status_info(self, text=None): if not text: self.MainWindow.statusBar().clearMessage() return self.MainWindow.statusBar().setVisible(False) if not self.MainWindow.statusBar().isVisible(): self.MainWindow.statusBar().setVisible(True) self.MainWindow.statusBar().showMessage(text) def update_global_progress_bar(self, value): self.progressBar_destination.setValue(value) def update_file_progress_bar(self, value): self.progressBar_fileProgress.setValue(value) def reset_progress_bars(self): self.progressBar_fileProgress.setValue(0) self.progressBar_destination.setValue(0) def hide_progress_bars(self): self.progressBar_fileProgress.setVisible(False) self.progressBar_destination.setVisible(False) def show_progress_bars(self): self.progressBar_fileProgress.setVisible(True) self.progressBar_destination.setVisible(True) def update_art_work(self, list_name): identifier = self.get_selection(list_name) box = self.default_box_artwork disc = self.default_disc_artwork if not identifier: return region = self.manager.get_game_region(identifier) try: if GameTDBclient.get_art_work(region, identifier, True, None): box = str( os.path.join(self.box_artwork_path, region, identifier + ".png")) if GameTDBclient.get_art_work(region, identifier, None, True): disc = str( os.path.join(self.disc_artwork_path, region, identifier + ".png")) except GameTDBclient.ErrorFetchingData: print("Unable to fetch artwork for game id: '{}' region: '{}'". format(identifier, region)) self.label_box.setPixmap(QtGui.QPixmap(box)) self.label_disc.setPixmap(QtGui.QPixmap(disc)) def get_selection(self, list_name): games_collection = dict() model = None if list_name == 'source': model = self.listView_source.currentIndex() games_collection = self.source_game_collection elif list_name == 'destination': model = self.listView_destination.currentIndex() games_collection = self.destination_game_collection title = QModelIndex.data(model) for identifier in games_collection: if games_collection[identifier]["title"] == title: return identifier def select_directory(self): return QtWidgets.QFileDialog.getExistingDirectory(self.MainWindow) def update_source_list(self, select=False): try: if select: directory = self.select_directory() if not directory: return self.source_directory = directory if not self.source_directory: return list_of_found_files = self.manager.find_supported_files( self.source_directory) self.source_game_collection = self.manager.generate_game_collection( list_of_found_files) self.label_source.setText('Source: ' + self.source_directory) list_of_titles = self.manager.get_sorted_game_titles( self.source_game_collection) if not list_of_titles: return self.listView_source.setModel( QStringListModel(['No Wii or GameCube game found'])) self.listView_source.setModel(QStringListModel(list_of_titles)) self.listView_source.selectionModel().selectionChanged.connect( lambda: self.update_art_work('source')) self.listView_source.setEditTriggers( QtWidgets.QAbstractItemView.NoEditTriggers) except PermissionError as err: details = f"Directory '{self.source_directory}' can not be read" self.msg.warning('Directory not readable', details, str(err)) def update_destination_list(self, select=False): try: while select: directory = self.select_directory() if not directory: return if not self.manager.test_directory_writeable(directory): response = self.msg.question( "Directory is not writeable.\nDo you want to select a different directory?" ) if not response: return continue select = False self.destination_directory = directory if not self.destination_directory: return list_of_found_files = self.manager.find_supported_files( self.destination_directory) self.destination_game_collection = self.manager.generate_game_collection( list_of_found_files) self.label_destination.setText('Destination: ' + self.destination_directory) self.destination_directory = self.destination_directory list_of_titles = self.manager.get_sorted_game_titles( self.destination_game_collection) if not list_of_titles: return self.listView_destination.setModel( QStringListModel(['No Wii or GameCube game found'])) self.listView_destination.setModel( QStringListModel(list_of_titles)) self.listView_destination.selectionModel( ).selectionChanged.connect( lambda: self.update_art_work('destination')) self.listView_source.setEditTriggers( QtWidgets.QAbstractItemView.NoEditTriggers) except PermissionError as err: details = f"Directory '{self.destination_directory}' can not be read" self.msg.warning('Directory not readable', details, str(err)) def export(self): if not self.source_game_collection: return self.msg.info("Source list is empty") if not self.source_directory: return self.msg.info("Please select source folder") if not self.destination_directory: return self.msg.info("Please select destination folder") if self.destination_directory == self.source_directory: return self.msg.warning( "Source and destination should not be the same directory.") if not self.games_to_export: return self.msg.info( "Please select games from source or click \"Export All\"") print("\nProcessing") self.export_btn.setDisabled(True) self.exportSelected_btn.setDisabled(True) self.source_btn.setDisabled(True) self.destination_btn.setDisabled(True) self.cancel_btn.setEnabled(True) self.show_progress_bars() # Create a QThread object self.thread = QThread() # Create a worker object self.worker = CopyWorker(self.games_to_export, self.destination_directory) # Move worker to the thread self.worker.moveToThread(self.thread) # Connect signals and slots self.thread.started.connect(self.worker.run) self.worker.thread_file_progress.progress.connect( self.update_file_progress_bar) self.worker.progress.connect(self.update_global_progress_bar) self.worker.processing.connect(self.handle_worker_processing_update) self.worker.finished.connect(self.handle_worker_finished) self.worker.error.connect(self.msg.critical) self.thread.start() def handle_worker_processing_update(self, info=None): self.update_status_info(info) self.update_destination_list() def handle_worker_finished(self): print("\nFinished") self.update_destination_list() self.reset_progress_bars() self.hide_progress_bars() self.worker.quit() self.thread.quit() self.export_btn.setDisabled(False) self.exportSelected_btn.setDisabled(False) self.source_btn.setDisabled(False) self.destination_btn.setDisabled(False) self.cancel_btn.setEnabled(False) self.cancel_btn.setText("Cancel") def quit(self): if self.clear_destination: self.manager.delete_all_files_in_directory( self.destination_directory) sys.exit(0) def cancel_copy(self): try: self.worker.stop() self.thread.quit() self.cancel_btn.setText("Cancelling...") self.cancel_btn.setEnabled(False) print("\nCanceling") except AttributeError: self.msg.info("There is nothing to cancel. ")