def loadFile(self): mnFileName = unicode(self.mnFileNameInput.text()) if not mnFileName: QMessageBox.warning(glb.mainWin, QCoreApplication.translate('SmileKit', 'No filename specified'), QCoreApplication.translate('SmileKit', 'Please enter a filename in the input box!')) return progressDlg = QProgressDialog(glb.mainWin) progressDlg.setRange(0, 100) progressDlg.setLabelText('Reading File...') progressDlg.show() a = glb.application def progFunc(p): progressDlg.setValue(p) if a.hasPendingEvents(): a.processEvents() r = readMnFile(mnFileName, progress=progFunc) self.data = r progressDlg.close() self.locationFrame.setEnabled(1) self.statisticsFrame.setEnabled(1) if ncOk: self.ncFileFrame.setEnabled(1) self.statisticsButton.setCheckState(Qt.Unchecked) self.locNameInput.setText(r['name']) c = unicode(QCoreApplication.translate('SmileKit', "created %s from %s by Meteo2Nc.py (v%d)")) self.locCommentInput.setText(c % (time.ctime(), mnFileName, version)) self.locLatitudeInput.setValue(r['latitude']) self.locLongitudeInput.setValue(r['longitude']) self.locHeightInput.setValue(r['height']) self.locTimeZoneInput.setValue(r['timezone']) path, tmp = os.path.split(mnFileName) ncFileName = os.path.join(path, makeFileName(r['name'])+'_weather.nc') self.ncFileNameInput.setText(ncFileName)
def createPortfolioListModel(self): portfolios = self.getPortfolios() listModel = PortfolioListModel(portfolios) numPortfolios = len(portfolios) progress = QProgressDialog( self.tr("Loading portfolios from Google"), QString(), 0, numPortfolios, self.mainWindow ) progress.setWindowTitle(self.tr("Loading portfolios from Google")) if self.updater: self.updater.terminate() self.disconnect(self.updater, SIGNAL("quotesUpdated"), self.processQuotesUpdated) self.updater = Updater(self.quoter) QObject.connect(self.updater, SIGNAL("quotesUpdated"), self.processQuotesUpdated) for pIndex in range(numPortfolios): portfolio = portfolios[pIndex] positions = self.gDataClient.GetPositionFeed(portfolio) for position in positions.entry: tickerTuple = position.symbol.exchange, position.symbol.symbol self.updater.addTickers(tickerTuple) portfolioName = portfolio.title.text.decode("utf-8") labelText = QString("'%s' (%d / %d)" % (portfolioName, pIndex + 1, numPortfolios)) progress.setLabelText(labelText) progress.setValue(pIndex + 1) QApplication.processEvents() self.updater.start() return listModel
def stop_experiment(self, msg, stop_storing=False): progress = QProgressDialog(None, Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) progress.setLabelText("Stopping...") progress.setRange(0, 5) progress.setCancelButton(None) progress.show() print("STOP EXPERIMENT!!!!") uid = str(msg) index = self.index_of(uid) if index is None: print("experiment uuid not found: ", uid) return exp = self.experiments[index] if not exp.launcher_data: print("this exp is not running...", uid) return if stop_storing: # stop storing ONLY if the experiment was fired from this very obci gui # otherwise the data is lost .... # below code was to stop storing every time signal saver is in scenarios`es modules # but it sometimes hangs forever eg. when we are using morph extensively ... # ` # or ("signal_saver" in exp.exp_config.peers and\ # exp.status.peer_status("signal_saver").status_name \ # in [launcher_tools.RUNNING, launcher_tools.LAUNCHING]): print("STOP STORING") exp.stop_storing(self.client) for i in range(4): time.sleep(0.6) # FIXME - without it some problem with below kill... progress.setValue(i + 1) progress.setValue(5) self._process_response(self.client.kill_exp(exp.uuid))
def dump_script(self): to_dump = self.get_checked([self.ui.treeFileList.topLevelItem(i) for i in range(self.ui.treeFileList.topLevelItemCount())]) if not to_dump: QtGui.QMessageBox.warning(self, "No Selection", "No folders have beens selected to dump.") return out_file = get_save_file(self, self.last_file, "Text files (*.txt)") if out_file == "": return translated = not self.ui.chkUntranslated.isChecked() strip_clt = self.ui.chkStripClt.isChecked() only_voiced = self.ui.chkOnlyVoiced.isChecked() line_numbers = self.ui.chkLineNumbers.isChecked() progress = QProgressDialog("Dumping...", QtCore.QString(), 0, len(to_dump), self) progress.setWindowTitle("Dumping...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setValue(0) progress.setAutoClose(False) progress.setMinimumDuration(0) # print out_file with open(out_file, "wb") as f: for dir in to_dump: progress.setLabelText("Dumping %s..." % dir) f.write(script_to_text(dir, translated, strip_clt, only_voiced, line_numbers).encode("UTF-8")) progress.setValue(progress.value() + 1) progress.close() self.last_file = out_file
def on_action_2_triggered(self): """ Slot documentation goes here. """ # TODO: not implemented yet if self.model.rowCount < 1: QtGui.QMessageBox.warning(self,'warning', "Nothing could be export") return fileName = QFileDialog.getSaveFileName(self,self.tr('Save csv'),'',self.tr("*.csv")) if platform.system() == 'Windows': fileName = str(fileName.toUtf8()).encode('gbk') content = '' for j in range(self.model.columnCount()): content += str(self.model.headerData(j, QtCore.Qt.Horizontal).toString().toUtf8())+ ',' for j in range(self.model.columnCount()): content += str(self.model2.headerData(j, QtCore.Qt.Horizontal).toString().toUtf8())+ ',' content = content[:-1] + '\r\n' progressDialog = QProgressDialog(u"正在导出 (%d/%d)" %(0, self.model.rowCount()), u"取消", 0, self.model.rowCount(), self) for i in range(self.model.rowCount()): for j in range(self.model.columnCount()): content += str(self.model.data(self.model.index(i, j)).toString().toUtf8())+ ',' for j in range(self.model2.columnCount()): content += str(self.model2.data(self.model2.index(i, j)).toString().toUtf8())+ ',' content = content[:-1] + '\r\n' if progressDialog.wasCanceled(): return progressDialog.setLabelText (u"正在导出 (%d/%d)" %(i+1, self.model.rowCount())) progressDialog.setValue(i+1) if platform.system() == 'Windows': content = content.decode('utf-8').encode('gbk') f = open(fileName, 'wb') f.write(content) f.close()
def on_btn_save_udf_param_clicked(self): """ Slot documentation goes here. """ msg = u'保存参数并同时更新UDF中建筑负载文件名,确定吗?' reply = self.show_yesno_msgbox(msg) if reply == 0: return fname = self.le_fluent_udf_file.text() if fname == '': msg = u'UDF文件名为空, 请先设置一个有效的UDF文件' self._show_tips(msg, tip_type=1) return # check if file path exists if not os.path.exists(fname): msg = u'UDF文件路径不存在, 请打开一个有效的UDF文件!' self._show_tips(msg, tip_type=1) return # first, get params from widgets params = self.get_udf_param_from_widgets() # read the load file progress_dlg = QProgressDialog(self) progress_dlg.setModal(True) progress_dlg.setMinimumDuration(1) progress_dlg.setWindowTitle(u"处理数据") progress_dlg.setLabelText(u"正在处理建筑负荷数据...") progress_dlg.setCancelButtonText("Cancel") # we don't know how many lines in the load file progress_dlg.setMinimum(1) progress_dlg.setMaximum(10000) max_q = 0.0 min_q = 0.0 line_cnt = 0 with open(params['load_file'], 'r') as rfh: for line in rfh: val = float(line) if val > max_q: max_q = val if val < min_q: min_q = val progress_dlg.setValue(line_cnt) if progress_dlg.wasCanceled(): return line_cnt += 1 # set the max value to terminate the progress dialog if line_cnt < 10000: QThread.sleep(1) progress_dlg.setValue(10000) params['copc_max_q'] = max_q params['coph_max_q'] = min_q # modify the udf file result = self.udf_model.write_params(params, fname) if result == True: msg = u'文件%s更新成功' % fname self._show_tips(msg) else: msg = u'文件更新失败, 请确保%s是有效的UDF文件' % fname self._show_tips(msg, tip_type=1)
def on_actionOpenSession_triggered(self, filename=None): if not filename: filename = QFileDialog.getOpenFileName(self, 'Open Session') if filename: if self.session.messages: args = argv[:] if len(args) > 1: args[1] = filename else: args.append(abspath(str(filename))) try: pid = spawnvp(P_NOWAIT, args[0], args) except (NameError, ): Popen('"%s" "%s" "%s"' % (executable, args[0], args[1])) return if not self.warningOpenTabs(): return dlg = QProgressDialog(self) dlg.setLabelText('Reading session file.') dlg.setCancelButtonText('Abort') dlg.setWindowModality(Qt.WindowModal) dlg.setWindowTitle('Reading...') self.show() processEvents() dlg.show() processEvents() try: loadit = self.session.load(str(filename)) count = loadit.next() last = count - 1 except (StopIteration, ): msg = 'Warning session not loaded from "%s"' % filename dlg.close() else: dlg.setLabelText('Loading session messages.') dlg.setWindowTitle('Loading...') dlg.setMaximum(last) msgid = -1 for msgid in loadit: processEvents() dlg.setValue(msgid) if dlg.wasCanceled(): dlg.close() break if msgid == last: msg = 'Loaded all %s messages from file "%s".' msg %= (count, filename) self.setCurrentSession(filename) else: msg = 'Load aborted; loaded %s messages of %s.' msg %= (msgid+1, count) self.statusBar().showMessage(msg, 5000)
def showAllChartWindows(sg, maximized=False): dlg = QProgressDialog(SimuVis4.Globals.mainWin) dlg.setWindowModality(Qt.WindowModal) dlg.setMaximum(len(sg.charts)) dlg.setAutoClose(True) dlg.setMinimumDuration(0) dlg.setValue(0) i = 1 app = SimuVis4.Globals.application for name, chart in sg.charts.items(): dlg.setLabelText(name) app.processEvents() showChartWindow(chart, maximized) dlg.setValue(i) i += 1 if dlg.wasCanceled(): break
def generate_font(self): progress = QProgressDialog("", QtCore.QString(), 0, 0, self) progress.setWindowModality(Qt.Qt.WindowModal) progress.setWindowTitle("Generating font...") progress.setLabelText("Generating font...") progress.setMinimumDuration(0) progress.setAutoClose(False) # Thread this because it's slow as hell and we don't want to lock up the GUI. thread = threading.Thread(target = self.__generate_font__) thread.start() while thread.isAlive(): thread.join(THREAD_TIMEOUT) # It has to change by some amount or it won't update and the UI will lock up. progress.setValue(progress.value() - 1) progress.close()
def scan_ros_distro(): global main_widget global ROS_PKGS, ROS_MSGS, ROS_SRVS # reset current ROS_MSGS = [] ROS_SRVS = [] # scan with progress shown progress_dialog = QProgressDialog('Scanning ROS Distro', 'Cancel', 0, len(ROS_PKGS), parent=main_widget) progress_dialog.setWindowModality(Qt.WindowModal) count = 0 total = len(ROS_PKGS) for package in ROS_PKGS: if progress_dialog.wasCanceled(): ROS_MSGS = [] ROS_SRVS = [] break progress_dialog.setValue(count) progress_dialog.setLabelText('Scanning ROS Distro\nscanning {0} from {1}: {2}...'.format( count+1, total, package)) if len(rosmsg.list_msgs(package)) > 0: ROS_MSGS.append(package) progress_dialog.setLabelText('Scanning ROS Distro\nscanning {0} from {1}: {2}...\nfound messages...'.format( count+1, total, package)) if len(rosmsg.list_srvs(package)) > 0: progress_dialog.setLabelText('Scanning ROS Distro\nscanning {0} from {1}: {2}...\nfound services...'.format( count+1, total, package)) ROS_SRVS.append(package) count += 1 progress_dialog.setValue(len(ROS_PKGS)) # store settings store_settings() print 'stored {0} msgs and {1} srvs...'.format(len(ROS_MSGS), len(ROS_SRVS))
def doExport(self, model): # print model.rowCount() if model.rowCount() < 1: QMessageBox.warning(self,'warning', "导出内容为空") return fileName = QFileDialog.getSaveFileName(self,self.tr('Save csv'),'',self.tr("*.csv")) if not fileName: return if platform.system() == 'Windows': fileName = str(fileName.toUtf8()).encode('gbk') content = '' for j in range(model.columnCount()): try: content += str(model.headerData(j, QtCore.Qt.Horizontal).toString().toUtf8())+ ',' except: content += str(model.headerData(j, QtCore.Qt.Horizontal).toUtf8())+ ',' # for j in range(model.columnCount()): # content += str(model2.headerData(j, QtCore.Qt.Horizontal).toString().toUtf8())+ ',' content = content[:-1] + '\r\n' progressDialog = QProgressDialog(u"正在导出 (%d/%d)" %(0, model.rowCount()), u"取消", 0, model.rowCount(), self) for i in range(model.rowCount()): for j in range(model.columnCount()): try: content += str(model.data(model.index(i, j)).toString().toUtf8())+ ',' except: content += str(model.data(model.index(i, j)).toUtf8())+ ',' # for j in range(model2.columnCount()): # content += str(model2.data(model2.index(i, j)).toString().toUtf8())+ ',' content = content[:-1] + '\r\n' if progressDialog.wasCanceled(): return progressDialog.setLabelText (u"正在导出 (%d/%d)" %(i+1, model.rowCount())) progressDialog.setValue(i+1) if platform.system() == 'Windows': content = content.decode('utf-8').encode('gbk') f = open(fileName, 'wb') f.write(content) f.close()
class Progress: def __init__(self, parent): self.parent = parent self.dialog = None self.application = None def started(self, title): self.dialog = QProgressDialog(title, "Stop", 0, 0, self.parent) self.dialog.setCancelButton(None) self.dialog.show() QCoreApplication.processEvents(QEventLoop.AllEvents) def progress(self, msg, percent): self.dialog.setLabelText(msg) # otherwise KProgressDialog automatically closes itself, sigh if percent < 100: self.dialog.setValue(percent) QCoreApplication.processEvents(QEventLoop.AllEvents) def finished(self): if self.dialog: self.dialog.done(0) self.dialog = None
def saveAllChartImages(sg): if SimuVis4.Globals.config.getboolean('matplot', 'set_default_backend'): QMessageBox.warning(SimuVis4.Globals.mainWin, QCoreApplication.translate('DataStorageBrowser', 'Configuration error'), QCoreApplication.translate('DataStorageBrowser', """The option "set_default_backend" in section "matplot" is enabled. The requested action will not work with this setting. Change this setting and restart the application to make this work!""")) return f = QFileDialog.getExistingDirectory(SimuVis4.Globals.mainWin, QCoreApplication.translate('DataStorageBrowser', "Select a folder (existing image files will be overwritten!)"), SimuVis4.Globals.defaultFolder) if f.isEmpty(): return folder = unicode(f) SimuVis4.Globals.defaultFolder = folder dlg = QProgressDialog(SimuVis4.Globals.mainWin) dlg.setWindowModality(Qt.WindowModal) dlg.setMaximum(len(sg.charts)) dlg.setAutoClose(True) dlg.setMinimumDuration(0) dlg.setValue(0) i = 1 app = SimuVis4.Globals.application for name, chart in sg.charts.items(): fileName = "%s.png" % name dlg.setLabelText(fileName) app.processEvents() #chart.setTimeslice(1*86400) chart(starttime=(sg.stop-chart.standardSlice), filename=os.path.join(folder, fileName)) dlg.setValue(i) i += 1 if dlg.wasCanceled(): break
class specread: def __init__(self, specfile, startLineNum=0, endScanNum=0, beamline='APS-15IDC', det='CCD', data={}, par={}): self.Data = data self.Par = par self.specfile = specfile if beamline == 'APS-15IDC': self.APS_15IDC(startLineNum=startLineNum, endScanNum=endScanNum, det=det) if beamline == 'APS-9IDC': self.APS_9IDC(startLineNum=startLineNum, endScanNum=endScanNum, det=det) def updateProgress(self): self.progressDialog.setValue(self.progressDialog.value() + 1) def APS_15IDC(self, startLineNum=0, endScanNum=0, det='CCD'): """ Function to read a complete spec File collected at APS 15IDC """ self.progressDialog = QProgressDialog('Reading scans form SPEC File:', 'Abort', 0, 100) self.progressDialog.setWindowModality(Qt.WindowModal) self.progressDialog.setWindowTitle('Wait') self.progressDialog.setAutoClose(True) self.progressDialog.setAutoReset(True) self.progressDialog.setMinimum(1) self.Data['YCol'] = 'Apex2' self.Data['NCol'] = 'Monc' fid = open(self.specfile) fdata = fid.readlines() self.SpecFileFull = fdata fid.close() if fdata[0][:2] != '#F': self.Data['NumOfScans'] = 0 self.Data['Message'] = 'The file is not a valid specfile!!' print 'Error:: The file is not a valid specfile!!' else: startScanLineNums = [ i for i in range(startLineNum, len(fdata)) if fdata[i][:2] == '#S' ] self.progressDialog.setMaximum(len(startScanLineNums)) self.progressDialog.show() if startLineNum > 0: startScanLineNums = sorted(startScanLineNums) numOfScans = len(startScanLineNums) scanLines = [fdata[i] for i in startScanLineNums] if startLineNum == 0: tmp = 0 self.Data['NumOfScans'] = 0 #numOfScans self.Data['ScanNums'] = [] offset = 0 # self.Data['ScanLines']=[]#scanLines # self.Data['StartScanLineNums']=[]#startScanLineNums else: tmp = self.Data['NumOfScans'] self.Data[ 'NumOfScans'] = self.Data['NumOfScans'] - 1 #+numOfScans offset = 1 # self.Data['ScanLines']=self.Data['ScanLines'][:-1]#+scanLines[1:] # self.Data['StartScanLineNums']=self.Data['StartScanLineNums'][:-1]#+startScanLineNums if int(scanLines[-1].split() [1]) != len(startScanLineNums) + endScanNum - offset: print len( startScanLineNums), scanLines[-1].split()[1], endScanNum self.Data['Error'] = True self.Data['Message'] = 'There are identical scans in the file' else: self.Data['Error'] = False for i in range(numOfScans): start = startScanLineNums[i] + 1 line = fdata[start] num = int(fdata[startScanLineNums[i]].split()[1]) i = i + tmp self.Data[num] = {} self.Par[num] = {} if fdata[start - 1].split()[2] == 'getandsave_mca': self.Par[num]['Detector'] = 'Vortex' self.Data[num]['ScanVar'] = 'Empty' else: self.Par[num]['Detector'] = 'Monitor' tmpdata = [] while line[:2] != '\n' and line[:2] != '#C': if line[:2] == '#P': parName = line[4:].split() start = start + 1 parValue = map(eval, fdata[start][1:].split()) for j in range(len(parName)): self.Par[num][parName[j]] = parValue[j] if line[:2] == '#W': tmppar = line[2:].split() self.Par[num]['Wavelength'] = eval(tmppar[1]) if line[:3] == '#G0': self.Par[num]['g_l1'] = float(line[4:].split()[5]) self.Par[num]['g_l2'] = float(line[4:].split()[6]) self.Par[num]['g_l3'] = float(line[4:].split()[7]) if line[:2] == '#A': tmppar = line[2:].split() self.Par[num]['Absorber'] = eval(tmppar[1]) if line[:2] == '#Q': tmppar = line[2:].split() self.Par[num]['Q'] = map(eval, tmppar) if line[:2] == '#V': self.Par[num]['Detector'] = 'Vortex' if line[:3] == '#B0': tmppar = line[3:].split('.') self.Par[num]['ImageNumber'] = len( line[3:].split('_')[-1].split('.')[0]) if tmppar[1] == 'tif\n': self.Par[num]['Detector'] = 'Pilatus' elif tmppar[1] == 'sfrm\n': self.Par[num]['Detector'] = 'Bruker' if line[:3] == '#B1': try: tmppar = map(eval, line[3:].split()) except: tmppar = map(eval, line[3:].split()[:-1]) self.Par[num]['DBPos'] = tmppar[:2] self.Par[num]['S2D_Dist'] = tmppar[2] self.Par[num]['S7D_Dist'] = tmppar[3] if line[:3] == '#B2': tmppar = map(eval, line[3:].split()) self.Par[num]['DBPos'] = tmppar[:2] self.Par[num]['S2D_Dist'] = tmppar[2] self.Par[num]['S7D_Dist'] = tmppar[3] if line[:2] == '#L': scanVar = line[3:-1].split() self.Data[num]['ScanVar'] = scanVar if line[0] != '#': try: tmpdata.append(map(eval, line.split())) except: self.Data[num][ 'Message'] = 'Something wrong with Scan Number %d', num, '.Please check the the scan in the specfile.' print 'Something wrong with Scan Number %d', num start = start + 1 try: line = fdata[start] except: break if self.Data[num]['ScanVar'] != 'Empty': for j in range(len(scanVar)): try: self.Data[num][scanVar[j]] = np.array( tmpdata, dtype='float')[:, j] except: self.Data[num][scanVar[j]] = None if len(self.Par[num]) == 1: self.Par[num]['Message'] = 'No parameters!!' self.progressDialog.setLabelText('Reading Scan #' + str(num)) self.updateProgress() self.Data['NumOfScans'] = num # self.Data['ScanLines']=self.Data['ScanLines']+[scanLines[num-tmp]] self.Data[num]['ScanLine'] = fdata[startScanLineNums[i - tmp]] self.Data[num]['StartScanLineNum'] = startScanLineNums[i - tmp] self.endLineNum = startScanLineNums[i - tmp] self.Data['ScanNums'].append(num) if self.progressDialog.wasCanceled() == True: break self.progressDialog.hide() def APS_9IDC(self, startLineNum=0, endScanNum=0, det='CCD'): """ Function to read a complete spec File collected at APS 9IDC """ self.progressDialog = QProgressDialog('Reading scans form SPEC File:', 'Abort', 0, 100) self.progressDialog.setWindowModality(Qt.WindowModal) self.progressDialog.setWindowTitle('Wait') self.progressDialog.setAutoClose(True) self.progressDialog.setAutoReset(True) self.progressDialog.setMinimum(1) self.Data['YCol'] = 'Bicron1' self.Data['NCol'] = 'i2' fid = open(self.specfile) fdata = fid.readlines() self.SpecFileFull = fdata fid.close() if fdata[0][:2] != '#F': self.Data['NumOfScans'] = 0 self.Data['Message'] = 'The file is not a valid specfile!!' print 'Error:: The file is not a valid specfile!!' else: startScanLineNums = [ i for i in range(startLineNum, len(fdata)) if fdata[i][:2] == '#S' ] self.progressDialog.setMaximum(len(startScanLineNums)) self.progressDialog.show() self.endLineNum = startScanLineNums[-1] if startLineNum > 0: startScanLineNums = sorted(startScanLineNums) self.Data['StartScanLineNums'] = startScanLineNums numOfScans = len(self.Data['StartScanLineNums']) scanLines = [fdata[i] for i in startScanLineNums] if startLineNum == 0: tmp = 0 self.Data['NumOfScans'] = 0 #numOfScans self.Data['ScanLines'] = [] #scanLines self.Data['StartScanLineNums'] = [] #startScanLineNums self.Par['ParName'] = [] for i in range(startScanLineNums[0]): line = fdata[i].split() if fdata[i][:2] == '#O': self.Par['ParName'] = self.Par['ParName'] + line[1:] else: tmp = self.Data['NumOfScans'] self.Data[ 'NumOfScans'] = self.Data['NumOfScans'] - 1 #+numOfScans self.Data['ScanLines'] = self.Data[ 'ScanLines'][:-1] #+scanLines[1:] self.Data['StartScanLineNums'] = self.Data[ 'StartScanLineNums'][:-1] #+startScanLineNums for i in range(numOfScans): start = startScanLineNums[i] + 1 line = fdata[start] i = i + tmp self.Data[i] = {} self.Par[i] = {} if fdata[start - 1].split()[2] == 'getandsave_mca' or fdata[ start - 1].split()[2] == 'MCAscanpt': self.Par[i]['Mca'] = 1 self.Data[i]['ScanVar'] = 'Empty' else: self.Par[i]['Mca'] = 0 self.Par[i]['CCD'] = 0 tmpdata = [] pstart = 0 while line[:2] != '\n' and line[:2] != '#C': if line[:2] == '#P': parValue = map(eval, fdata[start].split()[1:]) for j in range(len(parValue)): self.Par[i][self.Par['ParName'] [pstart]] = parValue[j] pstart = pstart + 1 if line[:2] == '#Q': tmppar = line[2:].split() self.Par[i]['Q'] = map(eval, tmppar) if line[:2] == '#L': scanVar = line[3:-1].split() self.Data[i]['ScanVar'] = scanVar if line[0] != '#': tmpdata.append(map(eval, line.split())) start = start + 1 line = fdata[start] for j in range(len(scanVar)): try: self.Data[i][scanVar[j]] = np.array(tmpdata)[:, j] except: self.Data[i][scanVar[j]] = None if len(self.Par[i]) == 1: self.Par[i]['Message'] = 'No parameters!!' self.progressDialog.setLabelText( 'Reading scans form SPEC File: ' + str(i + 1)) self.updateProgress() self.Data['NumOfScans'] = i self.Data['ScanLines'] = self.Data['ScanLines'] + [ scanLines[i - tmp] ] self.Data['StartScanLineNums'] = self.Data[ 'StartScanLineNums'] + [startScanLineNums[i - tmp]] self.endLineNum = startScanLineNums[i - tmp] if self.progressDialog.wasCanceled() == True: break self.progressDialog.hide()
class ImportDialog(QDialog, Ui_ImportDialogBase): def __init__(self, theParent=None, theIface=None): """Constructor for import dialog. Args: * theParent - Optional widget to use as parent * theIface - an instance of QGisInterface Returns: not applicable Raises: no exceptions explicitly raised """ QDialog.__init__(self, theParent) self.parent = theParent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = theIface self.url = "http://osm.linfiniti.com/buildings-shp" ## region coordinate: (latitude, longtitude, zoom_level) self.regionExtent = { '0': [18.87685, -71.493, 6], # haiti '1': [-2.5436300, 116.8887, 3], # indonesia '2': [1.22449, 15.40999, 2], # africa '3': [34.05, 56.55, 3], # middle east '4': [12.98855, 121.7166, 4], # philipine } # creating progress dialog for download self.progressDialog = QProgressDialog(self) self.progressDialog.setAutoClose(False) myTitle = self.tr("InaSAFE OpenStreetMap Downloader") self.progressDialog.setWindowTitle(myTitle) ## set map parameter based on placeholder self.map widget theMap = InasafeLightMaps(self.gbxMap) theMap.setGeometry(self.map.geometry()) theMap.setSizePolicy(self.map.sizePolicy()) self.map = theMap self.nam = QNetworkAccessManager(self) self.setupOptions() self.restoreState() self.cbxRegion.currentIndexChanged.connect(self.regionChanged) self.map.m_normalMap.updated.connect(self.updateExtent) def regionChanged(self, theIndex): """ Slot that called when region combo box changed. Params: theIndex - index of combo box """ myRegionIndex = str(self.cbxRegion.itemData(theIndex).toString()) myCenter = self.regionExtent[myRegionIndex] self.map.setCenter(myCenter[0], myCenter[1], myCenter[2]) # pylint: disable=W0613 def resizeEvent(self, theEvent): """ Function that called when resize event occurred. Params: theEvent - QEvent instance. Not used. """ self.map.resize(self.gbxMap.width() - 30, self.gbxMap.height() - 30) # pylint: disable=W0613 def setupOptions(self): """ Set the content of combo box for region and preset """ self.cbxRegion.insertItem(0, 'Indonesia', 1) self.cbxRegion.insertItem(1, 'Africa', 2) self.cbxRegion.insertItem(2, 'Philippines', 4) self.cbxRegion.insertItem(3, 'Central Asia/Middle East', 3) self.cbxRegion.insertItem(4, 'Haiti', 0) self.cbxPreset.insertItem(0, self.tr('Buildings'), 'building') self.cbxPreset.insertItem(0, self.tr('Highway'), 'highway') def restoreState(self): """ Read last state of GUI from configuration file """ mySetting = QSettings() myRegion = mySetting.value('region').toInt() if myRegion[1] is True: self.cbxRegion.setCurrentIndex(myRegion[0]) myPreset = mySetting.value('preset').toInt() if myPreset[1] is True: self.cbxPreset.setCurrentIndex(myPreset[0]) self.outDir.setText(mySetting.value('directory').toString()) myZoomLevel = mySetting.value('zoom_level').toInt() myLatitude = mySetting.value('latitude').toDouble() myLongitude = mySetting.value('longitude').toDouble() if myZoomLevel[1] is True: self.map.setCenter(myLatitude[0], myLongitude[0], myZoomLevel[0]) else: # just set to indonesia extent myCenter = self.regionExtent['1'] self.map.setCenter(myCenter[0], myCenter[1], myCenter[2]) def saveState(self): """ Store current state of GUI to configuration file """ mySetting = QSettings() mySetting.setValue('region', self.cbxRegion.currentIndex()) mySetting.setValue('preset', self.cbxPreset.currentIndex()) mySetting.setValue('directory', self.outDir.text()) mySetting.setValue('zoom_level', self.map.getZoomLevel()) myCenter = self.map.getCenter() mySetting.setValue('latitude', myCenter[0]) mySetting.setValue('longitude', myCenter[1]) def updateExtent(self): """ Update extent value in GUI based from value in map widget""" myExtent = self.map.getExtent() self.minLongitude.setText(str(myExtent[1])) self.minLatitude.setText(str(myExtent[0])) self.maxLongitude.setText(str(myExtent[3])) self.maxLatitude.setText(str(myExtent[2])) @pyqtSignature('') # prevents actions being handled twice def on_pBtnDir_clicked(self): """ Show a dialog to choose directory """ self.outDir.setText(QFileDialog.getExistingDirectory( self, self.tr("Select Directory"))) def accept(self): """ Do import process """ try: self.saveState() self.ensureDirExist() self.doImport() self.loadShapeFile() self.done(QDialog.Accepted) except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as myEx: QMessageBox.warning( self, self.tr("InaSAFE OpenStreetMap Downloader Error"), str(myEx)) self.progressDialog.cancel() def ensureDirExist(self): """ Ensure directory path entered in dialog exist. When the path is not exist, this function will ask the user if he want to create it or not. Raises: CanceledImportDialogError - when user choose 'No' in question dialog for creating directory. """ myDir = str(self.outDir.text()) if os.path.exists(myDir): return myTitle = self.tr("Directory %1 not exist").arg(myDir) myQuestion = self.tr( "Directory %1 not exist. Are you want to create it?" ).arg(myDir) myAnswer = QMessageBox.question( self, myTitle, myQuestion, QMessageBox.Yes | QMessageBox.No) if myAnswer == QMessageBox.Yes: os.makedirs(myDir) else: raise CanceledImportDialogError() def doImport(self): """ Import shape files from Linfinti. Raises: * ImportDialogError - when network error occurred * CanceledImportDialogError - when user press cancel button """ ## preparing necessary data myMinLng = str(self.minLongitude.text()) myMinLat = str(self.minLatitude.text()) myMaxLng = str(self.maxLongitude.text()) myMaxLat = str(self.maxLatitude.text()) myCurrentIndex = self.cbxPreset.currentIndex() myType = str(self.cbxPreset.itemData(myCurrentIndex).toString()) myCoordinate = "{myMinLng},{myMinLat},{myMaxLng},{myMaxLat}".format( myMinLng=myMinLng, myMinLat=myMinLat, myMaxLng=myMaxLng, myMaxLat=myMaxLat ) myShapeUrl = "{url}?bbox={myCoordinate}&obj={type}".format( url=self.url, myCoordinate=myCoordinate, type=myType ) myFilePath = tempfile.mktemp('.shp.zip') # download and extract it self.downloadShapeFile(myShapeUrl, myFilePath) self.extractZip(myFilePath, str(self.outDir.text())) self.progressDialog.done(QDialog.Accepted) def downloadShapeFile(self, theUrl, theOutput): """ Download shape file from theUrl and write to theOutput. Params: * theUrl - URL of shape file * theOutput - path of output file Raises: * ImportDialogError - when network error occurred """ self.progressDialog.show() self.progressDialog.setMaximum(100) self.progressDialog.setValue(0) # myLabelText = "Begin downloading shapefile from " \ # + "%1 ..." # self.progressDialog.setLabelText(self.tr(myLabelText).arg(theUrl)) myLabelText = self.tr("Begin downloading shapefile") self.progressDialog.setLabelText(myLabelText) myResult = httpDownload(self.nam, theUrl, theOutput, self.progressDialog) if myResult is not True: _, myErrorMessage = myResult raise ImportDialogError(myErrorMessage) def extractZip(self, thePath, theOutDir): """ Extract all content of zip file from thePath to theOutDir. Args: * thePath - the path of zip file * theOutDir - output directory Raises: IOError - when cannot open thePath or theOutDir is not exist. """ import zipfile ## extract all files... myHandle = open(thePath, 'rb') myZip = zipfile.ZipFile(myHandle) for myName in myZip.namelist(): myOutPath = os.path.join(theOutDir, myName) myOutFile = open(myOutPath, 'wb') myOutFile.write(myZip.read(myName)) myOutFile.close() myHandle.close() def loadShapeFile(self): """ Load downloaded shape file to QGIS Main Window. Raises: ImportDialogError - when buildings.shp not exist """ myDir = str(self.outDir.text()) myPath = os.path.join(myDir, 'buildings.shp') if not os.path.exists(myPath): myMessage = self.tr( "%s don't exist. The server don't have buildings data." ) raise ImportDialogError(myMessage) self.iface.addVectorLayer(myPath, 'buildings', 'ogr')
def setup_workspace(self): data0 = os.path.join(self.iso_dir, DATA0_CPK) self.generate_directories() progress = QProgressDialog("", QtCore.QString(), 0, 11000, self) progress.setWindowTitle("Setting up workspace...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setMinimumDuration(0) progress.setValue(0) progress.setAutoClose(False) progress.setAutoReset(False) progress.setLabelText("Creating directories...") # Do the easy stuff first. if not os.path.isdir(self.changes_dir): os.makedirs(self.changes_dir) progress.setValue(progress.value() + 1) if not os.path.isdir(self.backup_dir): os.makedirs(self.backup_dir) progress.setValue(progress.value() + 1) thread_fns = [{"target": extract_cpk, "kwargs": {"filename": data0, "out_dir": self.data0_dir}}] # Going to capture stdout because I don't feel like # rewriting the extract functions to play nice with GUI. stdout = sys.stdout sys.stdout = cStringIO.StringIO() for thread_fn in thread_fns: thread = threading.Thread(**thread_fn) thread.start() while thread.isAlive(): thread.join(THREAD_TIMEOUT) output = [line for line in sys.stdout.getvalue().split("\n") if len(line) > 0] progress.setValue(progress.value() + len(output)) if len(output) > 0: progress.setLabelText("Extracting %s..." % output[-1]) sys.stdout = cStringIO.StringIO() sys.stdout = stdout # Give us an ISO directory for the editor to place modified files in. progress.setLabelText("Copying ISO files...") # ISO directory needs to not exist for copytree. if os.path.isdir(self.edited_iso_dir): shutil.rmtree(self.edited_iso_dir) # One more thing we want threaded so it doesn't lock up the GUI. thread = threading.Thread(target=shutil.copytree, kwargs={"src": self.iso_dir, "dst": self.edited_iso_dir}) thread.start() while thread.isAlive(): thread.join(THREAD_TIMEOUT) progress.setLabelText("Copying ISO files...") # It has to increase by some amount or it won't update and the UI will lock up. progress.setValue(progress.value() + 1) # shutil.copytree(self.iso_dir, self.edited_iso_dir) progress.setValue(progress.value() + 1) # Files we want to make blank, because they're unnecessary. blank_files = [ os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "DATA.BIN"), os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "EBOOT.BIN"), os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "PARAM.SFO"), ] for blank in blank_files: with open(blank, "wb") as f: pass # Copy the decrypted EBOOT into the ISO folder and apply our hacks to it. progress.setLabelText("Hacking EBOOT...") progress.setValue(progress.value() + 1) hacked_eboot = BitStream(filename=self.eboot_path) hacked_eboot = apply_eboot_patches(hacked_eboot) with open(os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN"), "wb") as f: hacked_eboot.tofile(f) # shutil.copy(self.eboot_path, os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN")) progress.setLabelText("Extracting editor data...") progress.setValue(progress.value() + 1) # Extract the editor data. editor_data = zipfile.ZipFile("data/editor_data.zip", "r") editor_data.extractall(self.editor_data_dir) editor_data.close() progress.setValue(progress.maximum()) progress.close() self.ui.grpStep4.setEnabled(False) self.ui.grpStep5.setEnabled(True)
def copy_gfx(self): gfx_dir = os.path.join(self.editor_data_dir, "gfx") if os.path.isdir(gfx_dir): shutil.rmtree(gfx_dir) os.makedirs(gfx_dir) progress = QProgressDialog("", "Abort", 0, 0, self) progress.setWindowTitle("Copying GFX...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setMinimumDuration(0) progress.setValue(0) progress.setAutoClose(False) progress.setLabelText("Setting up GFX dir.") progress.setMaximum(5) progress.setValue(0) # Extract the images we can't just take directly from the game's data. gfx_bin = zipfile.ZipFile("data/gfx_base.zip", "r") progress.setValue(1) progress.setValue(2) gfx_bin.extractall(gfx_dir) progress.setValue(5) gfx_bin.close() # We can mostly loop this. gfx_data = [ ("ammo", "kotodama_icn_???.gim"), ("bgd", "bgd_???.gim"), ("cutin", "cutin_icn_???.gim"), ("events", "gallery_icn_???.gim"), ("movies", "bin_movie_gallery_l.pak/0000/000[1789].gim"), ("movies", "bin_movie_gallery_l.pak/0000/00[123]?.gim"), ("movies", "gallery_ico_m_none.gim"), ("movies", "gallery_thumbnail_m_???.gim"), ("nametags", "tex_system.pak/00[12]?.gim"), ("nametags", "tex_system.pak/003[0123456].gim"), ("presents", "present_icn_???.gim"), ("sprites", "bustup_??_??.gim"), ("sprites", "stand_??_??.gmo"), ] for (dir, file_glob) in gfx_data: out_dir = os.path.join(gfx_dir, dir) files = glob.glob(os.path.join(self.data0_dir, file_glob)) progress.setLabelText("Copying %s." % dir) progress.setMaximum(len(files)) progress.setValue(0) if not os.path.isdir(out_dir): os.makedirs(out_dir) for i, image in enumerate(files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return src = image dest = os.path.join(out_dir, os.path.basename(src)) shutil.copy(src, dest) progress.setValue(len(files)) progress.setLabelText("Copying font.") progress.setMaximum(4) progress.setValue(0) # The font we have to get from umdimage2. font_dir = os.path.join(gfx_dir, "font") if not os.path.isdir(font_dir): os.makedirs(font_dir) progress.setValue(1) # And convert to PNG with an alpha channel so our editor can use it. font1 = font_bmp_to_alpha(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0000.bmp")) progress.setValue(2) font2 = font_bmp_to_alpha(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0002.bmp")) progress.setValue(3) font1.save(os.path.join(font_dir, "Font01.png")) font2.save(os.path.join(font_dir, "Font02.png")) shutil.copy( os.path.join(self.data01_dir, "jp", "font", "font.pak", "0001.font"), os.path.join(font_dir, "Font01.font") ) shutil.copy( os.path.join(self.data01_dir, "jp", "font", "font.pak", "0003.font"), os.path.join(font_dir, "Font02.font") ) progress.setValue(4) # And then the flash files. This'll be fun. flash_dir = os.path.join(gfx_dir, "flash") if not os.path.isdir(flash_dir): os.makedirs(flash_dir) # Because there's so many in so many different places, I just stored a list # of the flash files we need in the gfx_base archive. So let's load that. with open(os.path.join(gfx_dir, "fla.txt"), "rb") as fla: fla_list = fla.readlines() progress.setLabelText("Copying flash.") progress.setMaximum(len(fla_list)) progress.setValue(0) for i, flash in enumerate(fla_list): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return flash = flash.strip() fla_name = flash[:7] # fla_### src = os.path.join(self.data01_dir, "all", "flash", flash) dest = os.path.join(flash_dir, "%s.gim" % fla_name) shutil.copy(src, dest) progress.setValue(len(fla_list)) # We have a couple sets of files that aren't named the way we want them to # be, just because of how they're stored in umdimage. progress.setLabelText("Renaming files.") to_rename = [("movies", "movie_%03d.gim", range(32)), ("nametags", "%02d.gim", range(23) + [24, 25, 30, 31])] for (folder, pattern, nums) in to_rename: folder = os.path.join(gfx_dir, folder) files = glob.glob(os.path.join(folder, "*.gim")) progress.setMaximum(len(files)) progress.setValue(0) for i, image in enumerate(files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return src = image dest = os.path.join(folder, pattern % nums[i]) if os.path.isfile(dest): os.remove(dest) shutil.move(src, dest) sprite_dir = os.path.join(gfx_dir, "sprites") gmo_files = glob.glob(os.path.join(sprite_dir, "*.gmo")) progress.setLabelText("Extracting GMO files.") progress.setValue(0) progress.setMaximum(len(gmo_files)) for i, gmo_file in enumerate(gmo_files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return name, ext = os.path.splitext(os.path.basename(gmo_file)) gim_file = os.path.join(sprite_dir, name + ".gim") gmo = GmoFile(filename=gmo_file) # Once we've loaded it, we're all done with it, so make it go away. os.remove(gmo_file) if gmo.gim_count() == 0: continue gim = gmo.get_gim(0) with open(gim_file, "wb") as f: gim.tofile(f) if self.ui.chkGimToPng.isChecked(): gim_files = glob.glob(os.path.join(gfx_dir, "*", "*.gim")) progress.setLabelText("Converting GIM to PNG.") progress.setValue(0) progress.setMaximum(len(gim_files)) converter = GimConverter() for i, gim_file in enumerate(gim_files): progress.setValue(i) if progress.wasCanceled(): return converter.gim_to_png(gim_file) os.remove(gim_file) progress.close() self.gfx_dir = gfx_dir self.ui.grpStep5.setEnabled(False) self.ui.grpStep6.setEnabled(True)
class OsmDownloader(QDialog, Ui_OsmDownloaderBase): """Downloader for OSM data.""" def __init__(self, parent=None, iface=None): """Constructor for import dialog. :param parent: Optional widget to use as parent :type parent: QWidget :param iface: An instance of QGisInterface :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = iface self.buildings_url = "http://osm.linfiniti.com/buildings-shp" self.roads_url = "http://osm.linfiniti.com/roads-shp" self.help_context = 'openstreetmap_downloader' # creating progress dialog for download self.progress_dialog = QProgressDialog(self) self.progress_dialog.setAutoClose(False) title = self.tr("InaSAFE OpenStreetMap Downloader") self.progress_dialog.setWindowTitle(title) # Set up context help help_button = self.button_box.button(QtGui.QDialogButtonBox.Help) help_button.clicked.connect(self.show_help) self.show_info() # set up the validator for the file name prefix expression = QRegExp('^[A-Za-z0-9-_]*$') validator = QRegExpValidator(expression) self.filename_prefix.setValidator(validator) # Set Proxy in webpage proxy = get_proxy() self.network_manager = QNetworkAccessManager(self) if not proxy is None: self.network_manager.setProxy(proxy) self.restore_state() self.update_extent() def show_info(self): """Show usage info to the user.""" # Read the header and footer html snippets header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE) body = self.tr( 'This tool will fetch building (\'structure\') or road (' '\'highway\') data from the OpenStreetMap project for you. ' 'The downloaded data will have InaSAFE keywords defined and a ' 'default QGIS style applied. To use this tool effectively:' ) tips = m.BulletedList() tips.add(self.tr( 'Your current extent will be used to determine the area for which ' 'you want data to be retrieved. You can adjust it manually using ' 'the bounding box options below.')) tips.add(self.tr( 'Check the output directory is correct. Note that the saved ' 'dataset will be called either roads.shp or buildings.shp (and ' 'associated files).' )) tips.add(self.tr( 'By default simple file names will be used (e.g. roads.shp, ' 'buildings.shp). If you wish you can specify a prefix to ' 'add in front of this default name. For example using a prefix ' 'of \'padang-\' will cause the downloaded files to be saved as ' '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that ' 'the only allowed prefix characters are A-Z, a-z, 0-9 and the ' 'characters \'-\' and \'_\'. You can leave this blank if you ' 'prefer.' )) tips.add(self.tr( 'If a dataset already exists in the output directory it will be ' 'overwritten.' )) tips.add(self.tr( 'This tool requires a working internet connection and fetching ' 'buildings or roads will consume your bandwidth.')) tips.add(m.Link( 'http://www.openstreetmap.org/copyright', text=self.tr( 'Downloaded data is copyright OpenStreetMap contributors' ' (click for more info).') )) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.web_view.setHtml(string) def restore_state(self): """ Read last state of GUI from configuration file.""" settings = QSettings() try: last_path = settings.value('directory', type=str) except TypeError: last_path = '' self.output_directory.setText(last_path) def save_state(self): """ Store current state of GUI to configuration file """ settings = QSettings() settings.setValue('directory', self.output_directory.text()) def show_help(self): """Load the help text for the dialog.""" show_context_help(self.help_context) def update_extent(self): """ Update extent value in GUI based from value in map.""" # Get the extent as [xmin, ymin, xmax, ymax] extent = viewport_geo_array(self.iface.mapCanvas()) self.min_longitude.setText(str(extent[0])) self.min_latitude.setText(str(extent[1])) self.max_longitude.setText(str(extent[2])) self.max_latitude.setText(str(extent[3])) @pyqtSignature('') # prevents actions being handled twice def on_directory_button_clicked(self): """ Show a dialog to choose directory """ # noinspection PyCallByClass,PyTypeChecker self.output_directory.setText(QFileDialog.getExistingDirectory( self, self.tr("Select download directory"))) def accept(self): """Do osm download and display it in QGIS.""" index = self.feature_type.currentIndex() if index == 0: feature_types = ['buildings', 'roads'] elif index == 1: feature_types = ['buildings'] else: feature_types = ['roads'] try: self.save_state() self.require_directory() for feature_type in feature_types: self.download(feature_type) self.load_shapefile(feature_type) self.done(QDialog.Accepted) except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as myEx: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, self.tr("InaSAFE OpenStreetMap downloader error"), str(myEx)) self.progress_dialog.cancel() def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ path = str(self.output_directory.text()) if os.path.exists(path): return title = self.tr("Directory %s not exist") % path question = self.tr( "Directory %s not exist. Do you want to create it?" ) % path # noinspection PyCallByClass,PyTypeChecker answer = QMessageBox.question( self, title, question, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: if len(path) != 0: os.makedirs(path) else: # noinspection PyCallByClass,PyTypeChecker, PyArgumentList QMessageBox.warning( self, self.tr('InaSAFE error'), self.tr('Output directory can not be empty.')) raise CanceledImportDialogError() else: raise CanceledImportDialogError() def download(self, feature_type): """Download shapefiles from Linfinti server. :param feature_type: What kind of features should be downloaded. Currently 'buildings' or 'roads' are supported. :type feature_type: str :raises: ImportDialogError, CanceledImportDialogError """ ## preparing necessary data min_longitude = str(self.min_longitude.text()) min_latitude = str(self.min_latitude.text()) max_longitude = str(self.max_longitude.text()) max_latitude = str(self.max_latitude.text()) box = ( '{min_longitude},{min_latitude},{max_longitude},' '{max_latitude}').format( min_longitude=min_longitude, min_latitude=min_latitude, max_longitude=max_longitude, max_latitude=max_latitude ) output_prefix = self.filename_prefix.text() if feature_type == 'buildings': url = "{url}?bbox={box}&qgis_version=2".format( url=self.buildings_url, box=box) else: url = "{url}?bbox={box}&qgis_version=2".format( url=self.roads_url, box=box) if output_prefix is not None: url += '&output_prefix=%s' % output_prefix path = tempfile.mktemp('.shp.zip') # download and extract it self.fetch_zip(url, path) #print path #print str(self.output_directory.text()) self.extract_zip(path, str(self.output_directory.text())) self.progress_dialog.done(QDialog.Accepted) def fetch_zip(self, url, output_path): """Download zip containing shp file and write to output_path. :param url: URL of the zip bundle. :type url: str :param output_path: Path of output file, :type output_path: str :raises: ImportDialogError - when network error occurred """ LOGGER.debug('Downloading file from URL: %s' % url) LOGGER.debug('Downloading to: %s' % output_path) self.progress_dialog.show() self.progress_dialog.setMaximum(100) self.progress_dialog.setValue(0) # label_text = "Begin downloading shapefile from " \ # + "%s ..." # self.progress_dialog.setLabelText(self.tr(label_text) % (url)) label_text = self.tr("Downloading shapefile") self.progress_dialog.setLabelText(label_text) result = download_url( self.network_manager, url, output_path, self.progress_dialog) if result[0] is not True: _, error_message = result raise ImportDialogError(error_message) @staticmethod def extract_zip(path, output_dir): """Extract all content of a .zip file from path to output_dir. :param path: The path of the .zip file :type path: str :param output_dir: Output directory where the shp will be written to. :type output_dir: str :raises: IOError - when not able to open path or output_dir does not exist. """ import zipfile # extract all files... handle = open(path, 'rb') zip_file = zipfile.ZipFile(handle) for name in zip_file.namelist(): output_path = os.path.join(output_dir, name) output_file = open(output_path, 'wb') output_file.write(zip_file.read(name)) output_file.close() handle.close() def load_shapefile(self, feature_type): """ Load downloaded shape file to QGIS Main Window. :param feature_type: What kind of features should be downloaded. Currently 'buildings' or 'roads' are supported. :type feature_type: str :raises: ImportDialogError - when buildings.shp not exist """ output_prefix = self.filename_prefix.text() path = str(self.output_directory.text()) path = os.path.join(path, '%s%s.shp' % (output_prefix, feature_type)) if not os.path.exists(path): message = self.tr( "%s don't exist. The server doesn't have any data." ) raise ImportDialogError(message) self.iface.addVectorLayer(path, feature_type, 'ogr')
def run(iface, lineLayer, nodeLayer, nodeRadiiExpr="0", lineWidthExpr="1", iterations=100, w_flows=1, w_nodes=0.5, w_antiTorsion=0.8, w_spring=1, w_angRes=3.75, snapThreshold=0, bezierRes=15, alpha=4, beta=4, kShort=0.5, kLong=0.05, Cp=2.5, K=4, C=4, constraintRectAspect=0.5, nodeBuffer=0): """ Runs the algorithm :return: """ # Generate a progress bar progDialog = QProgressDialog() progDialog.setWindowTitle("Progress") progDialog.setLabelText("Generating flowmap from layers") progBar = QProgressBar(progDialog) progBar.setTextVisible(True) progBar.setValue(0) progDialog.setBar(progBar) progDialog.setMinimumWidth(300) progBar.setMaximum(iterations) progDialog.show() # Load the nodes and flows into a data structure fm = FlowMap(w_flows=w_flows, w_nodes=w_nodes, w_antiTorsion=w_antiTorsion, w_spring=w_spring, w_angRes=w_angRes, snapThreshold=snapThreshold, bezierRes=bezierRes, alpha=alpha, beta=beta, kShort=kShort, kLong=kLong, Cp=Cp, K=K, C=C, constraintRectAspect=constraintRectAspect, nodeBuffer=nodeBuffer) fm.getNodesFromLineLayer(lineLayer) if nodeLayer is not None: fm.getNodeRadiiFromLayer(nodeLayer, nodeRadiiExpr) else: fm.nodeRadii = [0 for node in fm.nodes] fm.getLineWidthFromLayer(lineLayer, lineWidthExpr) fm.calculateMapScale() fm.loadFlowLinesFromLayer(lineLayer) # Iterate j = 0 # used in node collision avoidance algorithm progDialog.setLabelText("Iterating") for i in range(iterations): progBar.setValue(i) if progDialog.wasCanceled(): break w = 1 - float(i) / iterations # Calculate flowline-against-flowline forces flowline_forces, Fs = fm.calculateInterFlowLineForces( returnSumOfMagnitudes=True) # Calculate node-against-flowline forces node_forces = fm.calculateNodeToFlowLineForces() # Calculate anti-torsion forces antitorsion_forces = fm.calculateAntiTorsionForces() # Calculate spring forces spring_forces = fm.calculateSpringForces(flowline_forces, Fs) # Calculate angular-resolution-of-flowlines-around-nodes forces angRes_forces = fm.calculateAngleResForces() # Apply forces to arc control points resultantForces = [] for i in range(len(fm.flowlines)): rForce = (flowline_forces[i]*fm.w_flows + node_forces[i]*fm.w_nodes + antitorsion_forces[i]*fm.w_antiTorsion + spring_forces[i]*fm.w_spring)*w +\ (angRes_forces[i]*fm.w_angRes)*(w - w**2) resultantForces.append(rForce) fm.applyForces(resultantForces) # Apply rectangle constraint fm.applyRectangleConstraints() # Reduce intersections of flowlines with a common node fm.reduceFlowLineIntersections() # Move flows off of nodes if i > 0.1 * iterations and j <= 0: N = fm.getFlowLinesOverlappingNodes() j = (iterations - i) / (len(N) + 1) / 2 n = math.ceil(float(len(N)) / (iterations - i - 1)) movedFlows = 0 # number of flows which have been moved. Iterate until this equals n for flowline in N: movedFlows += 1 if fm.moveFlowLineOffNodes(flowline) else 0 if movedFlows >= n: break else: j -= 1 progDialog.setLabelText("Updating Geometry") # Update the geometry of the layer fm.updateGeometryOnLayer(lineLayer) iface.mapCanvas().refresh() # close the dialog progDialog.close()
class AddonManagerDialog(QDialog): def __init__(self, parent=None, **kwargs): super(AddonManagerDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self.addonwidget = AddonManagerWidget() self.addonwidget.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.addonwidget) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) buttons.accepted.connect(self.__accepted) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons) self.__progress = QProgressDialog( self, Qt.Sheet, minimum=0, maximum=0, labelText=self.tr("Retrieving package list"), sizeGripEnabled=False, windowTitle="Progress" ) self.__progress.canceled.connect(self.reject) # The installer thread self.__thread = None # The installer object self.__installer = None @Slot(list) def setItems(self, items): self.addonwidget.setItems(items) def progressDialog(self): return self.__progress def done(self, retcode): super(AddonManagerDialog, self).done(retcode) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def closeEvent(self, event): super(AddonManagerDialog, self).closeEvent(event) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def __accepted(self): steps = self.addonwidget.itemState() if steps: # Move all uninstall steps to the front steps = sorted( steps, key=lambda step: 0 if step[0] == Uninstall else 1 ) self.__installer = Installer(steps=steps) self.__thread = QThread(self) self.__thread.start() self.__installer.moveToThread(self.__thread) self.__installer.finished.connect(self.__on_installer_finished) self.__installer.error.connect(self.__on_installer_error) self.__installer.installStatusChanged.connect( self.__progress.setLabelText) self.__progress.show() self.__progress.setLabelText("Installing") self.__installer.start() else: self.accept() def __on_installer_error(self, command, pkg, retcode, output): message_error( "An error occurred while running a subprocess", title="Error", informative_text="{} exited with non zero status.".format(command), details="".join(output), parent=self ) self.reject() def __on_installer_finished(self): message_information( "Please restart the application for changes to take effect.", parent=self) self.accept()
class ImportDialog(QDialog, Ui_ImportDialogBase): def __init__(self, theParent=None, theIface=None): """Constructor for import dialog. Args: * theParent - Optional widget to use as parent * theIface - an instance of QGisInterface Returns: not applicable Raises: no exceptions explicitly raised """ QDialog.__init__(self, theParent) self.parent = theParent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = theIface self.url = "http://osm.linfiniti.com/buildings-shp" ## region coordinate: (latitude, longtitude, zoom_level) self.regionExtent = { '0': [18.87685, -71.493, 6], # haiti '1': [-2.5436300, 116.8887, 3], # indonesia '2': [1.22449, 15.40999, 2], # africa '3': [34.05, 56.55, 3], # middle east '4': [12.98855, 121.7166, 4], # philipine } # creating progress dialog for download self.progressDialog = QProgressDialog(self) self.progressDialog.setAutoClose(False) myTitle = self.tr("InaSAFE OpenStreetMap Downloader") self.progressDialog.setWindowTitle(myTitle) ## set map parameter based on placeholder self.map widget theMap = InasafeLightMaps(self.gbxMap) theMap.setGeometry(self.map.geometry()) theMap.setSizePolicy(self.map.sizePolicy()) self.map = theMap self.nam = QNetworkAccessManager(self) self.setupOptions() self.restoreState() self.cbxRegion.currentIndexChanged.connect(self.regionChanged) self.map.m_normalMap.updated.connect(self.updateExtent) def regionChanged(self, theIndex): """ Slot that called when region combo box changed. Params: theIndex - index of combo box """ myRegionIndex = str(self.cbxRegion.itemData(theIndex).toString()) myCenter = self.regionExtent[myRegionIndex] self.map.setCenter(myCenter[0], myCenter[1], myCenter[2]) # pylint: disable=W0613 def resizeEvent(self, theEvent): """ Function that called when resize event occurred. Params: theEvent - QEvent instance. Not used. """ self.map.resize(self.gbxMap.width() - 30, self.gbxMap.height() - 30) # pylint: disable=W0613 def setupOptions(self): """ Set the content of combo box for region and preset """ self.cbxRegion.insertItem(0, 'Indonesia', 1) self.cbxRegion.insertItem(1, 'Africa', 2) self.cbxRegion.insertItem(2, 'Philippines', 4) self.cbxRegion.insertItem(3, 'Central Asia/Middle East', 3) self.cbxRegion.insertItem(4, 'Haiti', 0) self.cbxPreset.insertItem(0, self.tr('Buildings'), 'building') self.cbxPreset.insertItem(0, self.tr('Highway'), 'highway') def restoreState(self): """ Read last state of GUI from configuration file """ mySetting = QSettings() myRegion = mySetting.value('region').toInt() if myRegion[1] is True: self.cbxRegion.setCurrentIndex(myRegion[0]) myPreset = mySetting.value('preset').toInt() if myPreset[1] is True: self.cbxPreset.setCurrentIndex(myPreset[0]) self.outDir.setText(mySetting.value('directory').toString()) myZoomLevel = mySetting.value('zoom_level').toInt() myLatitude = mySetting.value('latitude').toDouble() myLongitude = mySetting.value('longitude').toDouble() if myZoomLevel[1] is True: self.map.setCenter(myLatitude[0], myLongitude[0], myZoomLevel[0]) else: # just set to indonesia extent myCenter = self.regionExtent['1'] self.map.setCenter(myCenter[0], myCenter[1], myCenter[2]) def saveState(self): """ Store current state of GUI to configuration file """ mySetting = QSettings() mySetting.setValue('region', self.cbxRegion.currentIndex()) mySetting.setValue('preset', self.cbxPreset.currentIndex()) mySetting.setValue('directory', self.outDir.text()) mySetting.setValue('zoom_level', self.map.getZoomLevel()) myCenter = self.map.getCenter() mySetting.setValue('latitude', myCenter[0]) mySetting.setValue('longitude', myCenter[1]) def updateExtent(self): """ Update extent value in GUI based from value in map widget""" myExtent = self.map.getExtent() self.minLongitude.setText(str(myExtent[1])) self.minLatitude.setText(str(myExtent[0])) self.maxLongitude.setText(str(myExtent[3])) self.maxLatitude.setText(str(myExtent[2])) @pyqtSignature('') # prevents actions being handled twice def on_pBtnDir_clicked(self): """ Show a dialog to choose directory """ self.outDir.setText( QFileDialog.getExistingDirectory(self, self.tr("Select Directory"))) def accept(self): """ Do import process """ try: self.saveState() self.ensureDirExist() self.doImport() self.loadShapeFile() self.done(QDialog.Accepted) except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as myEx: QMessageBox.warning( self, self.tr("InaSAFE OpenStreetMap Downloader Error"), str(myEx)) self.progressDialog.cancel() def ensureDirExist(self): """ Ensure directory path entered in dialog exist. When the path is not exist, this function will ask the user if he want to create it or not. Raises: CanceledImportDialogError - when user choose 'No' in question dialog for creating directory. """ myDir = str(self.outDir.text()) if os.path.exists(myDir): return myTitle = self.tr("Directory %1 not exist").arg(myDir) myQuestion = self.tr( "Directory %1 not exist. Are you want to create it?").arg(myDir) myAnswer = QMessageBox.question(self, myTitle, myQuestion, QMessageBox.Yes | QMessageBox.No) if myAnswer == QMessageBox.Yes: os.makedirs(myDir) else: raise CanceledImportDialogError() def doImport(self): """ Import shape files from Linfinti. Raises: * ImportDialogError - when network error occurred * CanceledImportDialogError - when user press cancel button """ ## preparing necessary data myMinLng = str(self.minLongitude.text()) myMinLat = str(self.minLatitude.text()) myMaxLng = str(self.maxLongitude.text()) myMaxLat = str(self.maxLatitude.text()) myCurrentIndex = self.cbxPreset.currentIndex() myType = str(self.cbxPreset.itemData(myCurrentIndex).toString()) myCoordinate = "{myMinLng},{myMinLat},{myMaxLng},{myMaxLat}".format( myMinLng=myMinLng, myMinLat=myMinLat, myMaxLng=myMaxLng, myMaxLat=myMaxLat) myShapeUrl = "{url}?bbox={myCoordinate}&obj={type}".format( url=self.url, myCoordinate=myCoordinate, type=myType) myFilePath = tempfile.mktemp('.shp.zip') # download and extract it self.downloadShapeFile(myShapeUrl, myFilePath) self.extractZip(myFilePath, str(self.outDir.text())) self.progressDialog.done(QDialog.Accepted) def downloadShapeFile(self, theUrl, theOutput): """ Download shape file from theUrl and write to theOutput. Params: * theUrl - URL of shape file * theOutput - path of output file Raises: * ImportDialogError - when network error occurred """ self.progressDialog.show() self.progressDialog.setMaximum(100) self.progressDialog.setValue(0) # myLabelText = "Begin downloading shapefile from " \ # + "%1 ..." # self.progressDialog.setLabelText(self.tr(myLabelText).arg(theUrl)) myLabelText = self.tr("Begin downloading shapefile") self.progressDialog.setLabelText(myLabelText) myResult = httpDownload(self.nam, theUrl, theOutput, self.progressDialog) if myResult is not True: _, myErrorMessage = myResult raise ImportDialogError(myErrorMessage) def extractZip(self, thePath, theOutDir): """ Extract all content of zip file from thePath to theOutDir. Args: * thePath - the path of zip file * theOutDir - output directory Raises: IOError - when cannot open thePath or theOutDir is not exist. """ import zipfile ## extract all files... myHandle = open(thePath, 'rb') myZip = zipfile.ZipFile(myHandle) for myName in myZip.namelist(): myOutPath = os.path.join(theOutDir, myName) myOutFile = open(myOutPath, 'wb') myOutFile.write(myZip.read(myName)) myOutFile.close() myHandle.close() def loadShapeFile(self): """ Load downloaded shape file to QGIS Main Window. Raises: ImportDialogError - when buildings.shp not exist """ myDir = str(self.outDir.text()) myPath = os.path.join(myDir, 'buildings.shp') if not os.path.exists(myPath): myMessage = self.tr( "%s don't exist. The server don't have buildings data.") raise ImportDialogError(myMessage) self.iface.addVectorLayer(myPath, 'buildings', 'ogr')
class LodgementWizard(QWizard, Ui_ldg_wzd, MapperMixin): """ Wizard that incorporates lodgement of all information required for a Land Hold Title Scheme """ def __init__(self, parent=None): QWizard.__init__(self, parent) self.setupUi(self) # Equate number of pages in wizard to page IDs self._num_pages = len(self.pageIds()) self._base_win_title = self.windowTitle() # Current profile self.curr_p = current_profile() # Flag for checking if document type has been loaded self._supporting_docs_loaded = False # Entity names self._sch_entity_name = 'Scheme' self._rel_auth_entity_name = 'Relevant_authority' self._rel_auth_chk_entity_name = 'check_lht_relevant_authority' self._rgn_chk_entity_name = 'check_lht_region' self._reg_div_chk_entity_name = 'check_lht_reg_division' self._scheme_doc_type_lookup = 'cb_check_scheme_document_type' self._holders_entity_name = 'Holder' self._workflow_chk_entity_name = 'check_lht_workflow' self._approval_chk_entity_name = 'check_lht_approval_status' self._sch_workflow_entity_name = 'Scheme_workflow' # Check if the current profile exists if self.curr_p is None: QMessageBox.critical(self, self.tr('Missing Profile'), self.tr("No profile has been specified")) self.reject() # Scheme entity self.sch_entity = self.curr_p.entity(self._sch_entity_name) # Entity models self.schm_model, self._scheme_doc_model = entity_model( self.sch_entity, with_supporting_document=True) # Check if scheme entity models exist if self.schm_model is None: QMessageBox.critical( self, self.tr('Scheme Entity Model'), self.tr("The scheme entity model could not be generated.")) self.reject() # Entity objects self._relv_auth_entity = None self._relevant_auth_lookup = None self._region_lookup = None self._reg_div_lookup = None self._holder_entity = None self._workflow_lookup = None self._approval_lookup = None self._sch_workflow_entity = None # Entity models self._relevant_auth_type_model = None self._region_lookup_model = None self._relevant_auth_model = None self._regdiv_lookup_model = None self._workflow_lookup_model = None self._approval_lookup_model = None self._sch_workflow_model = None # Initialize Mappermixin for saving attribute data MapperMixin.__init__(self, self.schm_model, self.sch_entity) # Configure notification bars self.notif_bar = NotificationBar(self.vlNotification) self.docs_notif_bar = NotificationBar(self.vlNotification_docs) self.holders_notif_bar = NotificationBar(self.vlNotification_holders) # CMIS stuff for document management self._cmis_mgr = CmisManager() # Mapper will be set in 1st page initialization self._cmis_doc_mapper = None # Last int value used for generating the scheme number self._abs_last_scheme_value = None # Validator for holders data self._holders_validator = None # Progress dialog for showing validation status self._h_validation_prog_dlg = QProgressDialog(self) # Database importer self._holder_importer = None # Connect signals self.btn_brws_hld.clicked.connect(self.browse_holders_file) self.btn_upload_dir.clicked.connect(self.on_upload_multiple_files) self.currentIdChanged.connect(self.on_page_changed) self.cbx_region.currentIndexChanged.connect( self.update_relevant_authority) self.cbx_relv_auth.currentIndexChanged.connect( self.update_relevant_authority) self.cbx_relv_auth_name.currentIndexChanged.connect( self.on_ra_name_changed) self.btn_reload_holders.clicked.connect(self.load_holders_file) self.chk_holders_validate.toggled.connect(self.on_validate_holders) self.tr_summary.link_clicked.connect(self._on_summary_link_clicked) # Block area self.radio_sq_meters.setChecked(True) self.dbl_spinbx_block_area.setSuffix(" Sq.m") self.dbl_spinbx_block_area.setDecimals(0) self.radio_hectares.toggled.connect(self._on_hectares_clicked) self.radio_sq_meters.toggled.connect(self._on_sq_meters_clicked) # Populate lookup combo boxes self._populate_lookups() # Current date self._current_date = QDate.currentDate().getDate() self._current_year = self._current_date[0] # Set date limits self._configure_date_controls() # Specify MapperMixin widgets self.register_col_widgets() def _populate_combo(self, cbo, lookup_name): """ Populates comboboxes with items from the database. :param cbo: Combobox object :param lookup_name: name of the lookup table. """ res = export_data(lookup_name) cbo.clear() cbo.addItem('') for r in res: cbo.addItem(r.value, r.id) def _populate_lookups(self): """ Populate combobox dropdowns with values to be displayed when user clicks the dropdown. """ # Check if the tables exists self._populate_combo(self.cbx_region, 'cb_check_lht_region') self._populate_combo(self.cbx_relv_auth, 'cb_check_lht_relevant_authority') self._populate_combo(self.cbx_lro, 'cb_check_lht_land_rights_office') self.cbx_region.model().sort(0) def _configure_date_controls(self): """ Set the configuration of the date widget controls. """ self.date_apprv.setMaximumDate(QDate.currentDate()) self.date_establish.setMaximumDate(QDate.currentDate()) self.date_establish.setDate(QDate.currentDate()) self.date_apprv.setDate((QDate.currentDate())) def _update_entities_and_models(self): """ Update the entity objects and database models for the relevant authority. """ if not self._relv_auth_entity: self._relv_auth_entity = self.curr_p.entity( self._rel_auth_entity_name) if not self._relevant_auth_lookup: self._relevant_auth_lookup = self.curr_p.entity( self._rel_auth_chk_entity_name) if not self._region_lookup: self._region_lookup = self.curr_p.entity(self._rgn_chk_entity_name) if not self._reg_div_lookup: self._reg_div_lookup = self.curr_p.entity( self._reg_div_chk_entity_name) # Check if entities exist if self._relv_auth_entity is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity'), self.tr("The relevant authority entity is missing in the " "profile.")) self.reject() elif self._relevant_auth_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() elif self._region_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() elif self._reg_div_lookup is None: QMessageBox.critical( self, self.tr('Missing Relevant Authority Entity Lookup'), self.tr( "The relevant authority entity lookup is missing in the " "profile.")) self.reject() # Entity models if not self._relevant_auth_type_model: self._relevant_auth_type_model = entity_model( self._relevant_auth_lookup) if not self._region_lookup_model: self._region_lookup_model = entity_model(self._region_lookup) if not self._relevant_auth_model: self._relevant_auth_model = entity_model(self._relv_auth_entity) if not self._regdiv_lookup_model: self._regdiv_lookup_model = entity_model(self._reg_div_lookup) def update_relevant_authority(self): """ Slot for updating the Relevant Authority combobox based on the selections in related combo boxes. """ self._update_entities_and_models() # Entity object relv_entity_obj = self._relevant_auth_model() # Get the region ID region_id = self.cbx_region.itemData(self.cbx_region.currentIndex()) # Get the relevant authority ID ra_id_type = self.cbx_relv_auth.itemData( self.cbx_relv_auth.currentIndex()) # Check if region combobox is selected if not region_id and not ra_id_type: return self.cbx_relv_auth_name.clear() self.cbx_reg_div.clear() self.lnedit_sg_num.clear() self.cbx_relv_auth_name.addItem('') self.cbx_reg_div.addItem('') # Query object for filtering items on name of relevant authority res = relv_entity_obj.queryObject().filter( self._relevant_auth_model.region == region_id, self._relevant_auth_model.type_of_relevant_authority == ra_id_type).all() # Looping through the results to get details for r in res: authority_name = r.name_of_relevant_authority authority_id = r.id code = r.au_code last_val = r.last_val reg_divs = [] for i in r.cb_check_lht_reg_division_collection: reg_divs.append((i.id, i.value)) # Add items to combobox # Data will contain tuple(ID, code and registration division) self.cbx_relv_auth_name.addItem( authority_name, (authority_id, code, last_val, reg_divs)) def on_ra_name_changed(self): """ Slot for updating the scheme number based on selection of name of relevant authority combobox. """ self.lnedit_schm_num.clear() self.lnedit_landhold_num.clear() self.cbx_reg_div.clear() if not self.cbx_relv_auth_name.currentText(): return authority_id, code, last_value, reg_divs = self.cbx_relv_auth_name.itemData( self.cbx_relv_auth_name.currentIndex()) self.cbx_reg_div.addItem('') for regdiv in reg_divs: self.cbx_reg_div.addItem(regdiv[1], regdiv[0]) # Select the first item automatically if there is only one division if self.cbx_reg_div.count() == 2: self.cbx_reg_div.setCurrentIndex(1) scheme_code = self._gen_scheme_number(code, last_value) self.lnedit_schm_num.setText(scheme_code) def _gen_scheme_number(self, code, last_value): """ Generate the scheme number. """ if not last_value: last_value = 0 last_value += 1 self._abs_last_scheme_value = last_value scheme_code = u'{0}. {1} / {2}'.format(code, str(last_value).zfill(4), self._current_year) return scheme_code def _on_hectares_clicked(self): """ Slot raised when the hectares radio button is selected. """ self.dbl_spinbx_block_area.setDecimals(4) self.dbl_spinbx_block_area.setSuffix(" Ha") initial_value = self.dbl_spinbx_block_area.value() value = initial_value / 10000 self.dbl_spinbx_block_area.setValue(value) def _on_sq_meters_clicked(self): """ Slot raised when the area radio button is clicked. """ self.dbl_spinbx_block_area.setDecimals(0) self.dbl_spinbx_block_area.setSuffix(" Sq.m") initial_value = self.dbl_spinbx_block_area.value() value = initial_value * 10000 self.dbl_spinbx_block_area.setValue(value) def validate_block_area(self): """ Validate the block area value input. """ min_value = self.dbl_spinbx_block_area.minimum() if self.dbl_spinbx_block_area.value() == min_value: self.notif_bar.insertWarningNotification( self.tr("Block Area value cannot be zero.")) else: return True def on_page_changed(self, idx): """ Slot raised when the page with the given id is loaded. """ page_num = idx + 1 win_title = u'{0} - Step {1} of {2}'.format(self._base_win_title, str(page_num), str(self._num_pages)) self.setWindowTitle(win_title) # First page # Set entity document mapper if connection to CMIS is successful if idx == 0: self._init_cmis_doc_mapper() # Load scheme supporting documents elif idx == 1: self._load_scheme_document_types() # Disable widget if doc mapper could not be initialized if not self._cmis_doc_mapper: self.tbw_documents.setEnabled(False) # Initialize holders information elif idx == 2: self._init_holder_helpers() # Last page elif idx == 3: # Populate summary widget self.populate_summary() def _init_holder_helpers(self): """ Initialize helper classes for holder's data. """ if not self._holder_entity: self._holder_entity = self.curr_p.entity(self._holders_entity_name) if not self._holder_entity: msg = self.tr( 'Could not find the Holders entity.\nPlease check to ' 'confirm that it has been created in the configuration') QMessageBox.critical(self, self.tr('Missing Holders Entity'), msg) return def _init_cmis_doc_mapper(self): """ Initialize CMIS class methods. """ conn_status = self._cmis_mgr.connect() if not conn_status: msg = self.tr( 'Failed to connect to the CMIS Service.\nPlease check the ' 'URL and login credentials for the CMIS service.') QMessageBox.critical(self, self.tr('CMIS Server Error'), msg) if conn_status: if not self._cmis_doc_mapper: try: self._cmis_doc_mapper = CmisEntityDocumentMapper( cmis_manager=self._cmis_mgr, doc_model_cls=self._scheme_doc_model, entity_name=self._sch_entity_name) # Set the CMIS document mapper in document widget self.tbw_documents.cmis_entity_doc_mapper = \ self._cmis_doc_mapper except CmisDocumentMapperException as cm_ex: QMessageBox.critical(self, self.tr('CMIS Server Error'), str(cm_ex)) except CmisException as c_ex: QMessageBox.critical(self, self.tr('CMIS Server Error'), c_ex.status) def browse_holders_file(self): """ Browse the holders file in the file directory. """ last_doc_path = last_document_path() if not last_doc_path: last_doc_path = '~/' holders_file = QFileDialog.getOpenFileName( self, 'Browse Holders File', last_doc_path, 'Excel File (*.xls *xlsx);;CSV (Comma Delimited) (*.csv)') if holders_file: set_last_document_path(holders_file) self.lnEdit_hld_path.setText(holders_file) self.load_holders_file() def load_holders_file(self): """ Load the holders data into the table view based on the file specified in the path textbox. """ h_path = self.lnEdit_hld_path.text() if not h_path: QMessageBox.warning( self, self.tr('Empty File Path'), self.tr('Please specify the path to the Holders file.')) return self.tw_hld_prv.load_holders_file(h_path) curr_sheet = self.tw_hld_prv.current_sheet_view() # Clear validation result label self.lbl_validation_description.clear() # Check if a signal has been defined in the sheet view and disconnect # Use old-style signal to check if signal is connected receivers = curr_sheet.receivers(SIGNAL('itemSelectionChanged()')) # Disconnect all slots for the itemSelectionChanged signal if receivers > 0: curr_sheet.itemSelectionChanged.disconnect() # Reconnect signal curr_sheet.itemSelectionChanged.connect( self._on_holders_table_selection_changed) # Create validator object ds = self.tw_hld_prv.current_sheet_view().vector_layer self._holders_validator = EntityVectorLayerValidator( self._holder_entity, ds, parent=self) # Connect signals self._holders_validator.featureValidated.connect( self._on_holder_feat_validated) self._holders_validator.validationFinished.connect( self._on_holder_validation_complete) # Create holder importer self._holder_importer = HolderPlotNumberDbImporter( ds, unique_cols=['holder_identifier'], parent=self) # Perform validation immediately after loading the data if self.chk_holders_validate.isChecked(): self._validate_holders() def on_validate_holders(self, toggled): """ Slot raised when the checkbox for validating holders data is checked/unchecked. :param toggled: Toggle status :type toggled: bool """ if not toggled: msg = 'Validation of the holders data will be performed prior to ' \ 'loading the summary page upon clicking Next.' self.holders_notif_bar.insertInformationNotification(msg) def _validate_holders(self): """ Reset and validate loaded holders information. """ self._holders_validator.reset() try: # Performs some pre-validation checks. # Check if mandatory columns have been mapped passed_mandatory, cols = self._holders_validator.validate_mandatory( ) if not passed_mandatory: cols_str = '\n'.join(cols) msg = self.tr('The following mandatory columns have not been ' 'mapped: {0}'.format(cols_str)) QMessageBox.critical(self, self.tr('Missing Mandatory Columns'), msg) return # Check if at least one data source column has been mapped ds_mapped = self._holders_validator.validate_mapped_ds_columns() if not ds_mapped: msg = 'At least one column in the data source has to be ' \ 'mapped.' QMessageBox.critical(self, self.tr('Mapped Data Source Columns'), msg) return # Check if at least one entity column has been mapped entity_mapped = self._holders_validator.validate_entity_columns() if not entity_mapped: msg = 'At least one entity column has to be mapped.' QMessageBox.critical(self, self.tr('Mapped Entity Columns'), msg) return # Set progress dialog properties self._h_validation_prog_dlg.setMinimum(0) self._h_validation_prog_dlg.setMaximum( self._holders_validator.count) self._h_validation_prog_dlg.setWindowModality(Qt.WindowModal) self._h_validation_prog_dlg.setLabelText( self.tr('Validating holders records in the data source...')) self._h_validation_prog_dlg.setWindowTitle( self.tr('Validation Progress')) # Connect canceled signal self._h_validation_prog_dlg.canceled.connect( self._on_validation_canceled) self._h_validation_prog_dlg.setValue(0) # Start the validation process self._holders_validator.start() except ValidatorException as ve: QMessageBox.critical(self, self.tr('Holders Validation Error'), unicode(ve)) def _on_holder_feat_validated(self, results): """ Slot raised when a feature in the data source has been validated. """ for r in results: if len(r.warnings) > 0 or len(r.errors) > 0: self.tw_hld_prv.current_sheet_view(). \ highlight_validation_cell(r) # Update progress bar curr_val = self._h_validation_prog_dlg.value() curr_val += 1 self._h_validation_prog_dlg.setValue(curr_val) def _on_holder_validation_complete(self): """ Slot raised when holder validation is complete. """ num_features = self._holders_validator.count num_err_features = len( self._holders_validator.row_warnings_errors.keys()) # Get features that have warnings or errors msg = self.tr( u'Validation process complete.\nOut of the {0} features in the ' u'data source, {1} have warnings and/or errors.\nPlease click ' u'on a cell with an error icon in the preview table to get more ' u'details.'.format(str(num_features), str(num_err_features))) QMessageBox.information(self, self.tr('Validation Summary'), msg) def _on_validation_canceled(self): """" Slot raised when the validation process has been cancelled by the user. """ if self._holders_validator: self._holders_validator.cancel() def _on_holders_table_selection_changed(self): """ Slot raised when selection changes in the holders table widget. """ self.lbl_validation_description.setText('') # Check if validator has been initialized if not self._holders_validator: return curr_sheet = self.tw_hld_prv.current_sheet_view() sel_items = curr_sheet.selectedItems() if len(sel_items) == 0: return sel_item = sel_items[0] if self._holders_validator.status == \ EntityVectorLayerValidator.NOT_STARTED: self.lbl_validation_description.setText(self.tr('Not validated')) elif self._holders_validator.status == \ EntityVectorLayerValidator.NOT_COMPLETED: self.lbl_validation_description.setText( self.tr('UNKNOWN: Validation process not complete')) elif self._holders_validator.status == \ EntityVectorLayerValidator.FINISHED: # Get data stored in the user role val_results = sel_item.data(Qt.UserRole) if not val_results: self.lbl_validation_description.setText(self.tr('SUCCESSFUL')) else: combined_msgs = val_results.errors + val_results.warnings str_msgs = [str(vr) for vr in combined_msgs] self.lbl_validation_description.setText('\n- '.join(str_msgs)) def _load_scheme_document_types(self): """ Handles Uploading and viewing of the scheme supporting documents. """ doc_type_entity = self.curr_p.entity_by_name( self._scheme_doc_type_lookup) if doc_type_entity is None: QMessageBox.critical( self, self.tr('Scheme Document Type Lookup'), self.tr('The lookup table containing the document types is ' 'missing.')) self.tbw_documents.setEnabled(False) return # No need of fetching the documents again if already done before if self._supporting_docs_loaded: return # Check Doc mapper if not self._cmis_doc_mapper: QMessageBox.critical( self, self.tr('CMIS Server Error'), self.tr( 'Document mapper could not be initialized, please check ' 'the connection to the CMIS server.')) self.tbw_documents.setEnabled(False) self.btn_upload_dir.setEnabled(False) return doc_res = export_data(self._scheme_doc_type_lookup) # Add the documents types to the view for d in doc_res: doc_type = d.value code = d.code type_id = d.id self.tbw_documents.add_document_type(doc_type) # Also add the types to the CMIS doc mapper self._cmis_doc_mapper.add_document_type(doc_type, code, type_id) self._supporting_docs_loaded = True def on_upload_multiple_files(self): """ Browse and select multiple supporting documents. """ last_doc_path = last_document_path() if not last_doc_path: last_doc_path = '~/' docs_dir = QFileDialog.getExistingDirectory( self, 'Browse Supporting Documents Source Directory', last_doc_path) if not docs_dir: return # Check if there are files in the selected directory dir = QDir(docs_dir) els = dir.entryList(QDir.NoDot | QDir.NoDotDot | QDir.Files) if len(els) == 0: QMessageBox.warning( self, 'Supporting Documents', self.tr('There are no files in the selected directory.')) return doc_types = self.tbw_documents.document_types() dir_doc_dlg = DirDocumentTypeSelector(docs_dir, doc_types, self) res = dir_doc_dlg.exec_() if res == QDialog.Accepted: # Get document types selected by the user selected_doc_types = dir_doc_dlg.selected_document_types self.tbw_documents.upload_document(selected_doc_types) def register_col_widgets(self): """ Registers the column widgets to the table columns """ # Get the table columns and add mapping self.addMapping('region', self.cbx_region, pseudoname='Region') self.addMapping('relevant_authority', self.cbx_relv_auth, pseudoname='Relevant Authority Type') self.addMapping('relevant_authority_name', self.cbx_relv_auth_name, pseudoname='Relevant Authority Name') self.addMapping('registration_division', self.cbx_reg_div, pseudoname='Registration Division') self.addMapping('scheme_number', self.lnedit_schm_num, pseudoname='Scheme Number') self.addMapping('land_hold_plan_number', self.lnedit_landhold_num, pseudoname='Land Hold Plan Number') self.addMapping('sg_number', self.lnedit_sg_num, pseudoname='Surveyor General Number') self.addMapping('scheme_name', self.lnedit_schm_nam, pseudoname='Scheme Name') self.addMapping('date_of_approval', self.date_apprv, pseudoname='Approval Date') self.addMapping('date_of_establishment', self.date_establish, pseudoname='Establishment Date') self.addMapping('land_rights_office', self.cbx_lro, pseudoname='Land Rights Office') self.addMapping('area', self.dbl_spinbx_block_area, pseudoname='Area') self.addMapping('no_of_plots', self.dbl_spinbx_num_plots, pseudoname='Number of Plots') self.addMapping('title_deed_number', self.lnedit_title_deed_num, pseudoname='Title Deed Number') self.addMapping('constitution_ref_number', self.lnedit_constitution_ref_num, pseudoname='Constitution Reference Number') self.addMapping('scheme_description', self.lnedit_scheme_description, pseudoname='Scheme Description') def validate_num_plots(self): """ Check whether the number of plots is zero """ # Preset minimum value equals to zero min_value_plots = self.dbl_spinbx_num_plots.minimum() if self.dbl_spinbx_num_plots.value() == min_value_plots: self.notif_bar.insertWarningNotification( self.tr("Number of Plots cannot be zero.")) else: return True def validateCurrentPage(self): """ Validate each wizard page. """ current_id = self.currentId() ret_status = False self.notif_bar.clear() if current_id == 0: # Check if values have been specified for the attribute widgets errors = self.validate_all() if self.validate_block_area() and len(errors) == 0: if self.validate_num_plots(): ret_status = True # Holders page elif current_id == 2: if not self.lnEdit_hld_path.text(): self.holders_notif_bar.clear() self.holders_notif_bar.insertWarningNotification( self.tr('Please upload the file containing the Holders ' 'information.')) else: status = self._holders_validator.status if status == EntityVectorLayerValidator.NOT_STARTED: msg = self.tr( 'The holders data has not yet been validated.') elif status == EntityVectorLayerValidator.NOT_COMPLETED: msg = self.tr('The validation process was interrupted.') elif status == EntityVectorLayerValidator.FINISHED: # Check if there were errors (exclude warnings) num_err_features = len( self._holders_validator.row_errors.keys()) if num_err_features > 0: msg = self.tr( 'There were errors in the last validation ' 'process.') else: ret_status = True if not ret_status and msg: # Give user the option to (re)run the validation process. action_msg = self.tr( 'Do you want to (re)run the validation process?') res = QMessageBox.warning( self, self.tr('Validation Status'), u'{0}\n{1}'.format(msg, action_msg), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) # Run the validation if the user selects Yes if res == QMessageBox.Yes: self._validate_holders() # Documents page elif current_id == 1: ret_status = self._is_documents_page_valid() if not ret_status: self.docs_notif_bar.clear() msg = self.tr('Please upload all the supporting documents. ') self.docs_notif_bar.insertWarningNotification(msg) # Check if there is an active document upload/removal operation active_operation = self.tbw_documents.has_active_operation if active_operation: ret_status = False msg = self.tr( 'There is an ongoing operation with the CMIS server. ' 'Please wait a few moments.') self.docs_notif_bar.insertWarningNotification(msg) elif current_id == 3: # This is the last page try: self.save_scheme() self.populate_workflow() ret_status = True except Exception as err: QMessageBox.critical(self, self.tr('Error in Saving Scheme'), unicode(err)) return ret_status def _is_documents_page_valid(self): # Checks if the documents have been uploaded uploaded_docs = self.tbw_documents.uploaded_documents.values() return len(uploaded_docs) == self.tbw_documents.rowCount() def populate_summary(self): """ Populating the scheme summary widget with values from the user input """ self.tr_summary.scm_num.setText(1, self.lnedit_schm_num.text()) self.tr_summary.scm_desc.setText(1, self.lnedit_scheme_description.text()) self.tr_summary.scm_name.setText(1, self.lnedit_schm_nam.text()) self.tr_summary.scm_title_deed_num.setText( 1, self.lnedit_title_deed_num.text()) self.tr_summary.scm_date_apprv.setText(1, self.date_apprv.text()) self.tr_summary.scm_date_est.setText(1, self.date_establish.text()) self.tr_summary.scm_region.setText(1, self.cbx_region.currentText()) self.tr_summary.scm_ra_type.setText(1, self.cbx_relv_auth.currentText()) self.tr_summary.scm_ra_name.setText( 1, self.cbx_relv_auth_name.currentText()) self.tr_summary.scm_land_hold_num.setText( 1, self.lnedit_landhold_num.text()) self.tr_summary.scm_sg_num.setText(1, self.lnedit_sg_num.text()) self.tr_summary.scm_lro.setText(1, self.cbx_lro.currentText()) self.tr_summary.scm_reg_div.setText(1, self.cbx_reg_div.currentText()) self.tr_summary.scm_numplots.setText(1, self.dbl_spinbx_num_plots.text()) self.tr_summary.scm_blk_area.setText(1, self.dbl_spinbx_block_area.text()) def _on_summary_link_clicked(self, code): """ Slot raised when the hyperlink in summary widget is clicked :param code: Code identifier of the wizard page. :type code: str """ ref_id = -1 if code == 'DOC': ref_id = 1 elif code == 'HLD': ref_id = 2 if ref_id == -1: return while self.currentId() != ref_id: self.back() def _save_ra_last_value(self, scheme_number): """ Save the most recent value for the relevant authority. """ if not self._abs_last_scheme_value: return num_parts = scheme_number.split('.') if len(num_parts) > 0: code = num_parts[0] rel_auth_obj = self._relevant_auth_model() res = rel_auth_obj.queryObject().filter( self._relevant_auth_model.au_code == code).first() if res: # Update last value res.last_val = self._abs_last_scheme_value res.update() def save_scheme(self): """ Save scheme information, move supporting documents, save holders table and create appropriate notifications. """ sch_number = None pg_dlg = QProgressDialog(parent=self) pg_dlg.setWindowModality(Qt.WindowModal) pg_dlg.setMinimum(0) pg_dlg.setMaximum(4) pg_dlg.setCancelButton(None) pg_dlg.setWindowTitle(self.tr('Saving Scheme Information...')) pg_dlg.setLabelText(self.tr('Retrieving scheme attribute data...')) pg_dlg.setValue(1) # Get scheme db object for manual saving to database. self.submit(True) scheme_obj = self.model() scheme_obj.plot_status = 2 QgsApplication.processEvents() pg_dlg.setLabelText( self.tr('Saving supporting documents, please wait...')) pg_dlg.setValue(2) # Format scheme number for saving in document repository if not sch_number: sch_number = scheme_obj.scheme_number.replace(" / ", "_") sch_number = sch_number.replace(" ", "_") # Attach documents doc_objs = self._cmis_doc_mapper.persist_documents(sch_number) scheme_obj.documents = doc_objs QgsApplication.processEvents() pg_dlg.setLabelText(self.tr('Saving scheme data...')) pg_dlg.setValue(3) scheme_obj.save() # Update last value for generating scheme number self._save_ra_last_value(scheme_obj.scheme_number) QgsApplication.processEvents() pg_dlg.setLabelText(self.tr('Saving holders data...')) pg_dlg.setValue(4) QgsApplication.processEvents() # Attach the scheme object to the holders self._holder_importer.set_extra_attribute_value( 'cb_scheme_collection', [scheme_obj]) # Save holders data self._holder_importer.start() QgsApplication.processEvents() msg = self.tr( u'A new scheme (No. {0}) has been successfully lodged.'.format( scheme_obj.scheme_number)) QMessageBox.information(self, self.tr('New Scheme'), msg) def populate_workflow(self): """ Update the workflow table once lodgement has been done """ # Entities self._workflow_lookup = self.curr_p.entity( self._workflow_chk_entity_name) self._approval_lookup = self.curr_p.entity( self._approval_chk_entity_name) self._sch_workflow_entity = self.curr_p.entity( self._sch_workflow_entity_name) # Check if entity exists if self._workflow_lookup is None: QMessageBox.critical( self, self.tr('Missing workflow Entity'), self.tr("The workflow entity is missing in the " "profile.")) if self._approval_lookup is None: QMessageBox.critical( self, self.tr('Missing approval Entity'), self.tr("The approval entity is missing in the " "profile.")) if self._sch_workflow_entity is None: QMessageBox.critical( self, self.tr('Missing scheme workflow Entity'), self.tr("The scheme workflow entity is missing in the " "profile.")) # Models self._workflow_lookup_model = entity_model(self._workflow_lookup) self._approval_lookup_model = entity_model(self._approval_lookup) self._sch_workflow_model = entity_model(self._sch_workflow_entity) # Check if model exists if self._workflow_lookup_model is None: QMessageBox.critical( self, self.tr('Workflow Entity Model'), self.tr("The workflow entity model could not be generated.")) if self._approval_lookup_model is None: QMessageBox.critical( self, self.tr('Workflow Entity Model'), self.tr("The approval entity model could not be generated.")) if self._sch_workflow_model is None: QMessageBox.critical( self, self.tr('Scheme Workflow Entity Model'), self.tr("The scheme workflow entity model could not be " "generated.")) # Entity objects scheme_obj = self.schm_model() chk_workflow_obj = self._workflow_lookup_model() chk_approval_obj = self._approval_lookup_model() scheme_workflow_obj = self._sch_workflow_model() # Get last lodged scheme ID scheme_res = scheme_obj.queryObject().order_by( self.schm_model.id.desc()).first() # Filter the lookup IDs based on values workflow_res = chk_workflow_obj.queryObject().filter( self._workflow_lookup_model.value == 'Lodgement').one() approval_lodge_res = chk_approval_obj.queryObject().filter( self._approval_lookup_model.value == 'Approved').one() # Save details scheme_workflow_obj.scheme_id = scheme_res.id scheme_workflow_obj.workflow_id = workflow_res.id scheme_workflow_obj.approval_id = approval_lodge_res.id scheme_workflow_obj.save() self.populate_establishment_workflow() self.populate_plot_workflow() def populate_establishment_workflow(self): """ Update the workflow link table with establishment as unapproved. :return: """ # Entity objects scheme_obj = self.schm_model() chk_workflow_obj = self._workflow_lookup_model() chk_approval_obj = self._approval_lookup_model() scheme_workflow_obj = self._sch_workflow_model() # Get last lodged scheme ID scheme_res = scheme_obj.queryObject().order_by( self.schm_model.id.desc()).first() # Filter the lookup IDs based on values workflow_res = chk_workflow_obj.queryObject().filter( self._workflow_lookup_model.value == 'Establishment').one() approval_res = chk_approval_obj.queryObject().filter( self._approval_lookup_model.value == 'Pending').one() # Save details scheme_workflow_obj.scheme_id = scheme_res.id scheme_workflow_obj.workflow_id = workflow_res.id scheme_workflow_obj.approval_id = approval_res.id scheme_workflow_obj.save() def populate_plot_workflow(self): """ Update the workflow link table with import plot as unapproved. :return: None """ # Entity objects scheme_obj = self.schm_model() chk_workflow_obj = self._workflow_lookup_model() chk_approval_obj = self._approval_lookup_model() scheme_workflow_obj = self._sch_workflow_model() # Get last lodged scheme ID scheme_res = scheme_obj.queryObject().order_by( self.schm_model.id.desc()).first() # Filter the lookup IDs based on values workflow_res = chk_workflow_obj.queryObject().filter( self._workflow_lookup_model.value == 'Import Plot').one() approval_res = chk_approval_obj.queryObject().filter( self._approval_lookup_model.value == 'Pending').one() # Save details scheme_workflow_obj.scheme_id = scheme_res.id scheme_workflow_obj.workflow_id = workflow_res.id scheme_workflow_obj.approval_id = approval_res.id scheme_workflow_obj.save() def populate_third_workflow(self): """ Update the workflow link table with import plot as unapproved. """ # Entity objects scheme_obj = self.schm_model() chk_workflow_obj = self._workflow_lookup_model() chk_approval_obj = self._approval_lookup_model() scheme_workflow_obj = self._sch_workflow_model() # Get last lodged scheme ID scheme_res = scheme_obj.queryObject().order_by( self.schm_model.id.desc()).first() # Filter the lookup IDs based on values workflow_res = chk_workflow_obj.queryObject().filter( self._workflow_lookup_model.value == 'Third Assessment').one() approval_res = chk_approval_obj.queryObject().filter( self._approval_lookup_model.value == 'Pending').one() # Save details scheme_workflow_obj.scheme_id = scheme_res.id scheme_workflow_obj.workflow_id = workflow_res.id scheme_workflow_obj.approval_id = approval_res.id scheme_workflow_obj.save()
class AddonManagerDialog(QDialog): _packages = None def __init__(self, parent=None, **kwargs): super().__init__(parent, acceptDrops=True, **kwargs) self.setLayout(QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.addonwidget = AddonManagerWidget() self.layout().addWidget(self.addonwidget) info_bar = QWidget() info_layout = QHBoxLayout() info_bar.setLayout(info_layout) self.layout().addWidget(info_bar) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) buttons.accepted.connect(self.__accepted) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons) # No system access => install into user site-packages self.user_install = not os.access(sysconfig.get_path("purelib"), os.W_OK) self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) if AddonManagerDialog._packages is None: self._f_pypi_addons = self._executor.submit(list_pypi_addons) else: self._f_pypi_addons = concurrent.futures.Future() self._f_pypi_addons.set_result(AddonManagerDialog._packages) self._f_pypi_addons.add_done_callback( method_queued(self._set_packages, (object,)) ) self.__progress = QProgressDialog( self, Qt.Sheet, minimum=0, maximum=0, labelText=self.tr("Retrieving package list"), sizeGripEnabled=False, windowTitle="Progress" ) self.__progress.rejected.connect(self.reject) self.__thread = None self.__installer = None @Slot(object) def _set_packages(self, f): if self.__progress.isVisible(): self.__progress.close() try: packages = f.result() except (IOError, OSError) as err: message_warning( "Could not retrieve package list", title="Error", informative_text=str(err), parent=self ) packages = [] except Exception: raise else: AddonManagerDialog._packages = packages installed = list_installed_addons() dists = {dist.project_name: dist for dist in installed} packages = {pkg.name: pkg for pkg in packages} # For every pypi available distribution not listed by # list_installed_addons, check if it is actually already # installed. ws = pkg_resources.WorkingSet() for pkg_name in set(packages.keys()).difference(set(dists.keys())): try: d = ws.find(pkg_resources.Requirement.parse(pkg_name)) except pkg_resources.VersionConflict: pass except ValueError: # Requirements.parse error ? pass else: if d is not None: dists[d.project_name] = d project_names = unique( itertools.chain(packages.keys(), dists.keys()) ) items = [] for name in project_names: if name in dists and name in packages: item = Installed(packages[name], dists[name]) elif name in dists: item = Installed(None, dists[name]) elif name in packages: item = Available(packages[name]) else: assert False items.append(item) self.addonwidget.set_items(items) def showEvent(self, event): super().showEvent(event) if not self._f_pypi_addons.done(): QTimer.singleShot(0, self.__progress.show) def done(self, retcode): super().done(retcode) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def closeEvent(self, event): super().closeEvent(event) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) ADDON_EXTENSIONS = ('.zip', '.whl', '.tar.gz') def dragEnterEvent(self, event): urls = event.mimeData().urls() if any((OSX_NSURL_toLocalFile(url) or url.toLocalFile()) .endswith(self.ADDON_EXTENSIONS) for url in urls): event.acceptProposedAction() def dropEvent(self, event): """Allow dropping add-ons (zip or wheel archives) on this dialog to install them""" packages = [] names = [] for url in event.mimeData().urls(): path = OSX_NSURL_toLocalFile(url) or url.toLocalFile() if path.endswith(self.ADDON_EXTENSIONS): name, vers, summary, descr = (get_meta_from_archive(path) or (os.path.basename(path), '', '', '')) names.append(name) packages.append( Installable(name, vers, summary, descr or summary, path, [path])) future = concurrent.futures.Future() future.set_result((AddonManagerDialog._packages or []) + packages) self._set_packages(future) self.addonwidget.set_install_projects(names) def __accepted(self): steps = self.addonwidget.item_state() if steps: # Move all uninstall steps to the front steps = sorted( steps, key=lambda step: 0 if step[0] == Uninstall else 1 ) self.__installer = Installer(steps=steps, user_install=self.user_install) self.__thread = QThread(self) self.__thread.start() self.__installer.moveToThread(self.__thread) self.__installer.finished.connect(self.__on_installer_finished) self.__installer.error.connect(self.__on_installer_error) self.__installer.installStatusChanged.connect( self.__progress.setLabelText) self.__progress.show() self.__progress.setLabelText("Installing") self.__installer.start() else: self.accept() def __on_installer_error(self, command, pkg, retcode, output): message_error( "An error occurred while running a subprocess", title="Error", informative_text="{} exited with non zero status.".format(command), details="".join(output), parent=self ) self.reject() def __on_installer_finished(self): message = ( ("Changes successfully applied in <i>{}</i>.<br>".format( USER_SITE) if self.user_install else '') + "Please restart Orange for changes to take effect.") message_information(message, parent=self) self.accept()
class AddonManagerDialog(QDialog): def __init__(self, parent=None, **kwargs): super(AddonManagerDialog, self).__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self.addonwidget = AddonManagerWidget() self.addonwidget.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.addonwidget) buttons = QDialogButtonBox(orientation=Qt.Horizontal, standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttons.accepted.connect(self.__accepted) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons) self.__progress = QProgressDialog( self, Qt.Sheet, minimum=0, maximum=0, labelText=self.tr("Retrieving package list"), sizeGripEnabled=False, windowTitle="Progress") self.__progress.canceled.connect(self.reject) # The installer thread self.__thread = None # The installer object self.__installer = None @Slot(list) def setItems(self, items): self.addonwidget.setItems(items) def progressDialog(self): return self.__progress def done(self, retcode): super(AddonManagerDialog, self).done(retcode) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def closeEvent(self, event): super(AddonManagerDialog, self).closeEvent(event) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def __accepted(self): steps = self.addonwidget.itemState() if steps: # Move all uninstall steps to the front steps = sorted(steps, key=lambda step: 0 if step[0] == Uninstall else 1) self.__installer = Installer(steps=steps) self.__thread = QThread(self) self.__thread.start() self.__installer.moveToThread(self.__thread) self.__installer.finished.connect(self.__on_installer_finished) self.__installer.error.connect(self.__on_installer_error) self.__installer.installStatusChanged.connect( self.__progress.setLabelText) self.__progress.show() self.__progress.setLabelText("Installing") self.__installer.start() else: self.accept() def __on_installer_error(self, command, pkg, retcode, output): message_error( "An error occurred while running a subprocess", title="Error", informative_text="{} exited with non zero status.".format(command), details="".join(output), parent=self) self.reject() def __on_installer_finished(self): message_information( "Please restart the application for changes to take effect.", parent=self) self.accept()
class OsmDownloader(QDialog, Ui_OsmDownloaderBase): """Downloader for OSM data.""" def __init__(self, parent=None, iface=None): """Constructor for import dialog. :param parent: Optional widget to use as parent :type parent: QWidget :param iface: An instance of QGisInterface :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = iface self.url = "http://osm.linfiniti.com/buildings-shp" # creating progress dialog for download self.progressDialog = QProgressDialog(self) self.progressDialog.setAutoClose(False) myTitle = self.tr("InaSAFE OpenStreetMap Downloader") self.progressDialog.setWindowTitle(myTitle) # Set up context help helpButton = self.buttonBox.button(QtGui.QDialogButtonBox.Help) QtCore.QObject.connect(helpButton, QtCore.SIGNAL('clicked()'), self.show_help) self.show_info() # Set Proxy in webpage proxy = get_proxy() self.network_manager = QNetworkAccessManager(self) if not proxy is None: self.network_manager.setProxy(proxy) self.restore_state() self.update_extent() def show_info(self): """Show usage info to the user.""" # Read the header and footer html snippets header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE) body = self.tr( 'This tool will fetch building (\'structure\') data from the ' 'OpenStreetMap project for you. The downloaded data will have ' 'InaSAFE keywords defined and a default QGIS style applied. To ' 'use this tool effectively:') tips = m.BulletedList() tips.add( self. tr('Use QGIS to zoom in to the area for which you want building data ' 'to be retrieved.')) tips.add( self. tr('Check the output directory is correct. Note that the saved ' 'dataset will be called buildings.shp (and its associated files).' )) tips.add( self. tr('If a dataset already exists in the output directory it will be ' 'overwritten.')) tips.add( self. tr('This tool requires a working internet connection and fetching ' 'buildings will consume your bandwidth.')) tips.add( m.Link( 'http://www.openstreetmap.org/copyright', text=self.tr( 'Downloaded data is copyright OpenStreetMap contributors' ' (click for more info).'))) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.webView.setHtml(string) def restore_state(self): """ Read last state of GUI from configuration file.""" mySetting = QSettings() self.outDir.setText(mySetting.value('directory')) def save_state(self): """ Store current state of GUI to configuration file """ mySetting = QSettings() mySetting.setValue('directory', self.outDir.text()) def show_help(self): """Load the help text for the dialog.""" show_context_help('openstreetmap_downloader') def update_extent(self): """ Update extent value in GUI based from value in map.""" # Get the extent as [xmin, ymin, xmax, ymax] myExtent = viewport_geo_array(self.iface.mapCanvas()) self.minLongitude.setText(str(myExtent[0])) self.minLatitude.setText(str(myExtent[1])) self.maxLongitude.setText(str(myExtent[2])) self.maxLatitude.setText(str(myExtent[3])) @pyqtSignature('') # prevents actions being handled twice def on_pBtnDir_clicked(self): """ Show a dialog to choose directory """ # noinspection PyCallByClass,PyTypeChecker self.outDir.setText( QFileDialog.getExistingDirectory( self, self.tr("Select download directory"))) def accept(self): """Do osm download and display it in QGIS.""" try: self.save_state() self.require_directory() self.download() self.load_shapefile() self.done(QDialog.Accepted) except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as myEx: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, self.tr("InaSAFE OpenStreetMap downloader error"), str(myEx)) self.progressDialog.cancel() def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ myDir = str(self.outDir.text()) if os.path.exists(myDir): return myTitle = self.tr("Directory %s not exist") % myDir myQuestion = self.tr( "Directory %s not exist. Do you want to create it?") % myDir # noinspection PyCallByClass,PyTypeChecker myAnswer = QMessageBox.question(self, myTitle, myQuestion, QMessageBox.Yes | QMessageBox.No) if myAnswer == QMessageBox.Yes: os.makedirs(myDir) else: raise CanceledImportDialogError() def download(self): """Download shapefiles from Linfinti server. :raises: ImportDialogError, CanceledImportDialogError """ ## preparing necessary data myMinLng = str(self.minLongitude.text()) myMinLat = str(self.minLatitude.text()) myMaxLng = str(self.maxLongitude.text()) myMaxLat = str(self.maxLatitude.text()) myCoordinate = "{myMinLng},{myMinLat},{myMaxLng},{myMaxLat}".format( myMinLng=myMinLng, myMinLat=myMinLat, myMaxLng=myMaxLng, myMaxLat=myMaxLat) myShapeUrl = "{url}?bbox={myCoordinate}".format( url=self.url, myCoordinate=myCoordinate) myFilePath = tempfile.mktemp('.shp.zip') # download and extract it self.fetch_zip(myShapeUrl, myFilePath) print myFilePath print str(self.outDir.text()) self.extract_zip(myFilePath, str(self.outDir.text())) self.progressDialog.done(QDialog.Accepted) def fetch_zip(self, url, output_path): """Download zip containing shp file and write to output_path. :param url: URL of the zip bundle. :type url: str :param output_path: Path of output file, :type output_path: str :raises: ImportDialogError - when network error occurred """ self.progressDialog.show() self.progressDialog.setMaximum(100) self.progressDialog.setValue(0) # myLabelText = "Begin downloading shapefile from " \ # + "%s ..." # self.progressDialog.setLabelText(self.tr(myLabelText) % (url)) myLabelText = self.tr("Downloading shapefile") self.progressDialog.setLabelText(myLabelText) myResult = download_url(self.network_manager, url, output_path, self.progressDialog) if myResult is not True: _, myErrorMessage = myResult raise ImportDialogError(myErrorMessage) def extract_zip(self, path, output_dir): """Extract all content of a .zip file from path to output_dir. :param path: The path of the .zip file :type path: str :param output_dir: Output directory where the shp will be written to. :type output_dir: str :raises: IOError - when not able to open path or output_dir does not exist. """ import zipfile # extract all files... myHandle = open(path, 'rb') myZip = zipfile.ZipFile(myHandle) for myName in myZip.namelist(): myOutPath = os.path.join(output_dir, myName) myOutFile = open(myOutPath, 'wb') myOutFile.write(myZip.read(myName)) myOutFile.close() myHandle.close() def load_shapefile(self): """ Load downloaded shape file to QGIS Main Window. :raises: ImportDialogError - when buildings.shp not exist """ myDir = str(self.outDir.text()) myPath = os.path.join(myDir, 'buildings.shp') if not os.path.exists(myPath): myMessage = self.tr( "%s don't exist. The server don't have buildings data.") raise ImportDialogError(myMessage) self.iface.addVectorLayer(myPath, 'buildings', 'ogr')
class RebuildIndex(object): """ Tool class to rebuild the indexation """ def __init__(self, iface): """ Constructor :param iface: interface """ self.__iface = iface self.icon_path = ':/plugins/VDLTools/icons/rebuild_icon.png' self.text = QCoreApplication.translate("VDLTools", "Rebuild Index") self.killed = False def start(self): """ To start the rebuild """ snap_util = self.__iface.mapCanvas().snappingUtils() extent = self.__iface.mapCanvas().extent() self.__progressDialog = QProgressDialog() self.__progressDialog.setWindowTitle( QCoreApplication.translate("VDLTools", "Rebuild Index...")) self.__progressDialog.setLabelText( QCoreApplication.translate("VDLTools", "Percentage of indexed layers")) progressBar = QProgressBar(self.__progressDialog) progressBar.setTextVisible(True) cancelButton = QPushButton() cancelButton.setText(QCoreApplication.translate("VDLTools", "Cancel")) cancelButton.clicked.connect(self.kill) self.__progressDialog.setBar(progressBar) self.__progressDialog.setCancelButton(cancelButton) self.__progressDialog.setMinimumWidth(300) self.__progressDialog.show() lcs_list = snap_util.layers() step = 0 self.killed = False for lc in lcs_list: if self.killed: break locator = snap_util.locatorForLayer(lc.layer) if locator.extent() is not None: txt = locator.extent().toString() else: txt = "None" print("old extent : " + txt) print("new extent : " + extent.toString()) locator.setExtent(extent) if not locator.hasIndex(): locator.init() else: locator.rebuildIndex() locator.setExtent(None) progressBar.setValue(100 * step / len(lcs_list)) step += 1 self.__progressDialog.close() def kill(self): """ To stop the rebuild at the end of the current working layer """ self.killed = True
def copy_gfx(self): gfx_dir = os.path.join(self.editor_data_dir, "gfx") if os.path.isdir(gfx_dir): shutil.rmtree(gfx_dir) os.makedirs(gfx_dir) progress = QProgressDialog("", "Abort", 0, 0, self) progress.setWindowTitle("Copying GFX...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setMinimumDuration(0) progress.setValue(0) progress.setAutoClose(False) progress.setLabelText("Setting up GFX dir.") progress.setMaximum(5) progress.setValue(0) # Extract the images we can't just take directly from the game's data. gfx_bin = zipfile.ZipFile("data/gfx_base.zip", "r") progress.setValue(1) progress.setValue(2) gfx_bin.extractall(gfx_dir) progress.setValue(5) gfx_bin.close() # We can mostly loop this. gfx_data = [ ("ammo", "kotodama_icn_???.gim"), ("bgd", "bgd_???.gim"), ("cutin", "cutin_icn_???.gim"), ("events", "gallery_icn_???.gim"), ("movies", "bin_movie_gallery_l.pak/0000/000[1789].gim"), ("movies", "bin_movie_gallery_l.pak/0000/00[123]?.gim"), ("movies", "gallery_ico_m_none.gim"), ("movies", "gallery_thumbnail_m_???.gim"), ("nametags", "tex_system.pak/00[12]?.gim"), ("nametags", "tex_system.pak/003[0123456].gim"), ("presents", "present_icn_???.gim"), ("sprites", "bustup_??_??.gim"), ("sprites", "stand_??_??.gmo"), ] for (dir, file_glob) in gfx_data: out_dir = os.path.join(gfx_dir, dir) files = glob.glob(os.path.join(self.data01_dir, file_glob)) progress.setLabelText("Copying %s." % dir) progress.setMaximum(len(files)) progress.setValue(0) if not os.path.isdir(out_dir): os.makedirs(out_dir) for i, image in enumerate(files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return src = image dest = os.path.join(out_dir, os.path.basename(src)) shutil.copy(src, dest) progress.setValue(len(files)) progress.setLabelText("Copying font.") progress.setMaximum(4) progress.setValue(0) # The font we have to get from umdimage2. font_dir = os.path.join(gfx_dir, "font") if not os.path.isdir(font_dir): os.makedirs(font_dir) progress.setValue(1) # And convert to PNG with an alpha channel so our editor can use it. font1 = font_bmp_to_alpha(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0000.bmp")) progress.setValue(2) font2 = font_bmp_to_alpha(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0002.bmp")) progress.setValue(3) font1.save(os.path.join(font_dir, "Font01.png")) font2.save(os.path.join(font_dir, "Font02.png")) shutil.copy(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0001.font"), os.path.join(font_dir, "Font01.font")) shutil.copy(os.path.join(self.data01_dir, "jp", "font", "font.pak", "0003.font"), os.path.join(font_dir, "Font02.font")) progress.setValue(4) # And then the flash files. This'll be fun. flash_dir = os.path.join(gfx_dir, "flash") if not os.path.isdir(flash_dir): os.makedirs(flash_dir) #flash2_dir = os.path.join(gfx_dir, "flash2") #if not os.path.isdir(flash2_dir): #os.makedirs(flash2_dir) #Because there's so many in so many different places, I just stored a list #of the flash files we need in the gfx_base archive. So let's load that. with open(os.path.join(gfx_dir, "fla.txt"), "rb") as fla: fla_list = fla.readlines() progress.setLabelText("Copying flash.") progress.setMaximum(len(fla_list)) progress.setValue(0) for i, flash in enumerate(fla_list): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return flash = flash.strip() fla_name = flash[:7] # fla_### src = os.path.join(self.data01_dir, "all", "flash", flash) dest = os.path.join(flash_dir, "%s.gim" % fla_name) shutil.copy(src, dest) progress.setValue(len(fla_list)) # We have a couple sets of files that aren't named the way we want them to # be, just because of how they're stored in umdimage. progress.setLabelText("Renaming files.") to_rename = [ ("movies", "movie_%03d.gim", range(32)), ("nametags", "%02d.gim", range(23) + [24, 25, 30, 31]), ] for (folder, pattern, nums) in to_rename: folder = os.path.join(gfx_dir, folder) files = glob.glob(os.path.join(folder, "*.gim")) progress.setMaximum(len(files)) progress.setValue(0) for i, image in enumerate(files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return src = image dest = os.path.join(folder, pattern % nums[i]) if os.path.isfile(dest): os.remove(dest) shutil.move(src, dest) sprite_dir = os.path.join(gfx_dir, "sprites") gmo_files = glob.glob(os.path.join(sprite_dir, "*.gmo")) progress.setLabelText("Extracting GMO files.") progress.setValue(0) progress.setMaximum(len(gmo_files)) for i, gmo_file in enumerate(gmo_files): if i % 10 == 0: progress.setValue(i) if progress.wasCanceled(): return name, ext = os.path.splitext(os.path.basename(gmo_file)) gim_file = os.path.join(sprite_dir, name + ".gim") gmo = GmoFile(filename = gmo_file) # Once we've loaded it, we're all done with it, so make it go away. os.remove(gmo_file) if gmo.gim_count() == 0: continue gim = gmo.get_gim(0) with open(gim_file, "wb") as f: gim.tofile(f) if self.ui.chkGimToPng.isChecked(): gim_files = glob.glob(os.path.join(gfx_dir, "*", "*.gim")) progress.setLabelText("Converting GIM to PNG.") progress.setValue(0) progress.setMaximum(len(gim_files)) converter = GimConverter() for i, gim_file in enumerate(gim_files): progress.setValue(i) if progress.wasCanceled(): return converter.gim_to_png(gim_file) os.remove(gim_file) progress.close() self.gfx_dir = gfx_dir self.ui.grpStep5.setEnabled(False) self.ui.grpStep6.setEnabled(True)
class AddonManagerDialog(QDialog): _packages = None def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.addonwidget = AddonManagerWidget() self.layout().addWidget(self.addonwidget) info_bar = QWidget() info_layout = QHBoxLayout() info_bar.setLayout(info_layout) info_icon = QLabel() info_text = QLabel() info_layout.addWidget(info_icon) info_layout.addWidget(info_text) self.layout().addWidget(info_bar) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) buttons.accepted.connect(self.__accepted) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons) if not os.access(sysconfig.get_path("purelib"), os.W_OK): if sysconfig.get_platform().startswith("macosx"): info = "You must install Orange by dragging it into" \ " Applications before installing add-ons." else: info = "You do not have permissions to write into Orange " \ "directory.\nYou may need to contact an administrator " \ "for assistance." info_text.setText(info) style = QApplication.instance().style() info_icon.setPixmap(style.standardIcon( QStyle.SP_MessageBoxCritical).pixmap(14, 14)) buttons.button(QDialogButtonBox.Ok ).setEnabled(False) self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) if AddonManagerDialog._packages is None: self._f_pypi_addons = self._executor.submit(list_pypi_addons) else: self._f_pypi_addons = concurrent.futures.Future() self._f_pypi_addons.set_result(AddonManagerDialog._packages) self._f_pypi_addons.add_done_callback( method_queued(self._set_packages, (object,)) ) self.__progress = QProgressDialog( self, Qt.Sheet, minimum=0, maximum=0, labelText=self.tr("Retrieving package list"), sizeGripEnabled=False, windowTitle="Progress" ) self.__progress.rejected.connect(self.reject) self.__thread = None self.__installer = None @Slot(object) def _set_packages(self, f): if self.__progress.isVisible(): self.__progress.close() try: packages = f.result() except (IOError, OSError) as err: message_warning( "Could not retrieve package list", title="Error", informative_text=str(err), parent=self ) packages = [] except Exception: raise else: AddonManagerDialog._packages = packages installed = list_installed_addons() dists = {dist.project_name: dist for dist in installed} packages = {pkg.name: pkg for pkg in packages} # For every pypi available distribution not listed by # list_installed_addons, check if it is actually already # installed. ws = pkg_resources.WorkingSet() for pkg_name in set(packages.keys()).difference(set(dists.keys())): try: d = ws.find(pkg_resources.Requirement.parse(pkg_name)) except pkg_resources.VersionConflict: pass except ValueError: # Requirements.parse error ? pass else: if d is not None: dists[d.project_name] = d project_names = unique( itertools.chain(packages.keys(), dists.keys()) ) items = [] for name in project_names: if name in dists and name in packages: item = Installed(packages[name], dists[name]) elif name in dists: item = Installed(None, dists[name]) elif name in packages: item = Available(packages[name]) else: assert False items.append(item) self.addonwidget.set_items(items) def showEvent(self, event): super().showEvent(event) if not self._f_pypi_addons.done(): QTimer.singleShot(0, self.__progress.show) def done(self, retcode): super().done(retcode) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def closeEvent(self, event): super().closeEvent(event) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def __accepted(self): steps = self.addonwidget.item_state() if steps: # Move all uninstall steps to the front steps = sorted( steps, key=lambda step: 0 if step[0] == Uninstall else 1 ) self.__installer = Installer(steps=steps) self.__thread = QThread(self) self.__thread.start() self.__installer.moveToThread(self.__thread) self.__installer.finished.connect(self.__on_installer_finished) self.__installer.error.connect(self.__on_installer_error) self.__installer.installStatusChanged.connect( self.__progress.setLabelText) self.__progress.show() self.__progress.setLabelText("Installing") self.__installer.start() else: self.accept() def __on_installer_error(self, command, pkg, retcode, output): message_error( "An error occurred while running a subprocess", title="Error", informative_text="{} exited with non zero status.".format(command), details="".join(output), parent=self ) self.reject() def __on_installer_finished(self): message_information( "Please restart Orange for changes to take effect.", parent=self) self.accept()
class OsmDownloaderDialog(QDialog, FORM_CLASS): """Downloader for OSM data.""" def __init__(self, parent=None, iface=None): """Constructor for import dialog. :param parent: Optional widget to use as parent :type parent: QWidget :param iface: An instance of QGisInterface :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = iface self.buildings_url = 'http://osm.linfiniti.com/buildings-shp' self.building_points_url = \ 'http://osm.linfiniti.com/building-points-shp' self.roads_url = 'http://osm.linfiniti.com/roads-shp' self.help_context = 'openstreetmap_downloader' # creating progress dialog for download self.progress_dialog = QProgressDialog(self) self.progress_dialog.setAutoClose(False) title = self.tr('InaSAFE OpenStreetMap Downloader') self.progress_dialog.setWindowTitle(title) # Set up context help help_button = self.button_box.button(QtGui.QDialogButtonBox.Help) help_button.clicked.connect(self.show_help) self.show_info() # set up the validator for the file name prefix expression = QRegExp('^[A-Za-z0-9-_]*$') validator = QRegExpValidator(expression, self.filename_prefix) self.filename_prefix.setValidator(validator) # Set Proxy in webpage proxy = get_proxy() self.network_manager = QNetworkAccessManager(self) if proxy is not None: self.network_manager.setProxy(proxy) self.restore_state() # Setup the rectangle map tool self.canvas = iface.mapCanvas() self.rectangle_map_tool = \ RectangleMapTool(self.canvas) self.rectangle_map_tool.rectangle_created.connect( self.update_extent_from_rectangle) self.button_extent_rectangle.clicked.connect( self.drag_rectangle_on_map_canvas) # Setup pan tool self.pan_tool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.pan_tool) self.update_extent_from_map_canvas() def show_info(self): """Show usage info to the user.""" # Read the header and footer html snippets header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE) body = self.tr( 'This tool will fetch building (\'structure\') or road (' '\'highway\') data from the OpenStreetMap project for you. ' 'The downloaded data will have InaSAFE keywords defined and a ' 'default QGIS style applied. To use this tool effectively:' ) tips = m.BulletedList() tips.add(self.tr( 'Your current extent, when opening this window, will be used to ' 'determine the area for which you want data to be retrieved.' 'You can interactively select the area by using the ' '\'select on map\' button - which will temporarily hide this ' 'window and allow you to drag a rectangle on the map. After you ' 'have finished dragging the rectangle, this window will ' 'reappear.')) tips.add(self.tr( 'Check the output directory is correct. Note that the saved ' 'dataset will be called either roads.shp or buildings.shp (and ' 'associated files).' )) tips.add(self.tr( 'By default simple file names will be used (e.g. roads.shp, ' 'buildings.shp). If you wish you can specify a prefix to ' 'add in front of this default name. For example using a prefix ' 'of \'padang-\' will cause the downloaded files to be saved as ' '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that ' 'the only allowed prefix characters are A-Z, a-z, 0-9 and the ' 'characters \'-\' and \'_\'. You can leave this blank if you ' 'prefer.' )) tips.add(self.tr( 'If a dataset already exists in the output directory it will be ' 'overwritten.' )) tips.add(self.tr( 'This tool requires a working internet connection and fetching ' 'buildings or roads will consume your bandwidth.')) tips.add(m.Link( 'http://www.openstreetmap.org/copyright', text=self.tr( 'Downloaded data is copyright OpenStreetMap contributors' ' (click for more info).') )) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.web_view.setHtml(string) def restore_state(self): """ Read last state of GUI from configuration file.""" settings = QSettings() try: last_path = settings.value('directory', type=str) except TypeError: last_path = '' self.output_directory.setText(last_path) def save_state(self): """ Store current state of GUI to configuration file """ settings = QSettings() settings.setValue('directory', self.output_directory.text()) def show_help(self): """Load the help text for the dialog.""" show_context_help(self.help_context) def update_extent(self, extent): """Update extent value in GUI based from an extent. :param extent: A list in the form [xmin, ymin, xmax, ymax] where all coordinates provided are in Geographic / EPSG:4326. :type extent: list """ self.min_longitude.setText(str(extent[0])) self.min_latitude.setText(str(extent[1])) self.max_longitude.setText(str(extent[2])) self.max_latitude.setText(str(extent[3])) def update_extent_from_map_canvas(self): """Update extent value in GUI based from value in map. .. note:: Delegates to update_extent() """ self.groupBox.setTitle(self.tr('Bounding box from the map canvas')) # Get the extent as [xmin, ymin, xmax, ymax] extent = viewport_geo_array(self.iface.mapCanvas()) self.update_extent(extent) def update_extent_from_rectangle(self): """Update extent value in GUI based from the QgsMapTool rectangle. .. note:: Delegates to update_extent() """ self.show() self.canvas.unsetMapTool(self.rectangle_map_tool) self.canvas.setMapTool(self.pan_tool) rectangle = self.rectangle_map_tool.rectangle() if rectangle: self.groupBox.setTitle(self.tr('Bounding box from rectangle')) extent = rectangle_geo_array(rectangle, self.iface.mapCanvas()) self.update_extent(extent) def validate_extent(self): """Validate the bounding box before user click OK to download. :return: True if the bounding box is valid, otherwise False :rtype: bool """ min_latitude = float(str(self.min_latitude.text())) max_latitude = float(str(self.max_latitude.text())) min_longitude = float(str(self.min_longitude.text())) max_longitude = float(str(self.max_longitude.text())) # min_latitude < max_latitude if min_latitude >= max_latitude: return False # min_longitude < max_longitude if min_longitude >= max_longitude: return False # -90 <= latitude <= 90 if min_latitude < -90 or min_latitude > 90: return False if max_latitude < -90 or max_latitude > 90: return False # -180 <= longitude <= 180 if min_longitude < -180 or min_longitude > 180: return False if max_longitude < -180 or max_longitude > 180: return False return True @pyqtSignature('') # prevents actions being handled twice def on_directory_button_clicked(self): """Show a dialog to choose directory.""" # noinspection PyCallByClass,PyTypeChecker self.output_directory.setText(QFileDialog.getExistingDirectory( self, self.tr('Select download directory'))) def drag_rectangle_on_map_canvas(self): """Hide the dialog and allow the user to draw a rectangle.""" self.hide() self.rectangle_map_tool.reset() self.canvas.unsetMapTool(self.pan_tool) self.canvas.setMapTool(self.rectangle_map_tool) def accept(self): """Do osm download and display it in QGIS.""" error_dialog_title = self.tr('InaSAFE OpenStreetMap Downloader Error') # Lock the groupbox self.groupBox.setDisabled(True) # Validate extent valid_flag = self.validate_extent() if not valid_flag: message = self.tr( 'The bounding box is not valid. Please make sure it is ' 'valid or check your projection!') # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box(self, error_dialog_title, message) # Unlock the groupbox self.groupBox.setEnabled(True) return # Get all the feature types index = self.feature_type.currentIndex() if index == 0: feature_types = ['buildings', 'roads', 'building-points'] elif index == 1: feature_types = ['buildings'] elif index == 2: feature_types = ['building-points'] else: feature_types = ['roads'] try: self.save_state() self.require_directory() for feature_type in feature_types: output_directory = self.output_directory.text() output_prefix = self.filename_prefix.text() overwrite = self.overwrite_checkBox.isChecked() output_base_file_path = self.get_output_base_path( output_directory, output_prefix, feature_type, overwrite) self.download(feature_type, output_base_file_path) try: self.load_shapefile(feature_type, output_base_file_path) except FileMissingError as exception: display_warning_message_box( self, error_dialog_title, exception.message) self.done(QDialog.Accepted) self.rectangle_map_tool.reset() except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box( self, error_dialog_title, exception.message) self.progress_dialog.cancel() finally: # Unlock the groupbox self.groupBox.setEnabled(True) def get_output_base_path( self, output_directory, output_prefix, feature_type, overwrite): """Get a full base name path to save the shapefile. :param output_directory: The directory where to put results. :type output_directory: str :param output_prefix: The prefix to add for the shapefile. :type output_prefix: str :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param overwrite: Boolean to know if we can overwrite existing files. :type overwrite: bool :return: The base path. :rtype: str """ path = os.path.join( output_directory, '%s%s' % (output_prefix, feature_type)) if overwrite: # If a shapefile exists, we must remove it (only the .shp) shp = '%s.shp' % path if os.path.isfile(shp): os.remove(shp) else: separator = '-' suffix = self.get_unique_file_path_suffix( '%s.shp' % path, separator) if suffix: path = os.path.join(output_directory, '%s%s%s%s' % ( output_prefix, feature_type, separator, suffix)) return path @staticmethod def get_unique_file_path_suffix(file_path, separator='-', i=0): """Return the minimum number to suffix the file to not overwrite one. Example : /tmp/a.txt exists. - With file_path='/tmp/b.txt' will return 0. - With file_path='/tmp/a.txt' will return 1 (/tmp/a-1.txt) :param file_path: The file to check. :type file_path: str :param separator: The separator to add before the prefix. :type separator: str :param i: The minimum prefix to check. :type i: int :return: The minimum prefix you should add to not overwrite a file. :rtype: int """ basename = os.path.splitext(file_path) if i != 0: file_path_test = os.path.join( '%s%s%s%s' % (basename[0], separator, i, basename[1])) else: file_path_test = file_path if os.path.isfile(file_path_test): return OsmDownloaderDialog.get_unique_file_path_suffix( file_path, separator, i + 1) else: return i def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ path = self.output_directory.text() if os.path.exists(path): return title = self.tr('Directory %s not exist') % path question = self.tr( 'Directory %s not exist. Do you want to create it?') % path # noinspection PyCallByClass,PyTypeChecker answer = QMessageBox.question( self, title, question, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: if len(path) != 0: os.makedirs(path) else: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box( self, self.tr('InaSAFE error'), self.tr('Output directory can not be empty.')) raise CanceledImportDialogError() else: raise CanceledImportDialogError() def download(self, feature_type, output_base_path): """Download shapefiles from Kartoza server. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param output_base_path: The base path of the shape file. :type output_base_path: str :raises: ImportDialogError, CanceledImportDialogError """ # preparing necessary data min_longitude = str(self.min_longitude.text()) min_latitude = str(self.min_latitude.text()) max_longitude = str(self.max_longitude.text()) max_latitude = str(self.max_latitude.text()) box = ( '{min_longitude},{min_latitude},{max_longitude},' '{max_latitude}').format( min_longitude=min_longitude, min_latitude=min_latitude, max_longitude=max_longitude, max_latitude=max_latitude ) if feature_type == 'buildings': url = '{url}?bbox={box}&qgis_version=2'.format( url=self.buildings_url, box=box) elif feature_type == 'building-points': url = '{url}?bbox={box}&qgis_version=2'.format( url=self.building_points_url, box=box) else: url = '{url}?bbox={box}&qgis_version=2'.format( url=self.roads_url, box=box) if 'LANG' in os.environ: env_lang = os.environ['LANG'] url += '&lang=%s' % env_lang path = tempfile.mktemp('.shp.zip') # download and extract it self.fetch_zip(url, path, feature_type) self.extract_zip(path, output_base_path) self.progress_dialog.done(QDialog.Accepted) def fetch_zip(self, url, output_path, feature_type): """Download zip containing shp file and write to output_path. :param url: URL of the zip bundle. :type url: str :param output_path: Path of output file, :type output_path: str :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :raises: ImportDialogError - when network error occurred """ LOGGER.debug('Downloading file from URL: %s' % url) LOGGER.debug('Downloading to: %s' % output_path) self.progress_dialog.show() # Infinite progress bar when the server is fetching data. # The progress bar will be updated with the file size later. self.progress_dialog.setMaximum(0) self.progress_dialog.setMinimum(0) self.progress_dialog.setValue(0) # Get a pretty label from feature_type, but not translatable label_feature_type = feature_type.replace('-', ' ') label_text = self.tr('Fetching %s' % label_feature_type) self.progress_dialog.setLabelText(label_text) # Download Process downloader = FileDownloader( self.network_manager, url, output_path, self.progress_dialog) try: result = downloader.download() except IOError as ex: raise IOError(ex) if result[0] is not True: _, error_message = result if result[0] == QNetworkReply.OperationCanceledError: raise CanceledImportDialogError(error_message) else: raise DownloadError(error_message) @staticmethod def extract_zip(zip_path, destination_base_path): """Extract different extensions to the destination base path. Example : test.zip contains a.shp, a.dbf, a.prj and destination_base_path = '/tmp/CT-buildings Expected result : - /tmp/CT-buildings.shp - /tmp/CT-buildings.dbf - /tmp/CT-buildings.prj If two files in the zip with the same extension, only one will be copied. :param zip_path: The path of the .zip file :type zip_path: str :param destination_base_path: The destination base path where the shp will be written to. :type destination_base_path: str :raises: IOError - when not able to open path or output_dir does not exist. """ import zipfile handle = open(zip_path, 'rb') zip_file = zipfile.ZipFile(handle) for name in zip_file.namelist(): extension = os.path.splitext(name)[1] output_final_path = u'%s%s' % (destination_base_path, extension) output_file = open(output_final_path, 'wb') output_file.write(zip_file.read(name)) output_file.close() handle.close() def load_shapefile(self, feature_type, base_path): """Load downloaded shape file to QGIS Main Window. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param base_path: The base path of the shape file (without extension). :type base_path: str :raises: FileMissingError - when buildings.shp not exist """ path = '%s.shp' % base_path if not os.path.exists(path): message = self.tr( '%s does not exist. The server does not have any data for ' 'this extent.' % path) raise FileMissingError(message) self.iface.addVectorLayer(path, feature_type, 'ogr') canvas_srid = self.canvas.mapRenderer().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if QGis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_bar( self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326. ' 'You should enable \'on the fly\' to display ' 'correctly your layers') ) def reject(self): """Redefinition of the reject() method to remove the rectangle selection tool. It will call the super method. """ self.canvas.unsetMapTool(self.rectangle_map_tool) self.rectangle_map_tool.reset() super(OsmDownloaderDialog, self).reject()
def search_bar(self, query): matches = [] progress = QProgressDialog("", "Abort", 0, 50000, self) progress.setWindowTitle("Searching...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setValue(0) width = self.width() height = self.height() x = self.x() y = self.y() self.re_flags = re.UNICODE | re.MULTILINE if not self.ui.chkAdvRegex.isChecked(): query = re.escape(query) if not self.ui.chkAdvCase.isChecked(): self.re_flags |= re.IGNORECASE if self.ui.chkAdvNewline.isChecked(): self.re_flags |= re.DOTALL query_re = re.compile(query, self.re_flags) dir_filter = common.qt_to_unicode(self.ui.txtFilterRe.text()) if dir_filter == "": filter_re = script_analytics.DEFAULT_FILTER else: filter_re = re.compile(dir_filter, re.IGNORECASE | re.DOTALL | re.UNICODE) self.search_flags = 0 if self.ui.chkAdvTrans.isChecked(): self.search_flags |= script_analytics.SEARCH_TRANSLATED if self.ui.chkAdvOrig.isChecked(): self.search_flags |= script_analytics.SEARCH_ORIGINAL if self.ui.chkAdvComments.isChecked(): self.search_flags |= script_analytics.SEARCH_COMMENTS if self.ui.chkAdvNoTags.isChecked(): self.search_flags |= script_analytics.SEARCH_NOTAGS matches = [] for i, total, filename, partial_results in script_analytics.SA.search_gen(query_re, filter_re, self.search_flags): if progress.wasCanceled(): break progress.setValue(i) progress.setMaximum(total) progress.setLabelText(filename) # Re-center the dialog. progress_w = progress.geometry().width() progress_h = progress.geometry().height() new_x = x + ((width - progress_w) / 2) new_y = y + ((height - progress_h) / 2) progress.move(new_x, new_y) matches.extend(partial_results) progress.close() return matches
def setup_workspace(self): data00 = os.path.join(self.iso_dir, DATA00_CPK) data01 = os.path.join(self.iso_dir, DATA01_CPK) voice = os.path.join(self.workspace_dir, VOICE_AWB) self.generate_directories() progress = QProgressDialog("", QtCore.QString(), 0, 11000, self) progress.setWindowTitle("Setting up workspace...") progress.setWindowModality(Qt.Qt.WindowModal) progress.setMinimumDuration(0) progress.setValue(0) progress.setAutoClose(False) progress.setAutoReset(False) progress.setLabelText("Creating directories...") # Do the easy stuff first. if not os.path.isdir(self.changes_dir): os.makedirs(self.changes_dir) progress.setValue(progress.value() + 1) if not os.path.isdir(self.backup_dir): os.makedirs(self.backup_dir) progress.setValue(progress.value() + 1) if not os.path.isdir(self.editor_data_dir): os.makedirs(self.editor_data_dir) progress.setValue(progress.value() + 1) thread_fns = [ {"target": extract_cpk, "kwargs": {"filename": data00, "out_dir": self.data00_dir}}, {"target": extract_cpk, "kwargs": {"filename": data01, "out_dir": self.data01_dir}}, ] # Going to capture stdout because I don't feel like # rewriting the extract functions to play nice with GUI. stdout = sys.stdout sys.stdout = cStringIO.StringIO() for thread_fn in thread_fns: thread = threading.Thread(**thread_fn) thread.start() while thread.isAlive(): thread.join(THREAD_TIMEOUT) output = [line for line in sys.stdout.getvalue().split('\n') if len(line) > 0] progress.setValue(progress.value() + len(output)) if len(output) > 0: progress.setLabelText("Extracting %s..." % output[-1]) sys.stdout = cStringIO.StringIO() sys.stdout = stdout # Give us an ISO directory for the editor to place modified files in. progress.setLabelText("Copying ISO files...") # ISO directory needs to not exist for copytree. if os.path.isdir(self.edited_iso_dir): shutil.rmtree(self.edited_iso_dir) # One more thing we want threaded so it doesn't lock up the GUI. thread = threading.Thread(target = shutil.copytree, kwargs = {"src": self.iso_dir, "dst": self.edited_iso_dir}) thread.start() while thread.isAlive(): thread.join(THREAD_TIMEOUT) progress.setLabelText("Copying ISO files...") # It has to increase by some amount or it won't update and the UI will lock up. progress.setValue(progress.value() + 1) # shutil.copytree(self.iso_dir, self.edited_iso_dir) progress.setValue(progress.value() + 1) # Files we want to make blank, because they're unnecessary. blank_files = [ os.path.join(self.edited_iso_dir, "PSP_GAME", "INSDIR", "UMDIMAGE.DAT"), os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "DATA.BIN"), os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "EBOOT.BIN"), os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "UPDATE", "PARAM.SFO"), ] for blank in blank_files: with open(blank, "wb") as f: pass # NOTE: To re-enable this, Simply remove the hashtag before the codes. # Copy the decrypted EBOOT into the ISO folder and apply our hacks to it. # progress.setLabelText("Hacking EBOOT...") # progress.setValue(progress.value() + 1) # hacked_eboot = BitStream(filename = self.eboot_path) # hacked_eboot = apply_eboot_patches(hacked_eboot) # with open(os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN"), "wb") as f: #hacked_eboot.tofile(f) # shutil.copy(self.eboot_path, os.path.join(self.edited_iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN")) progress.setLabelText("Extracting editor data...") progress.setValue(progress.value() + 1) # Extract the editor data. editor_data = zipfile.ZipFile("data/editor_data.zip", "r") editor_data.extractall(self.editor_data_dir) editor_data.close() progress.setValue(progress.maximum()) progress.close() self.ui.grpStep4.setEnabled(False) self.ui.grpStep5.setEnabled(True)
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None): """ Prompt the user for layer import settings, and perform the layer import. :param labelLayer: The top label layer source :param labelingSlots: An instance of LabelingGui.LabelingSlots :param parent_widget: The Qt GUI parent object """ writeSeeds = labelingSlots.labelInput assert isinstance( writeSeeds, lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds)) opLabels = writeSeeds.getRealOperator() assert isinstance(opLabels, lazyflow.graph.Operator ), "slot's operator is of type %r" % (type(opLabels)) recentlyImported = PreferencesManager().get('labeling', 'recently imported') mostRecentProjectPath = PreferencesManager().get('shell', 'recently opened') mostRecentImageFile = PreferencesManager().get('DataSelection', 'recent image') if recentlyImported: defaultDirectory = os.path.split(recentlyImported)[0] elif mostRecentProjectPath: defaultDirectory = os.path.split(mostRecentProjectPath)[0] elif mostRecentImageFile: defaultDirectory = os.path.split(mostRecentImageFile)[0] else: defaultDirectory = os.path.expanduser('~') fileNames = DataSelectionGui.getImageFileNamesToOpen( parent_widget, defaultDirectory) fileNames = map(str, fileNames) if not fileNames: return PreferencesManager().set('labeling', 'recently imported', fileNames[0]) try: # Initialize operators opImport = OpInputDataReader(parent=opLabels.parent) opCache = OpArrayCache(parent=opLabels.parent) opMetadataInjector = OpMetadataInjector(parent=opLabels.parent) opReorderAxes = OpReorderAxes(parent=opLabels.parent) # Set up the pipeline as follows: # # opImport --> opCache --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput # / / # User-specified axisorder labelInput.meta.axistags opImport.WorkingDirectory.setValue(defaultDirectory) opImport.FilePath.setValue(fileNames[0] if len(fileNames) == 1 else os.path.pathsep.join(fileNames)) assert opImport.Output.ready() opCache.blockShape.setValue(opImport.Output.meta.shape) opCache.Input.connect(opImport.Output) assert opCache.Output.ready() opMetadataInjector.Input.connect(opCache.Output) metadata = opCache.Output.meta.copy() opMetadataInjector.Metadata.setValue(metadata) opReorderAxes.Input.connect(opImport.Output) # Transpose the axes for assignment to the labeling operator. opReorderAxes.AxisOrder.setValue(writeSeeds.meta.getAxisKeys()) # We'll show a little window with a busy indicator while the data is loading busy_dlg = QProgressDialog(parent=parent_widget) busy_dlg.setLabelText("Importing Label Data...") busy_dlg.setCancelButton(None) busy_dlg.setMinimum(100) busy_dlg.setMaximum(100) def close_busy_dlg(*args): QApplication.postEvent(busy_dlg, QCloseEvent()) # Load the data from file into our cache # When it's done loading, close the progress dialog. req = opCache.Output[:] req.notify_finished(close_busy_dlg) req.notify_failed(close_busy_dlg) req.submit() busy_dlg.exec_() readData = req.result maxLabels = len(labelingSlots.labelNames.value) unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True) labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) del readData # Ask the user how to interpret the data. settingsDlg = LabelImportOptionsDlg(parent_widget, fileNames, opMetadataInjector.Output, labelingSlots.labelInput, labelInfo) def handle_updated_axes(): # The user is specifying a new interpretation of the file's axes updated_axisorder = str(settingsDlg.axesEdit.text()) metadata = opMetadataInjector.Metadata.value.copy() metadata.axistags = vigra.defaultAxistags(updated_axisorder) opMetadataInjector.Metadata.setValue(metadata) settingsDlg.axesEdit.editingFinished.connect(handle_updated_axes) dlg_result = settingsDlg.exec_() if dlg_result != LabelImportOptionsDlg.Accepted: return # Get user's chosen label mapping from dlg labelMapping = settingsDlg.labelMapping # Get user's chosen offsets. # Offsets in dlg only include the file axes, not the 5D axes expected by the label input, # so expand them to full 5D axes_5d = opReorderAxes.Output.meta.getAxisKeys() tagged_offsets = collections.OrderedDict( zip(axes_5d, [0] * len(axes_5d))) tagged_offsets.update( dict( zip(opMetadataInjector.Output.meta.getAxisKeys(), settingsDlg.imageOffsets))) imageOffsets = tagged_offsets.values() # Optimization if mapping is identity if labelMapping.keys() == labelMapping.values(): labelMapping = None # This will be fast (it's already cached) label_data = opReorderAxes.Output[:].wait() # Map input labels to output labels if labelMapping: # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential) # But this supports potentially huge values of unique_read_labels (in the billions), # without needing GB of RAM. mapping_indexes = numpy.searchsorted(unique_read_labels, label_data) new_labels = numpy.array( [labelMapping[x] for x in unique_read_labels]) label_data[:] = new_labels[mapping_indexes] label_roi = numpy.array(roiFromShape(opReorderAxes.Output.meta.shape)) label_roi += imageOffsets label_slice = roiToSlice(*label_roi) writeSeeds[label_slice] = label_data finally: opReorderAxes.cleanUp() opMetadataInjector.cleanUp() opCache.cleanUp() opImport.cleanUp()
class CpkPacker(): def __init__(self, parent = None): self.parent = parent self.process = None def __pack_cpk(self, csv, cpk): self.progress.setValue(0) self.progress.setMaximum(1000) self.progress.setLabelText("Building %s" % cpk) process = QProcess() process.start("tools/cpkmakec", [csv, cpk, "-align=2048", "-mode=FILENAME"]) percent = 0 while not process.waitForFinished(100): output = QString(process.readAll()) output = output.split("\n", QString.SkipEmptyParts) for line in output: line = common.qt_to_unicode(line) match = OUTPUT_RE.search(line) if match == None: continue percent = float(match.group(1)) * 1000 self.progress.setValue(percent) percent += 1 def __cache_outdated(self, src_dir, cache_file): if not os.path.isfile(cache_file): return True cache_updated = os.path.getmtime(cache_file) for src_file in list_all_files(src_dir): if os.path.getmtime(src_file) > cache_updated: return True return False def create_archives(self): try: self.width = self.parent.width() self.height = self.parent.height() self.x = self.parent.x() self.y = self.parent.y() except: self.width = 1920 self.height = 1080 self.x = 0 self.y = 0 self.progress = QProgressDialog("Reading...", QtCore.QString(), 0, 7600, self.parent) self.progress.setWindowModality(Qt.Qt.WindowModal) self.progress.setValue(0) self.progress.setAutoClose(False) self.progress.setMinimumDuration(0) USRDIR = os.path.join(common.editor_config.iso_dir, "PSP_GAME", "USRDIR") eboot_path = os.path.join(common.editor_config.iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN") eboot = BitStream(filename = eboot_path) eboot = eboot_patch.apply_eboot_patches(eboot) # So we can loop. :) ARCHIVE_INFO = [ { "dir": common.editor_config.data00_dir, "cpk": os.path.join(USRDIR, "data00.cpk"), "csv": os.path.join("data", "data00.csv" if not common.editor_config.quick_build else "data00-quick.csv"), "name": "data00.cpk", "pack": common.editor_config.pack_data00, }, { "dir": common.editor_config.data01_dir, "cpk": os.path.join(USRDIR, "data01.cpk"), "csv": os.path.join("data", "data01.csv" if not common.editor_config.quick_build else "data01-quick.csv"), "name": "data01.cpk", "pack": common.editor_config.pack_data01, }, ] # temp_dir = tempfile.mkdtemp(prefix = "sdse-") temp_dir = common.editor_config.build_cache for archive in ARCHIVE_INFO: if not archive["pack"]: continue self.progress.setWindowTitle("Building " + archive["name"]) toc_info = {} file_list = None if archive["toc"]: file_list = [] toc = get_toc(eboot, archive["toc"]) for entry in toc: filename = entry["filename"] pos_pos = entry["file_pos_pos"] len_pos = entry["file_len_pos"] toc_info[filename] = [pos_pos, len_pos] file_list.append(filename) # Causes memory issues if I use the original order, for whatever reason. file_list = None csv_template_f = open(archive["csv"], "rb") csv_template = csv.reader(csv_template_f) csv_out_path = os.path.join(temp_dir, "cpk.csv") csv_out_f = open(csv_out_path, "wb") csv_out = csv.writer(csv_out_f) for row in csv_template: if len(row) < 4: continue base_path = row[0] real_path = os.path.join(archive["dir"], base_path) out_path = os.path.join(temp_dir, archive["name"], base_path) self.progress.setValue(self.progress.value() + 1) self.progress.setLabelText("Reading...\n%s" % real_path) # All items in the CPK list should be files. # Therefore, if we have a directory, then it needs to be packed. if os.path.isdir(real_path): if self.__cache_outdated(real_path, out_path): out_dir = os.path.dirname(out_path) try: os.makedirs(out_dir) except: pass data = pack_dir(real_path) with open(out_path, "wb") as out_file: data.tofile(out_file) del data elif os.path.isfile(real_path): # If it's a file, though, we can just use it directly. out_path = real_path row[0] = out_path csv_out.writerow(row) csv_template_f.close() csv_out_f.close() self.__pack_cpk(csv_out_path, archive["cpk"]) # We're playing fast and loose with the file count anyway, so why not? self.file_count += 1 self.progress.setValue(self.file_count) self.progress.setLabelText("Saving " + archive["name"] + "...") if archive["toc"]: for entry in table_of_contents: if not entry in toc_info: _LOGGER.warning("%s missing from %s table of contents." % (entry, archive["name"])) continue file_pos = table_of_contents[entry]["pos"] file_size = table_of_contents[entry]["size"] eboot.overwrite(BitStream(uintle = file_pos, length = 32), toc_info[entry][0] * 8) eboot.overwrite(BitStream(uintle = file_size, length = 32), toc_info[entry][1] * 8) del table_of_contents self.progress.setWindowTitle("Building...") self.progress.setLabelText("Saving EBOOT.BIN...") self.progress.setValue(self.progress.maximum()) with open(eboot_path, "wb") as f: eboot.tofile(f) # Text replacement to_replace = eboot_text.get_eboot_text() for replacement in to_replace: orig = bytearray(replacement.orig, encoding = replacement.enc) # If they left something blank, write the original text back. if len(replacement.text) == 0: data = orig else: data = bytearray(replacement.text, encoding = replacement.enc) pos = replacement.pos.int + eboot_offset padding = len(orig) - len(data) if padding > 0: # Null bytes to fill the rest of the space the original took. data.extend(bytearray(padding)) data = ConstBitStream(bytes = data) eboot.overwrite(data, pos * 8) eboot_out = os.path.join(common.editor_config.iso_dir, "PSP_GAME", "SYSDIR", "EBOOT.BIN") with open(eboot_out, "wb") as f: eboot.tofile(f) self.progress.close()
class OsmDownloaderDialog(QDialog, FORM_CLASS): """Downloader for OSM data.""" def __init__(self, parent=None, iface=None): """Constructor for import dialog. :param parent: Optional widget to use as parent :type parent: QWidget :param iface: An instance of QGisInterface :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = iface self.buildings_url = 'http://osm.linfiniti.com/buildings-shp' self.building_points_url = \ 'http://osm.linfiniti.com/building-points-shp' self.roads_url = 'http://osm.linfiniti.com/roads-shp' self.help_context = 'openstreetmap_downloader' # creating progress dialog for download self.progress_dialog = QProgressDialog(self) self.progress_dialog.setAutoClose(False) title = self.tr('InaSAFE OpenStreetMap Downloader') self.progress_dialog.setWindowTitle(title) # Set up context help help_button = self.button_box.button(QtGui.QDialogButtonBox.Help) help_button.clicked.connect(self.show_help) self.show_info() # set up the validator for the file name prefix expression = QRegExp('^[A-Za-z0-9-_]*$') validator = QRegExpValidator(expression, self.filename_prefix) self.filename_prefix.setValidator(validator) # Set Proxy in webpage proxy = get_proxy() self.network_manager = QNetworkAccessManager(self) if proxy is not None: self.network_manager.setProxy(proxy) self.restore_state() # Setup the rectangle map tool self.canvas = iface.mapCanvas() self.rectangle_map_tool = \ RectangleMapTool(self.canvas) self.rectangle_map_tool.rectangle_created.connect( self.update_extent_from_rectangle) self.button_extent_rectangle.clicked.connect( self.drag_rectangle_on_map_canvas) # Setup pan tool self.pan_tool = QgsMapToolPan(self.canvas) self.canvas.setMapTool(self.pan_tool) self.update_extent_from_map_canvas() def show_info(self): """Show usage info to the user.""" # Read the header and footer html snippets header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE) body = self.tr( 'This tool will fetch building (\'structure\') or road (' '\'highway\') data from the OpenStreetMap project for you. ' 'The downloaded data will have InaSAFE keywords defined and a ' 'default QGIS style applied. To use this tool effectively:') tips = m.BulletedList() tips.add( self. tr('Your current extent, when opening this window, will be used to ' 'determine the area for which you want data to be retrieved.' 'You can interactively select the area by using the ' '\'select on map\' button - which will temporarily hide this ' 'window and allow you to drag a rectangle on the map. After you ' 'have finished dragging the rectangle, this window will ' 'reappear.')) tips.add( self. tr('Check the output directory is correct. Note that the saved ' 'dataset will be called either roads.shp or buildings.shp (and ' 'associated files).')) tips.add( self. tr('By default simple file names will be used (e.g. roads.shp, ' 'buildings.shp). If you wish you can specify a prefix to ' 'add in front of this default name. For example using a prefix ' 'of \'padang-\' will cause the downloaded files to be saved as ' '\'padang-roads.shp\' and \'padang-buildings.shp\'. Note that ' 'the only allowed prefix characters are A-Z, a-z, 0-9 and the ' 'characters \'-\' and \'_\'. You can leave this blank if you ' 'prefer.')) tips.add( self. tr('If a dataset already exists in the output directory it will be ' 'overwritten.')) tips.add( self. tr('This tool requires a working internet connection and fetching ' 'buildings or roads will consume your bandwidth.')) tips.add( m.Link( 'http://www.openstreetmap.org/copyright', text=self.tr( 'Downloaded data is copyright OpenStreetMap contributors' ' (click for more info).'))) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.web_view.setHtml(string) def restore_state(self): """ Read last state of GUI from configuration file.""" settings = QSettings() try: last_path = settings.value('directory', type=str) except TypeError: last_path = '' self.output_directory.setText(last_path) def save_state(self): """ Store current state of GUI to configuration file """ settings = QSettings() settings.setValue('directory', self.output_directory.text()) def show_help(self): """Load the help text for the dialog.""" show_context_help(self.help_context) def update_extent(self, extent): """Update extent value in GUI based from an extent. :param extent: A list in the form [xmin, ymin, xmax, ymax] where all coordinates provided are in Geographic / EPSG:4326. :type extent: list """ self.min_longitude.setText(str(extent[0])) self.min_latitude.setText(str(extent[1])) self.max_longitude.setText(str(extent[2])) self.max_latitude.setText(str(extent[3])) def update_extent_from_map_canvas(self): """Update extent value in GUI based from value in map. .. note:: Delegates to update_extent() """ self.groupBox.setTitle(self.tr('Bounding box from the map canvas')) # Get the extent as [xmin, ymin, xmax, ymax] extent = viewport_geo_array(self.iface.mapCanvas()) self.update_extent(extent) def update_extent_from_rectangle(self): """Update extent value in GUI based from the QgsMapTool rectangle. .. note:: Delegates to update_extent() """ self.show() self.canvas.unsetMapTool(self.rectangle_map_tool) self.canvas.setMapTool(self.pan_tool) rectangle = self.rectangle_map_tool.rectangle() if rectangle: self.groupBox.setTitle(self.tr('Bounding box from rectangle')) extent = rectangle_geo_array(rectangle, self.iface.mapCanvas()) self.update_extent(extent) def validate_extent(self): """Validate the bounding box before user click OK to download. :return: True if the bounding box is valid, otherwise False :rtype: bool """ min_latitude = float(str(self.min_latitude.text())) max_latitude = float(str(self.max_latitude.text())) min_longitude = float(str(self.min_longitude.text())) max_longitude = float(str(self.max_longitude.text())) # min_latitude < max_latitude if min_latitude >= max_latitude: return False # min_longitude < max_longitude if min_longitude >= max_longitude: return False # -90 <= latitude <= 90 if min_latitude < -90 or min_latitude > 90: return False if max_latitude < -90 or max_latitude > 90: return False # -180 <= longitude <= 180 if min_longitude < -180 or min_longitude > 180: return False if max_longitude < -180 or max_longitude > 180: return False return True @pyqtSignature('') # prevents actions being handled twice def on_directory_button_clicked(self): """Show a dialog to choose directory.""" # noinspection PyCallByClass,PyTypeChecker self.output_directory.setText( QFileDialog.getExistingDirectory( self, self.tr('Select download directory'))) def drag_rectangle_on_map_canvas(self): """Hide the dialog and allow the user to draw a rectangle.""" self.hide() self.rectangle_map_tool.reset() self.canvas.unsetMapTool(self.pan_tool) self.canvas.setMapTool(self.rectangle_map_tool) def accept(self): """Do osm download and display it in QGIS.""" error_dialog_title = self.tr('InaSAFE OpenStreetMap Downloader Error') # Lock the groupbox self.groupBox.setDisabled(True) # Validate extent valid_flag = self.validate_extent() if not valid_flag: message = self.tr( 'The bounding box is not valid. Please make sure it is ' 'valid or check your projection!') # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box(self, error_dialog_title, message) # Unlock the groupbox self.groupBox.setEnabled(True) return # Get all the feature types index = self.feature_type.currentIndex() if index == 0: feature_types = ['buildings', 'roads', 'building-points'] elif index == 1: feature_types = ['buildings'] elif index == 2: feature_types = ['building-points'] else: feature_types = ['roads'] try: self.save_state() self.require_directory() for feature_type in feature_types: output_directory = self.output_directory.text() output_prefix = self.filename_prefix.text() overwrite = self.overwrite_checkBox.isChecked() output_base_file_path = self.get_output_base_path( output_directory, output_prefix, feature_type, overwrite) self.download(feature_type, output_base_file_path) try: self.load_shapefile(feature_type, output_base_file_path) except FileMissingError as exception: display_warning_message_box(self, error_dialog_title, exception.message) self.done(QDialog.Accepted) self.rectangle_map_tool.reset() except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as exception: # pylint: disable=broad-except # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box(self, error_dialog_title, exception.message) self.progress_dialog.cancel() finally: # Unlock the groupbox self.groupBox.setEnabled(True) def get_output_base_path(self, output_directory, output_prefix, feature_type, overwrite): """Get a full base name path to save the shapefile. :param output_directory: The directory where to put results. :type output_directory: str :param output_prefix: The prefix to add for the shapefile. :type output_prefix: str :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param overwrite: Boolean to know if we can overwrite existing files. :type overwrite: bool :return: The base path. :rtype: str """ path = os.path.join(output_directory, '%s%s' % (output_prefix, feature_type)) if overwrite: # If a shapefile exists, we must remove it (only the .shp) shp = '%s.shp' % path if os.path.isfile(shp): os.remove(shp) else: separator = '-' suffix = self.get_unique_file_path_suffix('%s.shp' % path, separator) if suffix: path = os.path.join( output_directory, '%s%s%s%s' % (output_prefix, feature_type, separator, suffix)) return path @staticmethod def get_unique_file_path_suffix(file_path, separator='-', i=0): """Return the minimum number to suffix the file to not overwrite one. Example : /tmp/a.txt exists. - With file_path='/tmp/b.txt' will return 0. - With file_path='/tmp/a.txt' will return 1 (/tmp/a-1.txt) :param file_path: The file to check. :type file_path: str :param separator: The separator to add before the prefix. :type separator: str :param i: The minimum prefix to check. :type i: int :return: The minimum prefix you should add to not overwrite a file. :rtype: int """ basename = os.path.splitext(file_path) if i != 0: file_path_test = os.path.join( '%s%s%s%s' % (basename[0], separator, i, basename[1])) else: file_path_test = file_path if os.path.isfile(file_path_test): return OsmDownloaderDialog.get_unique_file_path_suffix( file_path, separator, i + 1) else: return i def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ path = self.output_directory.text() if os.path.exists(path): return title = self.tr('Directory %s not exist') % path question = self.tr( 'Directory %s not exist. Do you want to create it?') % path # noinspection PyCallByClass,PyTypeChecker answer = QMessageBox.question(self, title, question, QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: if len(path) != 0: os.makedirs(path) else: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList display_warning_message_box( self, self.tr('InaSAFE error'), self.tr('Output directory can not be empty.')) raise CanceledImportDialogError() else: raise CanceledImportDialogError() def download(self, feature_type, output_base_path): """Download shapefiles from Kartoza server. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param output_base_path: The base path of the shape file. :type output_base_path: str :raises: ImportDialogError, CanceledImportDialogError """ # preparing necessary data min_longitude = str(self.min_longitude.text()) min_latitude = str(self.min_latitude.text()) max_longitude = str(self.max_longitude.text()) max_latitude = str(self.max_latitude.text()) box = ('{min_longitude},{min_latitude},{max_longitude},' '{max_latitude}').format(min_longitude=min_longitude, min_latitude=min_latitude, max_longitude=max_longitude, max_latitude=max_latitude) if feature_type == 'buildings': url = '{url}?bbox={box}&qgis_version=2'.format( url=self.buildings_url, box=box) elif feature_type == 'building-points': url = '{url}?bbox={box}&qgis_version=2'.format( url=self.building_points_url, box=box) else: url = '{url}?bbox={box}&qgis_version=2'.format(url=self.roads_url, box=box) if 'LANG' in os.environ: env_lang = os.environ['LANG'] url += '&lang=%s' % env_lang path = tempfile.mktemp('.shp.zip') # download and extract it self.fetch_zip(url, path, feature_type) self.extract_zip(path, output_base_path) self.progress_dialog.done(QDialog.Accepted) def fetch_zip(self, url, output_path, feature_type): """Download zip containing shp file and write to output_path. :param url: URL of the zip bundle. :type url: str :param output_path: Path of output file, :type output_path: str :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :raises: ImportDialogError - when network error occurred """ LOGGER.debug('Downloading file from URL: %s' % url) LOGGER.debug('Downloading to: %s' % output_path) self.progress_dialog.show() # Infinite progress bar when the server is fetching data. # The progress bar will be updated with the file size later. self.progress_dialog.setMaximum(0) self.progress_dialog.setMinimum(0) self.progress_dialog.setValue(0) # Get a pretty label from feature_type, but not translatable label_feature_type = feature_type.replace('-', ' ') label_text = self.tr('Fetching %s' % label_feature_type) self.progress_dialog.setLabelText(label_text) # Download Process downloader = FileDownloader(self.network_manager, url, output_path, self.progress_dialog) try: result = downloader.download() except IOError as ex: raise IOError(ex) if result[0] is not True: _, error_message = result if result[0] == QNetworkReply.OperationCanceledError: raise CanceledImportDialogError(error_message) else: raise DownloadError(error_message) @staticmethod def extract_zip(zip_path, destination_base_path): """Extract different extensions to the destination base path. Example : test.zip contains a.shp, a.dbf, a.prj and destination_base_path = '/tmp/CT-buildings Expected result : - /tmp/CT-buildings.shp - /tmp/CT-buildings.dbf - /tmp/CT-buildings.prj If two files in the zip with the same extension, only one will be copied. :param zip_path: The path of the .zip file :type zip_path: str :param destination_base_path: The destination base path where the shp will be written to. :type destination_base_path: str :raises: IOError - when not able to open path or output_dir does not exist. """ import zipfile handle = open(zip_path, 'rb') zip_file = zipfile.ZipFile(handle) for name in zip_file.namelist(): extension = os.path.splitext(name)[1] output_final_path = u'%s%s' % (destination_base_path, extension) output_file = open(output_final_path, 'wb') output_file.write(zip_file.read(name)) output_file.close() handle.close() def load_shapefile(self, feature_type, base_path): """Load downloaded shape file to QGIS Main Window. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param base_path: The base path of the shape file (without extension). :type base_path: str :raises: FileMissingError - when buildings.shp not exist """ path = '%s.shp' % base_path if not os.path.exists(path): message = self.tr( '%s does not exist. The server does not have any data for ' 'this extent.' % path) raise FileMissingError(message) self.iface.addVectorLayer(path, feature_type, 'ogr') canvas_srid = self.canvas.mapRenderer().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if QGis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_bar( self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326. ' 'You should enable \'on the fly\' to display ' 'correctly your layers')) def reject(self): """Redefinition of the reject() method to remove the rectangle selection tool. It will call the super method. """ self.canvas.unsetMapTool(self.rectangle_map_tool) self.rectangle_map_tool.reset() super(OsmDownloaderDialog, self).reject()
class OsmDownloader(QDialog, Ui_OsmDownloaderBase): """Downloader for OSM data.""" def __init__(self, parent=None, iface=None): """Constructor for import dialog. :param parent: Optional widget to use as parent :type parent: QWidget :param iface: An instance of QGisInterface :type iface: QGisInterface """ QDialog.__init__(self, parent) self.parent = parent self.setupUi(self) self.setWindowTitle(self.tr('InaSAFE OpenStreetMap Downloader')) self.iface = iface self.url = "http://osm.linfiniti.com/buildings-shp" # creating progress dialog for download self.progressDialog = QProgressDialog(self) self.progressDialog.setAutoClose(False) myTitle = self.tr("InaSAFE OpenStreetMap Downloader") self.progressDialog.setWindowTitle(myTitle) # Set up context help helpButton = self.buttonBox.button(QtGui.QDialogButtonBox.Help) QtCore.QObject.connect(helpButton, QtCore.SIGNAL('clicked()'), self.show_help) self.show_info() self.network_manager = QNetworkAccessManager(self) self.restore_state() self.update_extent() def show_info(self): """Show usage info to the user.""" # Read the header and footer html snippets header = html_header() footer = html_footer() string = header heading = m.Heading(self.tr('OSM Downloader'), **INFO_STYLE) body = self.tr( 'This tool will fetch building (\'structure\') data from the ' 'OpenStreetMap project for you. The downloaded data will have ' 'InaSAFE keywords defined and a default QGIS style applied. To ' 'use this tool effectively:' ) tips = m.BulletedList() tips.add(self.tr( 'Use QGIS to zoom in to the area for which you want building data ' 'to be retrieved.')) tips.add(self.tr( 'Check the output directory is correct. Note that the saved ' 'dataset will be called buildings.shp (and its associated files).' )) tips.add(self.tr( 'If a dataset already exists in the output directory it will be ' 'overwritten.' )) tips.add(self.tr( 'This tool requires a working internet connection and fetching ' 'buildings will consume your bandwidth.')) tips.add(m.Link( 'http://www.openstreetmap.org/copyright', text=self.tr( 'Downloaded data is copyright OpenStreetMap contributors' ' (click for more info).') )) message = m.Message() message.add(heading) message.add(body) message.add(tips) string += message.to_html() string += footer self.webView.setHtml(string) def restore_state(self): """ Read last state of GUI from configuration file.""" mySetting = QSettings() self.outDir.setText(mySetting.value('directory')) def save_state(self): """ Store current state of GUI to configuration file """ mySetting = QSettings() mySetting.setValue('directory', self.outDir.text()) def show_help(self): """Load the help text for the dialog.""" show_context_help('openstreetmap_downloader') def update_extent(self): """ Update extent value in GUI based from value in map.""" myExtent = self.iface.mapCanvas().extent() self.minLongitude.setText(str(myExtent.xMinimum())) self.minLatitude.setText(str(myExtent.yMinimum())) self.maxLongitude.setText(str(myExtent.xMaximum())) self.maxLatitude.setText(str(myExtent.yMaximum())) @pyqtSignature('') # prevents actions being handled twice def on_pBtnDir_clicked(self): """ Show a dialog to choose directory """ # noinspection PyCallByClass,PyTypeChecker self.outDir.setText(QFileDialog.getExistingDirectory( self, self.tr("Select download directory"))) def accept(self): """Do osm download and display it in QGIS.""" try: self.save_state() self.require_directory() self.download() self.load_shapefile() self.done(QDialog.Accepted) except CanceledImportDialogError: # don't show anything because this exception raised # when user canceling the import process directly pass except Exception as myEx: # noinspection PyCallByClass,PyTypeChecker,PyArgumentList QMessageBox.warning( self, self.tr("InaSAFE OpenStreetMap downloader error"), str(myEx)) self.progressDialog.cancel() def require_directory(self): """Ensure directory path entered in dialog exist. When the path does not exist, this function will ask the user if he want to create it or not. :raises: CanceledImportDialogError - when user choose 'No' in the question dialog for creating directory. """ myDir = str(self.outDir.text()) if os.path.exists(myDir): return myTitle = self.tr("Directory %s not exist") % myDir myQuestion = self.tr( "Directory %s not exist. Do you want to create it?" ) % myDir # noinspection PyCallByClass,PyTypeChecker myAnswer = QMessageBox.question( self, myTitle, myQuestion, QMessageBox.Yes | QMessageBox.No) if myAnswer == QMessageBox.Yes: os.makedirs(myDir) else: raise CanceledImportDialogError() def download(self): """Download shapefiles from Linfinti server. :raises: ImportDialogError, CanceledImportDialogError """ ## preparing necessary data myMinLng = str(self.minLongitude.text()) myMinLat = str(self.minLatitude.text()) myMaxLng = str(self.maxLongitude.text()) myMaxLat = str(self.maxLatitude.text()) myCoordinate = "{myMinLng},{myMinLat},{myMaxLng},{myMaxLat}".format( myMinLng=myMinLng, myMinLat=myMinLat, myMaxLng=myMaxLng, myMaxLat=myMaxLat ) myShapeUrl = "{url}?bbox={myCoordinate}".format( url=self.url, myCoordinate=myCoordinate ) myFilePath = tempfile.mktemp('.shp.zip') # download and extract it self.fetch_zip(myShapeUrl, myFilePath) print myFilePath print str(self.outDir.text()) self.extract_zip(myFilePath, str(self.outDir.text())) self.progressDialog.done(QDialog.Accepted) def fetch_zip(self, url, output_path): """Download zip containing shp file and write to output_path. :param url: URL of the zip bundle. :type url: str :param output_path: Path of output file, :type output_path: str :raises: ImportDialogError - when network error occurred """ self.progressDialog.show() self.progressDialog.setMaximum(100) self.progressDialog.setValue(0) # myLabelText = "Begin downloading shapefile from " \ # + "%s ..." # self.progressDialog.setLabelText(self.tr(myLabelText) % (url)) myLabelText = self.tr("Downloading shapefile") self.progressDialog.setLabelText(myLabelText) myResult = download_url( self.network_manager, url, output_path, self.progressDialog) if myResult is not True: _, myErrorMessage = myResult raise ImportDialogError(myErrorMessage) def extract_zip(self, path, output_dir): """Extract all content of a .zip file from path to output_dir. :param path: The path of the .zip file :type path: str :param output_dir: Output directory where the shp will be written to. :type output_dir: str :raises: IOError - when not able to open path or output_dir does not exist. """ import zipfile # extract all files... myHandle = open(path, 'rb') myZip = zipfile.ZipFile(myHandle) for myName in myZip.namelist(): myOutPath = os.path.join(output_dir, myName) myOutFile = open(myOutPath, 'wb') myOutFile.write(myZip.read(myName)) myOutFile.close() myHandle.close() def load_shapefile(self): """ Load downloaded shape file to QGIS Main Window. :raises: ImportDialogError - when buildings.shp not exist """ myDir = str(self.outDir.text()) myPath = os.path.join(myDir, 'buildings.shp') if not os.path.exists(myPath): myMessage = self.tr( "%s don't exist. The server don't have buildings data." ) raise ImportDialogError(myMessage) self.iface.addVectorLayer(myPath, 'buildings', 'ogr')
def choose_file(self, selected): global nb if os.path.isdir(selected[0]) : # on a sélectionné un répertoire i = 0 t = sum((len(f) for _, _, f in os.walk(selected[0]))) progbar = QProgressDialog('Copie des fichiers', None, 0, t, self) progbar.setWindowTitle('Copie des fichiers') progbar.setWindowModality(QtCore.Qt.ApplicationModal) for root, dirs, files in os.walk(selected[0]) : # on inspecte récursivement les sous-répertoires progbar.setLabelText('{0} fichiers examinés'.format(i)) for name in files : i += 1 if '%Resume%' in name : continue if fnmatch.fnmatch(name, '*.epub'): # sélection des epub jobfichier = [] jobfichier.append(os.path.abspath(os.path.join(root, name))) racine, ext = os.path.splitext(os.path.join(root, name)) if os.path.isfile(os.path.join(root, 'metadata.opf')): jobfichier.append(os.path.abspath(os.path.join(root, 'metadata.opf'))) elif os.path.isfile(os.path.join(racine, '.opf')): jobfichier.append(os.path.abspath(os.path.join(racine, '.opf'))) # selection des opf else : jobfichier.append(None) if os.path.isfile(os.path.join(root, 'cover.jpg')) : # sélection des covers jobfichier.append(os.path.abspath(os.path.join(root, 'cover.jpg'))) else : jobfichier.append(None) c = conn.cursor() c.execute("insert into ebook(epub, meta, cover) values(?,?,?)", (jobfichier[0], jobfichier[1], jobfichier[2])) progbar.setValue(i) progbar.setValue(t) progbar.hide() elif os.path.isfile(selected[0]) : # on a sélectionné des fichiers epub for elt in selected : if not '%Resume%' in elt : jobfichier = [] jobfichier.append(os.path.abspath(elt)) racine = elt[0:-4] # selection des opf f = os.path.abspath(racine + 'opf') if os.path.isfile(f) : jobfichier.append(f) elif os.path.isfile(os.path.join(os.path.dirname(elt), 'metadata.opf')): jobfichier.append(os.path.join(os.path.dirname(elt), 'metadata.opf')) else : jobfichier.append(None) # selection des couvertures f = os.path.abspath(racine + 'jpg') if os.path.isfile(f): jobfichier.append(f) elif os.path.isfile(os.path.join(os.path.dirname(elt), 'cover.jpg')): jobfichier.append(os.path.join(os.path.dirname(elt), 'cover.jpg')) elif os.path.isfile(os.path.join(os.path.dirname(elt), 'cover.jpeg')): jobfichier.append(os.path.join(os.path.dirname(elt), 'cover.jpeg')) else : jobfichier.append(None) c = conn.cursor() c.execute("insert into ebook values(?,?,?)", (jobfichier[0], jobfichier[1], jobfichier[2])) else : msg = QtGui.QMessageBox(QtGui.QMessageBox.Warning, 'Attention', 'Vous n\'avez pas sélectionné de fichiers', QtGui.QMessageBox.Ok) conn.commit() rowsQuery = "SELECT Count() FROM ebook" c = conn.cursor() c.execute(rowsQuery) global nb nb = c.fetchone()[0]
class specread: def __init__(self, specfile, startLineNum=0, beamline='APS-15IDC',det='CCD',data={},par={}): self.Data=data self.Par=par self.specfile=specfile if beamline=='APS-15IDC': self.APS_15IDC(startLineNum=startLineNum,det=det) if beamline=='APS-9IDC': self.APS_9IDC(startLineNum=startLineNum,det=det) def updateProgress(self): self.progressDialog.setValue(self.progressDialog.value()+1) def APS_15IDC(self,startLineNum=0, det='CCD'): """ Function to read a complete spec File collected at APS 15IDC """ self.progressDialog=QProgressDialog('Reading scans form SPEC File:','Abort',0,100) self.progressDialog.setWindowModality(Qt.WindowModal) self.progressDialog.setWindowTitle('Wait') self.progressDialog.setAutoClose(True) self.progressDialog.setAutoReset(True) self.progressDialog.setMinimum(1) self.Data['YCol']='Apex2' self.Data['NCol']='Monc' fid=open(self.specfile) fdata=fid.readlines() self.SpecFileFull=fdata fid.close() if fdata[0][:2]!='#F': self.Data['NumOfScans']=0 self.Data['Message']='The file is not a valid specfile!!' print 'Error:: The file is not a valid specfile!!' else: startScanLineNums=[i for i in range(startLineNum,len(fdata)) if fdata[i][:2]=='#S'] self.progressDialog.setMaximum(len(startScanLineNums)) self.progressDialog.show() self.endLineNum=startScanLineNums[-1] if startLineNum>0: startScanLineNums=sorted(startScanLineNums) numOfScans=len(startScanLineNums) scanLines=[fdata[i] for i in startScanLineNums] if startLineNum==0: tmp=0 self.Data['NumOfScans']=0#numOfScans self.Data['ScanLines']=[]#scanLines self.Data['StartScanLineNums']=[]#startScanLineNums else: tmp=self.Data['NumOfScans']-1 self.Data['NumOfScans']=self.Data['NumOfScans']-1#+numOfScans self.Data['ScanLines']=self.Data['ScanLines'][:-1]#+scanLines[1:] self.Data['StartScanLineNums']=self.Data['StartScanLineNums'][:-1]#+startScanLineNums for i in range(numOfScans): start=startScanLineNums[i]+1 line=fdata[start] i=i+tmp self.Data[i]={} self.Par[i]={} if fdata[start-1].split()[2]=='getandsave_mca' or fdata[start-1].split()[2]=='MCAscanpt': self.Par[i]['Mca']=1 self.Data[i]['ScanVar']='Empty' else: self.Par[i]['Mca']=0 tmpdata=[] self.Par[i]['CCD']=0 while line[:2]!='\n' and line[:2]!='#C': if line[:2]=='#P': parName=line[3:].split() start=start+1 parValue=map(eval,fdata[start][1:].split()) for j in range(len(parName)): self.Par[i][parName[j]]=parValue[j] if line[:2]=='#W': tmppar=line[2:].split() self.Par[i]['Wavelength']=eval(tmppar[1]) if line[:3]=='#G0': self.Par[i]['g_l1']=float(line[4:].split()[5]) self.Par[i]['g_l2']=float(line[4:].split()[6]) self.Par[i]['g_l3']=float(line[4:].split()[7]) if line[:2]=='#A': tmppar=line[2:].split() self.Par[i]['Absorber']=eval(tmppar[1]) if line[:2]=='#Q': tmppar=line[2:].split() self.Par[i]['Q']=map(eval, tmppar) if line[:3]=='#B0': tmppar=line[3:].split() self.Par[i]['CCD']=1 if line[:3]=='#B2': tmppar=map(eval, line[3:].split()) self.Par[i]['DBPos']=tmppar[:2] self.Par[i]['S2D_Dist']=tmppar[2] self.Par[i]['S7D_Dist']=tmppar[3] if line[:2]=='#L': scanVar=line[3:-1].split() self.Data[i]['ScanVar']=scanVar if line[0]!='#': tmpdata.append(map(eval, line.split( ))) start=start+1 try: line=fdata[start] except: break for j in range(len(scanVar)): try: self.Data[i][scanVar[j]]=np.array(tmpdata)[:,j] except: self.Data[i][scanVar[j]]=None if len(self.Par[i])==1: self.Par[i]['Message']='No parameters!!' self.progressDialog.setLabelText('Reading scans form SPEC File: '+str(i+1)) self.updateProgress() self.Data['NumOfScans']=i self.Data['ScanLines']=self.Data['ScanLines']+[scanLines[i-tmp]] self.Data['StartScanLineNums']=self.Data['StartScanLineNums']+[startScanLineNums[i-tmp]] self.endLineNum=startScanLineNums[i-tmp] if self.progressDialog.wasCanceled()==True: break self.progressDialog.hide() def APS_9IDC(self,startLineNum=0, det='CCD'): """ Function to read a complete spec File collected at APS 15IDC """ self.progressDialog=QProgressDialog('Reading scans form SPEC File:','Abort',0,100) self.progressDialog.setWindowModality(Qt.WindowModal) self.progressDialog.setWindowTitle('Wait') self.progressDialog.setAutoClose(True) self.progressDialog.setAutoReset(True) self.progressDialog.setMinimum(1) self.Data['YCol']='Bicron1' self.Data['NCol']='i2' fid=open(self.specfile) fdata=fid.readlines() self.SpecFileFull=fdata fid.close() if fdata[0][:2]!='#F': self.Data['NumOfScans']=0 self.Data['Message']='The file is not a valid specfile!!' print 'Error:: The file is not a valid specfile!!' else: startScanLineNums=[i for i in range(startLineNum, len(fdata)) if fdata[i][:2]=='#S'] self.progressDialog.setMaximum(len(startScanLineNums)) self.progressDialog.show() self.endLineNum=startScanLineNums[-1] if startLineNum>0: startScanLineNums=sorted(startScanLineNums) self.Data['StartScanLineNums']=startScanLineNums numOfScans=len(self.Data['StartScanLineNums']) scanLines=[fdata[i] for i in startScanLineNums] if startLineNum==0: tmp=0 self.Data['NumOfScans']=0#numOfScans self.Data['ScanLines']=[]#scanLines self.Data['StartScanLineNums']=[]#startScanLineNums self.Par['ParName']=[] for i in range(startScanLineNums[0]): line=fdata[i].split() if fdata[i][:2]=='#O': self.Par['ParName']=self.Par['ParName']+line[1:] else: tmp=self.Data['NumOfScans'] self.Data['NumOfScans']=self.Data['NumOfScans']-1#+numOfScans self.Data['ScanLines']=self.Data['ScanLines'][:-1]#+scanLines[1:] self.Data['StartScanLineNums']=self.Data['StartScanLineNums'][:-1]#+startScanLineNums for i in range(numOfScans): start=startScanLineNums[i]+1 line=fdata[start] i=i+tmp self.Data[i]={} self.Par[i]={} if fdata[start-1].split()[2]=='getandsave_mca' or fdata[start-1].split()[2]=='MCAscanpt': self.Par[i]['Mca']=1 self.Data[i]['ScanVar']='Empty' else: self.Par[i]['Mca']=0 self.Par[i]['CCD']=0 tmpdata=[] pstart=0 while line[:2]!='\n' and line[:2]!='#C': if line[:2]=='#P': parValue=map(eval,fdata[start].split()[1:]) for j in range(len(parValue)): self.Par[i][self.Par['ParName'][pstart]]=parValue[j] pstart=pstart+1 if line[:2]=='#Q': tmppar=line[2:].split() self.Par[i]['Q']=map(eval, tmppar) if line[:2]=='#L': scanVar=line[3:-1].split() self.Data[i]['ScanVar']=scanVar if line[0]!='#': tmpdata.append(map(eval, line.split( ))) start=start+1 line=fdata[start] for j in range(len(scanVar)): try: self.Data[i][scanVar[j]]=np.array(tmpdata)[:,j] except: self.Data[i][scanVar[j]]=None if len(self.Par[i])==1: self.Par[i]['Message']='No parameters!!' self.progressDialog.setLabelText('Reading scans form SPEC File: '+str(i+1)) self.updateProgress() self.Data['NumOfScans']=i self.Data['ScanLines']=self.Data['ScanLines']+[scanLines[i-tmp]] self.Data['StartScanLineNums']=self.Data['StartScanLineNums']+[startScanLineNums[i-tmp]] self.endLineNum=startScanLineNums[i-tmp] if self.progressDialog.wasCanceled()==True: break self.progressDialog.hide()
class BAONQtApplication(QApplication): BACKUP_DIALOG_CAPTION = 'Rename Plan Backup Detected' BACKUP_DIALOG_ERROR_CAPTION = 'Error' BACKUP_INTRO_TEXT = 'BAON has detected a backed up rename plan from a previous run of the '\ 'application. This suggests that the application crashed partway through executing a rename operation. The '\ 'files may have been left in an inconsistent state.' BACKUP_PROMPT_TEXT = 'What do you want to do?' REVERT_BACKUP_PROGRESS_TEXT = 'Reverting the rename operation' SUCCESS_DIALOG_CAPTION = 'Success' WARNING_DIALOG_CAPTION = 'Warning' BACKUP_DELETED_DIALOG_TEXT =\ 'The backed up plan has been deleted. Further runs of the application will proceed normally.' BACKUP_REVERTED_SUCCESS_DIALOG_TEXT = 'The rename operation has been reverted successfully. The directory state '\ 'should now have been completely restored.' BACKUP_REVERTED_WARNING_DIALOG_TEXT = 'There were inconsistencies while trying to revert the previous rename '\ 'operation. The directory state may not have been fully restored.' REVERT_BACKUP_BUTTON_TEXT = 'Revert the rename (recommended)' DELETE_BACKUP_BUTTON_TEXT = 'Delete the backup file' EXAMINE_BACKUP_BUTTON_TEXT = 'Examine the plan in a text editor' QUIT_BUTTON_TEXT = 'Quit BAON' request_revert_backup = pyqtSignal() request_delete_backup = pyqtSignal() _main_window = None _core = None _progress_dialog = None _core_thread = None def __init__(self, args): super().__init__(sys.argv) # Actually we do quit when the last window is closed, but we need to do this in a more controlled way self.setQuitOnLastWindowClosed(False) self._init_threads() self._init_main_objects(args) self._connect_main_objects() self._start_core() def event(self, evt): if isinstance(evt, QFileOpenEvent): path = evt.file() if not os.path.isdir(path): path, _ = os.path.split(path) self._main_window.set_base_path(path) return True return super().event(evt) def _init_threads(self): self._core_thread = QThread() self._core_thread.start() def _init_main_objects(self, args): self._main_window = MainWindow(args) self._core = BAONQtCore(args) self._core.moveToThread(self._core_thread) def _connect_main_objects(self): self.aboutToQuit.connect(self._on_quit) # Core vs. application self._core.request_backup_decision.connect(self.backup_decision_requested) self._core.reverted_backup.connect(self.notify_backup_reverted) self._core.revert_backup_error.connect(self.handle_backup_op_error) self._core.deleted_backup.connect(self.notify_backup_deleted) self._core.delete_backup_error.connect(self.handle_backup_op_error) self.request_revert_backup.connect(self._core.revert_backup) self.request_delete_backup.connect(self._core.delete_backup) # Core vs. main window self._core.prologue_finished.connect(self._main_window.show_first_time) self._core.status_changed.connect(self._main_window.report_status) self._core.scanned_files_updated.connect(self._main_window.update_scanned_files) self._core.renamed_files_updated.connect(self._main_window.update_renamed_files) self._core.has_shutdown.connect(self.quit) self._main_window.base_path_edited.connect(self._core.update_base_path) self._main_window.scan_recursive_changed.connect(self._core.update_scan_recursive) self._main_window.rules_text_changed.connect(self._core.update_rules_text) self._main_window.use_path_changed.connect(self._core.update_use_path) self._main_window.use_extension_changed.connect(self._core.update_use_extension) self._main_window.request_add_override.connect(self._core.add_override) self._main_window.request_remove_override.connect(self._core.remove_override) self._main_window.request_do_rename.connect(self._core.do_rename) self._main_window.request_rescan.connect(self._core.rescan) self._main_window.rejected.connect(self._core.shutdown) def _start_core(self): QMetaObject.invokeMethod(self._core, 'start', Qt.QueuedConnection) def _on_quit(self): self._core_thread.quit() self._core_thread.wait() @pyqtSlot() def backup_decision_requested(self): self._show_backup_decision() @pyqtSlot(Exception) def handle_backup_op_error(self, error): self._close_progress_dialog() self._show_backup_decision(error=error) @pyqtSlot() def notify_backup_deleted(self): QMessageBox.information( None, self.SUCCESS_DIALOG_CAPTION, self.BACKUP_DELETED_DIALOG_TEXT, ) @pyqtSlot(bool) def notify_backup_reverted(self, complete_success): self._close_progress_dialog() if complete_success: QMessageBox.information( None, self.SUCCESS_DIALOG_CAPTION, self.BACKUP_REVERTED_SUCCESS_DIALOG_TEXT, ) else: QMessageBox.warning( None, self.WARNING_DIALOG_CAPTION, self.BACKUP_REVERTED_WARNING_DIALOG_TEXT, ) def _show_backup_decision(self, error=None): text = '<p>{0}</p><p>{1}</p>'.format( self.BACKUP_INTRO_TEXT if error is None else error, self.BACKUP_PROMPT_TEXT, ) dialog = QMessageBox( QMessageBox.Question if error is None else QMessageBox.Critical, self.BACKUP_DIALOG_CAPTION if error is None else self.BACKUP_DIALOG_ERROR_CAPTION, text, ) revert_button = dialog.addButton(self.REVERT_BACKUP_BUTTON_TEXT, QMessageBox.AcceptRole) delete_button = dialog.addButton(self.DELETE_BACKUP_BUTTON_TEXT, QMessageBox.DestructiveRole) examine_button = dialog.addButton(self.EXAMINE_BACKUP_BUTTON_TEXT, QMessageBox.ActionRole) dialog.addButton(self.QUIT_BUTTON_TEXT, QMessageBox.RejectRole) dialog.exec() clicked_button = dialog.clickedButton() if clicked_button == examine_button: QMetaObject.invokeMethod(self, '_examine_backup', Qt.QueuedConnection) elif clicked_button == revert_button: self._progress_dialog = QProgressDialog(None) self._progress_dialog.setLabelText(self.REVERT_BACKUP_PROGRESS_TEXT) self._progress_dialog.setCancelButton(None) self._progress_dialog.setRange(0, 0) self._progress_dialog.forceShow() self.request_revert_backup.emit() elif clicked_button == delete_button: self.request_delete_backup.emit() else: self.quit() @pyqtSlot() def _examine_backup(self): error = None try: filename = get_rename_plan_backup_filename() QDesktopServices.openUrl(QUrl.fromLocalFile(filename)) except Exception as err: error = err finally: self._show_backup_decision(error) def _close_progress_dialog(self): if self._progress_dialog is not None: self._progress_dialog.close() self._progress_dialog = None
def import_labeling_layer(labelLayer, labelingSlots, parent_widget=None): """ Prompt the user for layer import settings, and perform the layer import. :param labelLayer: The top label layer source :param labelingSlots: An instance of LabelingGui.LabelingSlots :param parent_widget: The Qt GUI parent object """ writeSeeds = labelingSlots.labelInput assert isinstance(writeSeeds, lazyflow.graph.Slot), "slot is of type %r" % (type(writeSeeds)) opLabels = writeSeeds.getRealOperator() assert isinstance(opLabels, lazyflow.graph.Operator), "slot's operator is of type %r" % (type(opLabels)) recentlyImported = PreferencesManager().get('labeling', 'recently imported') mostRecentProjectPath = PreferencesManager().get('shell', 'recently opened') mostRecentImageFile = PreferencesManager().get( 'DataSelection', 'recent image' ) if recentlyImported: defaultDirectory = os.path.split(recentlyImported)[0] elif mostRecentProjectPath: defaultDirectory = os.path.split(mostRecentProjectPath)[0] elif mostRecentImageFile: defaultDirectory = os.path.split(mostRecentImageFile)[0] else: defaultDirectory = os.path.expanduser('~') fileNames = DataSelectionGui.getImageFileNamesToOpen(parent_widget, defaultDirectory) fileNames = map(str, fileNames) if not fileNames: return PreferencesManager().set('labeling', 'recently imported', fileNames[0]) try: # Initialize operators opImport = OpInputDataReader( parent=opLabels.parent ) opCache = OpArrayCache( parent=opLabels.parent ) opMetadataInjector = OpMetadataInjector( parent=opLabels.parent ) opReorderAxes = OpReorderAxes( parent=opLabels.parent ) # Set up the pipeline as follows: # # opImport --> opCache --> opMetadataInjector --------> opReorderAxes --(inject via setInSlot)--> labelInput # / / # User-specified axisorder labelInput.meta.axistags opImport.WorkingDirectory.setValue(defaultDirectory) opImport.FilePath.setValue(fileNames[0] if len(fileNames) == 1 else os.path.pathsep.join(fileNames)) assert opImport.Output.ready() opCache.blockShape.setValue( opImport.Output.meta.shape ) opCache.Input.connect( opImport.Output ) assert opCache.Output.ready() opMetadataInjector.Input.connect( opCache.Output ) metadata = opCache.Output.meta.copy() opMetadataInjector.Metadata.setValue( metadata ) opReorderAxes.Input.connect( opMetadataInjector.Output ) # Transpose the axes for assignment to the labeling operator. opReorderAxes.AxisOrder.setValue( writeSeeds.meta.getAxisKeys() ) # We'll show a little window with a busy indicator while the data is loading busy_dlg = QProgressDialog(parent=parent_widget) busy_dlg.setLabelText("Importing Label Data...") busy_dlg.setCancelButton(None) busy_dlg.setMinimum(100) busy_dlg.setMaximum(100) def close_busy_dlg(*args): QApplication.postEvent(busy_dlg, QCloseEvent()) # Load the data from file into our cache # When it's done loading, close the progress dialog. req = opCache.Output[:] req.notify_finished( close_busy_dlg ) req.notify_failed( close_busy_dlg ) req.submit() busy_dlg.exec_() readData = req.result maxLabels = len(labelingSlots.labelNames.value) # Can't use return_counts feature because that requires numpy >= 1.9 #unique_read_labels, readLabelCounts = numpy.unique(readData, return_counts=True) # This does the same as the above, albeit slower, and probably with more ram. unique_read_labels = numpy.unique(readData) readLabelCounts = vigra_bincount(readData)[unique_read_labels] labelInfo = (maxLabels, (unique_read_labels, readLabelCounts)) del readData # Ask the user how to interpret the data. settingsDlg = LabelImportOptionsDlg( parent_widget, fileNames, opMetadataInjector.Output, labelingSlots.labelInput, labelInfo ) def handle_updated_axes(): # The user is specifying a new interpretation of the file's axes updated_axisorder = str(settingsDlg.axesEdit.text()) metadata = opMetadataInjector.Metadata.value.copy() metadata.axistags = vigra.defaultAxistags(updated_axisorder) opMetadataInjector.Metadata.setValue( metadata ) if opReorderAxes._invalid_axes: settingsDlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) # Red background settingsDlg.axesEdit.setStyleSheet("QLineEdit { background: rgb(255, 128, 128);" "selection-background-color: rgb(128, 128, 255); }") settingsDlg.axesEdit.editingFinished.connect( handle_updated_axes ) # Initialize handle_updated_axes() dlg_result = settingsDlg.exec_() if dlg_result != LabelImportOptionsDlg.Accepted: return # Get user's chosen label mapping from dlg labelMapping = settingsDlg.labelMapping # Get user's chosen offsets. # Offsets in dlg only include the file axes, not the 5D axes expected by the label input, # so expand them to full 5D axes_5d = opReorderAxes.Output.meta.getAxisKeys() tagged_offsets = collections.OrderedDict( zip( axes_5d, [0]*len(axes_5d) ) ) tagged_offsets.update( dict( zip( opMetadataInjector.Output.meta.getAxisKeys(), settingsDlg.imageOffsets ) ) ) imageOffsets = tagged_offsets.values() # Optimization if mapping is identity if labelMapping.keys() == labelMapping.values(): labelMapping = None # This will be fast (it's already cached) label_data = opReorderAxes.Output[:].wait() # Map input labels to output labels if labelMapping: # There are other ways to do a relabeling (e.g skimage.segmentation.relabel_sequential) # But this supports potentially huge values of unique_read_labels (in the billions), # without needing GB of RAM. mapping_indexes = numpy.searchsorted(unique_read_labels, label_data) new_labels = numpy.array([labelMapping[x] for x in unique_read_labels]) label_data[:] = new_labels[mapping_indexes] label_roi = numpy.array( roiFromShape(opReorderAxes.Output.meta.shape) ) label_roi += imageOffsets label_slice = roiToSlice(*label_roi) writeSeeds[label_slice] = label_data finally: opReorderAxes.cleanUp() opMetadataInjector.cleanUp() opCache.cleanUp() opImport.cleanUp()
class MainWindow(QtGui.QWidget): label_text_update_require = pyqtSignal(str) def __init__(self): super(MainWindow, self).__init__() self.params = ParamsWidget() self.btn_run = QtGui.QPushButton(u"Запустити") self.progress_dialog = QProgressDialog(u'', u'Зупинити', 0, 100, self) self.progress_dialog.setWindowModality(Qt.WindowModal) self.progress_dialog.setAutoClose(False) self.progress_dialog_base_title = None self.setWindowTitle(u'Аналіз моделі') self.init_layout() self.init_events() self.adjustSize() self.move(QApplication.desktop().screen().rect().center() - self.rect().center()) self.update_widgets_state() def init_layout(self): vbox_layout = QtGui.QVBoxLayout() vbox_layout.addWidget(self.params) vbox_layout.addStretch(1) vbox_layout.addWidget(self.btn_run) self.setLayout(vbox_layout) def init_events(self): self.params.updated.connect(self.update_widgets_state) self.btn_run.clicked.connect(self.calculate) self.label_text_update_require.connect(self.update_progressdialog_label) def update_widgets_state(self): params_ready = self.params.is_params_specified() self.btn_run.setEnabled(params_ready) def calculate(self): self.run_job(u'Обробка файла...', self.process) def run_job(self, title, target, args=None, result_handler=None): self.progress_dialog.setWindowTitle(title) self.progress_dialog.setValue(0) self.calc = Calculator(target=target, args=args, clean_up_handler=self.calc_finished, result_handler=result_handler) self.calc.updated.connect(self.progress_dialog.setValue) self.calc.eta_updated.connect(self.update_eta_label) self.calc.finished.connect(self.calc_finished) self.progress_dialog.canceled.connect(self.calc.cancel) self.calc.start() @pyqtSlot() def calc_finished(self): self.progress_dialog.setAutoClose(True) self.progress_dialog.setValue(100) def process(self, update_percentage=None, check_cancelled=None): params = self.params.get_params() model_path = str(params['model_path']) filename, extension = os.path.splitext(model_path) if extension == '.obj': self.prepare_progressdialog(u'Імпорт файла... ') faces = importutils.get_faces(model_path, update_percentage, check_cancelled) print 'Faces imported' self.prepare_progressdialog(u'Перетворення трикутників... ') triangles = importutils.build_triangles(faces, update_percentage, check_cancelled) self.prepare_progressdialog(u'Корекція моделі... ') clean_triangles = importutils.discard_invalid_triangles(triangles, vector.Vector(20, 2, 20), update_percentage, check_cancelled) print 'Triangles: %d, clean triangles: %d, diff: %d' % ( len(triangles), len(clean_triangles), len(triangles) - len(clean_triangles)) pickle_path = model_path + '.pickle' with open(pickle_path, 'wb') as pickle_file: try: pickle.dump(clean_triangles, pickle_file, -1) print 'Pickle saved to %s' % pickle_path except Exception as e: print 'Failed to save clean triangles list: %s' % e elif extension == '.pickle': with open(model_path) as pickle_file: clean_triangles = pickle.load(pickle_file) else: raise Exception('Invalid extension %s' % extension) triangles = clean_triangles self.prepare_progressdialog(u'Обчислення E... ') E, sum_cos, sum_sin = processor.calculate_viewpoint_sums(triangles, params['wavelength'], vector.Vector(20, 2, 20), update_percentage, check_cancelled) def prepare_progressdialog(self, label): self.progress_dialog_base_title = label self.label_text_update_require.emit('') self.calc.mark_process_time() @pyqtSlot(str) def update_progressdialog_label(self, label): if not label: label = self.progress_dialog_base_title self.progress_dialog.setLabelText(label) @pyqtSlot(float) def update_eta_label(self, seconds): if seconds == 0: self.label_text_update_require.emit('') return t = time.gmtime(seconds) time_string = time.strftime('%M:%S', t) label_text = '%s %s' % (self.progress_dialog_base_title, time_string) self.label_text_update_require.emit(label_text)
class AddonManagerDialog(QDialog): _packages = None def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) self.setLayout(QVBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.addonwidget = AddonManagerWidget() self.layout().addWidget(self.addonwidget) buttons = QDialogButtonBox( orientation=Qt.Horizontal, standardButtons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) buttons.accepted.connect(self.__accepted) buttons.rejected.connect(self.reject) self.layout().addWidget(buttons) self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=1) if AddonManagerDialog._packages is None: self._f_pypi_addons = self._executor.submit(list_pypi_addons) else: self._f_pypi_addons = concurrent.futures.Future() self._f_pypi_addons.set_result(AddonManagerDialog._packages) self._f_pypi_addons.add_done_callback( method_queued(self._set_packages, (object,)) ) self.__progress = QProgressDialog( self, Qt.Sheet, minimum=0, maximum=0, labelText=self.tr("Retrieving package list"), sizeGripEnabled=False, ) self.__progress.rejected.connect(self.reject) self.__thread = None self.__installer = None @Slot(object) def _set_packages(self, f): if self.__progress.isVisible(): self.__progress.close() try: packages = f.result() except (IOError, OSError) as err: message_warning( "Could not retrieve package list", title="Error", informative_text=str(err), parent=self ) packages = [] except Exception: raise else: AddonManagerDialog._packages = packages installed = list_installed_addons() dists = {dist.project_name: dist for dist in installed} packages = {pkg.name: pkg for pkg in packages} project_names = unique( itertools.chain(packages.keys(), dists.keys()) ) items = [] for name in project_names: if name in dists and name in packages: item = Installed(packages[name], dists[name]) elif name in dists: item = Installed(None, dists[name]) elif name in packages: item = Available(packages[name]) else: assert False items.append(item) self.addonwidget.set_items(items) def showEvent(self, event): super().showEvent(event) if not self._f_pypi_addons.done(): QTimer.singleShot(0, self.__progress.show) def done(self, retcode): super().done(retcode) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def closeEvent(self, event): super().closeEvent(event) self._f_pypi_addons.cancel() self._executor.shutdown(wait=False) if self.__thread is not None: self.__thread.quit() self.__thread.wait(1000) def __accepted(self): steps = self.addonwidget.item_state() if steps: # Move all uninstall steps to the front steps = sorted( steps, key=lambda step: 0 if step[0] == Uninstall else 1 ) self.__installer = Installer(steps=steps) self.__thread = QThread(self) self.__thread.start() self.__installer.moveToThread(self.__thread) self.__installer.finished.connect(self.__on_installer_finished) self.__installer.error.connect(self.__on_installer_error) self.__installer.installStatusChanged.connect( self.__progress.setLabelText) self.__progress.show() self.__progress.setLabelText("Installing") self.__installer.start() else: self.accept() def __on_installer_error(self, command, pkg, retcode, output): message_error( "An error occurred while running a subprocess", title="Error", informative_text="{} exited with non zero status.".format(command), details="".join(output), parent=self ) self.reject() def __on_installer_finished(self): message_information( "Please restart the application for changes to take effect.", parent=self) self.accept()
def regenerateProjectTodos( self ): """ Collects TODO and FIXME items from the project files """ if GlobalData().project.fileName == "": return self.clearAll() files = GlobalData().project.filesList # now process them progress = QProgressDialog( "Extracting project todo items...", "Abort", 0, len( files ) ) progress.setMinimumDuration( 0 ) count = 0 for fileName in files: progress.setLabelText( "Extracting project todos...\n" + \ fileName ) progress.setValue( count ) QApplication.processEvents() if progress.wasCanceled(): break # Do nothing for the directories if fileName.endswith( os.path.sep ): count += 1 continue # read the file and split it into textlines try: f = open( fileName, 'r' ) text = f.read() lines = text.splitlines() f.close() except IOError: count += 1 self.progress.setValue( count ) continue # now look for todo items lineIndex = 0 for line in lines: lineIndex += 1 if not line.strip().startswith( '#' ): continue index = line.find( "TODO" ) if index >= 0: description = line[ index: ] self.addFileTodoItem( description, fileName, lineIndex ) continue index = line.find( "FIXME" ) if index >= 0: description = line[ index: ] self.addFileTodoItem( description, fileName, lineIndex ) count += 1 progress.setValue( len(files) ) return