示例#1
0
    def __login_to_server(self):
        if self.server:
            self.server.log_out()

        self.server = OpenSubtitlesServer(self.config['server'],
                                          self.config['ua'],
                                          self.config['lang'])
        self.server.login()
示例#2
0
class PySubGUI(QMainWindow, main_window.Ui_MainWindow):
    # noinspection PyUnresolvedReferences
    def __init__(self, parent=None):
        super(PySubGUI, self).__init__(parent)
        self.setupUi(self)
        self.settings_widget.setVisible(False)
        self.btn_cancel_add.setVisible(False)
        self.status_label.setVisible(False)
        self.progressBar.setVisible(False)
        self.actionStop.setEnabled(True)
        # fixme: for some reason setEnabled(True) is impossible to set in qt designer
        self.setWindowTitle("PySub {}".format(__version__))

        self.file_model = QStandardItemModel(0, 6, parent)
        self.sub_model = QStandardItemModel(0, 4, parent)

        self.config = None
        self.server = None
        self.load_settings()

        self.video_files = []
        self.c_video_index = -1
        self.download_mode = False
        self.update_file_table()

        # Toolbar
        self.actionAddFiles.triggered.connect(self.add_files)
        self.actionAddFolder.triggered.connect(self.add_folder)
        self.actionClearList.triggered.connect(self.clear_list)

        self.actionSearch.triggered.connect(self.start_search)
        self.actionStop.triggered.connect(self.stop_search)

        self.actionDownload.triggered.connect(self.download)
        self.actionSkip.triggered.connect(self.skip)

        self.actionSettings.triggered.connect(self.toggle_settings)
        self.actionExitSettings.triggered.connect(self.toggle_settings)

        self.actionAbout.triggered.connect(self.about)

        # Main UI
        self.btn_cancel_add.clicked.connect(self.cancel_add)

        # Settings
        self.btn_save_conf.clicked.connect(self.save_settings)
        self.btn_reset_conf.clicked.connect(self.reset_settings)
        self.btn_apply.clicked.connect(self.apply_settings)

#=========================================================================
# Toolbar Buttons/Actions
#=========================================================================


    def add_files(self):
        files = QFileDialog.getOpenFileNames(self, "Add Files",
                                             QDir.homePath())
        if files and files[0]:
            self.process_files([str(files[0])])


    def add_folder(self):
        directory = QFileDialog.getExistingDirectory(self,
                                                     "Add Folder",
                                                     QDir.homePath())

        if directory:
            self.process_files(
                [str(directory) + os.sep + name for name in os.listdir(directory)])

    def clear_list(self):
        self.video_files = []
        self.update_file_table()

    def start_search(self):
        self.actionAddFolder.setEnabled(False)
        self.actionAddFiles.setEnabled(False)
        self.actionClearList.setEnabled(False)

        self.actionSearch.setVisible(False)
        self.actionStop.setVisible(True)

        self.search()

    def stop_search(self):
        self.actionAddFolder.setEnabled(True)
        self.actionAddFiles.setEnabled(True)

        self.actionSearch.setVisible(True)
        self.actionStop.setVisible(False)

        self.actionDownload.setEnabled(False)
        self.actionSkip.setEnabled(False)

        self.c_video_index = -1

        self.update_file_table()

    def download(self):
        if self.file_list.selectionModel().selectedRows():
            try:
                sub_index = self.file_list.selectionModel().selectedRows()[0].row() - 1
            except:  # no sub selected
                QMessageBox.information(self, "Not selected",
                                        "Please select the subtitle  you want to download"
                                        "before clicking 'Download' button")
                return
        else:
            return

        self.statusBar.showMessage("Downloading...")
        self.video_files[self.c_video_index].subtitles[sub_index].download()

        self.statusBar.showMessage("Subtitle downloaded for {}".format(
            self.video_files[self.c_video_index].file_name))
        self.search()

    def skip(self):
        self.search()

    def toggle_settings(self):
        if self.actionSettings.isVisible():
            self.main_wdiget.hide()
            self.settings_widget.show()
            self.actionSettings.setVisible(False)
            self.actionExitSettings.setVisible(True)
        else:
            self.main_wdiget.show()
            self.settings_widget.hide()
            self.actionSettings.setVisible(True)
            self.actionExitSettings.setVisible(False)

    def about(self):
        dialog = QDialog()
        dialog.ui = uic.loadUi('ui/about_dialog.ui', dialog)
        dialog.setAttribute(Qt.WA_DeleteOnClose)
        dialog.ui.btn_license.clicked.connect(self.show_license)
        dialog.ui.btn_credits.clicked.connect(self.show_credits)
        dialog.exec_()

    def show_license(self):
        dialog = QDialog()
        dialog.ui = uic.loadUi('ui/license_dialog.ui', dialog)
        dialog.setAttribute(Qt.WA_DeleteOnClose)
        dialog.exec_()

    def show_credits(self):
        dialog = QDialog()
        dialog.ui = uic.loadUi('ui/credits_dialog.ui', dialog)
        dialog.setAttribute(Qt.WA_DeleteOnClose)
        dialog.exec_()

    def cancel_add(self):
        if self.addThread:
            self.addThread.stop()

