class AsyncPoolController(AsyncAbstractController): def __init__(self, # A number *n* to create a pool of *n* simple threads, where each thread # lacks an event loop, so that it can emit but not receive signals. # This means that ``g`` may **not** be run in a thread of this pool, # without manually adding a event loop. If *n* < 1, the global thread pool # is used. maxThreadCount, # |parent| parent=None): super(AsyncPoolController, self).__init__(parent) if maxThreadCount < 1: self.threadPool = QThreadPool.globalInstance() else: self.threadPool = QThreadPool() self.threadPool.setMaxThreadCount(maxThreadCount) # |_start| def _start(self, future): # Asynchronously invoke ``f``. apw = _AsyncPoolWorker(future) self.threadPool.start(apw) # |terminate| def _terminate(self): self.threadPool.waitForDone() del self.threadPool
class Tasks(QObject): def __init__(self, ar, process_result): super(Tasks, self).__init__() self.ar = ar self.process_result = process_result self.pool = QThreadPool() self.pool.setMaxThreadCount(10) # def process_result(self, rev): # # print 'Receiving', rev # self.ref.setText(rev) def start(self): self.factory = GenerWork(self.ar) self.factory.generateWorkers() workers = self.factory.get_workers() # print workers for worker in workers: worker.signals.result.connect(self.process_result) self.pool.start(worker) self.pool.waitForDone() return data def get_shell_data(self): return self.factory.get_shell_data()
def start(self): self.idmap = {} self.entries = [] pool = QThreadPool() pool.setMaxThreadCount(1) for label in LABELS: feed = Feed(label, self) pool.start(feed) imap = Imap(label, self) pool.start(imap) pool.waitForDone() self.done.emit()
class Validation: def __init__(self, iface, db, validation_dia, plugin_dir, params): self.iface = iface self.db = db self.params = params self.validation_dia = validation_dia self.app_root = plugin_dir self.open_image = QPixmap(os.path.join(self.app_root, "image", "folder_open_icon.png")) self.validation_dia.ui.openPushButton.setIcon(QIcon(self.open_image)) self.validation_dia.ui.openPushButton.setToolTip("Select File") self.export_globals = None self.validation_dk = None self.report_to_dialog = None self.re = QRegExp("CheckBox") self.check_boxes_names = [] self.long_task = QThreadPool(None).globalInstance() self.summary_tables = {} self.model_navigation() self.form_load() self.file_dialog = QFileDialog() self.summary_functions = {} self.report_file_path = None self.home_dir = os.path.expanduser('~') self.org_name = database.get_from_gaz_metadata(db, "owner") self.report = ExportValidationReport("roadNet Validation Report", self.org_name, self.db, self.iface, None) self.list_check_boxes = [] self.progress_win = QProgressDialog("", None, 0, 100, self.validation_dia) self.progress_win.setFixedSize(380, 100) self.progress_win.setModal(True) self.progress_win.setWindowTitle("Export Validation Report") self.summary_runnables = {'dupStreetCheckBox': [lambda: DupStreetDesc(), 0], 'notStreetEsuCheckBox': [lambda: StreetsNoEsuDesc(), 1], 'notType3CheckBox': [lambda: Type3Desc(False), 2], 'incFootPathCheckBox': [lambda: Type3Desc(True), 2], 'dupEsuRefCheckBox': [lambda: DupEsuRef(True), 3], 'notEsuStreetCheckBox': [lambda: NoLinkEsuStreets(), 4], 'invCrossRefCheckBox': [lambda: InvalidCrossReferences()], 'startEndCheckBox': [lambda: CheckStartEnd(), 8], 'tinyEsuCheckBox': [lambda: CheckTinyEsus("esu", 1)], 'notMaintReinsCheckBox': [lambda: CheckMaintReins()], 'asdStartEndCheckBox': [lambda: CheckAsdCoords()], 'notMaintPolysCheckBox': [lambda: MaintNoPoly(), 16], 'notPolysMaintCheckBox': [lambda: PolyNoMaint()], 'tinyPolysCheckBox': [lambda: CheckTinyEsus("rd_poly", 1)]} def init_functions(self, ref_class, tolerance): """ initialise a dictionary which keys are names of check boxes and values are all functions that create the respective table on the screen report functions are lambda because they will be called upon report creation and int references to a dictionary in the validation_summary class to the associated table widget to populate :param ref_class: class, the class holding the relative function :return: void """ self.summary_functions = {'dupStreetCheckBox': [lambda: ref_class.dup_street_desc(), 0], 'notStreetEsuCheckBox': [lambda: ref_class.street_not_esu_desc(), 1], 'notType3CheckBox': [lambda: ref_class.no_type3_desc(include_footpath=False), 2], 'incFootPathCheckBox': [lambda: ref_class.no_type3_desc(include_footpath=True), 2], 'dupEsuRefCheckBox': [lambda: ref_class.dup_esu_ref(), 3], 'notEsuStreetCheckBox': [lambda: ref_class.no_link_esu_streets(), 4], 'invCrossRefCheckBox': [lambda: ref_class.invalid_cross_references()], 'startEndCheckBox': [lambda: ref_class.check_start_end(tolerance), 8], 'tinyEsuCheckBox': [lambda: ref_class.check_tiny_esus("esu", 1)], 'notMaintReinsCheckBox': [lambda: ref_class.check_maint_reinst()], 'asdStartEndCheckBox': [lambda: ref_class.check_asd_coords()], 'notMaintPolysCheckBox': [lambda: ref_class.maint_no_poly(), 16], 'notPolysMaintCheckBox': [lambda: ref_class.poly_no_maint()], 'tinyPolysCheckBox': [lambda: ref_class.check_tiny_esus("rd_poly", 1)]} def model_navigation(self): """ events handler for buttons in the form :return: object """ buttons = self.validation_dia.ui.okCancelButtons.buttons() buttons[0].clicked.connect(self.get_data) buttons[1].clicked.connect(self.close_browser) self.validation_dia.ui.openPushButton.clicked.connect(self.select_file) self.validation_dia.ui.screenRadioButton.toggled.connect(lambda: self.selection_handler(0)) self.validation_dia.ui.fileRadioButton.toggled.connect(lambda: self.selection_handler(1)) self.validation_dia.ui.notType3CheckBox.toggled.connect(self.check_no_type_click) self.validation_dia.ui.startEndCheckBox.toggled.connect(self.check_coords_click) self.validation_dia.ui.selectAllButton.clicked.connect(self.select_all) self.validation_dia.ui.clearAllButton.clicked.connect(self.clear_all) def form_load(self): # set the initial status of the form self.validation_dia.ui.screenRadioButton.setChecked(True) self.validation_dia.ui.filePathLineEdit.setEnabled(False) self.check_coords_click() self.check_no_type_click() self.validation_dia.ui.dupStreetCheckBox.setChecked(True) self.validation_dia.ui.notStreetEsuCheckBox.setChecked(True) self.validation_dia.ui.notType3CheckBox.setChecked(True) self.validation_dia.ui.dupEsuRefCheckBox.setChecked(True) self.validation_dia.ui.notEsuStreetCheckBox.setChecked(True) self.validation_dia.ui.invCrossRefCheckBox.setChecked(True) self.validation_dia.ui.startEndCheckBox.setChecked(False) self.validation_dia.ui.tinyEsuCheckBox.setChecked(True) if self.params['RNsrwr'].lower() == 'true': self.validation_dia.ui.notMaintReinsCheckBox.setChecked(True) self.validation_dia.ui.asdStartEndCheckBox.setChecked(True) if self.params['RNsrwr'].lower() == 'false': self.validation_dia.ui.notMaintReinsCheckBox.setChecked(False) self.validation_dia.ui.asdStartEndCheckBox.setChecked(False) self.validation_dia.ui.notMaintReinsCheckBox.setEnabled(False) self.validation_dia.ui.asdStartEndCheckBox.setEnabled(False) if self.params['RNPolyEdit'].lower() == 'true': self.validation_dia.ui.notMaintPolysCheckBox.setChecked(True) self.validation_dia.ui.notPolysMaintCheckBox.setChecked(True) self.validation_dia.ui.tinyPolysCheckBox.setChecked(True) if self.params['RNPolyEdit'].lower() == 'false': self.validation_dia.ui.notMaintPolysCheckBox.setChecked(False) self.validation_dia.ui.notPolysMaintCheckBox.setChecked(False) self.validation_dia.ui.tinyPolysCheckBox.setChecked(False) self.validation_dia.ui.notMaintPolysCheckBox.setEnabled(False) self.validation_dia.ui.notPolysMaintCheckBox.setEnabled(False) self.validation_dia.ui.tinyPolysCheckBox.setEnabled(False) def close_browser(self): # close the dialog self.validation_dia.close() def get_data(self): """ produce the report according to the options specified by the user :return: validation report either on screen or as text file """ if self.validation_dia.ui.fileRadioButton.isChecked(): # alert the user if no path is specified if self.validation_dia.ui.filePathLineEdit.text() == "": no_path_msg_box = QMessageBox(QMessageBox.Warning, " ", "You must specify a path and filename for the report", QMessageBox.Ok, None) no_path_msg_box.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) no_path_msg_box.exec_() return # format the path and runs the export val_file_path = self.validation_dia.ui.filePathLineEdit.text() # checks if the export directory exists and it is valid if not os.path.isdir(os.path.dirname(val_file_path)): path_invalid_msg_box = QMessageBox(QMessageBox.Warning, " ", "A valid directory must be selected", QMessageBox.Ok, None) path_invalid_msg_box.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) path_invalid_msg_box.exec_() else: self.report_to_file(val_file_path) # text file report = false, create a screen report, instantiate the report creator class if not self.validation_dia.ui.fileRadioButton.isChecked(): self.report_to_screen() def select_file(self): """ open the dialog window to select the file and print the path on the main line edit :return: void """ self.file_dialog.setDirectory(self.home_dir) self.file_dialog.setFileMode(QFileDialog.ExistingFiles) filters = "Text files (*.txt)" self.file_dialog.setNameFilter(filters) save_file_name = self.file_dialog.getSaveFileName(self.file_dialog, "Export Validation Report", self.home_dir, filter="Text files (*.txt)") if save_file_name != "": self.validation_dia.ui.filePathLineEdit.setText(("{}.txt".format(save_file_name))) if save_file_name.endswith(".txt"): self.validation_dia.ui.filePathLineEdit.setText(save_file_name) def selection_handler(self, button_id): """ change the status of the line edit according to the radio button selection :return: """ # if screen report is selected disable line edit for the file path if button_id == 0: self.validation_dia.ui.filePathLineEdit.setEnabled(False) self.validation_dia.ui.openPushButton.setEnabled(False) self.check_boxes_names = [] else: self.validation_dia.ui.filePathLineEdit.setEnabled(True) self.validation_dia.ui.openPushButton.setEnabled(True) self.check_boxes_names = [] def check_coords_click(self): # show/hide tolerance metres spin box if self.validation_dia.ui.startEndCheckBox.isChecked(): self.validation_dia.ui.metresSpinBox.setVisible(True) self.validation_dia.ui.toleranceLabel.setVisible(True) else: self.validation_dia.ui.metresSpinBox.setVisible(False) self.validation_dia.ui.toleranceLabel.setVisible(False) def check_no_type_click(self): # enable/disable footpath check box if self.validation_dia.ui.notType3CheckBox.isChecked(): self.validation_dia.ui.incFootPathCheckBox.setEnabled(True) else: self.validation_dia.ui.notType3CheckBox.setChecked(False) self.validation_dia.ui.incFootPathCheckBox.setEnabled(False) def select_all(self): # reset the form to default status, select all self.form_load() def clear_all(self): # uncheck all checkboxes self.validation_dia.ui.dupStreetCheckBox.setChecked(False) self.validation_dia.ui.notStreetEsuCheckBox.setChecked(False) self.validation_dia.ui.notType3CheckBox.setChecked(False) self.validation_dia.ui.incFootPathCheckBox.setChecked(False) self.validation_dia.ui.incFootPathCheckBox.setEnabled(False) self.validation_dia.ui.dupEsuRefCheckBox.setChecked(False) self.validation_dia.ui.notEsuStreetCheckBox.setChecked(False) self.validation_dia.ui.invCrossRefCheckBox.setChecked(False) self.validation_dia.ui.startEndCheckBox.setChecked(False) self.validation_dia.ui.tinyEsuCheckBox.setChecked(False) self.validation_dia.ui.notMaintReinsCheckBox.setChecked(False) self.validation_dia.ui.asdStartEndCheckBox.setChecked(False) self.validation_dia.ui.notMaintPolysCheckBox.setChecked(False) self.validation_dia.ui.notPolysMaintCheckBox.setChecked(False) self.validation_dia.ui.tinyPolysCheckBox.setChecked(False) def report_to_file(self, val_file_path): """ creates a text file report :return: void """ # assign to the report class the file path property self.report_file_path = val_file_path # start writing # get all checked check-boxes if len(self.list_check_boxes) > 0: self.list_check_boxes = [] self.list_check_boxes = self.validation_dia.findChildren(QCheckBox, self.re) if len(self.check_boxes_names) > 0: self.check_boxes_names = [] for check_box in self.list_check_boxes: if check_box.isChecked(): self.check_boxes_names.append(str(check_box.objectName())) if len(self.check_boxes_names) < 1: no_val_check_msg_box = QMessageBox(QMessageBox.Warning, " ", "At least one validation option must be selected", QMessageBox.Ok, None) no_val_check_msg_box.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) no_val_check_msg_box.exec_() return tolerance = self.validation_dia.ui.metresSpinBox.value() if self.validation_dia.ui.startEndCheckBox.isChecked() and (tolerance is None or tolerance == 0): no_tol_msg_box_file = QMessageBox(QMessageBox.Warning, " ", "You must specify a tolerance", QMessageBox.Ok, None) no_tol_msg_box_file.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) no_tol_msg_box_file.exec_() return self.progress_win.setWindowTitle("Export Validation Report") self.progress_win.show() if self.validation_dia.ui.notType3CheckBox.isChecked(): if 'incFootPathCheckBox' in self.check_boxes_names: # locate the include footpath option and run just the appropriate function self.check_boxes_names.remove('notType3CheckBox') self.export_globals = InitGlobals(self.db, self.params, tolerance) self.long_task.setMaxThreadCount(1) start_report = StartReport(val_file_path, self.org_name) start_report.signals.result.connect(self.log_progress) end_report = EndReport() end_report.signals.result.connect(self.log_progress) end_report.signals.report_finished.connect(self.show_finished) self.long_task.start(start_report) for check_box_name in self.check_boxes_names: run_class = self.summary_runnables[check_box_name] runnable = run_class[0]() runnable.signals.result.connect(self.log_progress) self.long_task.start(runnable) self.long_task.start(end_report) self.list_check_boxes = [] self.check_boxes_names = [] @pyqtSlot() def show_finished(self): self.long_task.waitForDone() show_finished_msg_box = QMessageBox(QMessageBox.Information, " ", "Report successfully exported at \n {0}" .format(str(self.report_file_path)) .replace("\\\\", "\\"), QMessageBox.Ok, None) show_finished_msg_box.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) show_finished_msg_box.exec_() @pyqtSlot(str, int) def log_progress(self, task, value): self.progress_win.setLabelText(task) self.progress_win.setValue(value) def report_to_screen(self): tolerance = self.validation_dia.ui.metresSpinBox.value() if self.validation_dia.ui.startEndCheckBox.isChecked() and (tolerance is None or tolerance == 0): no_tol_msg_box_screen = QMessageBox(QMessageBox.Warning, " ", "You must specify a tolerance", QMessageBox.Ok, None) no_tol_msg_box_screen.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) no_tol_msg_box_screen.exec_() return report_to_screen = self.report report_to_screen.validation_dia = self.validation_dia # in case the user selects a screen report immediately after the generation of # a file report create a new instance of the report class and None the file path # instantiate the report window, the parent is the main validation report dialog if self.validation_dk is None: self.validation_dk = ValidationSummaryDock(self.validation_dia) self.validation_dk.setWindowTitle("Validation Report Summary") self.validation_dk.setWindowFlags(Qt.WindowMaximizeButtonHint | Qt.WindowMinimizeButtonHint) rn_icon = QIcon() rn_icon.addPixmap(QPixmap(os.path.join(self.app_root, "image", "rn_logo_v2.png"))) self.validation_dk.setWindowIcon(rn_icon) # instantiate the class handler (functions to create and format the screen report) # include the window in the instantiation report_to_dialog = ValidationSummary(self.validation_dk, self.iface, self.db, tolerance) # creates a list of the checked checkboxes to create the tables self.list_check_boxes = self.validation_dia.findChildren(QCheckBox, self.re) for check_box in self.list_check_boxes: if check_box.isChecked(): self.check_boxes_names.append(str(check_box.objectName())) # check if at least one checkbox is checked before running the report if len(self.check_boxes_names) < 1: no_val_check_msg_box = QMessageBox(QMessageBox.Warning, " ", "At least one validation option must be selected", QMessageBox.Ok, None) no_val_check_msg_box.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint) no_val_check_msg_box.exec_() return # initialises the functions self.init_functions(report_to_screen, tolerance) # runs the functions, each function passes a list and a table reference # to the handler class methods that create, populate and finally show the window if self.validation_dia.ui.notType3CheckBox.isChecked(): if 'incFootPathCheckBox' in self.check_boxes_names: # locate the include footpath option and run just the appropriate function self.check_boxes_names.remove('notType3CheckBox') report_to_dialog.include_footpath = True self.report.start_report() for check_box_name in self.check_boxes_names: function = self.summary_functions[check_box_name][0] # handles multiple results for a unique check box (cross references) if check_box_name == 'invCrossRefCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 5) report_to_dialog.set_table(function_list[1], 6) report_to_dialog.set_table(function_list[2], 7) # handles multiple results for a unique check box (tiny/empty ESUs Polys) elif check_box_name == 'tinyEsuCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 9) report_to_dialog.set_table(function_list[1], 10) elif check_box_name == 'tinyPolysCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 19) report_to_dialog.set_table(function_list[1], 20) # handles multiple results for a unique check box (maint/reins asd streets) elif check_box_name == 'notMaintReinsCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 11) report_to_dialog.set_table(function_list[1], 12) # handles multiple results for a unique check box (maint/reins asd coords) elif check_box_name == 'asdStartEndCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 13) report_to_dialog.set_table(function_list[1], 14) report_to_dialog.set_table(function_list[2], 15) # handles multiple results for a unique check box (polygons with no link, multi maintenance assignation) elif check_box_name == 'notPolysMaintCheckBox': function_list = function() report_to_dialog.set_table(function_list[0], 17) report_to_dialog.set_table(function_list[1], 18) # all other normal cases else: table_id = self.summary_functions[check_box_name][1] report_to_dialog.set_table(function(), table_id) self.report.end_report(self.validation_dia) self.report = ExportValidationReport("roadNet Validation Report", self.org_name, self.db, self.iface, None) report_to_dialog.show_validation_widget()
class KISS_Thread(QtCore.QThread): """ AX.25 Communication """ packet_received = pyqtSignal("QString", name="packetReceived") def __init__(self, control_system): """Make a instance of the ReaderAndWriterThread class. Args: protocol (SerialProtocol): It is a instance of a communication protocol. """ QThread.__init__(self, control_system) self.writer_thread = QThreadPool(self) self.writer_thread.setMaxThreadCount(1) def run(self): print "kiss started" self.kiss_connect() def read_callback(self, data): print "received packet, len", len(data) kiss_data = kiss.constants.FEND + kiss.util.escape_special_codes(data) + kiss.constants.FEND log_the_data("./log_files/telemetry_log_files/BSU_satellite.kss", kiss_data) data = data[1:] if len(data) < 15: print "bad packet" return dest = "".join([chr(ord(c) >> 1) for c in data[:6]]) # print "Destination", dest src = "".join([chr(ord(c) >> 1) for c in data[7:13]]) #print "Source", src if not dest.startswith(LOCAL_SSID): print "packet not for us" return start = 16 ssid = ord(data[13]) & 1 if ssid == 0: via = "".join([chr(ord(c) >> 1) for c in data[7:13]]) start = 23 size = len(data) - start if size == 0: print "packet is empty" return payload = data[start:] # self.control_system.on_packet_received(payload) self.packet_received.emit(payload) def kiss_connect(self): try: print "connect" self.kiss_prot = kiss.KISS(port=config.kiss_serial_name, speed=config.kiss_baudrate) self.kiss_prot.start() self.kiss_prot.read(self.read_callback) except: error_mesage = "CANNOT OPEN PORT" log_the_error(error_mesage) sound.play(error_mesage) print sys.exc_info() print "ax.25 is failed" def send_command(self, name, arg, device, time_of_execution): data = { "Timestamp": int(time.time()), "Schedule": time_of_execution, "Cmd": name, "Arg": arg, "Device": device } json_data = json.dumps(data) print "Formed packet", json_data writer = KissWriter(self.kiss_prot, LOCAL_SSID, REMOTE_SSID) writer.set_data(json_data) self.writer_thread.start(writer)
class DownloaderWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.DownloadPath = os.path.expanduser("~") # get home dir self.pool = QThreadPool() self.pool.setMaxThreadCount(1) self.initVariables() self.resize(700, 400) self.initUI() self.line_downpath.setText(self.down_control.getDownloadPath()) def initVariables(self): self.down_control = DownloadController(self.addInfo) self.down_control.setDownloadPath(self.DownloadPath) self.chapters = None self.chapters_filtered = None self.ch_from = None self.ch_to = None def initUI(self): cw = QWidget() self.setCentralWidget(cw) layout_main = QVBoxLayout() layout_main.setSpacing(5) ## Info self.info = QTextEdit() self.info.setReadOnly(True) self.info.setLineWrapMode(QTextEdit.NoWrap) layout_main.addWidget(self.info, 1) ## Line edit layout_url = QHBoxLayout() layout_url.setSpacing(5) self.line_url = QLineEdit() layout_url.addWidget(QLabel('<b>Series URL:</b>')) layout_url.addWidget(self.line_url, 1) layout_main.addLayout(layout_url) ## Comboboxes layout_combo = QHBoxLayout() layout_combo.setSpacing(5) self.combo_from = QComboBox() self.combo_from.setEnabled(False) self.combo_to = QComboBox() self.combo_to.setEnabled(False) layout_combo.addWidget(QLabel('<b>Download chapters: </b>')) layout_combo.addWidget(QLabel(' From:')) layout_combo.addWidget(self.combo_from, 1) layout_combo.addWidget(QLabel('To:')) layout_combo.addWidget(self.combo_to, 1) layout_main.addLayout(layout_combo) ## Download path layout_downpath = QHBoxLayout() layout_downpath.setSpacing(5) self.line_downpath = QLineEdit() self.line_downpath.setEnabled(False) self.btn_downpath = QPushButton('Change') self.btn_downpath.pressed.connect(self.selectDownloadPath) layout_downpath.addWidget(QLabel('<b>Download path:</b>')) layout_downpath.addWidget(self.line_downpath, 1) layout_downpath.addWidget(self.btn_downpath) layout_main.addLayout(layout_downpath) ## Buttons layout_btn = QHBoxLayout() layout_btn.setSpacing(5) self.btn_getlist = QPushButton('Get List of Chapters') self.btn_getlist.pressed.connect(self.getChaptersList) self.btn_download = QPushButton('Download chapters') self.btn_download.pressed.connect(self.downloadChapters) self.btn_download.setEnabled(False) self.btn_exit = QPushButton('Exit') self.btn_exit.pressed.connect(self.close) layout_btn.addStretch() layout_btn.addWidget(self.btn_getlist) layout_btn.addWidget(self.btn_download) layout_btn.addWidget(self.btn_exit) layout_btn.addStretch() layout_main.addLayout(layout_btn) # status bar self.statusBar().showMessage('Ready') # add layout to main window cw.setLayout(layout_main) self.setWindowTitle('OMAD - Online MAnga Downloader') self.show() def closeEvent(self, event): """ Runs when user tryes to close main window. sys.exit(0) - to fix wierd bug, where process is not terminated. """ sys.exit(0) def addInfo(self, s='Testing printing...', exception=False, downloadProgress=False, trace=[]): logger.info(s+', '+str(exception)+', '+str(downloadProgress)+', '+str(trace)) if type(s)!=type("") and type(s)!=type(b"") and type(s) != type(QtCore.QString('')): s = str(s) if exception: s = "!!! Exception: "+s if downloadProgress: s = "Downloading progress: "+s self.setStatusBarText(s) self.info.append(s) if exception: for t in trace: self.info.append(str(t)) sb = self.info.verticalScrollBar() sb.setValue(sb.maximum()) QtCore.QCoreApplication.processEvents() def setStatusBarText(self, s='Testing...'): """ Changes status bar text """ self.statusBar().showMessage(s) QtCore.QCoreApplication.processEvents() def getChaptersList(self): self.addInfo('Getting list of chapters...') # reinit clean variables self.initVariables() # get series url url = str(self.line_url.text()).strip() if not self.down_control.setSeriesUrl(url): return # bad url self.chapters = self.down_control.getChaptersList() logger.debug('Setting up comboBoxes...') for i in range(0, self.combo_from.count()): self.combo_from.removeItem(0) for i in range(0, self.combo_to.count()): self.combo_to.removeItem(0) for c in self.chapters: self.combo_from.addItem(c[0]) self.combo_to.addItem(c[0]) self.combo_from.setCurrentIndex(0) self.combo_to.setCurrentIndex(len(self.chapters)-1) self.addInfo('Chapter list loaded') self.combo_from.setEnabled(True) self.combo_to.setEnabled(True) self.btn_download.setEnabled(True) def downloadChapters(self): self.addInfo('Checking chapter range') self.ch_from = self.combo_from.currentIndex() self.ch_to = self.combo_to.currentIndex() if self.ch_from>self.ch_to: self.addInfo('Bad range. Cant download backwards!') return else: self.addInfo('Range OK, starting download of '+str((self.ch_to-self.ch_from)+1)+' chapters...') self.gui_disable(True) worker = DownloadWorker(self.down_control, self.ch_from, self.ch_to) worker.signals.update.connect(self.addInfo) worker.signals.finished.connect(self.downloadChapters_finished) self.pool.start(worker) def downloadChapters_finished(self): self.gui_disable(False) self.setStatusBarText('Ready - Download Finished!!') # Finished self.addInfo('Download Finished!!') # Print failed downloads failed_chs = [] for i, r in enumerate(self.down_control.results): if r is False: failed_chs.append(self.chapters[i+self.ch_from]) if len(failed_chs)==0: self.addInfo('\nNo failed downloads') else: self.addInfo('\nChapters with failed downloads:') for c in failed_chs: self.addInfo(c[0]) self.addInfo('') def selectDownloadPath(self): downdir = self._get_dir(directory=self.DownloadPath) self.down_control.setDownloadPath(downdir) self.DownloadPath = self.down_control.getDownloadPath() self.line_downpath.setText(self.DownloadPath) def _get_dir(self, directory=''): """ Draw a dialog for directory selection. """ downdir = QFileDialog.getExistingDirectory( caption='Select Folder', options=QFileDialog.ShowDirsOnly, directory=directory ) if len(downdir) > 0: downdir = "%s" % (downdir) else: downdir = directory return downdir def gui_disable(self, downloading=True): self.line_url.setEnabled(not downloading) self.combo_from.setEnabled(not downloading) self.combo_to.setEnabled(not downloading) self.btn_getlist.setEnabled(not downloading) self.btn_download.setEnabled(not downloading) self.btn_downpath.setEnabled(not downloading)
class MainWindow(QtGui.QMainWindow): """ Main window for the application Takes Ui_MainWindow from mainUI.py, which is automatically generated with pyuic4 from the UI file. """ def __init__(self, parent=None): """Init Window""" QtGui.QMainWindow.__init__(self, parent) self.gui = Ui_MainWindow() self.gui.setupUi(self) self.gscriptpath = '"' + os.getcwd() + r'\gs\gs9.02\bin' self.gui.progressBar.hide() self.single_output_dir = '' self.deletions = [] self.work = QThreadPool() self.work.setMaxThreadCount(1) self.thread_number = 5 self.setWindowIcon(QtGui.QIcon(":/ico.png")) self.resolution = 450 self.mode = 'tiffg4' def quit(self): """ Quit the window, in case we need some specific behaviour """ print self def dir_locate(self): """ Will locate a dir to split all pdfs """ pass def dir_output(self): """ Will locate an output dir for dir conversion """ pass def single_output_file(self): """ Spawns a find file dialog """ # get a local ref to dialog dir_dialog = QtGui.QFileDialog(self) # set dialog type dir_dialog.setFileMode(QtGui.QFileDialog.Directory) # if the dialog is 'executed' (hit ok) # then we take the string into a class attrib if dir_dialog.exec_() == True: for item in dir_dialog.selectedFiles(): self.single_output_dir = item self.gui.single_line_out.setText(item) break def single_locate_file(self): """ creates a dialog to find a single file """ # Create the file lookup dialog using built-in dialogs # We set the file type to PDF and only PDF self.gui.single_line_in.setText(QtGui.QFileDialog.getOpenFileName( self, 'Open', '' ,('PDF Files (*.pdf)'))) def update_progress_bar(self): """ Method to update progress bar whilst running conversion """ # When we get a call it's from a thread finishing # we increment the progress bar and check if we're at 100% self.gui.progressBar.setValue(self.gui.progressBar.value()+1) # This is bad, if a QProcess fails, we don't get a tick # and the progressBar will never get to 100% # we need to implement something that will catch errors with # QProcess if self.gui.progressBar.value() == self.gui.progressBar.maximum(): self.gui.progressBar.hide() # create the deleter thread with a reference to the deletions # list. deleter = QFileWorker(self.deletions, self) # wait for the deletions thread to return deleter.threadpool.waitForDone() # re-init deletions list so we don't try to delete # already deleted files next time self.deletions = [] # Re-enable the button self.gui.btn_single_convert.setEnabled(True) def convert(self): """ Implementation of multithreaded processing """ # if they click convert without looking for files if len(self.gui.single_line_in.text()) < 1: return if len(self.gui.single_line_out.text()) < 1: return # Open the PDF that we found in the dialog try: pdf = PdfFileReader(open(self.gui.single_line_in.text(), 'rb')) # if the file cannot be properly read raise error except AssertionError: QtGui.QMessageBox.warning(self, "Error", "This file is corrupt") return # if the file does not exist except IOError: QtGui.QMessageBox.warning(self, "Error", "Not a valid file path") return self.gui.btn_single_convert.setEnabled(False) # disable button self.gui.progressBar.setValue(0) # re-init progress bar # Show the progress bar self.gui.progressBar.show() # Set the progress bar's maximum number to the number of pages # in the PDF self.gui.progressBar.setMaximum(pdf.numPages) # Send the PDF object (PdfFileReader) to the ThreadHandler # along with a reference to ourself in order to set up signal # callbacks # most of the magic is in mthreading.py # this is the cleanest interface I could come up with # just pass it an opened PDF document and processing will begin self.work.start(QThreadHandle(pdf, self)) def convert_dir(self): """ Method to convert a whole directory """ pass def spawn_options(self): """ Spawns an options dialog """ options.OptionsDialog(self).exec_() def spawn_about(self): """ Spawns an options dialog """ about_dialog = about.AboutDialog(self) about_dialog.gui.label_2.setPixmap(QtGui.QPixmap(":/about.png")) about_dialog.exec_()