class DatasourceRegister(object): '''Wraps a dict of OGR DS references controlling access, instantiation and destruction''' #{'name':(rc=Ref Count,type={SOURCE|TRANSIENT|DESTINATION},uri={http://url/|file://path/file.gdb},ds=<ds_object>, ...} register = {} #sopposed to work something like; #SOURCE=check ref hasn't changed, if it has update the object #TRANSIENT=free DB locks by closing as soon as not needed (FileGDB, SQLite) #DESTINATION=normal rw access with object kept open TYPE = LU.enum('SOURCE', 'TRANSIENT', 'DESTINATION') REQ = LU.enum('INCR', 'FEAT', 'FULL') def __init__(self): pass def _register(self, fn, uri): '''Registers a new DS under the provided name overwriting any previous entries''' self._assignRef(uri) if fn: type = self._type(fn) if type == self.TYPE.SOURCE: endpoint = self._newSRC() else: endpoint = self._newDST(fn) self.register[fn] = {} self.register[fn]['rc'] = 0 self.register[fn]['type'] = type self.register[fn]['uri'] = uri self.register[fn]['ep'] = endpoint else: raise UnknownDSTypeException('Unknown DS requested, ' + str(fn)) def _deregister(self, name): fn = LU.standardiseDriverNames(name) #sync/rel the DS #self.register[fn]['ep'].closeDS()#DS should already have closed self.register[fn]['ep'] = None self.register[fn]['type'] = None self.register[fn]['uri'] = None del self.register[fn] def _assignRef(self, uri): '''mark ref value as either user config or a connection string based on the assumption conn strings contain certain suff/prefixes...''' #TODO Test different sl/fg cases self.cs, self.uc = (uri, None) if uri and re.search( 'PG:|MSSQL:|\.gdb|\.sqlite|\.db', uri, flags=re.IGNORECASE) else ( None, uri) def _type(self, fn): #fn = LU.standardiseDriverNames(name) #if fn == FileGDBDataStore.DRIVER_NAME: # return self.TYPE.TRANSIENT if fn == WFSDataStore.DRIVER_NAME: return self.TYPE.SOURCE return self.TYPE.DESTINATION def _connect(self, fn, req=None): '''Initialise an OGR datasource on the DST/SRC object or just return note the existing and increment count''' endpoint = self.register[fn]['ep'] self.register[fn]['rc'] += 1 if not endpoint.getDS(): if self.register[fn]['type'] == self.TYPE.SOURCE: self._connectSRC(fn, req) else: self._connectDST(fn) def _connectDST(self, fn): endpoint = self.register[fn]['ep'] uri = endpoint.destinationURI(None) conn = endpoint.initDS(uri) endpoint.setDS(conn) def _connectSRC(self, fn, req=None): #layername=None,fromdate=None,todate=None): endpoint = self.register[fn]['ep'] if req and req['type'] == self.REQ.INCR and (req['fromdate'] or req['todate']): uri = endpoint.sourceURIIncremental(req['layername'], req['fromdate'], req['todate']) elif req and req['type'] == self.REQ.FEAT: uri = endpoint.sourceURIFeatureCount(req['layername']) elif req and req['type'] == self.REQ.FULL: uri = endpoint.sourceURI(req['layername']) else: pass #conn = ep.initDS(uri) def _disconnect(self, fn): '''Decrement reference to the DS and delete it entirely if its the last one''' endpoint = self.register[fn]['ep'] self.register[fn]['rc'] -= 1 if self.register[fn]['rc'] <= 0: ldslog.info('Release EP ' + str(fn)) if self.register[fn]['type'] == self.TYPE.DESTINATION: self.closeLayerConfig(endpoint) endpoint.closeDS() #--------------------- def refCount(self, fn): return self.register[fn]['rc'] def openEndPoint(self, name, uri=None, req=None): #print 'GEP',name,uri,req '''Gets a named EP incrementing a refcount or registers a new one as needed''' fn = LU.standardiseDriverNames(name) #if fn+uri exist AND fn is valid AND (fn not prev registered OR the saved URI != uri) if (fn and uri)\ and (fn in DataStore.DRIVER_NAMES.values() or fn == WFSDataStore.DRIVER_NAME) \ and (not self.register.has_key(fn) or self.register[fn]['uri']!=uri): self._register(fn, uri) self._connect(fn, req) elif fn in self.register: self._connect(fn, req) else: raise EndpointConnectionException( 'Register Entry {} has not been initialised.'.format(fn)) return self.register[fn]['ep'] def closeEndPoint(self, name): '''Closes the DS is a named EP or delete the EP completely if not needed''' fn = LU.standardiseDriverNames(name) #<HACK6>. Bypass DS closing for FileGDB connections if fn == 'FileGDB': return #</HACK6> if self.register.has_key(fn): self._disconnect(fn) if self.register[fn]['rc'] == 0: self._deregister(fn) def _newDST(self, fn): '''Init a new destination using instantiated uconf (and dest str if provided)''' dest = { PostgreSQLDataStore.DRIVER_NAME: PostgreSQLDataStore, MSSQLSpatialDataStore.DRIVER_NAME: MSSQLSpatialDataStore, SpatiaLiteDataStore.DRIVER_NAME: SpatiaLiteDataStore, FileGDBDataStore.DRIVER_NAME: FileGDBDataStore }.get(fn) return dest(self.cs, self.uc) def _newSRC(self): '''Initialise a new source, LDS nominally''' src = LDSDataStore(self.cs, self.uc) #src.setPartitionSize(partition_size)#partitionsize may not exist when this is called but thats okay! src.applyConfigOptions() return src def __str__(self): s = '' for k in self.register.keys(): r = self.register[k] s += 'key=' + k + ': rc=' + str(r['rc']) + ' uri=' + str( r['uri']) + ': type=' + str(r['type']) + ': ep=' + str( r['ep']) + '\n' return s #---------------------------------------------------------------------------------- #This is the Layer Config stuff, its a bit of a mess! @staticmethod def setupLayerConfig(tp, sep, dep, initlc=None): '''Calls the TP LC setup function''' tp.getLayerConf(sep, dep, bool(initlc)) @staticmethod def closeLayerConfig(ep): '''Attempts to release DS resources used by LayerConfig''' layerconf = ep.getLayerConf() if layerconf: if layerconf.getDS(): #hasattr(lc,'ds'): #dont close the DS (lc not owner) just sync so any lc values are saved layerconf.syncDS() layerconf.close() ep.setLayerConf(None)
class LDSControls(QFrame): STATIC_IMG = ('error_static.png','linz_static.png','busy_static.png','clean_static.png') ANIM_IMG = ('error.gif','linz.gif','layer.gif','clean.gif') IMG_SPEED = 100 IMG_WIDTH = 64 IMG_HEIGHT = 64 MAX_WD = 450 GD_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../bin/gdal/gdal-data')) STATUS = LU.enum('ERROR','IDLE','BUSY','CLEAN') def __init__(self,parent): super(LDSControls, self).__init__() self.parent = parent self.initConf() self.initEPSG() self.initUI() def initConf(self): '''Read files in conf dir ending in conf''' self.cflist = ConfigInitialiser.getConfFiles() #self.imgset = self.STATIC_IMG if ConfigWrapper().readDSProperty('Misc','indicator')=='static' else self.ANIM_IMG #self.imgset = self.STATIC_IMG if self.parent.confconn.tp.src.confwrap.readDSProperty('Misc','indicator')=='static' else self.ANIM_IMG sep = self.parent.confconn.reg.openEndPoint(self.parent.confconn.SRCNAME,self.parent.confconn.uconf) self.imgset = self.STATIC_IMG if sep.confwrap.readDSProperty('Misc','indicator')=='static' else self.ANIM_IMG self.parent.confconn.reg.closeEndPoint(self.parent.confconn.SRCNAME) def initEPSG(self): '''Read GDAL EPSG files, splitting by NZ(RSR) and RestOfTheWorld''' gcsf = gdal.FindFile('gdal','gcs.csv') if not gcsf: gcsf = os.path.join(self.GD_PATH,'gcs.csv') pcsf = gdal.FindFile('gdal','pcs.csv') if not pcsf: pcsf = os.path.join(self.GD_PATH,'pcs.csv') gcs = ConfigInitialiser.readCSV(gcsf) pcs = ConfigInitialiser.readCSV(pcsf) self.nzlsr = [(e[0],e[0]+' - '+e[3]) for e in gcs if 'NZGD' in e[1] or 'RSRGD' in e[1]] \ + [(e[0],e[0]+' - '+e[1]) for e in pcs if 'NZGD' in e[1] or 'RSRGD' in e[1]] self.rowsr = [(e[0],e[0]+' - '+e[3]) for e in gcs if 'NZGD' not in e[1] and 'RSRGD' not in e[1]] \ + [(e[0],e[0]+' - '+e[1]) for e in pcs if 'NZGD' not in e[1] and 'RSRGD' not in e[1]] def initUI(self): # 0 1 2 3 4 5 6 7 8 #'destname','lgselect','layer','uconf','group','epsg','fd','td','int' #self.rdest,rlgselect,self.rlayer,ruconf,self.rgroup,repsg,rfd,rtd,rint = readlist QToolTip.setFont(QFont('SansSerif', 10)) #labels destLabel = QLabel('Destination') lgLabel = QLabel('Group/Layer') epsgLabel = QLabel('EPSG') fromDateLabel = QLabel('From Date') toDateLabel = QLabel('To Date') confLabel = QLabel('User Config') self.view = QLabel() self.view.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.view.setAlignment(Qt.AlignCenter) self.confcombo = QComboBox(self) self.confcombo.setToolTip('Enter your user config name (file) here') self.confcombo.addItems(self.cflist) self.confcombo.setEditable(False) #self.confcombo.currentIndexChanged.connect(self.doLGEditUpdate) #combos self.lgcombo = QComboBox(self) self.lgcombo.setMaximumWidth(self.MAX_WD) self.lgcombo.setDuplicatesEnabled(False) #self.lgcombo.setInsertPolicy(QComboBox.InsertAlphabetically)#?doesnt seem to work self.lgcombo.setToolTip('Select either Layer or Group entry') self.lgcombo.setEditable(False) self.sepindex = None #self.updateLGValues() self.epsgcombo = QComboBox(self) self.epsgcombo.setMaximumWidth(self.MAX_WD) self.epsgcombo.setToolTip('Setting an EPSG number here determines the output SR of the layer') self.epsgcombo.addItems([i[1] for i in self.nzlsr]) self.epsgcombo.insertSeparator(len(self.nzlsr)) self.epsgcombo.addItems([i[1] for i in self.rowsr]) self.epsgcombo.setEditable(True) self.epsgcombo.setEnabled(False) self.destlist = self.getConfiguredDestinations() self.destcombo = QComboBox(self) self.destcombo.setToolTip('Choose the desired output type') self.destcombo.setEditable(False) self.destcombo.addItems(self.destlist) #date selection self.fromdateedit = QDateEdit() self.fromdateedit.setCalendarPopup(True) self.fromdateedit.setEnabled(False) self.todateedit = QDateEdit() self.todateedit.setCalendarPopup(True) self.todateedit.setEnabled(False) #check boxes self.epsgenable = QCheckBox() self.epsgenable.setCheckState(False) self.epsgenable.clicked.connect(self.doEPSGEnable) self.fromdateenable = QCheckBox() self.fromdateenable.setCheckState(False) self.fromdateenable.clicked.connect(self.doFromDateEnable) self.todateenable = QCheckBox() self.todateenable.setCheckState(False) self.todateenable.clicked.connect(self.doToDateEnable) self.progressbar = QProgressBar() self.progressbar.setRange(0,100) self.progressbar.setVisible(True) self.progressbar.setMinimumWidth(self.MAX_WD) #buttons self.initbutton = QPushButton("waiting") self.initbutton.setToolTip('Initialise the Layer Configuration') self.initbutton.clicked.connect(self.doInitClickAction) self.cleanbutton = QPushButton("Clean") self.cleanbutton.setToolTip('Clean the selected layer/group from local storage') self.cleanbutton.clicked.connect(self.doCleanClickAction) self.replicatebutton = QPushButton("Replicate") self.replicatebutton.setToolTip('Execute selected replication') self.replicatebutton.clicked.connect(self.doReplicateClickAction) self.cancelbutton = QPushButton("Close") self.cancelbutton.setToolTip('Close the LDS Replicate application') self.cancelbutton.clicked.connect(self.parent.close) #set dialog values using GPR self.updateGUIValues(self.parent.gvs) #set onchange here otherwise we get circular initialisation self.destcombo.currentIndexChanged.connect(self.doDestChanged) self.confcombo.currentIndexChanged.connect(self.doConfChanged) self.lgcombo.currentIndexChanged.connect(self.doLGComboChanged) self.setStatus(self.STATUS.IDLE) #grid grid = QGridLayout() grid.setSpacing(10) #placement section ------------------------------------ #---------+---------+--------+---------+-------- # dest LB | | dest DD # grp LB | | grp DD # conf LB | | conf DD # epsg L | epsg CB | epsg DD # f dt L | f dt CB | f dt DD # t td L | t td CB | t td DD # icon | <- progress -> # layer B | <- . -> |repl B | clean B | close B #---------+---------+--------+---------+-------- grid.addWidget(destLabel, 1, 0) grid.addWidget(self.destcombo, 1, 2) #grid.addWidget(layerLabel, 2, 0) grid.addWidget(lgLabel, 2, 0) grid.addWidget(self.lgcombo, 2, 2) grid.addWidget(confLabel, 3, 0) grid.addWidget(self.confcombo, 3, 2) #grid.addWidget(groupLabel, 4, 0) #grid.addWidget(self.groupEdit, 4, 2) grid.addWidget(epsgLabel, 5, 0) grid.addWidget(self.epsgenable, 5, 1) grid.addWidget(self.epsgcombo, 5, 2) grid.addWidget(fromDateLabel, 6, 0) grid.addWidget(self.fromdateenable, 6, 1) grid.addWidget(self.fromdateedit, 6, 2) grid.addWidget(toDateLabel, 7, 0) grid.addWidget(self.todateenable, 7, 1) grid.addWidget(self.todateedit, 7, 2) hbox3 = QHBoxLayout() hbox3.addWidget(self.view) hbox3.addStretch(1) hbox3.addWidget(self.progressbar) #hbox3.addLayout(vbox2) #hbox3.addLayout(vbox3) hbox4 = QHBoxLayout() hbox4.addWidget(self.initbutton) hbox4.addStretch(1) hbox4.addWidget(self.replicatebutton) hbox4.addWidget(self.cleanbutton) hbox4.addWidget(self.cancelbutton) vbox = QVBoxLayout() #vbox.addStretch(1) vbox.addLayout(grid) vbox.addLayout(hbox3) vbox.addLayout(hbox4) self.setLayout(vbox) #def setProgress(self,pct): # self.progressbar.setValue(pct) def setStatus(self,status,message='',tooltip=None): '''Sets indicator icon and statusbar message''' self.parent.statusbar.showMessage(message) self.parent.statusbar.setToolTip(tooltip if tooltip else '') #progress loc = os.path.abspath(os.path.join(IMG_LOC,self.imgset[status])) #loc = os.path.abspath(os.path.join(os.path.dirname(__file__),self.parent.IMG_LOC,self.imgset[status])) self.progressbar.setVisible(status in (self.STATUS.BUSY, self.STATUS.CLEAN)) #icon anim = QMovie(loc, QByteArray(), self) anim.setScaledSize(QSize(self.IMG_WIDTH,self.IMG_HEIGHT)) anim.setCacheMode(QMovie.CacheAll) anim.setSpeed(self.IMG_SPEED) self.view.clear() self.view.setMovie(anim) anim.start() self.view.repaint() QApplication.processEvents(QEventLoop.AllEvents) def mainWindowEnable(self,enable=True): cons = (self.lgcombo, self.confcombo, self.destcombo, self.initbutton, self.replicatebutton, self.cleanbutton, self.cancelbutton, self.epsgenable,self.fromdateenable,self.todateenable, self.parent.menubar) for c in cons: c.setEnabled(enable) if enable: self.epsgcombo.setEnabled(self.epsgenable.checkState()) self.fromdateedit.setEnabled(self.fromdateenable.checkState()) self.todateedit.setEnabled(self.todateenable.checkState()) else: self.epsgcombo.setEnabled(False) self.fromdateedit.setEnabled(False) self.todateedit.setEnabled(False) QApplication.restoreOverrideCursor() if enable else QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) def refreshLGCombo(self): '''Re index LG combobox since a refreshLG call (new dest?) will usually mean new groups''' self.lgcombo.clear() self.lgcombo.addItems([i[2] for i in self.parent.confconn.lglist]) #NOTE the separator consumes an index, if not clearing the combobox selectively remove the old sepindex (assumes g preceeds l) #if self.sepindex: # self.lgcombo.removeItem(self.sepindex) self.sepindex = [i[0] for i in self.parent.confconn.lglist].count(LORG.GROUP) self.lgcombo.insertSeparator(self.sepindex) def updateLGValues(self,uconf,lgval,dest): '''Sets the values displayed in the Layer/Group combo''' #because we cant seem to sort combobox entries and want groups at the top, clear and re-add #TRACE# #pdb.set_trace() sf = None try: self.parent.confconn.initConnections(uconf,lgval,dest) except Exception as e: sf=1 ldslog.error('Error Updating UC Values. '+str(e)) if sf: self.setStatus(self.STATUS.ERROR,'Error Updating UC Values', str(e)) else: self.setStatus(self.STATUS.IDLE) self.refreshLGCombo() def centre(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def gprParameters(self,rdest): '''Zip default and GPR values''' return [x if LU.assessNone(x) else y for x,y in zip(self.parent.gpr.readsec(rdest),self.parent.DEF_RVALS[1:])] def getLCE(self,ln): '''Read layer parameters''' dep = self.parent.confconn.reg.openEndPoint(self.parent.confconn.destname,self.parent.confconn.uconf) #sep = self.parent.confconn.reg.openEndPoint('WFS',self.parent.confconn.uconf) self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp,None,dep,initlc=False) lce = dep.getLayerConf().readLayerParameters(ln) #self.parent.confconn.reg.closeEndPoint('WFS') self.parent.confconn.reg.closeEndPoint(self.parent.confconn.destname) sep,dep = None,None return lce def doDestChanged(self): '''Read the destname parameter and fill dialog with matching GPR values''' rdest = str(self.destlist[self.destcombo.currentIndex()]) rvals = self.gprParameters(rdest) self.updateGUIValues([rdest]+rvals) def doConfChanged(self): '''Read the user conf parameter and fill dialog with matching GPR values''' rdest = str(self.destlist[self.destcombo.currentIndex()]) rlg,_,rep,rfd,rtd = self.gprParameters(rdest) ruc = str(self.cflist[self.confcombo.currentIndex()]) self.updateGUIValues((rdest,rlg,ruc,rep,rfd,rtd)) def doLGComboChanged(self): '''Read the layer/group value and change epsg to layer or gpr match''' #get a matching LG entry and test whether its a layer or group #lgi = self.parent.confconn.getLayerGroupIndex(self.lgcombo.currentText().toUtf8().data()) lgi = self.parent.confconn.getLayerGroupIndex(LQ.readWidgetText(self.lgcombo.currentText())) #lgi can be none if we init a new group, in which case we use the GPR value if lgi: lge = self.parent.confconn.lglist[lgi] lce = self.getLCE(lge[1]) if lge[0]==LORG.LAYER else None else: lce = None #look for filled layer conf epsg OR use prefs stored in gpr if lce and LU.assessNone(lce.epsg): epsgval = lce.epsg else: rdest = str(self.destlist[self.destcombo.currentIndex()]) _,_,epsgval,_,_ = self.gprParameters(rdest) epsgindex = [i[0] for i in self.nzlsr+[(0,0)]+self.rowsr].index(epsgval) if self.epsgcombo.currentIndex() != epsgindex: self.epsgcombo.setCurrentIndex(int(epsgindex)) def updateGUIValues(self,readlist): '''Fill dialog values from provided list''' #TODO. Remove circular references when setCurrentIndex() triggers do###Changed() #Read user input rdest,self.rlgval,ruconf,repsg,rfd,rtd = readlist #-------------------------------------------------------------------- #Destination Menu selecteddest = LU.standardiseDriverNames(rdest) if selecteddest not in self.destlist: self.destlist = self.getConfiguredDestinations() self.destcombo.addItem(selecteddest) destindex = self.destlist.index(selecteddest) if selecteddest else 0 if self.destcombo.currentIndex() != destindex: self.destcombo.setCurrentIndex(destindex) #InitButton self.initbutton.setText('Layer Select') #Config File confindex = 0 if LU.assessNone(ruconf): ruconf = ruconf.split('.')[0] if ruconf not in self.cflist: self.cflist += [ruconf,] self.confcombo.addItem(ruconf) confindex = self.cflist.index(ruconf) if self.confcombo.currentIndex() != confindex: self.confcombo.setCurrentIndex(confindex) #self.confEdit.setText(ruconf if LU.assessNone(ruconf) else '') #Layer/Group Selection self.updateLGValues(ruconf,self.rlgval,rdest) lgindex = None if LU.assessNone(self.rlgval): #index of list value lgindex = self.parent.confconn.getLayerGroupIndex(self.rlgval,col=1) if LU.assessNone(lgindex): #advance by 1 for sep lgindex += 1 if lgindex>self.sepindex else 0 else: #using the separator index sets the combo to blank lgindex = self.sepindex if self.lgcombo.currentIndex() != lgindex: self.lgcombo.setCurrentIndex(lgindex) #self.doLGEditUpdate() #EPSG # user > layerconf #useepsg = LU.precedence(repsg, lce.epsg if lce else None, None) epsgindex = [i[0] for i in self.nzlsr+[(None,None)]+self.rowsr].index(repsg) if self.epsgcombo.currentIndex() != epsgindex: self.epsgcombo.setCurrentIndex(epsgindex) #epsgedit = self.epsgcombo.lineEdit() #epsgedit.setText([e[1] for e in self.nzlsr+self.rowsr if e[0]==repsg][0]) #epsgedit.setText([e for e in self.nzlsr+self.rowsr if re.match('^\s*(\d+).*',e).group(1)==repsg][0]) #To/From Dates if LU.assessNone(rfd): self.fromdateedit.setDate(QDate(int(rfd[0:4]),int(rfd[5:7]),int(rfd[8:10]))) else: early = DataStore.EARLIEST_INIT_DATE self.fromdateedit.setDate(QDate(int(early[0:4]),int(early[5:7]),int(early[8:10]))) if LU.assessNone(rtd): self.todateedit.setDate(QDate(int(rtd[0:4]),int(rtd[5:7]),int(rtd[8:10]))) else: today = DataStore.getCurrent() self.todateedit.setDate(QDate(int(today[0:4]),int(today[5:7]),int(today[8:10]))) #Internal/External CheckBox # if LU.assessNone(rint): # self.internalTrigger.setChecked(rint.lower()==DataStore.CONF_INT) # else: # self.internalTrigger.setChecked(DataStore.DEFAULT_CONF==DataStore.CONF_INT) def getConfiguredDestinations(self): defml = ['',]+DataStore.DRIVER_NAMES.values() return [d for d in self.parent.gpr.getDestinations() if d in defml] def doEPSGEnable(self): self.epsgcombo.setEnabled(self.epsgenable.isChecked()) def doFromDateEnable(self): self.fromdateedit.setEnabled(self.fromdateenable.isChecked()) def doToDateEnable(self): self.todateedit.setEnabled(self.todateenable.isChecked()) def readParameters(self): '''Read values out of dialogs''' destination = LU.assessNone(str(self.destlist[self.destcombo.currentIndex()])) #lgindex = self.parent.confconn.getLayerGroupIndex(self.lgcombo.currentText().toUtf8().data()) lgindex = self.parent.confconn.getLayerGroupIndex(LQ.readWidgetText(self.lgcombo.currentText())) #NB need to test for None explicitly since zero is a valid index lgval = self.parent.confconn.lglist[lgindex][1] if LU.assessNone(lgindex) else None #uconf = LU.standardiseUserConfigName(str(self.confcombo.lineEdit().text())) #uconf = str(self.confcombo.lineEdit().text()) uconf = str(self.cflist[self.confcombo.currentIndex()]) ee = self.epsgenable.isChecked() epsg = None if ee is False else re.match('^\s*(\d+).*',str(self.epsgcombo.lineEdit().text())).group(1) fe = self.fromdateenable.isChecked() te = self.todateenable.isChecked() fd = None if fe is False else str(self.fromdateedit.date().toString('yyyy-MM-dd')) td = None if te is False else str(self.todateedit.date().toString('yyyy-MM-dd')) return destination,lgval,uconf,epsg,fe,te,fd,td def doInitClickAction(self): '''Initialise the LC on LC-button-click, action''' try: try: self.setStatus(self.STATUS.BUSY,'Opening Layer-Config Editor') self.progressbar.setValue(0) self.parent.runLayerConfigAction() finally: self.setStatus(self.STATUS.IDLE,'Ready') except Exception as e: self.setStatus(self.STATUS.ERROR,'Error in Layer-Config',str(sys.exc_info()))#e)) def doCleanClickAction(self): '''Set clean anim and run clean''' #lgo = self.lgcombo.currentText().toUtf8().data() lgo = LQ.readWidgetText(self.lgcombo.currentText()) try: self.setStatus(self.STATUS.CLEAN,'Running Clean '+lgo) self.progressbar.setValue(0) self.runReplicationScript(True) except Exception as e: self.setStatus(self.STATUS.ERROR,'Failed Clean of '+lgo,str(sys.exc_info()))#e)) def doReplicateClickAction(self): '''Set busy anim and run repl''' lgo = self.lgcombo.currentText()#.toUtf8().data()#only used for error messages try: self.setStatus(self.STATUS.BUSY,'Running Replicate '+lgo) self.progressbar.setValue(0) self.runReplicationScript(False) ldslog.debug('TRPfinish') except Exception as e: self.setStatus(self.STATUS.ERROR,'Failed Replication of '+lgo,str(sys.exc_info()))#e)) def runReplicationScript(self,clean=False): '''Run the layer/group repliction script''' destination,lgval,uconf,epsg,fe,te,fd,td = self.readParameters() uconf_path = LU.standardiseUserConfigName(uconf) destination_path = LU.standardiseLayerConfigName(destination) destination_driver = LU.standardiseDriverNames(destination) if not os.path.exists(uconf_path): self.userConfMessage(uconf_path) return elif not MainFileReader(uconf_path).hasSection(destination_driver): self.userConfMessage(uconf_path,destination_driver) return #----------------------------------------------------- #'destname','layer','uconf','group','epsg','fd','td','int' self.parent.gpr.write((destination_driver,lgval,uconf,epsg,fd,td)) ldslog.info(u'dest={0}, lg={1}, conf={2}, epsg={3}'.format(destination_driver,lgval,uconf,epsg)) ldslog.info('fd={0}, td={1}, fe={2}, te={3}'.format(fd,td,fe,te)) lgindex = self.parent.confconn.getLayerGroupIndex(lgval,col=1) #lorg = self.parent.confconn.lglist[lgindex][0] #----------don't need lorg in TP anymore but it is useful for sorting/counting groups #self.parent.confconn.tp.setLayerOrGroup(lorg) self.parent.confconn.tp.setLayerGroupValue(lgval) if self.fromdateenable.isChecked(): self.parent.confconn.tp.setFromDate(fd) if self.todateenable.isChecked(): self.parent.confconn.tp.setToDate(td) self.parent.confconn.tp.setUserConf(uconf) if self.epsgenable: self.parent.confconn.tp.setEPSG(epsg) #because clean state persists in TP if clean: self.parent.confconn.tp.setCleanConfig() else: self.parent.confconn.tp.clearCleanConfig() #(re)initialise the data source since uconf may have changed #>>#self.parent.confconn.tp.src = self.parent.confconn.initSourceWrapper() #-------------------------- ###ep = self.parent.confconn.reg.openEndPoint(self.parent.confconn.destname,self.parent.confconn.uconf) ###self.parent.confconn.reg.closeEndPoint(self.parent.confconn.destname) ###ep = None #Open ProcessRunner and run with TP(proc)/self(gui) instances #HACK temp add of dest_drv to PR call try: #TODO. Test for valid LC first self.tpr = ProcessRunner(self,destination_driver) except Exception as e: ldslog.error('Cannot create ProcessRunner {}. NB Possible missing Layer Config {}'.format(str(e),destination_path)) self.layerConfMessage(destination_path) return #If PR has been successfully created we must vave a valid dst ldslog.debug('TRPstart') self.tpr.start() # def quitProcessRunner(self): # self.tpr.join() # self.tpr.quit() # self.trp = None def userConfMessage(self,uconf,secname=None): ucans = QMessageBox.warning(self, 'User Config Missing/Incomplete', 'Specified User-Config file, '+str(uconf)+' does not exist' if secname is None else 'User-Config file does not contain '+str(secname)+' section', 'Back','Initialise User Config') if not ucans: #Retry ldslog.warn('Retry specifying UC') #self.confcombo.setCurrentIndex(0) return #Init ldslog.warn('Reset User Config Wizard') self.parent.runWizardAction() def layerConfMessage(self,dest): lcans = QMessageBox.warning(self, 'Layer Config Missing', 'Required Layer-Config file, '+str(dest)+' does not exist', 'Back','Run Layer Select') if not lcans: #Retry ldslog.warn('Retry specifying LC') #self.destcombo.setCurrentIndex(0) return #Init ldslog.warn('Reset Layer Config') self.doInitClickAction()
class LayerConfigSelector(QMainWindow): STEP = LU.enum('PRE', 'POST') #def __init__(self,tp,uconf,group,dest='PostgreSQL',parent=None): def __init__(self, parent=None): '''Main entry point for the Layer selection dialog''' super(LayerConfigSelector, self).__init__(parent) self.parent = parent #Build models splitting by keyword if necessary #print 'LGVAL in LCS',self.parent.confconn.lgval av_sl = self.splitData( LU.recode(self.parent.confconn.lgval), self.parent.confconn.complete ) #if self.parent.confconn.lgval and self.parent.confconn.complete else (list(self.parent.confconn.complete),[]) self.available_model = LayerTableModel('L::available', self) self.available_model.initData(av_sl[0], self.parent.confconn.inclayers) self.selection_model = LayerTableModel('R::selection', self) self.selection_model.initData(av_sl[1], self.parent.confconn.inclayers) self.page = LayerSelectionPage(self) self.setCentralWidget(self.page) self.setWindowTitle("LDS Layer Selection") self.resize(725, 480) def resetLayers(self): '''Rebuilds lconf from scratch''' dep = self.parent.confconn.reg.openEndPoint( self.parent.confconn.destname, self.parent.confconn.uconf) sep = self.parent.confconn.reg.openEndPoint( self.parent.confconn.SRCNAME, self.parent.confconn.uconf) #self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp,sep,dep) self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp, sep, dep, initlc=True) self.refreshLayers(dep) self.parent.confconn.reg.closeEndPoint(self.parent.confconn.SRCNAME) self.parent.confconn.reg.closeEndPoint(self.parent.confconn.destname) def refreshLayers(self, dep, customkey=None): '''Refreshes from a reread of the lconf object''' self.parent.confconn.setupCompleteLayerList(dep) av_sl = self.splitData(customkey, self.parent.confconn.complete) self.signalModels(self.STEP.PRE) self.available_model.initData(av_sl[0], self.parent.confconn.inclayers) self.selection_model.initData(av_sl[1], self.parent.confconn.inclayers) self.signalModels(self.STEP.POST) def writeKeysToLayerConfig(self, ckey): '''Add custom key to the selection_model list of layers (assumes required av->sl transfer completed) not just the transferring entry''' layerlist = [ll[0] for ll in self.selection_model.mdata] replacementlist = () dep = self.parent.confconn.reg.openEndPoint( self.parent.confconn.destname, self.parent.confconn.uconf) #print 'opened dep=',dep,'reg=',self.parent.confconn.reg#DEBUG self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp, None, dep, initlc=False) #categorylist = [f.encode('utf8').strip() for f in dep.getLayerConf().readLayerProperty(layerlist, 'category') if f] categorylist = [ LU.assessNone(f) for f in dep.getLayerConf().readLayerProperty( layerlist, 'category') ] for cat in categorylist: replacementlist += ((cat if ckey in cat.split(',') else cat + ',' + ckey) if cat else ckey, ) #print '>>> writing this replacementlist to LC',replacementlist dep.getLayerConf().writeLayerProperty(layerlist, 'category', replacementlist) #new keyword written so re-read complete (LC) and update assigned keys list self.parent.confconn.setupCompleteLayerList(dep, refresh=True) self.parent.confconn.setupAssignedLayerList() self.parent.confconn.buildLayerGroupList() #self.refreshLayers(dep,customkey) #print 'closing dep=',dep,'reg=',self.parent.confconn.reg#DEBUG self.parent.confconn.reg.closeEndPoint(self.parent.confconn.destname) dep = None def deleteKeysFromLayerConfig(self, layerlist, ckey): '''Remove custom keys from selected layers''' replacementlist = () dep = self.parent.confconn.reg.openEndPoint( self.parent.confconn.destname, self.parent.confconn.uconf) #print 'opening',dep#DEBUG self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp, None, dep, initlc=False) categorylist = [ f.encode('utf8').strip() for f in dep.getLayerConf().readLayerProperty( layerlist, 'category') if f ] for cat in categorylist: #replacementlist += (re.sub(',+',',',''.join(cat.split(ckey)).strip(',')),) try: cat = cat.split(',') cat.remove(LU.recode(ckey, uflag='encode')) except ValueError: pass replacementlist += (','.join(cat), ) dep.getLayerConf().writeLayerProperty(layerlist, 'category', replacementlist) #----------------------------------- self.parent.confconn.setupCompleteLayerList(dep) self.parent.confconn.setupAssignedLayerList() self.parent.confconn.buildLayerGroupList() #self.refreshLayers(dep,customkey) self.parent.confconn.reg.closeEndPoint(self.parent.confconn.destname) #print 'closing', dep,self.parent.confconn.reg#DEBUG dep = None return self.selection_model.rowCount() @staticmethod def splitData(keyword, complete): '''Splits up the 'complete' layer list according to whether it has the selection keyword or not''' alist = [] slist = [] #assert complete, 'Need complete layerlist to generate selection menu'#it'll be empty prior to init for dp in complete: if keyword and keyword in dp[2]: slist.append(dp) else: alist.append(dp) return alist, slist def signalModels(self, prepost): '''Convenience method to call the Layout Change signals when models are modified''' if prepost == self.STEP.PRE: self.available_model.layoutAboutToBeChanged.emit() self.selection_model.layoutAboutToBeChanged.emit() elif prepost == self.STEP.POST: self.available_model.layoutChanged.emit() self.selection_model.layoutChanged.emit() def closeEvent(self, event): '''Intercept close event to signal parent to update status''' self.parent.controls.setStatus(self.parent.controls.STATUS.IDLE, 'Done') #return last group selection #lastgroup = LU.recode(self.page.keywordcombo.lineEdit().text().toUtf8().data()) lastgroup = LU.recode( LQ.readWidgetText(self.page.keywordcombo.lineEdit().text())) #self.parent.controls.gpr.writeline('lgvalue',lastgroup) if LU.assessNone(lastgroup): dep = self.parent.confconn.reg.openEndPoint( self.parent.confconn.destname, self.parent.confconn.uconf) #sep = self.parent.confconn.reg.openEndPoint('WFS',self.parent.confconn.uconf) self.parent.confconn.reg.setupLayerConfig(self.parent.confconn.tp, None, dep) self.parent.confconn.setupCompleteLayerList(dep) self.parent.confconn.setupAssignedLayerList() self.parent.confconn.buildLayerGroupList() lgindex = self.parent.confconn.getLayerGroupIndex(lastgroup, col=1) self.parent.controls.refreshLGCombo() #current index wont be available in parent if this is the init run self.parent.controls.lgcombo.setCurrentIndex( lgindex if lgindex else 0) #self.parent.confconn.reg.closeEndPoint('WFS') self.parent.confconn.reg.closeEndPoint( self.parent.confconn.destname) sep, dep = None, None
from __builtin__ import classmethod ldslog = LU.setupLogging() class InputMisconfigurationException(Exception): def __init__(self, msg): super(InputMisconfigurationException,self).__init__(msg) ldslog.error('InputMisconfigurationException :: Improperly formatted input argument, '+str(msg)) class PrimaryKeyUnavailableException(Exception): pass class LayerConfigurationException(Exception): pass class DatasourceInitialisationException(Exception): pass class IncompleteParametersForInitialisation(Exception): pass LORG = LU.enum('GROUP','LAYER') class TransferProcessor(object): '''Primary class controlling data transfer objects and the parameters for these''' #Hack. To read 64bit integers we have to translate tables without GDAL's driver copy mechanism. #Step 1 identify tables where 64 bit ints are used #Step 2 intercept feature build and copy and overwrite with string values #The tables listed below are ASP tables using a sufi number which is 64bit ###layers_with_64bit_ints = map(lambda s: 'v:x'+s, ('1203','1204','1205','1028','1029')) #Note. This won't work for any layers that don't have a primary key, i.e. Topo and Hydro. Since feature ids are only used in ASP this shouldnt be a problem LP_SUFFIX = ".layer.properties" DEF_IE = DataStore.CONF_EXT POLL_INTERVAL = 1