def clipping_thematic_raster(self): # first check input files requirements if not valid_file_selected_in(self.QCBox_ThematicRaster, "thematic raster"): return if not valid_file_selected_in(self.QCBox_AreaOfInterest, "area of interest shape"): return # first select the target dir for save the clipping file filename, ext = os.path.splitext(get_current_file_path_in(self.QCBox_ThematicRaster)) ext = ext if ext in [".tif", ".TIF", ".img", ".IMG"] else ".tif" suggested_filename = filename + "_clip" + ext file_out, _ = QFileDialog.getSaveFileName(self, self.tr("Select the output file to save the clipping file"), suggested_filename, self.tr("GeoTiff files (*.tif);;Img files (*.img);;All files (*.*)")) if file_out == '': return # clipping clip_file = do_clipping_with_shape( self.QCBox_ThematicRaster.currentLayer(), self.QCBox_AreaOfInterest.currentLayer(), file_out, get_nodata_value(self.QCBox_ThematicRaster.currentLayer())) # copy the style thematic_basename = os.path.splitext(get_current_file_path_in(self.QCBox_ThematicRaster))[0] if os.path.isfile(thematic_basename + ".qml"): copyfile(thematic_basename + ".qml", os.path.splitext(file_out)[0] + ".qml") # unload old thematic file unload_layer(get_current_file_path_in(self.QCBox_ThematicRaster)) # load to qgis and update combobox list load_and_select_filepath_in(self.QCBox_ThematicRaster, clip_file) self.select_thematic_raster(self.QCBox_ThematicRaster.currentLayer()) iface.messageBar().pushMessage("AcATaMa", "Clipping the thematic raster with shape, completed", level=Qgis.Success)
def fileDialog_saveClassificationConfig(self): if not valid_file_selected_in(self.QCBox_SamplingFile): iface.messageBar().pushMessage( "AcATaMa", "Error, please select a sampling file to save configuration", level=Qgis.Warning) return # get file path to suggest to save but not in tmp directory file_path = get_file_path_of_layer( self.QCBox_SamplingFile.currentLayer()) path, filename = os.path.split(file_path) if self.tmp_dir in path: path = os.path.split( get_file_path_of_layer( self.QCBox_ThematicRaster.currentLayer()))[0] suggested_filename = os.path.splitext(os.path.join( path, filename))[0] + "_acatama.yml" if filename else "" file_out, _ = QFileDialog.getSaveFileName( self, self.tr("Save settings and classification status"), suggested_filename, self.tr("Yaml (*.yaml *.yml);;All files (*.*)")) if file_out != '': sampling_layer = self.QCBox_SamplingFile.currentLayer() if sampling_layer in Classification.instances: Classification.instances[sampling_layer].save_config(file_out) iface.messageBar().pushMessage("AcATaMa", "File saved successfully", level=Qgis.Success) else: iface.messageBar().pushMessage( "AcATaMa", "Failed to save, there isn't any configuration to save", level=Qgis.Warning)
def select_categorical_raster_StraRS(self, layer): # first unselect/clear sampling method self.QCBox_StraRS_Method.setCurrentIndex(-1) # check if not valid_file_selected_in(self.QCBox_CategRaster_StraRS, "categorical raster"): self.QCBox_band_CategRaster_StraRS.clear() self.nodata_CategRaster_StraRS.setValue(-1) self.QGBox_Sampling_Method.setEnabled(False) return # check if categorical raster data type is integer or byte if layer.dataProvider().dataType(1) not in [1, 2, 3, 4, 5]: self.QCBox_CategRaster_StraRS.setCurrentIndex(-1) self.QCBox_band_CategRaster_StraRS.clear() self.nodata_CategRaster_StraRS.setValue(-1) self.QGBox_Sampling_Method.setEnabled(False) iface.messageBar().pushMessage( "AcATaMa", "Error, categorical raster must be byte or integer as data type.", level=Qgis.Warning) return # set band count self.QCBox_band_CategRaster_StraRS.clear() self.QCBox_band_CategRaster_StraRS.addItems( [str(x) for x in range(1, layer.bandCount() + 1)]) self.QGBox_Sampling_Method.setEnabled(True) # set the same nodata value if select the thematic raster if layer == self.QCBox_ThematicRaster.currentLayer(): self.nodata_CategRaster_StraRS.setValue( self.nodata_ThematicRaster.value()) return self.nodata_CategRaster_StraRS.setValue(get_nodata_value(layer))
def fileDialog_saveSamplingClassification(self): if not valid_file_selected_in(self.QCBox_SamplingFile): iface.messageBar().pushMessage("AcATaMa", "Error, please first select a sampling file", level=Qgis.Warning) return # get instance sampling_layer = self.QCBox_SamplingFile.currentLayer() if sampling_layer in Classification.instances: classification = Classification.instances[sampling_layer] if not classification.is_completed: quit_msg = "The classification for this sampling file is not completed, " \ "the result will have all sampling partially classified." \ "\nDo you want to continue?" reply = QMessageBox.question(None, 'The classification is not completed', quit_msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if reply == QMessageBox.No: return else: iface.messageBar().pushMessage("AcATaMa", "Error, the classification for the sampling selected has not been initiated", level=Qgis.Warning) return # get file path to suggest to save but not in tmp directory file_path = get_file_path_of_layer(self.QCBox_SamplingFile.currentLayer()) path, filename = os.path.split(file_path) if self.tmp_dir in path: path = os.path.split(get_file_path_of_layer(self.QCBox_ThematicRaster.currentLayer()))[0] suggested_filename = os.path.splitext(os.path.join(path, filename))[0] + "_classified.gpkg" if filename else "" file_out, _ = QFileDialog.getSaveFileName(self, self.tr("Save sampling file with the classification"), suggested_filename, self.tr("GeoPackage files (*.gpkg);;Shape files (*.shp);;All files (*.*)")) if file_out != '': classification.save_sampling_classification(file_out) iface.messageBar().pushMessage("AcATaMa", "File saved successfully", level=Qgis.Success)
def check_before_accept(self): from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa # check if all buttons are associated to thematic classes if it is working with thematic classes if valid_file_selected_in(AcATaMa.dockwidget.QCBox_ThematicRaster, "thematic raster"): items_with_classes = [ self.tableBtnsConfig.item(row, 2).text() != "" for row in range(self.tableBtnsConfig.rowCount()) if self.tableBtnsConfig.item(row, 0).text() != "" ] if False in items_with_classes: msg = "Invalid configuration:\n\nA) If you are classifying with thematic classes, then " \ "you must configure the thematic class value for all buttons. \n\nB) Or if you are " \ "classifying the sampling without pairing with thematic classes, then deselect the " \ "thematic raster layer." QMessageBox.warning(self, 'Error with the classification buttons', msg, QMessageBox.Ok) return # check if all button configured have a valid name items_with_valid_names = [ self.tableBtnsConfig.item(row, 0).text() != "" for row in range(self.tableBtnsConfig.rowCount()) if self.tableBtnsConfig.item(row, 2).text() != "" ] if False in items_with_valid_names: msg = "Invalid configuration:\n\nTo create the buttons for classify, they must have a valid name." QMessageBox.warning(self, 'Error with the classification buttons', msg, QMessageBox.Ok) return # pass all checks self.accept()
def file_dialog_save_acatama_state(self): if self.suggested_yml_file: suggested_filename = self.suggested_yml_file elif valid_file_selected_in(self.QCBox_ThematicRaster) or valid_file_selected_in(self.QCBox_SamplingFile): # get file path to suggest where to save if valid_file_selected_in(self.QCBox_ThematicRaster): file_path = get_file_path_of_layer(self.QCBox_ThematicRaster.currentLayer()) else: file_path = get_file_path_of_layer(self.QCBox_SamplingFile.currentLayer()) path, filename = os.path.split(file_path) suggested_filename = os.path.splitext(os.path.join(path, filename))[0] + "_acatama.yml" if filename else "_acatama.yml" else: suggested_filename = "_acatama.yml" file_out, _ = QFileDialog.getSaveFileName(self, self.tr("Save AcATaMa configuration and state"), suggested_filename, self.tr("Yaml (*.yaml *.yml);;All files (*.*)")) if file_out != '': config.save(file_out) self.suggested_yml_file = file_out iface.messageBar().pushMessage("AcATaMa", "Configuration file saved successfully", level=Qgis.Success)
def select_categorical_raster_SimpRS(self, layer): # first check if not valid_file_selected_in(self.QCBox_CategRaster_SimpRS, "categorical raster"): self.QCBox_band_CategRaster_SimpRS.clear() return # check if categorical raster data type is integer or byte if layer.dataProvider().dataType(1) not in [1, 2, 3, 4, 5]: self.QCBox_CategRaster_SimpRS.setCurrentIndex(-1) self.QCBox_band_CategRaster_SimpRS.clear() iface.messageBar().pushMessage("AcATaMa", "Error, categorical raster must be byte or integer as data type.", level=Qgis.Warning) return # set band count self.QCBox_band_CategRaster_SimpRS.clear() self.QCBox_band_CategRaster_SimpRS.addItems([str(x) for x in range(1, layer.bandCount() + 1)])
def select_thematic_raster(self, layer): def clear_and_unset_the_thematic_raster(): with block_signals_to(self.QCBox_ThematicRaster): self.QCBox_ThematicRaster.setCurrentIndex(-1) self.QCBox_band_ThematicRaster.clear() self.nodata_ThematicRaster.setValue(-1) # SimpRS self.minDistance_SimpRS.setSuffix("") self.minDistance_SimpRS.setToolTip("") self.minDistance_SimpRS.setValue(0) # StraRS self.minDistance_StraRS.setSuffix("") self.minDistance_StraRS.setToolTip("") self.minDistance_StraRS.setValue(0) # disable sampling tab self.scrollAreaWidgetContents_S.setDisabled(True) # unset the thematic classes in classification instance sampling_layer = self.QCBox_SamplingFile.currentLayer() if sampling_layer and sampling_layer in Classification.instances: Classification.instances[ sampling_layer].with_thematic_classes = False # updated state of sampling file selected for accuracy assessment tab self.set_sampling_file_accuracy_assessment() # first check if not layer or not valid_file_selected_in(self.QCBox_ThematicRaster, "thematic raster"): clear_and_unset_the_thematic_raster() return # check if thematic raster data type is integer or byte if layer.dataProvider().dataType(1) not in [1, 2, 3, 4, 5]: clear_and_unset_the_thematic_raster() iface.messageBar().pushMessage( "AcATaMa", "Error, thematic raster must be byte or integer as data type.", level=Qgis.Warning) return # set band count self.QCBox_band_ThematicRaster.clear() self.QCBox_band_ThematicRaster.addItems( [str(x) for x in range(1, layer.bandCount() + 1)]) # set nodata value of thematic raster in nodata field self.nodata_ThematicRaster.setValue(get_nodata_value(layer)) # set/update the units in minimum distance items in sampling tab layer_dist_unit = layer.crs().mapUnits() str_unit = QgsUnitTypes.toString(layer_dist_unit) abbr_unit = QgsUnitTypes.toAbbreviatedString(layer_dist_unit) # Set the properties of the QdoubleSpinBox based on the QgsUnitTypes of the thematic raster # https://qgis.org/api/classQgsUnitTypes.html # SimpRS self.minDistance_SimpRS.setSuffix(" {}".format(abbr_unit)) self.minDistance_SimpRS.setToolTip( "Minimum distance in {} (units based on thematic raster selected)". format(str_unit)) self.minDistance_SimpRS.setRange( 0, 360 if layer_dist_unit == QgsUnitTypes.DistanceDegrees else 10e6) self.minDistance_SimpRS.setDecimals(4 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.minDistance_SimpRS.setSingleStep(0.0001 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.minDistance_SimpRS.setValue(0) # StraRS self.minDistance_StraRS.setSuffix(" {}".format(abbr_unit)) self.minDistance_StraRS.setToolTip( "Minimum distance in {} (units based on thematic raster selected)". format(str_unit)) self.minDistance_StraRS.setRange( 0, 360 if layer_dist_unit == QgsUnitTypes.DistanceDegrees else 10e6) self.minDistance_StraRS.setDecimals(4 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.minDistance_StraRS.setSingleStep(0.0001 if layer_dist_unit in [ QgsUnitTypes.DistanceKilometers, QgsUnitTypes. DistanceNauticalMiles, QgsUnitTypes.DistanceMiles, QgsUnitTypes. DistanceDegrees ] else 1) self.minDistance_StraRS.setValue(0) # enable sampling tab self.scrollAreaWidgetContents_S.setEnabled(True)
def do_simple_random_sampling(dockwidget): # first check input files requirements if not valid_file_selected_in(dockwidget.QCBox_ThematicRaster, "thematic raster"): return if dockwidget.QGBox_SimpRSwithCR.isChecked(): if not valid_file_selected_in(dockwidget.QCBox_CategRaster_SimpRS, "categorical raster"): return # get and define some variables number_of_samples = int(dockwidget.numberOfSamples_SimpRS.value()) min_distance = float(dockwidget.minDistance_SimpRS.value()) ThematicR = Raster(file_selected_combo_box=dockwidget.QCBox_ThematicRaster, band=int( dockwidget.QCBox_band_ThematicRaster.currentText()), nodata=int(dockwidget.nodata_ThematicRaster.value())) # simple random sampling in categorical raster if dockwidget.QGBox_SimpRSwithCR.isChecked(): CategoricalR = Raster( file_selected_combo_box=dockwidget.QCBox_CategRaster_SimpRS, band=int(dockwidget.QCBox_band_CategRaster_SimpRS.currentText())) try: pixel_values = [ int(p) for p in dockwidget.pixelsValuesCategRaster.text().split(",") ] except: iface.messageBar().pushMessage( "AcATaMa", "Error, wrong pixel values, set only integers and separated by commas", level=Qgis.Warning) return else: CategoricalR = None pixel_values = None # check neighbors aggregation if dockwidget.widget_generate_SimpRS.QGBox_neighbour_aggregation.isChecked( ): number_of_neighbors = int(dockwidget.widget_generate_SimpRS. QCBox_NumberOfNeighbors.currentText()) same_class_of_neighbors = int(dockwidget.widget_generate_SimpRS. QCBox_SameClassOfNeighbors.currentText()) neighbor_aggregation = (number_of_neighbors, same_class_of_neighbors) else: neighbor_aggregation = None # set the attempts_by_sampling if dockwidget.widget_generate_SimpRS.button_attempts_by_sampling.isChecked( ): attempts_by_sampling = int( dockwidget.widget_generate_SimpRS.attempts_by_sampling.value()) else: attempts_by_sampling = None # first select the target dir for save the sampling file suggested_filename = os.path.join(os.path.dirname(ThematicR.file_path), "random_sampling.gpkg") output_file, _ = QFileDialog.getSaveFileName( dockwidget, dockwidget.tr("Select the output file to save the sampling"), suggested_filename, dockwidget.tr( "GeoPackage files (*.gpkg);;Shape files (*.shp);;All files (*.*)")) if output_file == '': return # define the random seed if dockwidget.widget_generate_SimpRS.button_random_seed_by_user.isChecked( ): random_seed = dockwidget.widget_generate_SimpRS.random_seed_by_user.text( ) try: random_seed = int(random_seed) except: pass else: random_seed = None # process sampling = Sampling("simple", ThematicR, CategoricalR, output_file=output_file) sampling.generate_sampling_points( pixel_values, number_of_samples, min_distance, neighbor_aggregation, attempts_by_sampling, dockwidget.widget_generate_SimpRS.QPBar_GenerateSampling, random_seed) # success if sampling.total_of_samples == number_of_samples: load_layer(sampling.output_file) iface.messageBar().pushMessage( "AcATaMa", "Generate the simple random sampling, completed", level=Qgis.Success) # success but not completed if number_of_samples > sampling.total_of_samples > 0: load_layer(sampling.output_file) iface.messageBar().pushMessage( "AcATaMa", "Generated the simple random sampling, but can not generate requested number of " "random points {}/{}, attempts exceeded".format( sampling.total_of_samples, number_of_samples), level=Qgis.Warning, duration=-1) # zero points if sampling.total_of_samples < number_of_samples and sampling.total_of_samples == 0: # delete instance where storage all sampling generated Sampling.samplings.pop(sampling.filename, None) iface.messageBar().pushMessage( "AcATaMa", "Error, could not generate any random points with this settings, " "attempts exceeded", level=Qgis.Warning, duration=-1)
def do_stratified_random_sampling(dockwidget): # first check input files requirements if not valid_file_selected_in(dockwidget.QCBox_ThematicRaster, "thematic raster"): return if not valid_file_selected_in(dockwidget.QCBox_CategRaster_StraRS, "categorical raster"): return # get and define some variables min_distance = float(dockwidget.minDistance_StraRS.value()) ThematicR = Raster(file_selected_combo_box=dockwidget.QCBox_ThematicRaster, band=int( dockwidget.QCBox_band_ThematicRaster.currentText()), nodata=int(dockwidget.nodata_ThematicRaster.value())) CategoricalR = Raster( file_selected_combo_box=dockwidget.QCBox_CategRaster_StraRS, band=int(dockwidget.QCBox_band_CategRaster_StraRS.currentText()), nodata=int(dockwidget.nodata_CategRaster_StraRS.value())) # get values from category table ######### pixel_values = [] number_of_samples = [] for row in range(dockwidget.QTableW_StraRS.rowCount()): pixel_values.append(int(dockwidget.QTableW_StraRS.item(row, 0).text())) number_of_samples.append(dockwidget.QTableW_StraRS.item(row, 2).text()) # convert and check if number of samples only positive integers try: number_of_samples = [int(ns) for ns in number_of_samples] if True in [ns < 0 for ns in number_of_samples]: raise Exception except: iface.messageBar().pushMessage( "AcATaMa", "Error, the number of samples should be only positive integers", level=Qgis.Warning) return total_of_samples = sum(number_of_samples) if total_of_samples == 0: iface.messageBar().pushMessage( "AcATaMa", "Error, no number of samples configured!", level=Qgis.Warning) return # check neighbors aggregation if dockwidget.widget_generate_StraRS.QGBox_neighbour_aggregation.isChecked( ): number_of_neighbors = int(dockwidget.widget_generate_StraRS. QCBox_NumberOfNeighbors.currentText()) same_class_of_neighbors = int(dockwidget.widget_generate_StraRS. QCBox_SameClassOfNeighbors.currentText()) neighbor_aggregation = (number_of_neighbors, same_class_of_neighbors) else: neighbor_aggregation = None # set the attempts_by_sampling if dockwidget.widget_generate_StraRS.button_attempts_by_sampling.isChecked( ): attempts_by_sampling = int( dockwidget.widget_generate_StraRS.attempts_by_sampling.value()) else: attempts_by_sampling = None # set the method of stratified sampling and save StraRS config if dockwidget.QCBox_StraRS_Method.currentText().startswith("Fixed values"): sampling_method = "fixed values" srs_config = None if dockwidget.QCBox_StraRS_Method.currentText().startswith( "Area based proportion"): sampling_method = "area based proportion" srs_config = {} # save total expected std error srs_config["total_std_error"] = dockwidget.TotalExpectedSE.value() # get std_dev from table srs_config["std_dev"] = [] for row in range(dockwidget.QTableW_StraRS.rowCount()): srs_config["std_dev"].append( float(dockwidget.QTableW_StraRS.item(row, 3).text())) # first select the target dir for save the sampling file suggested_filename = os.path.join(os.path.dirname(ThematicR.file_path), "stratified_random_sampling.gpkg") output_file, _ = QFileDialog.getSaveFileName( dockwidget, dockwidget.tr("Select the output file to save the sampling"), suggested_filename, dockwidget.tr( "GeoPackage files (*.gpkg);;Shape files (*.shp);;All files (*.*)")) if output_file == '': return # define the random seed if dockwidget.widget_generate_StraRS.button_random_seed_by_user.isChecked( ): random_seed = dockwidget.widget_generate_StraRS.random_seed_by_user.text( ) try: random_seed = int(random_seed) except: pass else: random_seed = None # process sampling = Sampling("stratified", ThematicR, CategoricalR, sampling_method, srs_config=srs_config, output_file=output_file) sampling.generate_sampling_points( pixel_values, number_of_samples, min_distance, neighbor_aggregation, attempts_by_sampling, dockwidget.widget_generate_StraRS.QPBar_GenerateSampling, random_seed) # success if sampling.total_of_samples == total_of_samples: load_layer(sampling.output_file) iface.messageBar().pushMessage( "AcATaMa", "Generate the stratified random sampling, completed", level=Qgis.Success) # success but not completed if sampling.total_of_samples < total_of_samples and sampling.total_of_samples > 0: load_layer(sampling.output_file) iface.messageBar().pushMessage( "AcATaMa", "Generated the stratified random sampling, but can not generate requested number of " "random points {}/{}, attempts exceeded".format( sampling.total_of_samples, total_of_samples), level=Qgis.Warning, duration=-1) # zero points if sampling.total_of_samples < total_of_samples and sampling.total_of_samples == 0: # delete instance where storage all sampling generated Sampling.samplings.pop(sampling.filename, None) iface.messageBar().pushMessage( "AcATaMa", "Error, could not generate any stratified random points with this settings, " "attempts exceeded", level=Qgis.Warning, duration=-1)
def create_table(self): from AcATaMa.gui.acatama_dockwidget import AcATaMaDockWidget as AcATaMa header = ["Classification Name", "Color", "Thematic Class", ""] # clear table self.tableBtnsConfig.clear() # init table self.tableBtnsConfig.setRowCount(len(self.table_buttons)) self.tableBtnsConfig.setColumnCount(4) # hidden row labels self.tableBtnsConfig.verticalHeader().setVisible(False) # add Header self.tableBtnsConfig.setHorizontalHeaderLabels(header) # insert items for n, h in enumerate(header): if h == "Classification Name": for m, (key, item) in enumerate(self.table_buttons.items()): if m + 1 in self.buttons_config: item_table = QTableWidgetItem( self.buttons_config[m + 1]["name"]) else: item_table = QTableWidgetItem(str(item)) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) item_table.setToolTip( "Classification button ID: {}".format(key)) self.tableBtnsConfig.setItem(m, n, item_table) if h == "Color": for m, item in enumerate(self.table_buttons.values()): item_table = QTableWidgetItem() if m + 1 in self.buttons_config: item_table.setBackground( QColor(self.buttons_config[m + 1]["color"])) item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) self.tableBtnsConfig.setItem(m, n, item_table) if h == "Thematic Class": for m, item in enumerate(self.table_buttons.values()): if valid_file_selected_in( AcATaMa.dockwidget.QCBox_ThematicRaster): if m + 1 in self.buttons_config and self.buttons_config[ m + 1]["thematic_class"] is not None: item_table = QTableWidgetItem( self.buttons_config[m + 1]["thematic_class"]) else: item_table = QTableWidgetItem(str(item)) item_table.setToolTip( "Click to open the pixel value/color table of the thematic classes" ) else: item_table = QTableWidgetItem("none") item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item_table.setForeground(QColor("lightGrey")) item_table.setToolTip( "No thematic layer, if you want enable the thematic classes,\n" "select first a valid thematic layer in thematic tab" ) item_h = QTableWidgetItem(h) item_h.setForeground(QColor("lightGrey")) self.tableBtnsConfig.setHorizontalHeaderItem(2, item_h) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) self.tableBtnsConfig.setItem(m, n, item_table) if h == "": for m, item in enumerate(self.table_buttons.values()): item_table = QTableWidgetItem() path = ':/plugins/AcATaMa/icons/trash.svg' icon = QIcon(path) item_table.setIcon(icon) item_table.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item_table.setTextAlignment(Qt.AlignCenter | Qt.AlignVCenter) item_table.setToolTip("Clean this row") self.tableBtnsConfig.setItem(m, n, item_table) # set the minimum width to 0 for headers self.tableBtnsConfig.horizontalHeader().setMinimumSectionSize(0) # adjust size of Table self.tableBtnsConfig.resizeColumnsToContents() self.tableBtnsConfig.resizeRowsToContents() # adjust the dialog based on table content dialog_width = self.tableBtnsConfig.horizontalHeader().length() + 50 self.resize(dialog_width, self.height())