def on_restore_button_clicked(self): if len(self.snap_layers_lwidget.selectedItems()) == 0: QMessageBox.information(self, self.tr("Restore Geometries"), self.tr("No layer(s) selected.")) return if QMessageBox.question(None, self.tr('Restore Geometries'), self.tr('Geometries will be restored for the selected layer(s).' ' Do you want to continue?') , QMessageBox.Yes|QMessageBox.No) == QMessageBox.No: return self.__reset_progress() self.restore_button.setEnabled(False) self.snap_button.setEnabled(False) self.cancel_snap_button.setEnabled(False) self.remove_layer_button.setEnabled(False) self.remove_all_layers_button.setEnabled(False) self.add_layers_button.setEnabled(False) self.snap_settings_gbox.setEnabled(False) self.create_backup_gbox.setEnabled(False) backup_path = self.backup_folder_edit.text() self.restore_geom_thread = RestoreGeometry(self.plugin, backup_path, self.plugin.iface.mainWindow()) self.restore_geom_thread.run_finished.connect(self.restore_geom_finished) self.restore_geom_thread.run_progressed.connect(self.progressed) self.restore_geom_thread.report_message.connect(self.report_message) self.selected_layers = list() for item in self.snap_layers_lwidget.selectedItems(): layer_id = item.data(Qt.UserRole) self.selected_layers.append(layer_id) self.remaining_layer_count = len(self.selected_layers) - 1 self.__run_restore_geom_thread(0)
class SnapToGridWidget(QDockWidget, Ui_SnapToGridWidget): def __init__(self, plugin, parent=None): super(SnapToGridWidget, self).__init__(parent) self.setupUi(self) self.plugin = plugin self.remaining_layer_count = 0 self.snap_thread = None self.restore_geom_thread = None self.layers = dict() self.selected_layers = None self.lock = QReadWriteLock() self.map_extent = None self.backup_folder_button.setIcon(self.plugin.get_icon("folder.png")) self.__set_backup_path() @pyqtSlot() def on_add_layers_button_clicked(self): layers = self.plugin.iface.legendInterface().selectedLayers() for layer in layers: caps = layer.dataProvider().capabilities() if layer.type() == QgsMapLayer.VectorLayer and not layer.isReadOnly() \ and caps & QgsVectorDataProvider.ChangeGeometries: layer_id = layer.id() if self.__layer_in_list(layer_id): continue name = layer.name() item = QListWidgetItem(name) item.setData(Qt.UserRole, layer_id) self.snap_layers_lwidget.addItem(item) self.layers[layer_id] = layer @pyqtSlot() def on_remove_layer_button_clicked(self): for item in self.snap_layers_lwidget.selectedItems(): item = self.snap_layers_lwidget.takeItem(self.snap_layers_lwidget.row(item)) layer_id = item.data(Qt.UserRole) del self.layers[layer_id] del item @pyqtSlot() def on_remove_all_layers_button_clicked(self): for row in range(0, self.snap_layers_lwidget.count()): item = self.snap_layers_lwidget.takeItem(0) del item self.layers.clear() @pyqtSlot() def on_restore_button_clicked(self): if len(self.snap_layers_lwidget.selectedItems()) == 0: QMessageBox.information(self, self.tr("Restore Geometries"), self.tr("No layer(s) selected.")) return if QMessageBox.question(None, self.tr('Restore Geometries'), self.tr('Geometries will be restored for the selected layer(s).' ' Do you want to continue?') , QMessageBox.Yes|QMessageBox.No) == QMessageBox.No: return self.__reset_progress() self.restore_button.setEnabled(False) self.snap_button.setEnabled(False) self.cancel_snap_button.setEnabled(False) self.remove_layer_button.setEnabled(False) self.remove_all_layers_button.setEnabled(False) self.add_layers_button.setEnabled(False) self.snap_settings_gbox.setEnabled(False) self.create_backup_gbox.setEnabled(False) backup_path = self.backup_folder_edit.text() self.restore_geom_thread = RestoreGeometry(self.plugin, backup_path, self.plugin.iface.mainWindow()) self.restore_geom_thread.run_finished.connect(self.restore_geom_finished) self.restore_geom_thread.run_progressed.connect(self.progressed) self.restore_geom_thread.report_message.connect(self.report_message) self.selected_layers = list() for item in self.snap_layers_lwidget.selectedItems(): layer_id = item.data(Qt.UserRole) self.selected_layers.append(layer_id) self.remaining_layer_count = len(self.selected_layers) - 1 self.__run_restore_geom_thread(0) def __run_restore_geom_thread(self, row): layer_id = self.selected_layers[row] self.restore_geom_thread.initialize(layer_id) self.restore_geom_thread.start() @pyqtSlot(str, bool) def restore_geom_finished(self, layer_id, completed): self.restore_geom_thread.wait() if completed: if self.plugin.iface.mapCanvas().isCachingEnabled(): self.layers[layer_id].setCacheImage(None) else: self.plugin.iface.mapCanvas().refresh() if self.remaining_layer_count > 0: row = len(self.selected_layers)-self.remaining_layer_count with QReadLocker(self.lock): self.remaining_layer_count -= 1 self.__run_restore_geom_thread(row) return QMessageBox.information(self, self.tr("Restoring Geometries"), self.tr("Restoring completed.")) else: QMessageBox.information(self, self.tr("Restoring Geometries"), self.tr("Restoring cancelled.")) self.restore_button.setEnabled(True) self.snap_button.setEnabled(True) self.cancel_snap_button.setEnabled(True) self.remove_layer_button.setEnabled(True) self.remove_all_layers_button.setEnabled(True) self.add_layers_button.setEnabled(True) self.snap_settings_gbox.setEnabled(True) self.create_backup_gbox.setEnabled(True) del self.restore_geom_thread self.restore_geom_thread = None @pyqtSlot() def on_cancel_restore_button_clicked(self): if not self.restore_geom_thread: return if self.restore_geom_thread.isRunning(): self.restore_geom_thread.stop() @pyqtSlot() def on_snap_button_clicked(self): if self.snap_layers_lwidget.count() == 0: return if QMessageBox.question(None, self.tr('Snap To Grid'), self.tr('Snapping to grid might change the geometries significantly' ' depending on the grid size set. Do you want to continue?'), QMessageBox.Yes|QMessageBox.No) == QMessageBox.No: return self.__reset_progress() self.snap_button.setEnabled(False) self.remove_layer_button.setEnabled(False) self.remove_all_layers_button.setEnabled(False) self.add_layers_button.setEnabled(False) self.snap_settings_gbox.setEnabled(False) self.create_backup_gbox.setEnabled(False) self.restore_geom_gbox.setEnabled(False) grid_size = self.grid_size_sbox.value() self.map_extent = self.plugin.map_canvas.extent() create_backup = self.create_backup_gbox.isChecked() backup_path = self.backup_folder_edit.text() self.snap_thread = SnapToGrid(self.plugin, grid_size, create_backup, backup_path, self.plugin.iface.mainWindow()) self.snap_thread.run_finished.connect(self.snapping_finished) self.snap_thread.run_progressed.connect(self.progressed) self.snap_thread.report_message.connect(self.report_message) self.remaining_layer_count = self.snap_layers_lwidget.count() - 1 self.__run_snap_thread(0) def __run_snap_thread(self, row): layer_id = self.snap_layers_lwidget.item(row).data(Qt.UserRole) snap_extent = self.__snap_extent(layer_id) self.snap_thread.initialize(layer_id, snap_extent) self.snap_thread.start() @pyqtSlot() def on_cancel_snap_button_clicked(self): if not self.snap_thread: return if self.snap_thread.isRunning(): self.snap_thread.stop() @pyqtSlot(str, bool) def snapping_finished(self, layer_id, completed): self.snap_thread.wait() if completed: if self.plugin.iface.mapCanvas().isCachingEnabled(): self.layers[layer_id].setCacheImage(None) else: self.plugin.iface.mapCanvas().refresh() if self.remaining_layer_count > 0: row = self.snap_layers_lwidget.count()-self.remaining_layer_count with QReadLocker(self.lock): self.remaining_layer_count -= 1 self.__run_snap_thread(row) return QMessageBox.information(self, self.tr("Snapping"), self.tr("Snapping completed.")) else: QMessageBox.information(self, self.tr("Snapping"), self.tr("Snapping cancelled.")) self.snap_button.setEnabled(True) self.remove_layer_button.setEnabled(True) self.remove_all_layers_button.setEnabled(True) self.add_layers_button.setEnabled(True) self.snap_settings_gbox.setEnabled(True) self.create_backup_gbox.setEnabled(True) self.restore_geom_gbox.setEnabled(True) del self.snap_thread self.snap_thread = None @pyqtSlot(str, int, int) def progressed(self, layer_id, progress_val, total_val): for row in range(0, self.snap_layers_lwidget.count()): layer_id2 = self.snap_layers_lwidget.item(row).data(Qt.UserRole) if layer_id2 == layer_id: item = self.snap_layers_lwidget.item(row) break text = item.text() idx = text.find('[') progress_rate = (float(progress_val)*100) / total_val if idx != -1: text = text[0:idx-1] item.setText(text + ' [{0:6.2f} %]'.format(progress_rate)) @pyqtSlot(str, str) def report_message(self, layer_id, message): for row in range(0, self.snap_layers_lwidget.count()): layer_id2 = self.snap_layers_lwidget.item(row).data(Qt.UserRole) if layer_id2 == layer_id: item = self.snap_layers_lwidget.item(row) break text = item.text() idx = text.find('[') if idx != -1: text = text[0:idx-1] item.setText(text + self.tr(' [{0}]').format(message)) def __layer_in_list(self, layer_id): for row in range(0, self.snap_layers_lwidget.count()): layer_id2 = self.snap_layers_lwidget.item(row).data(Qt.UserRole) if layer_id2 == layer_id: return True return False def __snap_extent(self, layer_id): if self.map_extent_rbutton.isChecked(): return self.map_extent else: layer = QgsMapLayerRegistry.instance().mapLayer(layer_id) return layer.extent() def __set_backup_path(self): settings = QSettings("GCI", "vertex-tools") settings.beginGroup("BackupSettings") default_path = QDir.tempPath() backup_path = settings.value("backup_path", default_path) self.backup_folder_edit.setText(backup_path) settings.endGroup() @pyqtSlot() def on_backup_folder_button_clicked(self): backup_path = self.backup_folder_edit.text() if len(backup_path) == 0: backup_path = QDir.tempPath() backup_path = QFileDialog.getExistingDirectory(self, self.tr("Select Backup Folder"), backup_path, QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks) if len(backup_path) == 0: return self.backup_folder_edit.setText(backup_path) settings = QSettings("GCI", "vertex-tools") settings.beginGroup("BackupSettings") settings.setValue("backup_path", backup_path) settings.endGroup() def __reset_progress(self): for row in range(0, self.snap_layers_lwidget.count()): item = self.snap_layers_lwidget.item(row) text = item.text() idx = text.find('[') if idx != -1: text = text[0:idx-1] item.setText(text)