def view(self): """create view and import layers""" layer = QgsMapLayerRegistry.instance().mapLayer( self.current_layers[0] ) uri = QgsDataSourceURI(layer.source()) mtch = re.match(r'(.+)_([^_]+)_rev_(head|\d+)', uri.schema()) schema = mtch.group(1) assert(schema) # Disconnect signals previously connected upon calling this function # The first time this function is called will throw an error because no # previous connections to the slots were made try: #print "Disconnecting ..." self.q_view_dlg.tblw.itemChanged.disconnect() self.q_view_dlg.diffmode_chk.stateChanged.disconnect() except: #print "Failed disconnection" pass # Make sure combobox is initalized correctly self.q_view_dlg.diffmode_chk.setCheckState(Qt.Unchecked) self.q_view_dlg.diffmode_chk.setEnabled(False) pcur = versioning_base.Db( psycopg2.connect(self.pg_conn_info()) ) pcur.execute("SELECT rev, author, date::timestamp(0), branch, commit_msg " "FROM "+schema+".revisions ORDER BY rev ASC") revs = pcur.fetchall() pcur.close() self.q_view_dlg.tblw.setRowCount(len(revs)) self.q_view_dlg.tblw.setColumnCount(5) self.q_view_dlg.tblw.setHorizontalHeaderLabels(['Rev#', 'Author', 'Date', 'Branch', 'Commit Message']) for i, rev in enumerate(revs): for j, item in enumerate(rev): self.q_view_dlg.tblw.setItem(i,j,QTableWidgetItem( str(item) )) # set rev# checkable if j == 0: self.q_view_dlg.tblw.item(i,j).setCheckState(Qt.Unchecked) self.q_view_dlg.tblw.itemChanged.connect(self.enable_diffmode) self.q_view_dlg.tblw.resizeRowsToContents() self.q_view_dlg.tblw.resizeColumnsToContents() self.q_view_dlg.diffmode_chk.stateChanged.connect(self.check_branches) if not self.q_view_dlg.exec_(): return rows = set() revision_number_list = [] branches = [] for i in range(len(revs)): if self.q_view_dlg.tblw.item(i,0).checkState(): print "Revision "+ self.q_view_dlg.tblw.item(i,0).text() +" will be fetched" revision_number_list.append(int(self.q_view_dlg.tblw.item(i,0).text())) branches.append(self.q_view_dlg.tblw.item(i,3).text()) rows.add(self.q_view_dlg.tblw.item(i,0).row()) progressMessageBar = self.iface.messageBar().createMessage("Querying " "the database for revision(s) "+str(revision_number_list)) progress = QProgressBar() progress.setMaximum(len(rows)) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO) progress.setValue(0) # if diffmode, create one layer with feature differences between the # two revisions; else checkout the full data sets for the specified # revisions and put them in separate layers (original behaviour) rev_begin = 0 rev_end = 0 empty_layers = [] grp_name='' if self.q_view_dlg.diffmode_chk.isChecked(): print "Diffmode checked" # revision_number_list necessarily has only two items in diffmode rev_begin = revision_number_list[0] rev_end = revision_number_list[1] if rev_begin > rev_end: rev_begin, rev_end = rev_end, rev_begin # if the two revisions are not on the same branch, exit if revs[rev_begin - 1][3] != revs[rev_end - 1][3]: print "Revisions are not on the same branch, exiting" #print "Rev_begin " + str(rev_begin) + " is on " + revs[rev_begin - 1][3] #print "Rev_end " + str(rev_end) + " is on " + revs[rev_end - 1][3] return else : print "Revisions are on the same branch" #print "Rev_begin " + str(rev_begin) + " is on " + revs[rev_begin - 1][3] #print "Rev_end " +str(rev_end) + " is on " + revs[rev_end - 1][3] grp_name = "Compare revisions "+str(rev_begin)+" vs "+ str(rev_end) grp_idx = self.iface.legendInterface().addGroup( grp_name ) for i, layer_id in enumerate(reversed(self.current_layers)): progress.setValue(i+1) layer = QgsMapLayerRegistry.instance().mapLayer(layer_id) new_uri = QgsDataSourceURI(layer.source()) select_str = versioning_base.diff_rev_view_str( uri.connectionInfo(), schema, new_uri.table(), branches[0], rev_begin, rev_end ) # change data source uri to point to select sql # schema needs to be set to empty new_uri.setDataSource("", "("+select_str+")", new_uri.geometryColumn(), new_uri.sql(), new_uri.keyColumn()) display_name = QgsMapLayerRegistry.instance().mapLayer(layer_id).name() #print "new_uri.uri() = " + new_uri.uri() tmp_pg_layer = self.iface.addVectorLayer( new_uri.uri(), display_name, 'postgres') #print "Number of features in layer " + display_name + " = " + str(tmp_pg_layer.featureCount()) # if layer has no feature, delete tmp layer and resume for loop if not(tmp_pg_layer.featureCount()): QgsMapLayerRegistry.instance().removeMapLayer( tmp_pg_layer.id() ) empty_layers.append(str(display_name)) continue mem_uri = self.mem_layer_uri(tmp_pg_layer) #print "mem_uri = " + mem_uri if mem_uri == "Unknown": return new_mem_layer = self.iface.addVectorLayer( mem_uri, display_name + '_diff', 'memory') pr = new_mem_layer.dataProvider() source_layer_features = [f for f in tmp_pg_layer.getFeatures()] #print "Got features from source vector layer" QgsMapLayerRegistry.instance().removeMapLayer( tmp_pg_layer.id() ) #print "Removed tmp layer" pr.addFeatures(source_layer_features) #print "Copied source features to mem layer" # Style layer to show features as a function of whether they were # - added/created ('a') # - updated ('u') # - deleted ('d') # For all feature types, so do once # Code from http://snorf.net/blog/2014/03/04/symbology-of-vector-layers-in-qgis-python-plugins # For colors, use the names at http://www.w3schools.com/HTML/html_colornames.asp, but lowercase only; tested with "aliceblue" # define some rules: label, expression, color name, size, (min scale, max scale) modification_type_rules = ( ('Intermediate', '"diff_status" LIKE \'i\'', 'aliceblue', 2.0, None), ('Created', '"diff_status" LIKE \'a\'', 'chartreuse', 3.0, None), ('Updated', '"diff_status" LIKE \'u\'', 'sandybrown', 3.0, None), ('Deleted', '"diff_status" LIKE \'d\'', 'red', 3.0, None),) symbol = QgsSymbolV2.defaultSymbol(new_mem_layer.geometryType()) renderer = QgsRuleBasedRendererV2(symbol) root_rule = renderer.rootRule() for label, expression, color_name, size, scale in modification_type_rules: # create a clone (i.e. a copy) of the default rule rule = root_rule.children()[0].clone() # set the label, expression and color rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color_name)) ##rule.symbol().setSize(size) # works only for POINT layers # set the scale limits if they have been specified ##if scale is not None: ## rule.setScaleMinDenom(scale[0]) ## rule.setScaleMaxDenom(scale[1]) # append the rule to the list of rules root_rule.appendChild(rule) # delete the default rule root_rule.removeChildAt(0) new_mem_layer.setRendererV2(renderer) # refresh map and legend self.iface.mapCanvas().refresh() self.iface.legendInterface().refreshLayerSymbology(new_mem_layer) self.iface.legendInterface().moveLayer( new_mem_layer, grp_idx) else: print "Diffmode unchecked" for i, row in enumerate(rows): progress.setValue(i+1) branch = revs[row][3] rev = revs[row][0] grp_name = branch+' revision '+str(rev) grp_idx = self.iface.legendInterface().addGroup( grp_name ) for layer_id in reversed(self.current_layers): layer = QgsMapLayerRegistry.instance().mapLayer(layer_id) new_uri = QgsDataSourceURI(layer.source()) select_str, where_str = versioning_base.rev_view_str( self.pg_conn_info(), schema, new_uri.table(), branches[0], rev) new_uri.setSql(where_str) new_uri.setDataSource("", "("+select_str+")", new_uri.geometryColumn(), new_uri.sql(), new_uri.keyColumn()) display_name = QgsMapLayerRegistry.instance().mapLayer(layer_id).name() src = new_uri.uri().replace('()','') new_layer = self.iface.addVectorLayer( src, display_name, 'postgres') self.iface.legendInterface().moveLayer( new_layer, grp_idx) self.iface.messageBar().clearWidgets() #print "len (self.current_layers) = " + str(len (self.current_layers)) #print "len(empty_layers) = " + str(len(empty_layers)) if empty_layers and len(empty_layers) == len (self.current_layers): print "No layers in layer group" self.iface.messageBar().pushMessage("Notice", "No layers will be shown; deleted the \"" +grp_name +"\" layer group", level=QgsMessageBar.WARNING, duration = 15) self.iface.legendInterface().removeGroup(grp_idx) elif empty_layers : print "Empty layers" self.iface.messageBar().pushMessage("Notice", "No modified features between revisions "+str(rev_begin)+" " "and "+str(rev_end)+" for layer(s) "+str(empty_layers)+". ", level=QgsMessageBar.WARNING, duration = 15)
versioning_base.add_branch( pg_conn_info, 'epanet', 'mybranch', 'test msg' ) pcur = versioning_base.Db(psycopg2.connect(pg_conn_info)) pcur.execute("SELECT * FROM epanet_mybranch_rev_head.junctions") assert( len(pcur.fetchall()) == 2 ) pcur.execute("SELECT * FROM epanet_mybranch_rev_head.pipes") assert( len(pcur.fetchall()) == 1 ) ##versioning_base.add_revision_view( pg_conn_info, 'epanet', 'mybranch', 2) ##pcur.execute("SELECT * FROM epanet_mybranch_rev_2.junctions") ##assert( len(pcur.fetchall()) == 2 ) ##pcur.execute("SELECT * FROM epanet_mybranch_rev_2.pipes") ##assert( len(pcur.fetchall()) == 1 ) select_and_where_str = versioning_base.rev_view_str( pg_conn_info, 'epanet', 'junctions','mybranch', 2) print select_and_where_str[0] + " WHERE " + select_and_where_str[1] pcur.execute(select_and_where_str[0] + " WHERE " + select_and_where_str[1]) assert( len(pcur.fetchall()) == 2 ) select_and_where_str = versioning_base.rev_view_str( pg_conn_info, 'epanet', 'pipes','mybranch', 2) print select_and_where_str[0] + " WHERE " + select_and_where_str[1] pcur.execute(select_and_where_str[0] + " WHERE " + select_and_where_str[1]) assert( len(pcur.fetchall()) == 1 ) ##pcur.execute("SELECT ST_AsText(geometry), ST_AsText(geometry_schematic) FROM epanet_mybranch_rev_2.junctions") pcur.execute("SELECT ST_AsText(geometry), ST_AsText(geometry_schematic) FROM epanet.junctions") res = pcur.fetchall() assert( res[0][0] == 'POINT(0 0)' ) assert( res[1][1] == 'POLYGON((0 0,2 0,2 2,0 2,0 0))' )
versioning_base.add_branch(pg_conn_info, 'epanet', 'mybranch', 'test msg') pcur = versioning_base.Db(psycopg2.connect(pg_conn_info)) pcur.execute("SELECT * FROM epanet_mybranch_rev_head.junctions") assert (len(pcur.fetchall()) == 2) pcur.execute("SELECT * FROM epanet_mybranch_rev_head.pipes") assert (len(pcur.fetchall()) == 1) ##versioning_base.add_revision_view( pg_conn_info, 'epanet', 'mybranch', 2) ##pcur.execute("SELECT * FROM epanet_mybranch_rev_2.junctions") ##assert( len(pcur.fetchall()) == 2 ) ##pcur.execute("SELECT * FROM epanet_mybranch_rev_2.pipes") ##assert( len(pcur.fetchall()) == 1 ) select_and_where_str = versioning_base.rev_view_str(pg_conn_info, 'epanet', 'junctions', 'mybranch', 2) print select_and_where_str[0] + " WHERE " + select_and_where_str[1] pcur.execute(select_and_where_str[0] + " WHERE " + select_and_where_str[1]) assert (len(pcur.fetchall()) == 2) select_and_where_str = versioning_base.rev_view_str(pg_conn_info, 'epanet', 'pipes', 'mybranch', 2) print select_and_where_str[0] + " WHERE " + select_and_where_str[1] pcur.execute(select_and_where_str[0] + " WHERE " + select_and_where_str[1]) assert (len(pcur.fetchall()) == 1) ##pcur.execute("SELECT ST_AsText(geometry), ST_AsText(geometry_schematic) FROM epanet_mybranch_rev_2.junctions") pcur.execute( "SELECT ST_AsText(geometry), ST_AsText(geometry_schematic) FROM epanet.junctions" ) res = pcur.fetchall() assert (res[0][0] == 'POINT(0 0)')