class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsEditorWidgetRegistry.initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() self.am.loadAttributes() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100 * i, 2 ^ i))) features.append(f) assert pr.addFeatures(features) return layer def testLoad(self): assert self.am.rowCount() == 10, self.am.rowCount() assert self.am.columnCount() == 2, self.am.columnCount() def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) assert self.am.rowCount() == 9, self.am.rowCount() self.layer.setSelectedFeatures([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() assert self.am.rowCount() == 5, self.am.rowCount() def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200))) self.layer.addFeature(f) assert self.am.rowCount() == 11, self.am.rowCount() def testRemoveColumns(self): assert self.layer.startEditing() assert self.layer.deleteAttribute(1) assert self.am.columnCount() == 1, self.am.columnCount()
class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsEditorWidgetRegistry.initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() self.am.loadAttributes() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100 * i, 2 ^ i))) features.append(f) self.assertTrue(pr.addFeatures(features)) return layer def testLoad(self): self.assertEqual(self.am.rowCount(), 10) self.assertEqual(self.am.columnCount(), 2) def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) self.assertEqual(self.am.rowCount(), 9) self.layer.selectByIds([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() self.assertEqual(self.am.rowCount(), 5) def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPoint(QgsPoint(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11) def testRemoveColumns(self): self.assertTrue(self.layer.startEditing()) self.assertTrue(self.layer.deleteAttribute(1)) self.assertEqual(self.am.columnCount(), 1)
class ApplicationDialog(QDialog, FORM_CLASS): def __init__(self, parent): QDialog.__init__(self) self.setupUi(self) uri = QgsDataSourceUri() uri.setConnection('localhost', '5432', 'etienne', 'postgres', os.environ['APP_PASSWORD']) uri.setDataSource('public', 'equipements', None) self.layer = QgsVectorLayer(uri.uri(False), 'equipements', 'postgres') self.layer_cache = QgsVectorLayerCache(self.layer, 120) self.model = QgsAttributeTableModel(self.layer_cache) self.model.loadLayer() tbl_filter_model = QgsAttributeTableFilterModel( QgsMapCanvas(), self.model) self.attribute_table.setModel(tbl_filter_model) self.attribute_table.resizeRowsToContents() self.attribute_table.resizeColumnsToContents() self.add_item.clicked.connect(self.add_new_item) self.exec_() def add_new_item(self): feature = QgsFeature() attribute_form = QgsAttributeForm(self.layer, parent=self) attribute_form.setMode(QgsAttributeEditorContext.AddFeatureMode) attribute_form.show()
def attb_table(self): from PyQt4.QtGui import QApplication, QTableView from qgis.gui import QgsAttributeTableModel QMessageBox.about(self.view, 'teste', str(self.view.currentLayer())) cache = QgsVectorLayerCache(self.view.currentLayer(), 10000) model = QgsAttributeTableModel(cache) model.loadLayer() table = QTableView() table.setModel(model) table.show()
def testTransactionRollback(self): """Test issue https://github.com/qgis/QGIS/issues/48171#issuecomment-1132709901""" d = QTemporaryDir() path = d.path() source_fields = QgsFields() source_fields.append(QgsField('int', QVariant.Int)) vl = QgsMemoryProviderUtils.createMemoryLayer('test', source_fields) f = QgsFeature() f.setAttributes([1]) vl.dataProvider().addFeature(f) tmpfile = os.path.join(path, 'testTransactionRollback.sqlite') options = { 'driverName': 'SpatiaLite', 'layerName': 'test' } err = QgsVectorLayerExporter.exportLayer(vl, tmpfile, "ogr", vl.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) vl = QgsVectorLayer( 'dbname=\'{}\' table="test" () sql='.format(tmpfile), 'test', 'spatialite') self.assertTrue(vl.isValid()) p = QgsProject.instance() p.setTransactionMode(Qgis.TransactionMode.AutomaticGroups) self.assertTrue(p.addMapLayer(vl)) cache = QgsVectorLayerCache(vl, 100) am = QgsAttributeTableModel(cache) am.loadLayer() self.assertEqual(am.rowCount(), 1) self.assertTrue(vl.startEditing()) vl.beginEditCommand('edit1') f = QgsFeature() f.setAttributes([2]) self.assertTrue(vl.addFeature(f)) self.assertEqual(am.rowCount(), 2) self.assertEqual(len([f for f in vl.getFeatures()]), 2) vl.endEditCommand() self.assertTrue(vl.rollBack()) self.assertEqual(len([f for f in vl.getFeatures()]), 1) self.assertEqual(am.rowCount(), 1)
def loadTable(self): """ Loads the attribute table. This is still not working properly. QGIS crashes. """ currLayer = self.iface.activeLayer() if not currLayer: return if currLayer.type() != QgsMapLayer.VectorLayer: return cache = QgsVectorLayerCache(currLayer, 10) model = QgsAttributeTableModel(cache) model.loadLayer() filterModel = QgsAttributeTableFilterModel(self.iface.mapCanvas(), model) self.tableView.setModel(model) self.tableView.show()
def loadTable(self): """ Loads the attribute table. This is still not working properly. QGIS crashes. """ currLayer = self.iface.activeLayer() if not currLayer: return if currLayer.type() != QgsMapLayer.VectorLayer: return cache = QgsVectorLayerCache(currLayer, 10) model = QgsAttributeTableModel(cache) model.loadLayer() filterModel = QgsAttributeTableFilterModel(self.iface.mapCanvas(), model) self.tableView.setModel(model) self.tableView.show()
def __init__(self, parent=None): """Constructor.""" super(ChartDockWidget, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) project = QgsProject.instance() self._layers.addItem("") for layerid, layer in project.mapLayers().items(): self._layers.addItem(layer.sourceName(), layerid) self._layers.currentIndexChanged.connect(self.__on_layer_changed) self._axisX.currentIndexChanged.connect(self.__refresh_chart) self._axisY.currentIndexChanged.connect(self.__refresh_chart) chart = QChart() chartView = QChartView(chart, self) self._main.layout().addWidget(chartView) series = QLineSeries() series.setName("Line 1") self._mapper = QVXYModelMapper(chartView) self._mapper.setXColumn(0) self._mapper.setYColumn(2) self._mapper.setSeries(series) layer = iface.activeLayer() layer_cache = QgsVectorLayerCache(layer, 10000, chartView) layer_cache.setFullCache(True) model = QgsAttributeTableModel(layer_cache, chartView) model.loadLayer() self._mapper.setModel(model) chart.addSeries(series)
class AttributeDialog(QDialog): def __init__(self, mapCanvas, parent=None): super().__init__(parent) self.mapCanvas = mapCanvas self.resize(600, 400) self.tableView = QgsAttributeTableView(self) self.hl = QHBoxLayout(self) self.hl.addWidget(self.tableView) def openAttributeDialog(self, layer): self.layerCache = QgsVectorLayerCache(layer, layer.featureCount()) self.tableModel = QgsAttributeTableModel(self.layerCache) self.tableModel.loadLayer() self.tableFilterModel = QgsAttributeTableFilterModel(self.mapCanvas, self.tableModel, parent=self.tableModel) self.tableFilterModel.setFilterMode(QgsAttributeTableFilterModel.ShowAll) self.tableView.setModel(self.tableFilterModel)
class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsGui.editorWidgetRegistry().initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100 * i, 2 ^ i))) features.append(f) self.assertTrue(pr.addFeatures(features)) return layer def testLoad(self): self.assertEqual(self.am.rowCount(), 10) self.assertEqual(self.am.columnCount(), 2) def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) self.assertEqual(self.am.rowCount(), 9) self.layer.selectByIds([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() self.assertEqual(self.am.rowCount(), 5) def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11) def testRemoveColumns(self): self.assertTrue(self.layer.startEditing()) self.assertTrue(self.layer.deleteAttribute(1)) self.assertEqual(self.am.columnCount(), 1) def testEdit(self): fid = 2 field_idx = 1 new_value = 333 # get the same feature from model and layer feature = self.layer.getFeature(fid) model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that feature from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) # change attribute value for a feature and commit self.layer.startEditing() self.layer.changeAttributeValue(fid, field_idx, new_value) self.layer.commitChanges() # check the feature in layer is good feature = self.layer.getFeature(fid) self.assertEqual(feature.attribute(field_idx), new_value) # get the same feature from model and layer model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that index from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx))
class UploadImages: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'UploadImages_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = UploadImagesDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Upload Images') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'UploadImages') self.toolbar.setObjectName(u'UploadImages') self.dlg.pushButton.clicked.connect(self.selectOutputFile) self.dlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) self.dlg.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.copyFiles) self.dlg.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(self.cancelAction) self.downloadOK = None def selectOutputFile(self): #filename = QFileDialog.getSaveFileName(self.dlg, "Selecione ","", '*.txt') filename = QFileDialog.getExistingDirectory(self.dlg, "Selecione ","") self.dlg.lineEdit.setText(filename) def cancelAction(self): if self.p is not None: self.p.kill() #pyqtRemoveInputHook() #pdb.set_trace() self.downloadOK = False self.dlg.reject() def dbInsertData(self): pass def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginVectorMenu( self.tr(u'&Task Manager'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('UploadImages', message) def copyFiles(self): #actlayer1 = qgis.utils.iface.activeLayer() #features1 = actlayer1.selectedFeatures() self.dlg.progressBar.setMaximum(len(self.features)) self.dlg.progressBar.setValue(0) msgBox = PyQt4.QtGui.QMessageBox() diretorioDestino = self.dlg.lineEdit.text() if(diretorioDestino): pass else: msgBox.setText("Selecione a Pasta de Destino!") msgBox.setStandardButtons(QMessageBox.Ok); msgBox.exec_() return #actlayer = qgis.utils.iface.activeLayer() index = self.modelt.index(0,0) contadorBarra = 0 for row in range(self.modelt.rowCount()): self.downloadArquivo(self.modelt.data(self.modelt.index(row,self.dlg.comboBoxCampos.currentIndex()), 0),diretorioDestino) contadorBarra += 1 self.dlg.progressBar.setValue(contadorBarra) #pyqtRemoveInputHook() #pdb.set_trace() if self.downloadOK is not False: self.downloadOK = True if self.downloadOK is True: msgBox.setText("Imagens Copiadas com Sucesso!") msgBox.setStandardButtons(QMessageBox.Ok); msgBox.exec_() self.dlg.accept() def downloadArquivo(self, caminhoArquivo, diretorioDestino): print("Inicio3") #caminhoArquivo = r'\\172.23.5.17\cotec\divabd\Mario\SIGRH.png' caminhoSalvar = caminhoArquivo[caminhoArquivo.find("\\indice_imagens\\"):] #caminhoSalvar = '\cotec\divabd\Mario\SIGRH.png' caminhoSalvar.replace("\\", "/") print("caminho 2 = "+caminhoArquivo) print("CaminhoSalvar"+caminhoSalvar) #nomeArquivo = caminhoArquivo #print("NomeArquivo="+nomeArquivo) nomeArquivo = os.path.basename(caminhoArquivo) print(caminhoArquivo) #pyqtRemoveInputHook() #pdb.set_trace() #if(os.path.isfile(diretorioDestino,nomeArquivo)) if "win" in _platform: #for generic use, test fullpath directory delimiter #and replace in case of using Linux path print("caminhoArquivo1=" + caminhoArquivo) caminhoArquivo.replace("/","\\") print("caminhoArquivo2=" + caminhoArquivo) command = '' if not (os.path.isfile(diretorioDestino+os.path.dirname(caminhoSalvar) + "\\" + nomeArquivo + '.zr')): command = ['robocopy', os.path.dirname(caminhoArquivo), diretorioDestino+os.path.dirname(caminhoSalvar), nomeArquivo] #command = ['robocopy', os.path.dirname(caminhoArquivo), diretorioDestino, nomeArquivo] print("Caminho de onde foi copiado = " + os.path.dirname(caminhoArquivo)+"\\"+nomeArquivo) print("CaminhoNovoArquivo = " + diretorioDestino + os.path.dirname(caminhoSalvar)) if command is not '': self.p = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = self.p.stdout.readline(500) if out is not '': self.dlg.textEditDownloadProgress.setText(out) sys.stdout.flush() PyQt4.QtGui.QApplication.processEvents() #update UI while self.p.poll() is None: out = self.p.stdout.readline(500) match = re.search('\\r.+\\r',out) if out is not '' and match is not None: self.dlg.textEditDownloadProgress.setText(match.group(0).split('\r')[1]) sys.stdout.flush() PyQt4.QtGui.QApplication.processEvents() #arq = open(diretorioDestino + '/' + nomeArquivo + '.zr', "w") print('Caminho ZR 1= ' + diretorioDestino+os.path.dirname(caminhoSalvar)) if not os.path.exists(diretorioDestino+os.path.dirname(caminhoSalvar)): os.makedirs(diretorioDestino+os.path.dirname(caminhoSalvar)) arq = open(diretorioDestino+os.path.dirname(caminhoSalvar) + "\\" + nomeArquivo + '.zr', "w") arq.close() elif "linux" in _platform: #for generic use, test fullpath directory delimiter #and replace in case of using Windows UNC caminhoArquivo.replace("\\","/") command = '' command1 = '' if not (os.path.isfile(diretorioDestino+os.path.dirname(caminhoSalvar) + '/' + nomeArquivo + '.zr', "w")): #testing if file path is samba relative #TODO - Define other methods if ("smb" in caminhoArquivo): #defining command (depends on smbclient tools installed) command = ['/usr/bin/smbget', '--guest', '--nonprompt', caminhoArquivo, '-o', '%s/%s' % (diretorioDestino+os.path.dirname(caminhoSalvar), nomeArquivo)] if command is not '': self.p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) #update UI while self.p.poll() is None: out = self.p.stdout.readline(500) match = re.search('\\r.+\\r',out) if out is not '' and match is not None: self.dlg.textEditDownloadProgress.setText(match.group(0).split('\r')[1]) sys.stdout.flush() PyQt4.QtGui.QApplication.processEvents() arq = open(diretorioDestino+os.path.dirname(caminhoSalvar) + '/' + nomeArquivo + '.zr', "w") arq.close() else: #levantar exceção de plataforma não identificada pass return def moveArquivo(self, caminhoArquivo, nomeArquivio): #print "Nome Original111 => " + str(caminhoArquivo) #print "Nome Original111 => " + str(nomeArquivio) diretorio = self.dlg.lineEdit.text() diretorioNovoArquivo = os.path.dirname(os.path.realpath(caminhoArquivo)) if not os.path.exists(diretorio + diretorioNovoArquivo): os.makedirs(diretorio + diretorioNovoArquivo) shutil.copy2(caminhoArquivo, diretorio + caminhoArquivo) #print "Pasta destino" + self.dlg.lineEdit.text return def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget elf.modelt.headerData(i, Qt.Horizontal, 0)param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/UploadImages/upload.png' self.add_action( icon_path, text=self.tr(u'Upload Images'), callback=self.run, parent=self.iface.mainWindow()) icon_path = ':/plugins/UploadImages/upload.png' self.add_action( icon_path, text=self.tr(u'Upload Images11111'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Upload Images'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar def populateTable(self): actlayer = qgis.utils.iface.activeLayer() self.features = actlayer.selectedFeatures() fidlist = [] if len(self.features) > 0: for f in self.features: fidlist.append(f[self.keycolumn]) selection=[] strsel=self.keycolumn + " IN (" for fid in fidlist: selection.append(fid) strsel=strsel+ "'" + str(fid) + "'," strsel=strsel[:-1] + ")" actlayer.setSubsetString(strsel) cache = QgsVectorLayerCache(actlayer, 50000) self.modelt = QgsAttributeTableModel(cache) self.modelt.loadLayer() table = self.dlg.tableView table.setModel(self.modelt) self.dlg.show() self.dlg.exec_() else: self.iface.messageBar().pushMessage("Error", QCoreApplication.translate("sipamsar","At least one feature need to be selected."), level=QgsMessageBar.WARNING) QgsMessageLog.logMessage("At least one feature need to be selected.", level=QgsMessageLog.WARNING) def populateFields(self): actlayer = qgis.utils.iface.activeLayer() cache = QgsVectorLayerCache(actlayer, 50000) self.modelc = QgsAttributeTableModel(cache) self.modelc.loadLayer() index = self.modelc.index(0,0) campos = [] for i in range(0,self.modelc.columnCount(index)): campos.append(self.modelc.headerData(i, Qt.Horizontal, Qt.DisplayRole)) self.dlg.comboBoxCampos.addItems(campos) def run(self): """Run method that performs all the real work""" #self.dlg.comboBox.clear() actlayer = qgis.utils.iface.activeLayer() if actlayer is None: self.iface.messageBar().pushMessage("Error", QCoreApplication.translate("sipamsar","No loaded layer available. Please, choose one layer and select the features to download/upload."), level=QgsMessageBar.WARNING) QgsMessageLog.logMessage("No loaded layer available. Please, choose one layer and select the features to download/upload.", level=QgsMessageLog.WARNING) return dsu = QgsDataSourceURI( actlayer.dataProvider().dataSourceUri() ) self.keycolumn = dsu.keyColumn() self.populateFields() self.populateTable()
class taskmanager: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join( self.plugin_dir, 'i18n', 'taskmanager_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Create the dialog (after translation) and keep reference self.dlg = taskmanagerDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Gerenciador de Tarefas') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'taskmanager') self.toolbar.setObjectName(u'taskmanager') self.dlg.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) self.dlg.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.dbInsertData) self.dlg.buttonBox.button(QDialogButtonBox.Ignore).clicked.connect(self.cancelAction) self.dlg.buttonBox.button(QDialogButtonBox.Close).clicked.connect(self.removeRelationship) self.dlg.buttonBox.button(QDialogButtonBox.Ok).setText("Vincular") self.dlg.buttonBox.button(QDialogButtonBox.Close).setText("Desvincular") self.dlg.buttonBox.button(QDialogButtonBox.Ignore).setText("Cancelar") self.dbdialog = dbconnectionDialog() # self.dbdialog.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) # self.dbdialog.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.getCredentials) # self.dbdialog.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(self.cancelAction) # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('taskmanager', message) def add_action( self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: self.toolbar.addAction(action) if add_to_menu: self.iface.addPluginToVectorMenu( self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/taskmanager/icon.png' self.add_action( icon_path, text=self.tr(u'Task Manager'), callback=self.run, parent=self.iface.mainWindow()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginVectorMenu( self.tr(u'&Task Manager'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar def removeRelationship(self): actlayer = qgis.utils.iface.activeLayer() index = self.modelt.index(0,0) columnindex=0 for i in range(0,self.modelt.columnCount(index)): qresult = self.modelt.headerData(i, Qt.Horizontal, 0) if self.keycolumn == qresult: columnindex=i break idlist = [] for row in range(self.modelt.rowCount()): index = self.modelt.index(row,columnindex) id = self.modelt.data(index,columnindex) idlist.append(id) queryinsert = QSqlQuery() querystr3 = "SELECT " + self.schema + ".del_row(:schema, :ref_id);" # "DELETE FROM " + self.schema+ " prodser.user_cim WHERE " self.keycolumn + " IN (" + stringlist + ");" for id in idlist: # create an item with a caption #print "id="+str(id)+", curruid="+str(curruid)+", fullname="+fullname queryinsert.prepare(querystr3) queryinsert.bindValue(":schema", self.schema) queryinsert.bindValue(":ref_id", id) testquery = queryinsert.exec_() if testquery: print "deleted: ", id else: print "not deleted: " + id + queryinsert.lastError().text() print querystr3 actlayer.setSubsetString("") self.dlg.accept() def dbInsertData(self): actlayer = qgis.utils.iface.activeLayer() index = self.modelt.index(0,0) columnindex=0 for i in range(0,self.modelt.columnCount(index)): qresult = self.modelt.headerData(i, Qt.Horizontal, 0) if self.keycolumn == qresult: columnindex=i break idlist = [] curruid = self.dlg.comboBox.itemData(self.dlg.comboBox.currentIndex()) if curruid=="0": msgBox = PyQt4.QtGui.QMessageBox(QMessageBox.Warning, u"Atenção", u"Selecione um usuário") msgBox.setText("Selecione um usuario") msgBox.setStandardButtons(QMessageBox.Ok); msgBox.exec_() return for row in range(self.modelt.rowCount()): index = self.modelt.index(row,columnindex) id = self.modelt.data(index,columnindex) idlist.append(id) queryinsert = QSqlQuery() querystr3 = "SELECT "+self.schema+ ".insert_or_update(:ref_index, :ref_user);" for id in idlist: #create an item with a caption #print "id="+str(id)+", curruid="+str(curruid)+", fullname="+fullname queryinsert.prepare(querystr3) queryinsert.bindValue(":ref_user", curruid) queryinsert.bindValue(":ref_index", id) testquery = queryinsert.exec_() if testquery: print "inserted: ", id else: print "not inserted: " + id + queryinsert.lastError().text() print querystr3 actlayer.setSubsetString("") self.dlg.accept() def cancelAction(self): self.dlg.reject() def populateTable(self): actlayer = qgis.utils.iface.activeLayer() label = "Feicoes selecionadas em " + actlayer.name() + ":" self.dlg.label_2.setText(label) # Add some textual items features = actlayer.selectedFeatures() fidlist = [] for f in features: fidlist.append(f[self.keycolumn]) selection=[] strsel=self.keycolumn + " IN (" for fid in fidlist: selection.append(fid) strsel=strsel+ "'" + str(fid) + "'," strsel=strsel[:-1] + ")" actlayer.setSubsetString(strsel) cache = QgsVectorLayerCache(actlayer, 50000) self.modelt = QgsAttributeTableModel(cache) self.modelt.loadLayer() table = self.dlg.tableView table.setModel(self.modelt) # show the dialog self.dlg.show() # Run the dialog event loop # global curruid # curruid = self.dlg.comboBox.itemData(self.dlg.comboBox.currentIndex()) self.dlg.exec_() def run(self): """Run method that performs all the real work""" self.dlg.comboBox.clear() actlayer = qgis.utils.iface.activeLayer() self.db = QSqlDatabase.addDatabase("QPSQL") if self.db.isValid(): dsu = QgsDataSourceURI( actlayer.dataProvider().dataSourceUri() ) realmsc = actlayer.dataProvider().dataSourceUri() self.schema = dsu.schema() self.db.setHostName(dsu.host()) self.db.setDatabaseName(dsu.database()) self.db.setUserName(dsu.username()) self.db.setPassword(dsu.password()) self.db.setPort(int(dsu.port())) self.keycolumn = dsu.keyColumn() ok = self.db.open() if ok: query = self.db.exec_("select * from " + self.schema + ".user order by responsavel asc") self.dlg.comboBox.addItem("", "0") # iterate over the rows while query.next(): record = query.record() name = record.value(1) uid = record.value(0) self.dlg.comboBox.addItem(name, uid) self.populateTable() else: self.dbdialog.setRealm(realmsc) self.dbdialog.setUsername(QgsDataSourceURI( actlayer.dataProvider().dataSourceUri()).username()) if self.dbdialog.exec_() == QDialog.Accepted: self.db.setUserName(self.dbdialog.getUsername()) self.db.setPassword(self.dbdialog.getPassword()) ok = self.db.open() if ok: query = self.db.exec_("select * from " + self.schema + ".user order by responsavel asc") # iterate over the rows self.dlg.comboBox.addItem("", "0") while query.next(): record = query.record() name = record.value(1) uid = record.value(0) self.dlg.comboBox.addItem(name, uid) self.populateTable() else: print self.db.lastError().text()
class ReportingConnector(abstract_model.AbstractConnector): def __init__(self,dlg,reportingModel): self.dlg = dlg self.parser_name = "Reporting" #self.model = reportingModel #reportingModel = ReportingModel() super().__init__(reportingModel,self.dlg.resultsView) def initGui(self): self.dlg.resultsInputLayer.setFilters(QgsMapLayerProxyModel.VectorLayer) self.dlg.resultsReportingLayer.setStorageMode(QgsFileWidget.GetFile) self.dlg.resultsReportingLayer.setFilter(qgsUtils.getVectorFilters()) self.dlg.resultsOutLayer.setStorageMode(QgsFileWidget.SaveFile) self.dlg.resultsOutLayer.setFilter(qgsUtils.getVectorFilters()) #self.attrView = QgsAttributeTableView(self.dlg) #self.dlg.gridLayout_9.removeWidget(self.dlg.resultsView) # self.dlg.gridLayout_9.addWidget(self.attrView) #self.dlg.resultsView.hide() #self.dlg.gridLayout_9.removeWidget(self.dlg.resultsView) def connectComponents(self): super().connectComponents() #self.dlg.reportingLayerCombo.layerChanged.connect(self.setLayer) self.dlg.resultsInputLayer.layerChanged.connect(self.setInputLayer) self.dlg.resultsSelection.fieldChanged.connect(self.setSelectExpr) self.dlg.resultsReportingLayer.fileChanged.connect(self.setReportingLayer) self.dlg.resultsCutMode.currentIndexChanged.connect(self.setMethod) self.dlg.resultsUnit.currentIndexChanged.connect(self.setUnit) self.dlg.resultsOutLayer.fileChanged.connect(self.model.setOutLayer) self.dlg.resultsRun.clicked.connect(self.runReporting) def runReporting(self): (res1, res2) = self.model.runReportingWithContext(self.dlg.context,self.dlg.feedback) out_path = res1[FragScape_algs.EffectiveMeshSizeGlobalAlgorithm.OUTPUT] out_global_meff = res2[FragScape_algs.EffectiveMeshSizeGlobalAlgorithm.OUTPUT_GLOBAL_MEFF] # UI update self.dlg.resultsGlobalRes.setText(str(out_global_meff)) self.loaded_layer = qgsUtils.loadVectorLayer(out_path,loadProject=True) self.layer_cache = QgsVectorLayerCache(self.loaded_layer,24) self.attribute_model = QgsAttributeTableModel(self.layer_cache) self.attribute_model.loadLayer() self.dlg.resultsView.setModel(self.attribute_model) self.dlg.resultsView.show() def unloadResults(self): self.dlg.resultsGlobalRes.setText(str(0)) self.loaded_layer = None self.layer_cache = None self.attribute_model = None #self.model.items = [] self.dlg.resultsView.setModel(None) # def setLayer(self,layer): # utils.debug("setLayer " + str(layer.type)) # self.dlg.reportingLayerCombo.setLayer(layer) # self.model.reporting_layer = qgsUtils.pathOfLayer(layer) def setMethod(self,idx): if idx == 0: self.model.method = ReportingModel.CUT_METHOD elif idx == 1: self.model.method = ReportingModel.CBC_METHOD else: utils.internal_error("Unexpected index for reporting method : " + str(idx)) def setUnit(self,idx): self.model.unit = idx def setInputLayer(self,layer): utils.debug("setInputLayer to " + str(layer)) self.dlg.resultsSelection.setLayer(layer) self.unloadResults() #self.dlg.resultsSelection.setLayer(loaded_layer) #self.model.input_layer = path def setSelectExpr(self,expr): self.model.select_expr = expr def setReportingLayer(self,path): utils.debug("setReportingLayer") #loaded_layer = qgsUtils.loadVectorLayer(path,loadProject=True) #self.dlg.reportingLayerCombo.setLayer(loaded_layer) #self.dlg.resultsSelection.setLayer(loaded_layer) self.model.reporting_layer = path #self.setLayer(loaded_layer) def updateUI(self): abs_input_layer = self.model.getInputLayer() utils.debug("") if os.path.isfile(abs_input_layer): loaded_layer = qgsUtils.loadVectorLayer(abs_input_layer,loadProject=True) self.dlg.resultsInputLayer.setLayer(loaded_layer) else: utils.warn("Could not find results input layer : " + str(abs_input_layer)) if self.model.select_expr: self.dlg.resultsSelection.setExpression(self.model.select_expr) if self.model.reporting_layer: #qgsUtils.loadVectorLayer(self.model.reporting_layer,loadProject=True) self.dlg.resultsReportingLayer.setFilePath(self.model.reporting_layer) if self.model.method: self.dlg.resultsCutMode.setCurrentIndex(int(self.model.method)) if self.model.unit: self.dlg.resultsUnit.setCurrentIndex(int(self.model.unit)) if self.model.out_layer: self.dlg.resultsOutLayer.setFilePath(self.model.out_layer) def fromXMLRoot(self,root): self.model.fromXMLRoot(root) self.updateUI() def toXML(self,indent=" "): return self.model.toXML()
class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsGui.editorWidgetRegistry().initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100 * i, 2 ^ i))) features.append(f) self.assertTrue(pr.addFeatures(features)) return layer def testLoad(self): self.assertEqual(self.am.rowCount(), 10) self.assertEqual(self.am.columnCount(), 2) def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) self.assertEqual(self.am.rowCount(), 9) self.layer.selectByIds([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() self.assertEqual(self.am.rowCount(), 5) def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11) def testRemoveColumns(self): self.assertTrue(self.layer.startEditing()) self.assertTrue(self.layer.deleteAttribute(1)) self.assertEqual(self.am.columnCount(), 1) def testEdit(self): fid = 2 field_idx = 1 new_value = 333 # get the same feature from model and layer feature = self.layer.getFeature(fid) model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that feature from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) # change attribute value for a feature and commit self.layer.startEditing() self.layer.changeAttributeValue(fid, field_idx, new_value) self.layer.commitChanges() # check the feature in layer is good feature = self.layer.getFeature(fid) self.assertEqual(feature.attribute(field_idx), new_value) # get the same feature from model and layer model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that index from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx))
# coding: utf-8 from PyQt4.QtGui import QDialog, QTableView from qgis.core import QgsVectorLayerCache from qgis.gui import (QgsAttributeTableModel, QgsAttributeTableView, QgsAttributeTableFilterModel) from qgis.utils import iface new_dialog = QDialog() new_dialog.resize(800, 600) vector_layer_cache = QgsVectorLayerCache(iface.activeLayer(), 10000) attribute_table_model = QgsAttributeTableModel(vector_layer_cache) attribute_table_model.loadLayer() attribute_table_filter_model = QgsAttributeTableFilterModel( iface.mapCanvas(), attribute_table_model ) attribute_table_view = QgsAttributeTableView(new_dialog) attribute_table_view.setModel(attribute_table_filter_model) new_dialog.show() # Or display the attribute_table_model with QTableView (pure QT solution) table_view = QTableView() table_view.setModel(attribute_table_model) table_view.show()
# coding: utf-8 from PyQt4.QtGui import QDialog, QTableView from qgis.core import QgsVectorLayerCache from qgis.gui import (QgsAttributeTableModel, QgsAttributeTableView, QgsAttributeTableFilterModel) from qgis.utils import iface new_dialog = QDialog() new_dialog.resize(800, 600) vector_layer_cache = QgsVectorLayerCache(iface.activeLayer(), 10000) attribute_table_model = QgsAttributeTableModel(vector_layer_cache) attribute_table_model.loadLayer() attribute_table_filter_model = QgsAttributeTableFilterModel( iface.mapCanvas(), attribute_table_model) attribute_table_view = QgsAttributeTableView(new_dialog) attribute_table_view.setModel(attribute_table_filter_model) new_dialog.show() # Or display the attribute_table_model with QTableView (pure QT solution) table_view = QTableView() table_view.setModel(attribute_table_model) table_view.show()
class GtoDockWidgetAttributeTable(QDockWidget): def __init__(self, gtomain, parent=None): super(GtoDockWidgetAttributeTable, self).__init__(parent) self.gtomain = gtomain self.info = gtomain.info self.debug = gtomain.debug self.iface = gtomain.iface self.layer = self.iface.activeLayer() self.canvas = self.iface.mapCanvas() self.canvas.currentLayerChanged.connect(self.reload) self.setObjectName('GtoAttributeTable') # layout self.dockWidgetContents = QWidget() self.view = QgsAttributeTableView() try: self.layout = QVBoxLayout(self) path = os.path.dirname(__file__) btn_wid = uic.loadUi( os.path.join(path, 'mActionGTOopenGtoTable.ui')) self.btnSelect = btn_wid.btnReload self.btnSelect.clicked.connect(self.reload) self.btnSelectAll = btn_wid.btnSelectAll self.btnSelectAll.clicked.connect(self.select_all) self.btnClose = btn_wid.btnClose self.btnClose.clicked.connect(lambda: self.setHidden(True)) # layout self.layout.addWidget(btn_wid) self.layout.addWidget(self.view) self.dockWidgetContents.setLayout(self.layout) self.setWidget(self.dockWidgetContents) # start self.reload() except Exception as e: self.info.err(e) def select_all(self): try: self.layer.selectByIds( self.attribute_table_filter_model.filteredFeatures()) except Exception as e: self.info.err(e) def reload(self, *args): try: # the table self.layer = self.iface.activeLayer() self.setWindowTitle(self.iface.activeLayer().name() + ":: Ursprünglich selektierte Objekte: {0}". format(self.layer.selectedFeatureCount())) self.vector_layer_cache = QgsVectorLayerCache(self.layer, 10000) self.attribute_table_model = QgsAttributeTableModel( self.vector_layer_cache) self.attribute_table_model.loadLayer() self.attribute_table_filter_model = QgsAttributeTableFilterModel( self.canvas, self.attribute_table_model) # filter self.attribute_table_filter_model.setFilterMode( QgsAttributeTableFilterModel.ShowFilteredList) self.attribute_table_filter_model.setFilteredFeatures( self.layer.selectedFeatureIds()) self.view.setModel(self.attribute_table_filter_model) self.view.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) for f in self.layer.fields(): # if self.debug: self.info.log("editorWidgetSetup:",f.name(),f.editorWidgetSetup().type()) if f.editorWidgetSetup().type() == 'Hidden' and not self.debug: self.view.horizontalHeader().setSectionHidden( self.layer.fields().indexOf(f.name()), True) # only follow selection on the map # self.selectionManager = qgis.QgsVectorLayerSelectionManager(self.layer, self.attribute_table_filter_model) # self.view.setFeatureSelectionManager(self.selectionManager) self.layer.selectionChanged.connect(self._selectionChanged) except Exception as e: self.info.err(e) def _selectionChanged(self, *args): if self.isVisible(): self.gtomain.runcmd("mActionZoomToSelected")
class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsGui.editorWidgetRegistry().initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100 * i, 2 ^ i))) features.append(f) self.assertTrue(pr.addFeatures(features)) return layer def testLoad(self): self.assertEqual(self.am.rowCount(), 10) self.assertEqual(self.am.columnCount(), 2) def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) self.assertEqual(self.am.rowCount(), 9) self.layer.selectByIds([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() self.assertEqual(self.am.rowCount(), 5) def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11) def testRemoveColumns(self): self.assertTrue(self.layer.startEditing()) self.assertTrue(self.layer.deleteAttribute(1)) self.assertEqual(self.am.columnCount(), 1) def testEdit(self): fid = 2 field_idx = 1 new_value = 333 # get the same feature from model and layer feature = self.layer.getFeature(fid) model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that feature from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) # change attribute value for a feature and commit self.layer.startEditing() self.layer.changeAttributeValue(fid, field_idx, new_value) self.layer.commitChanges() # check the feature in layer is good feature = self.layer.getFeature(fid) self.assertEqual(feature.attribute(field_idx), new_value) # get the same feature from model and layer model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that index from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) def testStyle(self): style_threshold = 2 color = QColor(133, 133, 133) style = QgsConditionalStyle() style.setRule(f'"fldint" <= {style_threshold}') style.setTextColor(color) self.layer.conditionalStyles().setRowStyles([style]) for f in self.layer.getFeatures(): model_index = self.am.idToIndex(f.id()) text_color = self.am.data(model_index, Qt.TextColorRole) if f['fldint'] <= style_threshold: self.assertEqual(text_color, color) else: self.assertIsNone(text_color) self.assertTrue(self.layer.startEditing()) feature1 = self.layer.getFeature(2) feature1['fldint'] = style_threshold + 1 feature2 = self.layer.getFeature(8) feature2['fldint'] = style_threshold self.assertTrue(self.layer.updateFeature(feature1)) self.assertTrue(self.layer.updateFeature(feature2)) self.assertTrue(self.layer.commitChanges()) for f in self.layer.getFeatures(): model_index = self.am.idToIndex(f.id()) text_color = self.am.data(model_index, Qt.TextColorRole) if f['fldint'] <= style_threshold: self.assertEqual(color, text_color, f'Feature {f.id()} should have color') else: self.assertIsNone(text_color, f'Feature {f.id()} should have no color') self.layer.conditionalStyles().setRowStyles([]) def testTransactionRollback(self): """Test issue https://github.com/qgis/QGIS/issues/48171#issuecomment-1132709901""" d = QTemporaryDir() path = d.path() source_fields = QgsFields() source_fields.append(QgsField('int', QVariant.Int)) vl = QgsMemoryProviderUtils.createMemoryLayer('test', source_fields) f = QgsFeature() f.setAttributes([1]) vl.dataProvider().addFeature(f) tmpfile = os.path.join(path, 'testTransactionRollback.sqlite') options = { 'driverName': 'SpatiaLite', 'layerName': 'test' } err = QgsVectorLayerExporter.exportLayer(vl, tmpfile, "ogr", vl.crs(), False, options) self.assertEqual(err[0], QgsVectorLayerExporter.NoError, 'unexpected import error {0}'.format(err)) vl = QgsVectorLayer( 'dbname=\'{}\' table="test" () sql='.format(tmpfile), 'test', 'spatialite') self.assertTrue(vl.isValid()) p = QgsProject.instance() p.setTransactionMode(Qgis.TransactionMode.AutomaticGroups) self.assertTrue(p.addMapLayer(vl)) cache = QgsVectorLayerCache(vl, 100) am = QgsAttributeTableModel(cache) am.loadLayer() self.assertEqual(am.rowCount(), 1) self.assertTrue(vl.startEditing()) vl.beginEditCommand('edit1') f = QgsFeature() f.setAttributes([2]) self.assertTrue(vl.addFeature(f)) self.assertEqual(am.rowCount(), 2) self.assertEqual(len([f for f in vl.getFeatures()]), 2) vl.endEditCommand() self.assertTrue(vl.rollBack()) self.assertEqual(len([f for f in vl.getFeatures()]), 1) self.assertEqual(am.rowCount(), 1)
class TestQgsAttributeTableModel(unittest.TestCase): @classmethod def setUpClass(cls): QgsGui.editorWidgetRegistry().initEditors() def setUp(self): self.layer = self.createLayer() self.cache = QgsVectorLayerCache(self.layer, 100) self.am = QgsAttributeTableModel(self.cache) self.am.loadLayer() def tearDown(self): del self.am del self.cache del self.layer def createLayer(self): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() features = list() for i in range(10): f = QgsFeature() f.setAttributes(["test", i]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100 * i, 2 ^ i))) features.append(f) self.assertTrue(pr.addFeatures(features)) return layer def testLoad(self): self.assertEqual(self.am.rowCount(), 10) self.assertEqual(self.am.columnCount(), 2) def testRemove(self): self.layer.startEditing() self.layer.deleteFeature(5) self.assertEqual(self.am.rowCount(), 9) self.layer.selectByIds([1, 3, 6, 7]) self.layer.deleteSelectedFeatures() self.assertEqual(self.am.rowCount(), 5) def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11) def testRemoveColumns(self): self.assertTrue(self.layer.startEditing()) self.assertTrue(self.layer.deleteAttribute(1)) self.assertEqual(self.am.columnCount(), 1) def testEdit(self): fid = 2 field_idx = 1 new_value = 333 # get the same feature from model and layer feature = self.layer.getFeature(fid) model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that feature from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) # change attribute value for a feature and commit self.layer.startEditing() self.layer.changeAttributeValue(fid, field_idx, new_value) self.layer.commitChanges() # check the feature in layer is good feature = self.layer.getFeature(fid) self.assertEqual(feature.attribute(field_idx), new_value) # get the same feature from model and layer model_index = self.am.idToIndex(fid) feature_model = self.am.feature(model_index) # check that index from layer and model are sync self.assertEqual(feature.attribute(field_idx), feature_model.attribute(field_idx)) def testStyle(self): style_threshold = 2 color = QColor(133, 133, 133) style = QgsConditionalStyle() style.setRule(f'"fldint" <= {style_threshold}') style.setTextColor(color) self.layer.conditionalStyles().setRowStyles([style]) for f in self.layer.getFeatures(): model_index = self.am.idToIndex(f.id()) text_color = self.am.data(model_index, Qt.TextColorRole) if f['fldint'] <= style_threshold: self.assertEqual(text_color, color) else: self.assertIsNone(text_color) self.assertTrue(self.layer.startEditing()) feature1 = self.layer.getFeature(2) feature1['fldint'] = style_threshold + 1 feature2 = self.layer.getFeature(8) feature2['fldint'] = style_threshold self.assertTrue(self.layer.updateFeature(feature1)) self.assertTrue(self.layer.updateFeature(feature2)) self.assertTrue(self.layer.commitChanges()) for f in self.layer.getFeatures(): model_index = self.am.idToIndex(f.id()) text_color = self.am.data(model_index, Qt.TextColorRole) if f['fldint'] <= style_threshold: self.assertEqual(color, text_color, f'Feature {f.id()} should have color') else: self.assertIsNone(text_color, f'Feature {f.id()} should have no color') self.layer.conditionalStyles().setRowStyles([])