#=========================================================================
#   Configuration/Settings
#=========================================================================

    def load_settings(self, force_default=False, from_dict=None):
        if not from_dict:
            if force_default:
                self.config = settings.default_config
            else:
                self.config = settings.get_config()
        else:
            if from_dict == self.config:
                return

            self.config = from_dict

        if self.server:
            #TODO: Set to none only if server settings changed
            self.server = None

        self.set_ui_config()


    def set_ui_config(self):
        auto_dl = self.config['auto_download']
        self.chk_auto_dl.setCheckState(Qt.Checked if auto_dl else Qt.Unchecked)

        ovw = self.config['overwrite']
        self.chk_overwrite.setCheckState(Qt.Checked if ovw else Qt.Unchecked)

        prompt = self.config['not_found_prompt']
        self.chk_prompt.setCheckState(Qt.Checked if prompt else Qt.Unchecked)

        self.lne_save_folder.setText(self.config['subfolder'])

        lang_list = sorted(self.config['languages'].keys())
        # Move the currently selected language to the top of the list
        lang_list.insert(0, lang_list.pop(lang_list.index(self.config['lang_name'])))
        self.cbo_language.addItems(lang_list)

        # Advanced Settings
        self.txt_file_ext.setPlainText(json.dumps(self.config['file_ext']))
        self.txt_sub_ext.setPlainText(json.dumps(self.config['sub_ext']))
        self.txt_lang_json.setPlainText(json.dumps(self.config['languages']))

        self.sl_label.setText("{}".format(int(self.config['cutoff'] * 100)))
        self.sl_cutoff.setValue(int(self.config['cutoff'] * 100))

        self.lne_ua.setText(self.config['ua'])
        self.lne_server.setText(self.config['server'])

    def get_ui_config(self):
        try:
            ui_config = {'file_ext': json.loads(str(self.txt_file_ext.toPlainText())),
                         'sub_ext': json.loads(str(self.txt_sub_ext.toPlainText())),
                         'overwrite': self.chk_overwrite.checkState() == Qt.Checked,
                         'auto_download': self.chk_auto_dl.checkState() == Qt.Checked,
                         'not_found_prompt': self.chk_prompt.checkState() == Qt.Checked,
                         'subfolder': None if str(self.lne_save_folder.text()) == "" else str(self.lne_save_folder.text()),
                         'cutoff': float(str(self.sl_label.text())) / 100.00,
                         'languages': json.loads(str(self.txt_lang_json.toPlainText())),
                         'lang': self.config['languages'].get(str(self.cbo_language.currentText())),
                         'lang_name': str(self.cbo_language.currentText()),
                         'ua': str(self.lne_ua.text()),
                         'server': str(self.lne_server.text())}

            if not ui_config['lang']:
                return None

            return ui_config
        except:
            return None

    def save_settings(self, this_session_only=False):
        ui_config = self.get_ui_config()

        if not ui_config:
            QMessageBox.critical(self, "Save error",
                                 "Saving new configuration has failed."
                                 "Fix the configuration options manually "
                                 "or reset to default settings and then save")
        else:
            if not this_session_only:
                if not settings.save_config(ui_config):
                    QMessageBox.critical(self, "Save error",
                                         "Saving new configuration has failed. "
                                         "The required file or folder could not be saved or created "
                                         "as '{}'".format(settings.config_file))
                    return

            if this_session_only:
                self.load_settings(from_dict=ui_config)
            else:
                self.load_settings()

            self.toggle_settings()

    def reset_settings(self):
        self.load_settings(force_default=True)

    def apply_settings(self):
        self.save_settings(this_session_only=True)
        #TODO: Re-configuring is only necessary when certain things change
        # like subfolder, this is a waste of time to do on each applied change
        #FIXME: Should be fixed before v1.0
        file_list = [v.file_path for v in self.video_files]
        self.clear_list()
        self.process_files(file_list)


