You can get something like this :

The +
button allow the user to add a new line, and the -
button remove the last line. It's possible to remove the selected line with the selectedIndexes()
method from the QAbstractItemView Class.
The Get Value
button print a dictionary in the python console with an element for each row and a list with all the values.
{'layer_1': ['connexions', 'id', 'first_layer', 'True'], 'layer_2': ['lineaire_spirit_m', 'fid', 'second_layer', 'False']}
Here is the full code, it works in the QGIS Python Console :
from PyQt5.QtWidgets import QPushButton, QTableWidget, QComboBox, QDialog
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
# Create the dialog
self.resize(700, 400) # Set the size of the dialog.
# Create the table
self.tableWidget = QTableWidget(self)
self.tableWidget.setGeometry(130, 50, 500, 300) # Set the size of the table.
self.tableWidget.setColumnCount(4) # Number of columns.
self.tableWidget.setRowCount(0) # Number of rows.
self.tableWidget.setHorizontalHeaderLabels(["Layer", "Field", "String", "Bool"]) # Set labels for columns.
self.add_layer() # Add the first row.
# Create the add layer button
button_plus = QPushButton(self)
button_plus.setText("+") # Set label of the button.
button_plus.setGeometry(30, 50, 50, 50) # Set the size of the button.
button_plus.clicked.connect(self.add_layer) # Connect the button to a function.
# Create the remove layer button
button_minus = QPushButton(self)
button_minus.setText("-") # Set label of the button.
button_minus.setGeometry(30, 150, 50, 50) # Set the size of the button.
button_minus.clicked.connect(self.remove_layer) # Connect the button to a function.
# Create the get value button
button_result = QPushButton(self)
button_result.setText("Get Value") # Set label of the button.
button_result.setGeometry(10, 250, 100, 50) # Set the size of the button.
button_result.clicked.connect(self.get_result) # Connect the button to a function.
def add_layer(self):
'''
Function to add a row in the table. Add 3 widgets to the row:
- a layer combo box
- a field combo box
- a boolean combo box
'''
row_number = self.tableWidget.rowCount() # Get row number.
self.tableWidget.insertRow(row_number) # Insert a row.
layer_comboBox = QgsMapLayerComboBox() # Create the layer combo box.
self.tableWidget.setCellWidget(row_number, 0, layer_comboBox) # Add the layer combo box to the row in first column.
field_comboBox = QgsFieldComboBox() # Create the field combo box.
self.tableWidget.setCellWidget(row_number, 1, field_comboBox) # Add the field combo box to the row in second column.
layer_comboBox.layerChanged.connect(field_comboBox.setLayer) # Connect the layer combo box to the field combo box.
bool_comboBox = QComboBox() # Create the boolean combo box.
bool_comboBox.addItems(["True", "False"]) # Add the value to the boolean combo box.
self.tableWidget.setCellWidget(row_number, 3, bool_comboBox) # Add the boolean combo box to the row in fourth column.
def remove_layer(self):
'''
Function to remove the last row in the table.
'''
row_number = self.tableWidget.rowCount() # Get row number.
self.tableWidget.removeRow(row_number - 1) # Remove a row.
def get_result(self):
'''
Function to get the values in the table.
'''
result = {} # Create a dictionary to get the values of every row.
# Iteration over the rows.
for row in range(self.tableWidget.rowCount()):
row_result = [] # Create a list to get the values of every column.
# Iteration over the columns.
for column in range(self.tableWidget.columnCount()):
if column == 2:
row_result.append(self.tableWidget.item(row, column).text()) # The third column is not a cellWidget, the value is fetch differently.
else:
row_result.append(self.tableWidget.cellWidget(row, column).currentText())
result["layer_"+str(row + 1)] = row_result # Add the list of every column to the dictionary with the layer number as key.
print(result)
dialog = Dialog()
dialog.show()