def __init__(self, iface, project, offline_editing, parent=None): """Constructor.""" super(PackageDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.offline_editing = offline_editing self.project = project self.qfield_preferences = Preferences() self.project_lbl.setText(get_project_title(self.project)) self.button_box.button(QDialogButtonBox.Save).setText( self.tr('Create')) self.button_box.button(QDialogButtonBox.Save).clicked.connect( self.package_project) self.button_box.button(QDialogButtonBox.Reset).setText( self.tr('Configure current project...')) self.button_box.button(QDialogButtonBox.Reset).setIcon( QIcon( os.path.join(os.path.dirname(__file__), '../resources/project_properties.svg'))) self.button_box.button(QDialogButtonBox.Reset).clicked.connect( self.show_settings) self.iface.mapCanvas().extentsChanged.connect(self.extent_changed) self.extent_changed() self.devices = None # self.refresh_devices() self.setup_gui() self.offline_editing.warning.connect(self.show_warning)
def __init__(self, iface, offline_editing, parent=None): """Constructor. """ super(SynchronizeDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.preferences = Preferences() self.offline_editing = offline_editing self.button_box.button(QDialogButtonBox.Save).setText( self.tr('Synchronize')) self.button_box.button(QDialogButtonBox.Save).clicked.connect( self.start_synchronization) self.qfieldDir.setText( self.preferences.value('importDirectoryProject') or self.preferences.value('importDirectory')) self.qfieldDir_button.clicked.connect( make_folder_selector(self.qfieldDir)) self.offline_editing_done = False
def __init__(self, parent=None): preferences = Preferences() SettingDialog.__init__(self, setting_manager=preferences) super().__init__(parent, setting_manager=preferences) self.setupUi(self) self.init_widgets() self.setting_widget('importDirectory').widget.setStorageMode( QgsFileWidget.GetDirectory) self.setting_widget('exportDirectory').widget.setStorageMode( QgsFileWidget.GetDirectory)
def __init__(self, iface, project, offline_editing, parent=None): """Constructor.""" super(PackageDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.offline_editing = offline_editing self.project = project self.qfield_preferences = Preferences() self.project_lbl.setText(get_project_title(self.project)) self.push_btn = QPushButton(self.tr('Create')) self.push_btn.clicked.connect(self.package_project) self.button_box.addButton(self.push_btn, QDialogButtonBox.ActionRole) self.iface.mapCanvas().extentsChanged.connect(self.extent_changed) self.extent_changed() self.devices = None # self.refresh_devices() self.setup_gui() self.offline_editing.warning.connect(self.show_warning)
def __init__(self, parent=None): preferences = Preferences() super(PreferencesDialog, self).__init__(parent=parent) SettingDialog.__init__(self, setting_manager=preferences, mode=UpdateMode.DialogAccept) self.setupUi(self) self.init_widgets() self.setting_widget('importDirectory').widget.setStorageMode( QgsFileWidget.GetDirectory) self.setting_widget('exportDirectory').widget.setStorageMode( QgsFileWidget.GetDirectory)
class PackageDialog(QDialog, DialogUi): def __init__(self, iface, project, offline_editing, parent=None): """Constructor.""" super(PackageDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.offline_editing = offline_editing self.project = project self.qfield_preferences = Preferences() self.project_lbl.setText(get_project_title(self.project)) self.push_btn = QPushButton(self.tr('Create')) self.push_btn.clicked.connect(self.package_project) self.button_box.addButton(self.push_btn, QDialogButtonBox.ActionRole) self.iface.mapCanvas().extentsChanged.connect(self.extent_changed) self.extent_changed() self.devices = None # self.refresh_devices() self.setup_gui() self.offline_editing.warning.connect(self.show_warning) def update_progress(self, sent, total): progress = float(sent) / total * 100 self.progress_bar.setValue(progress) def setup_gui(self): """Populate gui and connect signals of the push dialog""" export_folder_path = self.qfield_preferences.value( 'exportDirectoryProject') if not export_folder_path: project_fn = QgsProject.instance().fileName() export_folder_name = fileparts(project_fn)[1] export_folder_path = os.path.join( self.qfield_preferences.value('exportDirectory'), export_folder_name) self.manualDir.setText(export_folder_path) self.manualDir_btn.clicked.connect(make_folder_selector( self.manualDir)) self.update_info_visibility() self.infoLabel.setTextInteractionFlags(Qt.TextBrowserInteraction) self.infoLabel.linkActivated.connect(lambda: self.show_settings()) def get_export_folder_from_dialog(self): """Get the export folder according to the inputs in the selected""" # manual return self.manualDir.text() def package_project(self): self.push_btn.setEnabled(False) self.informationStack.setCurrentWidget(self.progressPage) export_folder = self.get_export_folder_from_dialog() self.qfield_preferences.set_value('exportDirectoryProject', export_folder) offline_convertor = OfflineConverter(self.project, export_folder, self.iface.mapCanvas().extent(), self.offline_editing) # progress connections offline_convertor.total_progress_updated.connect(self.update_total) offline_convertor.task_progress_updated.connect(self.update_task) offline_convertor.convert() self.do_post_offline_convert_action() self.close() self.progress_group.setEnabled(False) def do_post_offline_convert_action(self): """ Show an information label that the project has been copied with a nice link to open the result folder. """ export_folder = self.get_export_folder_from_dialog() result_label = QLabel( self. tr('Finished creating the project at {result_folder}. Please copy this folder to ' 'your QField device.').format( result_folder='<a href="{folder}">{folder}</a>'.format( folder=export_folder))) result_label.setTextFormat(Qt.RichText) result_label.setTextInteractionFlags(Qt.TextBrowserInteraction) result_label.linkActivated.connect(lambda: open_folder(export_folder)) result_label.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self.iface.messageBar().pushWidget(result_label, Qgis.Info, 0) def update_info_visibility(self): """ Show the info label if there are unconfigured layers """ self.infoGroupBox.hide() for layer in list(self.project.mapLayers().values()): if not LayerSource(layer).is_configured: self.infoGroupBox.show() project_configuration = ProjectConfiguration(self.project) if project_configuration.offline_copy_only_aoi or project_configuration.create_base_map: self.informationStack.setCurrentWidget(self.selectExtentPage) else: self.informationStack.setCurrentWidget(self.progressPage) def show_settings(self): dlg = ProjectConfigurationDialog(self.iface, self.iface.mainWindow()) dlg.exec_() self.update_info_visibility() @pyqtSlot(int, int, str) def update_total(self, current, layer_count, message): self.totalProgressBar.setMaximum(layer_count) self.totalProgressBar.setValue(current) self.statusLabel.setText(message) @pyqtSlot(int, int) def update_task(self, progress, max_progress): self.layerProgressBar.setMaximum(max_progress) self.layerProgressBar.setValue(progress) @pyqtSlot() def extent_changed(self): extent = self.iface.mapCanvas().extent() self.xMinLabel.setText(str(extent.xMinimum())) self.xMaxLabel.setText(str(extent.xMaximum())) self.yMinLabel.setText(str(extent.yMinimum())) self.yMaxLabel.setText(str(extent.yMaximum())) @pyqtSlot(str, str) def show_warning(self, _, message): # Most messages from the offline editing plugin are not important enough to show in the message bar. # In case we find important ones in the future, we need to filter them. QgsApplication.instance().messageLog().logMessage( message, 'QFieldSync')
class SynchronizeDialog(QDialog, DialogUi): def __init__(self, iface, offline_editing, parent=None): """Constructor. """ super(SynchronizeDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.preferences = Preferences() self.offline_editing = offline_editing self.button_box.button(QDialogButtonBox.Save).setText( self.tr('Synchronize')) self.button_box.button(QDialogButtonBox.Save).clicked.connect( self.start_synchronization) self.qfieldDir.setText( self.preferences.value('importDirectoryProject') or self.preferences.value('importDirectory')) self.qfieldDir_button.clicked.connect( make_folder_selector(self.qfieldDir)) self.offline_editing_done = False def start_synchronization(self): self.button_box.button(QDialogButtonBox.Save).setEnabled(False) qfield_folder = self.qfieldDir.text() self.preferences.set_value('importDirectoryProject', qfield_folder) try: current_import_file_checksum = import_file_checksum(qfield_folder) imported_files_checksums = import_checksums_of_project( qfield_folder) if imported_files_checksums and current_import_file_checksum and current_import_file_checksum in imported_files_checksums: message = self.tr( "Data from this file are already synchronized with the original project." ) raise NoProjectFoundError(message) qgs_file = get_project_in_folder(qfield_folder) open_project(qgs_file) self.offline_editing.progressStopped.connect(self.update_done) self.offline_editing.layerProgressUpdated.connect( self.update_total) self.offline_editing.progressModeSet.connect(self.update_mode) self.offline_editing.progressUpdated.connect(self.update_value) self.offline_editing.synchronize() if self.offline_editing_done: original_project_path = ProjectConfiguration( QgsProject.instance()).original_project_path if original_project_path: # import the DCIM folder copy_images( os.path.join(qfield_folder, "DCIM"), os.path.join(os.path.dirname(original_project_path), "DCIM")) if open_project(original_project_path): # save the data_file_checksum to the project and save it imported_files_checksums.append( import_file_checksum(qfield_folder)) ProjectConfiguration(QgsProject.instance( )).imported_files_checksums = imported_files_checksums QgsProject.instance().write() self.iface.messageBar().pushInfo( 'QFieldSync', self.tr("Opened original project {}".format( original_project_path))) else: self.iface.messageBar().pushInfo( 'QFieldSync', self. tr("The data has been synchronized successfully but the original project ({}) could not be opened" .format(original_project_path))) else: self.iface.messageBar().pushInfo( 'QFieldSync', self.tr("No original project path found")) self.close() else: message = self.tr( "The project you imported does not seem to be an offline project" ) raise NoProjectFoundError(message) except NoProjectFoundError as e: self.iface.messageBar().pushWarning('QFieldSync', str(e)) @pyqtSlot(int, int) def update_total(self, current, layer_count): self.totalProgressBar.setMaximum(layer_count) self.totalProgressBar.setValue(current) @pyqtSlot(int) def update_value(self, progress): self.layerProgressBar.setValue(progress) @pyqtSlot('QgsOfflineEditing::ProgressMode', int) def update_mode(self, _, mode_count): self.layerProgressBar.setMaximum(mode_count) self.layerProgressBar.setValue(0) @pyqtSlot() def update_done(self): self.offline_editing.progressStopped.disconnect(self.update_done) self.offline_editing.layerProgressUpdated.disconnect(self.update_total) self.offline_editing.progressModeSet.disconnect(self.update_mode) self.offline_editing.progressUpdated.disconnect(self.update_value) self.offline_editing_done = True
class PackageDialog(QDialog, DialogUi): def __init__(self, iface, project, offline_editing, parent=None): """Constructor.""" super(PackageDialog, self).__init__(parent=parent) self.setupUi(self) self.iface = iface self.offline_editing = offline_editing self.project = project self.qfield_preferences = Preferences() self.project_lbl.setText(get_project_title(self.project)) self.button_box.button(QDialogButtonBox.Save).setText( self.tr('Create')) self.button_box.button(QDialogButtonBox.Save).clicked.connect( self.package_project) self.button_box.button(QDialogButtonBox.Reset).setText( self.tr('Configure current project...')) self.button_box.button(QDialogButtonBox.Reset).setIcon( QIcon( os.path.join(os.path.dirname(__file__), '../resources/project_properties.svg'))) self.button_box.button(QDialogButtonBox.Reset).clicked.connect( self.show_settings) self.iface.mapCanvas().extentsChanged.connect(self.extent_changed) self.extent_changed() self.devices = None # self.refresh_devices() self.setup_gui() self.offline_editing.warning.connect(self.show_warning) def update_progress(self, sent, total): progress = float(sent) / total * 100 self.progress_bar.setValue(progress) def setup_gui(self): """Populate gui and connect signals of the push dialog""" export_folder_path = self.qfield_preferences.value( 'exportDirectoryProject') if not export_folder_path: project_fn = QgsProject.instance().fileName() export_folder_name = fileparts(project_fn)[1] export_folder_path = os.path.join( self.qfield_preferences.value('exportDirectory'), export_folder_name) self.manualDir.setText(export_folder_path) self.manualDir_btn.clicked.connect(make_folder_selector( self.manualDir)) self.update_info_visibility() def get_export_folder_from_dialog(self): """Get the export folder according to the inputs in the selected""" # manual return self.manualDir.text() def package_project(self): self.button_box.button(QDialogButtonBox.Save).setEnabled(False) self.informationStack.setCurrentWidget(self.progressPage) export_folder = self.get_export_folder_from_dialog() self.qfield_preferences.set_value('exportDirectoryProject', export_folder) offline_convertor = OfflineConverter(self.project, export_folder, self.iface.mapCanvas().extent(), self.offline_editing) # progress connections offline_convertor.total_progress_updated.connect(self.update_total) offline_convertor.task_progress_updated.connect(self.update_task) offline_convertor.convert() self.do_post_offline_convert_action() self.close() self.progress_group.setEnabled(False) def do_post_offline_convert_action(self): """ Show an information label that the project has been copied with a nice link to open the result folder. """ export_folder = self.get_export_folder_from_dialog() result_message = self.tr( 'Finished creating the project at {result_folder}. Please copy this folder to ' 'your QField device.').format( result_folder='<a href="{folder}">{folder}</a>'.format( folder=export_folder)) self.iface.messageBar().pushMessage(result_message, Qgis.Success, 0) def update_info_visibility(self): """ Show the info label if there are unconfigured layers """ pathResolver = QgsProject.instance().pathResolver() showInfoConfiguration = False localizedDataPathLayers = [] for layer in list(self.project.mapLayers().values()): if not LayerSource(layer).is_configured: showInfoConfiguration = True if layer.dataProvider() is not None: metadata = QgsProviderRegistry.instance().providerMetadata( layer.dataProvider().name()) if metadata is not None: decoded = metadata.decodeUri(layer.source()) if "path" in decoded: path = pathResolver.writePath(decoded["path"]) if path.startswith("localized:"): localizedDataPathLayers.append('- {} ({})'.format( layer.name(), path[10:])) self.infoConfigurationLabel.setVisible(showInfoConfiguration) if localizedDataPathLayers: if len(localizedDataPathLayers) == 1: self.infoLocalizedLayersLabel.setText( self.tr('The layer stored in a localized data path is:\n{}' ).format("\n".join(localizedDataPathLayers))) else: self.infoLocalizedLayersLabel.setText( self.tr( 'The layers stored in a localized data path are:\n{}'). format("\n".join(localizedDataPathLayers))) self.infoLocalizedLayersLabel.setVisible(True) self.infoLocalizedPresentLabel.setVisible(True) else: self.infoLocalizedLayersLabel.setVisible(False) self.infoLocalizedPresentLabel.setVisible(False) self.infoGroupBox.setVisible(showInfoConfiguration or len(localizedDataPathLayers) > 0) project_configuration = ProjectConfiguration(self.project) if project_configuration.offline_copy_only_aoi or project_configuration.create_base_map: self.informationStack.setCurrentWidget(self.selectExtentPage) else: self.informationStack.setCurrentWidget(self.progressPage) def show_settings(self): if Qgis.QGIS_VERSION_INT >= 31500: self.iface.showProjectPropertiesDialog('QField') else: dlg = ProjectConfigurationDialog(self.iface.mainWindow()) dlg.exec_() self.update_info_visibility() @pyqtSlot(int, int, str) def update_total(self, current, layer_count, message): self.totalProgressBar.setMaximum(layer_count) self.totalProgressBar.setValue(current) self.statusLabel.setText(message) @pyqtSlot(int, int) def update_task(self, progress, max_progress): self.layerProgressBar.setMaximum(max_progress) self.layerProgressBar.setValue(progress) @pyqtSlot() def extent_changed(self): extent = self.iface.mapCanvas().extent() self.xMinLabel.setText(str(extent.xMinimum())) self.xMaxLabel.setText(str(extent.xMaximum())) self.yMinLabel.setText(str(extent.yMinimum())) self.yMaxLabel.setText(str(extent.yMaximum())) @pyqtSlot(str, str) def show_warning(self, _, message): # Most messages from the offline editing plugin are not important enough to show in the message bar. # In case we find important ones in the future, we need to filter them. QgsApplication.instance().messageLog().logMessage( message, 'QFieldSync')