#=========================================================================
#   Backend - logging to server, downloading subtitles etc
#=========================================================================


    def __login_to_server(self):
        if self.server:
            self.server.log_out()

        self.server = OpenSubtitlesServer(self.config['server'],
                                          self.config['ua'],
                                          self.config['lang'])
        self.server.login()

    def process_files(self, file_list):
        to_process = []
        self.actionSearch.setEnabled(False)

        for video_file in file_list:
            if os.path.splitext(video_file)[1] in self.config['file_ext']:
                to_process.append(video_file)

        self.addThread = addThread(to_process, self.config)

        self.connect(self.addThread, SIGNAL("update(QString)"), self.add_progress)
        self.connect(self.addThread, SIGNAL("done(PyQt_PyObject)"), self.done_adding)

        self.addThread.start()
        self.progressBar.setVisible(True)
        self.btn_cancel_add.setVisible(True)

    def add_progress(self, text):
        self.progressBar.setMaximum(len(self.addThread.to_process))
        self.progressBar.setValue(int(text))
        self.progressBar.setFormat("Processed: {} out of {} files".format(text, len(self.addThread.to_process)))

    def done_adding(self, processed_files):
        self.video_files.extend(processed_files)
        self.update_file_table()
        self.btn_cancel_add.setVisible(False)
        self.progressBar.setVisible(False)

    def auto_search_all(self):
        #TODO: Not implemented
        for index, video in enumerate(self.video_files):
            if self.config['not_found_prompt'] and not video.auto_download():
                self.search(index)

        self.update_file_table()

    def search(self, index=None):
        if index:
            self.c_video_index = index
        else:
            self.c_video_index += 1

        if self.c_video_index >= len(self.video_files):
            self.stop_search()
            return
        else:
            video = self.video_files[self.c_video_index]
        if video.sub_exists and not self.config['overwrite']:
            self.search()
        else:
            if not video.subtitles:
                try:
                    if not self.server:
                        self.__login_to_server()

                    if video.file_search_query:
                        video.parse_response(self.server.query(video.file_search_query,
                                                               desc="File Based Search"))
                    if video.hash_search_query:
                        video.parse_response(self.server.query(video.hash_search_query,
                                                               desc="Hash Based Search"))
                except:
                    pass
            if self.config['auto_download'] and video.subtitles:
                if self.config['not_found_prompt'] and not video.auto_download():
                    self.update_sub_table(video)
                    return
            else:
                self.update_sub_table(video)
                return

#=========================================================================
#   Table models
#=========================================================================


    def update_file_table(self):

        self.file_model.clear()
        self.file_model = QStandardItemModel(0, 6, None)

        for row_num, video in enumerate(self.video_files):
            vid_index = QStandardItem(str(row_num + 1))
            vid_filename = QStandardItem(video.file_name)
            vid_series = QStandardItem(video.ep_info.get('series', 'Unknown'))
            vid_season = QStandardItem(str(video.ep_info.get('season', 'Unknown')))
            vid_episode = QStandardItem(str(video.ep_info.get('episodeNumber', 'Unknown')))
            vid_sub_exist = QStandardItem("Yes" if video.sub_exists else "No")

            self.file_model.setItem(row_num, 0, vid_index)
            self.file_model.setItem(row_num, 1, vid_filename)
            self.file_model.setItem(row_num, 2, vid_series)
            self.file_model.setItem(row_num, 3, vid_season)
            self.file_model.setItem(row_num, 4, vid_episode)
            self.file_model.setItem(row_num, 5, vid_sub_exist)

        self.file_model.setHeaderData(0, Qt.Horizontal, '#')
        self.file_model.setHeaderData(1, Qt.Horizontal, 'File')
        self.file_model.setHeaderData(2, Qt.Horizontal, 'Series')
        self.file_model.setHeaderData(3, Qt.Horizontal, 'Season')
        self.file_model.setHeaderData(4, Qt.Horizontal, 'Episode')
        self.file_model.setHeaderData(5, Qt.Horizontal, 'Sub Exists')

        number_proxy = NumberSortModel()
        number_proxy.setSourceModel(self.file_model)
        self.file_list.setModel(number_proxy)

        for i in range(5):
            self.file_list.resizeColumnToContents(i)

        self.actionSearch.setEnabled(bool(self.video_files))
        self.actionClearList.setEnabled(bool(self.video_files))

        if self.status_label.isVisible():
            self.status_label.setVisible(False)


    def update_sub_table(self, video):
        self.sub_model.clear()

        self.status_label.setVisible(True)
        self.status_label.setText("Choose subtitle for: '{}'".format(video.file_name))

        if not video.subtitles:
            self.sub_model.setItem(0, 0, QStandardItem("N/A"))
            self.sub_model.setItem(0, 1, QStandardItem("N/A"))
            self.sub_model.setItem(0, 2, QStandardItem("Subtitle not found"))
            self.sub_model.setItem(0, 3, QStandardItem("N/A"))
            self.actionDownload.setEnabled(False)
            self.actionSkip.setEnabled(True)

        else:
            for row, sub in enumerate(video.subtitles):
                sub_index = QStandardItem(str(row + 1))
                sub_downloads = QStandardItem(str(sub.download_count))
                sub_name = QStandardItem(sub.sub_filename)
                sub_synced = QStandardItem("Yes" if sub.synced else "No")

                self.sub_model.setItem(row, 0, sub_index)
                self.sub_model.setItem(row, 1, sub_downloads)
                self.sub_model.setItem(row, 2, sub_name)
                self.sub_model.setItem(row, 3, sub_synced)

            self.actionDownload.setEnabled(True)
            self.actionSkip.setEnabled(True)

        self.sub_model.setHeaderData(0, Qt.Horizontal, '#')
        self.sub_model.setHeaderData(1, Qt.Horizontal, 'Downloads')
        self.sub_model.setHeaderData(2, Qt.Horizontal, 'File Name')
        self.sub_model.setHeaderData(3, Qt.Horizontal, 'Synced')

        number_proxy = NumberSortModel()
        number_proxy.setSourceModel(self.sub_model)
        self.file_list.setModel(number_proxy)

        for i in range(3):
            self.file_list.resizeColumnToContents(i)