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.""" 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
class QScatterPlugin: def __init__(self, iface): self.iface = iface overrideLocale = QSettings().value('locale/overrideFlag', False, bool) if not overrideLocale: locale = QLocale.system().name()[:2] else: locale = QSettings().value('locale/userLocale', '') qmPath = '{}/i18n/qscatter_{}.qm'.format(pluginPath, locale) if os.path.exists(qmPath): self.translator = QTranslator() self.translator.load(qmPath) QCoreApplication.installTranslator(self.translator) def initGui(self): self.actionRun = QAction( self.tr('QScatter'), self.iface.mainWindow()) self.actionRun.setIcon( QIcon(os.path.join(pluginPath, 'icons', 'qscatter.svg'))) self.actionRun.setWhatsThis( self.tr('Interactive scatter plot')) self.actionRun.setObjectName('runQScatter') self.actionAbout = QAction( self.tr('About...'), self.iface.mainWindow()) self.actionAbout.setIcon( QgsApplication.getThemeIcon('/mActionHelpContents.svg')) self.actionAbout.setWhatsThis(self.tr('About QScatter')) self.actionRun.setObjectName('aboutQScatter') self.iface.addPluginToVectorMenu( self.tr('QScatter'), self.actionRun) self.iface.addPluginToVectorMenu( self.tr('QScatter'), self.actionAbout) self.iface.addVectorToolBarIcon(self.actionRun) self.actionRun.triggered.connect(self.run) self.actionAbout.triggered.connect(self.about) def unload(self): self.iface.removePluginVectorMenu( self.tr('QScatter'), self.actionRun) self.iface.removePluginVectorMenu( self.tr('QScatter'), self.actionAbout) self.iface.removeVectorToolBarIcon(self.actionRun) def run(self): dlg = QScatterDialog(self.iface) dlg.show() dlg.exec_() def about(self): dlg = AboutDialog() dlg.exec_() def tr(self, text): return QCoreApplication.translate('QScatter', text)
class Send2GE: def __init__(self, iface): """Initialize class""" # save reference to QGIS interface self.iface = iface self.plugin_dir = get_file_dir(__file__) def initGui(self): """Initialize graphic user interface""" #create action that will be run by the plugin self.action = QAction( QIcon("%s/icons/cursor2.png" % self.plugin_dir), "Send to Google Earth", self.iface.mainWindow() ) self.action.setWhatsThis("Send to Google Earth") self.action.setStatusTip("Send coordinates of a mouse click to Google Earth") # add plugin menu to Vector toolbar self.iface.addPluginToMenu("Send2GoogleEarth",self.action) # add icon to new menu item in Vector toolbar self.iface.addToolBarIcon(self.action) # connect action to the run method self.action.triggered.connect(self.run) # prepare map tool self.mapTool = Send2GEtool(self.iface) #self.iface.mapCanvas().mapToolSet.connect(self.mapToolChanged) def unload(self): """Actions to run when the plugin is unloaded""" # remove menu and icon from the menu self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("Send2GoogleEarth",self.action) if self.iface.mapCanvas().mapTool() == self.mapTool: self.iface.mapCanvas().unsetMapTool(self.mapTool) del self.mapTool def run(self): """Action to run""" # create a string and show it self.iface.mapCanvas().setMapTool(self.mapTool)
def add_action( self, icon_path, text, callback, enabled_flag=True, checkable=False, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, menu=None, parent=None): icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) action.setCheckable(checkable) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if menu is not None: action.setMenu(menu) 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 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. Parameters ---------- icon_path : str Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path text : str Text that should be shown in menu items for this action callback : function Function to be called when the action is triggered enabled_flag : bool, optional A flag indicating if the action should be enabled by default (defaults to True) add_to_menu : bool, optional Flag indicating whether the action should also be added to the menu (defaults to True) add_to_toolbar : bool, optional Flag indicating whether the action should also be added to the toolbar (defaults to True) status_tip : str or None, optional Text to show in a popup when mouse pointer hovers over the action (defaults to None) whats_this : str or None, optional Text to show in the status bar when the mouse pointer hovers over the action (defaults to None) parent : QWidget or None, optional Parent widget for the new action (defaults to None) Returns ---------- QAction The action that was created. Note that the action is also added to self.actions list. """ 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: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action
class HuntRegister: """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__) # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # This plugin depends on alkisplugin self.alkisplugin = None # Members self.alkisToolBar = None # the toolbar instance where the alkisplugin and huntplugin QAction symbols are placed self.alkisSelectAreaLayer = None # QgsVectorLayer selected parcels of alkisplugin self.huntSelectAreaLayer = None # QgsVectorLayer selected parcels of huntplugin # help web view self.helpiew = None # webview containing manuals # All actions are assigned to alter self.huntSelectAreaLayer self.hswapAction = None # single QAction copy selected parcels from alkisplugin to huntplugin self.hAddMarkAction = None # checkable QAction select and unselect parcels self.hlistAction = None # single QAction select parcels by parcel attributes self.hclearAction = None # single QAction unselect all selected parcels self.hownerAction = None # single QAction get parcel certificates for all selected parcels self.hhuntAction = None # single QAction create a hunt register self.hinfoAction = None # single QAction get a basic summary of all selected parcels self.helpAction = None # single QAction open help files webview browser window # self.testAction = None # single QAction used for testing program fragments self.hAddMarkTool = None # click recognizing map tool for self.hAddMarkAction self.core = None # function core for this plugin self.initTimer = QTimer( self.iface ) # timer used to init self.huntSelectAreaLayer dynamically when alkis layers are added self.initTimer.setInterval(1000) # 1 sec interval self.initTimer.timeout.connect(self.initLayers) self.init() # init main instances def init(self): """init main instances""" if (alkisAvailable): try: self.alkisplugin = Alkis.alkisplugin.alkisplugin( self.iface) # create alkisplugin object self.alkisplugin.queryOwnerAction = QAction( None ) # this is used in akisplugin "opendb" and must therefore be set to prevent runtime errors except AttributeError: QMessageBox.critical( None, "Fehler", "norGIS ALKIS-Einbindung zuerst aktivieren und \"JagdKataster\" erneut aktivieren" ) raise AttributeError("alkisplugin not active") else: QMessageBox.critical( None, "Fehler", "norGIS ALKIS-Einbindung installieren und zuerst aktivieren. Dann \"JagdKataster\" erneut aktivieren" ) raise AttributeError("alkisplugin not installed") self.core = HuntCore(self) # function core for this plugin def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" # will be set False in run() self.first_start = True self.helpview = QWebView() self.helpview.resize(1280, 850) self.helpview.setWindowTitle("JagdKataster Anleitungen") help_dir = os.path.join(self.plugin_dir, "help", "build", "html", "index.html") self.helpview.load(QUrl.fromLocalFile(help_dir)) # the toolbar entries of this plugin should be placed alongside the alkisplugin entries # therefore the alkisplugin toolbar is derived tBars = self.iface.mainWindow().findChildren( QToolBar) # get all toolbars from main window self.alkisToolBar = next( (n for n in tBars if n.objectName() == "norGIS_ALKIS_Toolbar"), None ) # find the instance of alkisplugin toolbar by its static name if self.alkisToolBar is None: # in case the toolbar is not yet loaded create the instance with its static name # create alkis toolbar in case it is not yet loaded self.alkisToolBar = self.iface.addToolBar(u"norGIS: ALKIS") self.alkisToolBar.setObjectName("norGIS_ALKIS_Toolbar") #create toolbar items self.hswapAction = QAction(QIcon("hunt:mark_transfer.svg"), "Flächenmarkierung übertragen", self.iface.mainWindow()) self.hswapAction.setWhatsThis( "Flächenmarkierung (gelb) nach Jagd-Flächenmarkierung (blau) übertragen" ) self.hswapAction.setStatusTip( "Flächenmarkierung (gelb) nach Jagd-Flächenmarkierung (blau) übertragen" ) self.hswapAction.triggered.connect(lambda: self.core.swapAlkisToHunt()) self.alkisToolBar.addAction(self.hswapAction) self.hAddMarkAction = QAction(QIcon("hunt:mark_add.svg"), u"Flurstück (de)selektieren", self.iface.mainWindow()) self.hAddMarkAction.setWhatsThis( "Flurstück in Jagd-Flächenmarkierung selektieren oder deselektieren" ) self.hAddMarkAction.setStatusTip( "Flurstück in Jagd-Flächenmarkierung selektieren oder deselektieren" ) self.hAddMarkAction.setCheckable(True) self.hAddMarkAction.triggered.connect( lambda: self.iface.mapCanvas().setMapTool(self.hAddMarkTool)) self.alkisToolBar.addAction(self.hAddMarkAction) self.hAddMarkTool = HAdd(self) self.hAddMarkTool.setAction(self.hAddMarkAction) self.hlistAction = QAction(QIcon("hunt:mark_list.svg"), "Selektieren nach Flurstückseigenschaft", self.iface.mainWindow()) self.hlistAction.setWhatsThis( "Selektierung der Flurstücke in Jagd-Flächenmarkierung anhand Flurstückseigenschaften" ) self.hlistAction.setStatusTip( "Selektierung der Flurstücke in Jagd-Flächenmarkierung anhand Flurstückseigenschaften" ) self.hlistAction.triggered.connect( lambda: self.core.showListSelection()) self.alkisToolBar.addAction(self.hlistAction) self.hclearAction = QAction(QIcon("hunt:mark_clear.svg"), "Alle deselektieren", self.iface.mainWindow()) self.hclearAction.setWhatsThis( "Alle Flurstücke in Jagd-Flächenmarkierung deselektieren") self.hclearAction.setStatusTip( "Alle Flurstücke in Jagd-Flächenmarkierung deselektieren") self.hclearAction.triggered.connect(lambda: self.core.clearHighlight()) self.alkisToolBar.addAction(self.hclearAction) self.hownerAction = QAction(QIcon("hunt:mark_own.svg"), "Flurstücksnachweise anzeigen", self.iface.mainWindow()) self.hownerAction.setWhatsThis( "Flurstücksnachweise für selektierte Flurstücke in Jagd-Flächenmarkierung anzeigen" ) self.hownerAction.setStatusTip( "Flurstücksnachweise für selektierte Flurstücke in Jagd-Flächenmarkierung anzeigen" ) self.hownerAction.triggered.connect( lambda: self.core.showParcelCerts()) self.alkisToolBar.addAction(self.hownerAction) self.hhuntAction = QAction(QIcon("hunt:mark_hunt.svg"), "Jagdkataster erstellen", self.iface.mainWindow()) self.hhuntAction.setWhatsThis( "Jagdkataster für selektierte Flurstücke in Jagd-Flächenmarkierung erstellen" ) self.hhuntAction.setStatusTip( "Jagdkataster für selektierte Flurstücke in Jagd-Flächenmarkierung erstellen" ) self.hhuntAction.triggered.connect(lambda: self.core.showHuntReg()) self.alkisToolBar.addAction(self.hhuntAction) self.hinfoAction = QAction(QIcon("hunt:mark_info.svg"), "Flurstückszusammenfassung anzeigen", self.iface.mainWindow()) self.hinfoAction.setWhatsThis( "Flurstückszusammenfassung für selektierte Flurstücke in Jagd-Flächenmarkierung anzeigen" ) self.hinfoAction.setStatusTip( "Flurstückszusammenfassung für selektierte Flurstücke in Jagd-Flächenmarkierung anzeigen" ) self.hinfoAction.triggered.connect( lambda: self.core.showSummaryDialog()) self.alkisToolBar.addAction(self.hinfoAction) self.helpAction = QAction(QIcon("hunt:logo.svg"), "Anleitungen", self.iface.mainWindow()) self.helpAction.setWhatsThis("JagdKataster-Anleitungen") self.helpAction.setStatusTip("JagdKataster-Anleitungen") self.helpAction.triggered.connect(lambda: self.helpview.show()) # self.testAction = QAction(QIcon("hunt:test.svg"), "Test", self.iface.mainWindow()) # self.testAction.setWhatsThis("Test action") # self.testAction.setStatusTip("Test action") # self.testAction.triggered.connect(lambda: self.core.test(self.huntSelectAreaLayer)) # self.alkisToolBar.addAction(self.testAction) self.iface.addPluginToDatabaseMenu("&ALKIS", self.helpAction) QgsProject.instance().layersAdded.connect( self.initTimer.start ) # react to changes in the layer tree. Maybe the alkis layers were added QgsProject.instance().layersWillBeRemoved.connect( self.layersRemoved ) # remove entries in case this plugin layers are to be removed def initLayers(self): """init self.huntSelectAreaLayer in case the alkis layers from alkisplugin are loaded""" self.initTimer.stop( ) # this methode may be called by a timer started when layers are added => stop the timer after first timeout event if self.alkisSelectAreaLayer is None: # are alkisplugin layers loaded ad readable from entry? (layerId, res) = QgsProject.instance().readEntry("alkis", "/areaMarkerLayer") if res and layerId: self.alkisSelectAreaLayer = QgsProject.instance().mapLayer( layerId) if self.huntSelectAreaLayer is None: # is the huntplugin layer already loaded? (layerId, res) = QgsProject.instance().readEntry("hunt", "/areaMarkerLayer") if res and layerId: self.huntSelectAreaLayer = QgsProject.instance().mapLayer( layerId) if self.huntSelectAreaLayer is None and self.alkisSelectAreaLayer is not None: # alkisplugin layers are loaded but huntplugin layer is not self.createLayer() # create huntplugin layer def layersRemoved(self, layersIds): """remove entries and references in case this plugin layers are to be removed""" if self.alkisSelectAreaLayer is not None and self.alkisSelectAreaLayer.id( ) in layersIds: self.alkisSelectAreaLayer = None if self.huntSelectAreaLayer is not None and self.huntSelectAreaLayer.id( ) in layersIds: QgsProject.instance().removeEntry("hunt", "/areaMarkerLayer") self.core.hlayer = None self.huntSelectAreaLayer = None def createLayer(self): """create and add huntplugin layer to the layer tree""" if (self.alkisSelectAreaLayer is not None): parent = QgsProject.instance().layerTreeRoot().findLayer( self.alkisSelectAreaLayer).parent() layeropts = QgsVectorLayer.LayerOptions(False, False) self.init( ) # reinit main instances because alkis instance conninfo might have changed (db, conninfo) = self.core.openDB() if db is None: return self.huntSelectAreaLayer = QgsVectorLayer( u"%s estimatedmetadata=true checkPrimaryKeyUnicity=0 key='ogc_fid' type=MULTIPOLYGON srid=%d table=%s.po_polygons (polygon) sql=false" % (conninfo, self.alkisplugin.epsg, self.alkisplugin.quotedschema()), u"Jagd-Flächenmarkierung", "postgres", layeropts) sym = QgsSymbol.defaultSymbol(QgsWkbTypes.PolygonGeometry) sym.setColor(Qt.blue) sym.setOpacity(0.3) self.huntSelectAreaLayer.setRenderer(QgsSingleSymbolRenderer(sym)) QgsProject.instance().addMapLayer(self.huntSelectAreaLayer, False) parent.insertLayer(0, self.huntSelectAreaLayer) self.core.hlayer = None QgsProject.instance().writeEntry("hunt", "/areaMarkerLayer", self.huntSelectAreaLayer.id()) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" if self.hswapAction: self.hswapAction.deleteLater() self.hswapAction = None if self.hAddMarkAction: self.hAddMarkAction.deleteLater() self.hAddMarkAction = None if self.hlistAction: self.hlistAction.deleteLater() self.hlistAction = None if self.hclearAction: self.hclearAction.deleteLater() self.hclearAction = None if self.hownerAction: self.hownerAction.deleteLater() self.hownerAction = None if self.hhuntAction: self.hhuntAction.deleteLater() self.hhuntAction = None if self.hinfoAction: self.hinfoAction.deleteLater() self.hinfoAction = None if self.helpAction: self.helpAction.deleteLater() self.helpAction = None # if self.testAction: # self.testAction.deleteLater() # self.testAction = None QgsProject.instance().layersAdded.disconnect(self.initTimer.start) QgsProject.instance().layersWillBeRemoved.disconnect( self.layersRemoved) def run(self): """Run method""" if self.first_start: self.first_start = False
class Cbers4aDownloader: """Plugin implementation """ def __init__(self, iface): """ Constructor Args: iface (qgis.gui.QgisInterface): a reference to the QGIS GUI interface """ self.iface = iface self.plugin_dir = os.path.dirname(__file__) self.dockwidget = None self.provider = None self.action = None self.name = 'CBERS4A Downloader' self.about = 'Search and download CBERS4A imagery' self.search = None self.collections = None self.result = None self.footprint = QgsRubberBand(iface.mapCanvas(), True) self.mux_grid = None self.wfi_grid = None self.downloading = False self.outputfolder = QgsProject.instance().absolutePath() or gettempdir( ) def initProcessing(self): self.provider = Provider() QgsApplication.processingRegistry().addProvider(self.provider) def initGui(self): """ This method is called by QGIS when the main GUI starts up or when the plugin is enabled in the Plugin Manager. Only want to register the menu items and toolbar buttons here, and connects action with run method. """ self.initProcessing() icon = QIcon(':/plugins/cbers4a/cbers4a.svg') self.action = QAction(icon, self.name, self.iface.mainWindow()) self.action.setWhatsThis(self.about) self.action.setStatusTip(self.about) self.action.setCheckable(True) self.action.triggered.connect(self.run) # for raster menu/toolbar # self.iface.addRasterToolBarIcon(self.action) # self.iface.addPluginToRasterMenu(self.name, self.action) # for plugin menu/toolbar self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu(self.name, self.action) # for custom toolbar # self.toolbar = self.iface.addToolBar('Plugin') # self.toolbar.setObjectName('Plugin') # self.toolbar.addAction(self.action) def unload(self): """ Will be executed when the plugin is disabled. Either in the Plugin Manager or when QGIS shuts down. It removes the previously defined QAction object from the menu and remove the plugin icon from the toolbar. """ # disconnect triggers if self.search is not None: self.iface.mapCanvas().extentsChanged.disconnect( self.update_extent) self.iface.mapCanvas().destinationCrsChanged.disconnect( self.update_extent) self.dockwidget.startdate.dateChanged.disconnect( self.update_startdate) self.dockwidget.enddate.dateChanged.disconnect(self.update_enddate) self.iface.projectRead.disconnect(self.update_outputfolder) self.iface.newProjectCreated.disconnect(self.update_outputfolder) QgsProject.instance().projectSaved.disconnect( self.update_outputfolder) self.dockwidget.limit.valueChanged.disconnect(self.update_limit) self.dockwidget.cloudcover.valueChanged.disconnect( self.update_cloudcover) self.dockwidget.collection.currentIndexChanged.disconnect( self.update_collection) self.dockwidget.searchButton.clicked.disconnect(self.do_search) self.dockwidget.resultsList.itemClicked.disconnect(self.preview) # self.dockwidget.credential.textChanged[str].disconnect(self.credential_changed) # self.dockwidget.credential.editingFinished.disconnect(self.credential_filled) self.dockwidget.tabs.currentChanged[int].disconnect( self.toggle_download_button) self.dockwidget.downloadButton.clicked.disconnect( self.start_download) # footprint pushbutton self.dockwidget.footprint.clicked.disconnect(self.toggle_footprint) # close search session self.search.close() # for raster menu/toolbar # self.iface.removePluginRasterMenu(self.name, self.action) # self.iface.removeRasterToolBarIcon(self.action) # for plugin menu/toolbar self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu(self.name, self.action) # remove canvas item (footprint) self.iface.mapCanvas().scene().removeItem(self.footprint) if self.dockwidget is not None: self.dockwidget.close() self.dockwidget.visibilityChanged.disconnect( self.visibility_changed) self.iface.removeDockWidget(self.dockwidget) del self.dockwidget # remove custom toolbar # if self.toolbar is not None: # del self.toolbar # remove processing provider QgsApplication.processingRegistry().removeProvider(self.provider) # clean up task try: del globals()['cbers4a_tasks'] except KeyError: pass def run(self): """ Executes the custom plugin functionality. This method is called by the previously defined QAction object (callback), which went into the toolbar icon and the menu entry. """ if self.dockwidget is None: self.dockwidget = DockCbers4aDownloader() self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dockwidget) self.dockwidget.visibilityChanged.connect(self.visibility_changed) self.init() self.dockwidget.show() else: if self.dockwidget.isVisible(): self.dockwidget.footprint.setChecked(False) self.footprint.hide() self.dockwidget.hide() else: self.dockwidget.show() def visibility_changed(self, change): """ Change icon checked status with dockwidget visibility """ self.action.setChecked(change) def get_canvas_extent(self): """ Return a tuple with current extent and crs """ crs = self.iface.mapCanvas().mapSettings().destinationCrs() extent = self.iface.mapCanvas().extent() return extent, crs def update_extent(self): """ Update extent from mapcanvas """ current_extent, current_crs = self.get_canvas_extent() output_crs = QgsCoordinateReferenceSystem('EPSG:4326') # WGS84 transform = QgsCoordinateTransform(current_crs, output_crs, QgsProject.instance()) extent = transform.transformBoundingBox(current_extent) self.dockwidget.north.setText('{0:.6f}'.format(extent.yMaximum())) self.dockwidget.south.setText('{0:.6f}'.format(extent.yMinimum())) self.dockwidget.east.setText('{0:.6f}'.format(extent.xMaximum())) self.dockwidget.west.setText('{0:.6f}'.format(extent.xMinimum())) self.search.bbox([ extent.xMinimum(), extent.yMinimum(), extent.xMaximum(), extent.yMaximum() ]) # also update footprint self.update_footprint() def update_startdate(self, new_date): defaults = QgsSettings() self.dockwidget.enddate.setDate( new_date.addDays(int(defaults.value("cbers4a/timespan", 30)))) self.search.date( self.dockwidget.startdate.date().toString('yyyy-MM-dd'), self.dockwidget.enddate.date().toString('yyyy-MM-dd')) def update_enddate(self, end_date): if end_date <= self.dockwidget.startdate.date(): self.dockwidget.startdate.setDate(end_date.addDays(-1)) self.search.date( self.dockwidget.startdate.date().toString('yyyy-MM-dd'), self.dockwidget.enddate.date().toString('yyyy-MM-dd')) def update_outputfolder(self): """ Update default output folder on new/read project """ self.outputfolder = QgsProject.instance().absolutePath() or gettempdir( ) self.dockwidget.outputfolder.lineEdit().setPlaceholderText( self.outputfolder) def update_limit(self): """ Set max number of scenes in the search """ self.search.limit(self.dockwidget.limit.value()) def update_cloudcover(self): """ Set max cloud cover in the search """ self.search.cloud_cover('<=', self.dockwidget.cloudcover.value()) def update_collection(self): """ Set collection to search in and valid start and end dates for this collection """ collection_id = self.dockwidget.collection.currentText() inpe_collections = { description: id for id, description in self.collections } # set collection to search self.search.collections([inpe_collections[collection_id]]) # set valid minimum dates mindate = self.collections.get_temporal_extent( inpe_collections[collection_id])[0].split('-') year, month, day = int(mindate[0]), int(mindate[1]), int(mindate[2]) self.dockwidget.startdate.setMinimumDate(QDate(year, month, day)) self.dockwidget.enddate.setMinimumDate(QDate(year, month, day)) # set valid maximum dates self.dockwidget.startdate.setMaximumDate(QDate.currentDate()) self.dockwidget.enddate.setMaximumDate(QDate.currentDate()) def do_search(self): """ Run search in INPE STAC Catalog """ self.result = self.search() self.dockwidget.resultsList.clear() # add items to result list # self.dockwidget.resultsList.addItems([str(item) for item in self.result]) icon = QIcon(":/images/themes/default/mIconRaster.svg") for item in self.result: list_item = QListWidgetItem(icon, str(item.id), self.dockwidget.resultsList) self.dockwidget.resultsList.addItem(list_item) if self.result.complete: self.dockwidget.resultsMsg.setText('Returned {0} scenes.'.format( self.result.returned)) else: self.dockwidget.resultsMsg.setText( 'Returned {0} scenes from {1} matched.'.format( self.result.returned, self.result.matched)) self.dockwidget.tabs.setCurrentIndex(1) self.clear_preview() def clear_preview(self): """ Clear preview tab """ self.dockwidget.webView.setHtml('') self.dockwidget.item_id.clear() self.dockwidget.item_date.clear() self.dockwidget.item_cloudcover.clear() self.dockwidget.footprint.setChecked(False) self.footprint.hide() self.dockwidget.footprint.setDisabled(True) self.dockwidget.assetsList.clear() self.dockwidget.assetsList.setDefaultText('') def preview(self, item): """ Preview selected scene """ self.clear_preview() item_id = item.text() self.dockwidget.webView.setHtml(self.result[item_id].html) self.dockwidget.item_id.setText(item_id) self.dockwidget.item_date.setText('{0}'.format( self.result[item_id].date)) self.dockwidget.item_cloudcover.setText('{0:.1f} %'.format( self.result[item_id].cloud_cover)) self.update_footprint() self.dockwidget.footprint.setEnabled(True) self.dockwidget.assetsList.setDefaultText('ALL') self.dockwidget.assetsList.addItems(self.result[item_id].assets) self.dockwidget.tabs.setCurrentIndex(2) def toggle_download_button(self, tab): """ Enable/disable download button and hide footprint on tab change """ if tab == 2: item_id = self.dockwidget.item_id.text() credential = self.dockwidget.credential.text() if item_id and credential: self.dockwidget.downloadButton.setEnabled(True) elif self.downloading: self.dockwidget.downloadButton.setEnabled(True) else: self.dockwidget.downloadButton.setDisabled(True) else: self.dockwidget.footprint.setChecked(False) self.footprint.hide() # update valid maximum dates on tab change self.dockwidget.startdate.setMaximumDate(QDate.currentDate()) self.dockwidget.enddate.setMaximumDate(QDate.currentDate()) def start_download(self): """ Start/cancel task to download item asset(s) """ if self.downloading: globals()['cbers4a_tasks'].cancel() else: item_id = self.dockwidget.item_id.text() sel_assets = self.dockwidget.assetsList.checkedItems() if sel_assets: assets = [asset for asset in sel_assets] else: assets = self.result[item_id].assets # # create the task variable with global scope # workaround for QGIS Issue #28531 # https://gis.stackexchange.com/questions/296175/issues-with-qgstask-and-task-manager/304801#304801 # globals()['cbers4a_tasks'] = QgsTask.fromFunction( 'Download {0}'.format(item_id), self.download_asset, on_finished=self.download_finished, item_id=item_id, assets=assets) # self.info('Starting task to download {} asset(s)'.format(item_id), duration=1) QgsApplication.taskManager().addTask(globals()['cbers4a_tasks']) # lock downloading self.downloading = True self.dockwidget.options.setDisabled(True) self.dockwidget.results.setDisabled(True) self.dockwidget.downloadButton.setText('Cancel Download') self.dockwidget.downloadButton.setStyleSheet( 'background-color: #ff3336') self.dockwidget.assetsList.setDisabled(True) def info(self, msg, level=Qgis.Info, duration=5): """ docstring """ self.iface.messageBar().pushMessage(msg, level, duration) def log(self, msg, level=Qgis.Info): """ docstring """ QgsMessageLog.logMessage(msg, self.name, level) def download_asset(self, task, item_id, assets): """ Task function to download asset(s) for a given item id """ self.log('Started task {}'.format(task.description())) credential = self.dockwidget.credential.text() collection = self.result[item_id].collection outdir = self.dockwidget.outputfolder.lineEdit().text( ) or self.outputfolder session = self.search.session filenames = {} for asset in assets: url = self.result[item_id].url(asset) filename = url.split("/")[-1] outfile = os.path.join(outdir, filename) r = session.get(url, params={ 'email': credential, 'item_id': item_id, 'collection': collection }, stream=True, allow_redirects=True) if r.status_code == 200: total_size = int(r.headers.get('content-length')) size = 0 with open(outfile + '.part', 'wb') as f: for ch in r.iter_content(chunk_size=4096): # page size 4kb if ch: f.write(ch) size = size + len(ch) progress = (size / total_size) * 100 # use task.setProgress to report progress task.setProgress(progress) # check task.isCanceled() to handle cancellation if task.isCanceled(): self.log('Task "{name}" was canceled'.format( name=task.description())) return None os.rename(outfile + '.part', outfile) self.log( f'Task {task.description()}:\nDownloaded file: {outfile} ({size} of {total_size} bytes)' ) filenames[asset] = outfile else: raise Exception('ERROR in ' + url + ' (' + r.reason + ')') return { 'description': item_id, 'filenames': filenames, 'outdir': outdir } def download_finished(self, exception, result=None): """ This is called when download_asset is finished. Exception is not None if download_asset raises an exception. result is the return value of download_asset. """ # VERY SLOW TO DO HERE # def __pszXML(nbands): # specband = '\n'.join([f"""<SpectralBand dstBand="{n+1}">\n</SpectralBand>""" for n in range(nbands)]) # return f"""<VRTDataset subClass="VRTPansharpenedDataset"> # <PansharpeningOptions> # {specband} # </PansharpeningOptions> # </VRTDataset>""" def __add_images(images, description, outdir, msgbar, check, vrt=True, shown=True): if check.isChecked() and vrt: pan = images.pop('pan', None) # take out pan if len(images) > 1: # stack images in a VRT file if there are more than one image left vrtfile = os.path.join(outdir, description + '.vrt') # to sort in r/g/b/nir order here sort(images.keys, key=lambda k: rgbn[k]) _RGBN = {'red': 1, 'green': 2, 'blue': 3, 'nir': 4} images_keys_ordered = sorted(images.keys(), key=lambda k: _RGBN.get(k, 5)) filenames = [images[k] for k in images_keys_ordered ] # filenames list in RGBN order ds = gdal.BuildVRT( vrtfile, filenames, options=gdal.BuildVRTOptions(separate=True, resolution='highest')) for i, bn in enumerate(images_keys_ordered): b = ds.GetRasterBand(i + 1) b.SetDescription(bn) ds.FlushCache() ds = None if pan is None: # nothing to do anymore, add VRT file __add_images({'vrt': vrtfile}, description, outdir, msgbar, check, vrt=False) else: # VERY SLOW TO DO HERE (perhaps as ProcessingProvider?) # nbands = len(images) # if nbands > 2: # may be a setting here for pansharpening choice # pan_ds = gdal.Open(pan) # pansharpened_ds = gdal.CreatePansharpenedVRT(__pszXML(nbands), pan_ds.GetRasterBand(1), # [ds.GetRasterBand(i + 1) for i in range(nbands)]) # pansharpened_filename = os.path.join(outdir, description + '_pansharpened.vrt') # driver = gdal.GetDriverByName('VRT') # driver.CreateCopy(pansharpened_filename, pansharpened_ds, 0) # # add ALL # __add_images({'pansharpened': pansharpened_filename, # 'pan': pan, 'vrt': vrtfile}, description, outdir, msgbar, check, vrt=False, shown=False) # else: # # just add pan and vrt files __add_images({ 'pan': pan, 'vrt': vrtfile }, description, outdir, msgbar, check, vrt=False) else: # do not stack since there are not enough images assert pan is not None # 'pan' should be not 'None' here images.update({'pan': pan}) # restore pan __add_images(images, description, outdir, msgbar, check, vrt=False) else: for k in images.keys(): fn = images[k] name = os.path.basename(fn).split('.')[0] layer = QgsRasterLayer(fn, name) if layer.isValid(): QgsProject.instance().addMapLayer(layer) if not shown: QgsProject.instance().layerTreeRoot().findLayer( layer.id()).setItemVisibilityChecked(shown) msgbar.dismiss() # unlock another downloading self.downloading = False self.dockwidget.options.setEnabled(True) self.dockwidget.results.setEnabled(True) self.dockwidget.downloadButton.setText('Download') self.dockwidget.downloadButton.setStyleSheet( 'background-color: None') # restore default background color self.dockwidget.assetsList.setEnabled(True) if exception is None: if result is None: self.log( 'Finished with no exception and no result (probably manually canceled by the user)', level=Qgis.Warning) else: assets = result['filenames'].keys() images = { asset: result['filenames'][asset] for asset in assets if not asset.lower().endswith(('_xml', 'thumbnail')) } if images: # ask to add image(s) to canvas widget = self.iface.messageBar().createMessage( f"Download {result['description']} finished") button = QPushButton(widget) button.setText('Add image(s)') widget.layout().addWidget(button) check = QCheckBox(widget) check.setText('Stack in VRT file') widget.layout().addWidget(check) if len(images) < 2: check.setDisabled(True) button.clicked.connect( lambda: __add_images(images, result['description'], result['outdir'], widget, check)) self.iface.messageBar().pushWidget(widget, Qgis.Info) else: self.info(f"Download {result['description']} finished") else: self.log("Exception: {}".format(exception), level=Qgis.Critical) raise exception def toggle_footprint(self): """ Toggle footprint image view on canvas """ if self.dockwidget.footprint.isChecked(): self.footprint.show() else: self.footprint.hide() def update_footprint(self): """ Update image footprint (image extent) """ item_id = self.dockwidget.item_id.text() if item_id and self.result is not None: try: if self.result[item_id].sensor == 'WFI': geojson = self.wfi_grid[self.result[item_id].path_row] else: geojson = self.mux_grid[ self.result[item_id].path_row] # MUX and WPAN qgis_geom = QgsGeometry.fromPolygonXY([[ QgsPointXY(pt[0], pt[1]) for pt in geojson['coordinates'][0] ]]) except KeyError: # use bbox xmin, ymin, xmax, ymax = self.result[item_id].bbox qgis_geom = QgsGeometry.fromRect( QgsRectangle(xmin, ymin, xmax, ymax)) self.footprint.setToGeometry( qgis_geom, QgsCoordinateReferenceSystem('EPSG:4326')) defaults = QgsSettings() self.footprint.setStrokeColor( defaults.value("cbers4a/colorstroke", QColor(255, 255, 82))) self.footprint.setWidth(3) self.toggle_footprint() def load_grids(self): """ Load CBERS4A MUX and WFI grids """ # json files json_mux = os.path.join(self.plugin_dir, 'grid/cbers4a_mux.json') json_wfi = os.path.join(self.plugin_dir, 'grid/cbers4a_wfi.json') # read mux grid with open(json_mux) as mux: self.mux_grid = json.load(mux) # read wfi grid with open(json_wfi) as wfi: self.wfi_grid = json.load(wfi) def defaults_settings(self): """ Init plugin settings defaults: - cbers4a/colorstroke - cbers4a/cloudcover - cbers4a/credential - cbers4a/timespan - cbers4a/limit """ s = QgsSettings() if not s.contains("cbers4a/colorstroke"): s.setValue("cbers4a/colorstroke", QColor(255, 255, 82)) s.setValue("cbers4a/cloudcover", 10) s.setValue("cbers4a/credential", '') s.setValue("cbers4a/timespan", 30) s.setValue("cbers4a/limit", 100) def init(self): """ Fill options, default values and connect triggers of the dockwidget """ # init settings self.defaults_settings() # init Search instance self.search = Search() # get collections self.collections = self.search.get_collections() inpe_collections = { description: id for id, description in self.collections } # load grids self.load_grids() # connect triggers self.iface.mapCanvas().extentsChanged.connect(self.update_extent) self.iface.mapCanvas().destinationCrsChanged.connect( self.update_extent) self.dockwidget.startdate.dateChanged.connect(self.update_startdate) self.dockwidget.enddate.dateChanged.connect(self.update_enddate) self.iface.projectRead.connect(self.update_outputfolder) self.iface.newProjectCreated.connect(self.update_outputfolder) QgsProject.instance().projectSaved.connect(self.update_outputfolder) self.dockwidget.limit.valueChanged.connect(self.update_limit) self.dockwidget.cloudcover.valueChanged.connect(self.update_cloudcover) self.dockwidget.collection.currentIndexChanged.connect( self.update_collection) self.dockwidget.searchButton.clicked.connect(self.do_search) self.dockwidget.resultsList.itemClicked.connect(self.preview) # self.dockwidget.credential.textChanged[str].connect(self.credential_changed) # self.dockwidget.credential.editingFinished.connect(self.credential_filled) self.dockwidget.tabs.currentChanged[int].connect( self.toggle_download_button) self.dockwidget.downloadButton.clicked.connect(self.start_download) self.dockwidget.footprint.clicked.connect(self.toggle_footprint) # fill collections combobox self.dockwidget.collection.addItems(inpe_collections.keys()) # set defaults defaults = QgsSettings() self.dockwidget.cloudcover.setValue( int(defaults.value("cbers4a/cloudcover", 10))) self.dockwidget.limit.setValue( int(defaults.value("cbers4a/limit", 100))) self.dockwidget.startdate.setDate(QDate.currentDate().addDays( -int(defaults.value("cbers4a/timespan", 30)))) self.dockwidget.credential.setText( defaults.value("cbers4a/credential", '')) self.update_extent() self.update_outputfolder() # disable download button # self.dockwidget.downloadButton.setDisabled(True) # validate credential (seems email) # self.dockwidget.credential.clear() # validator = QRegExpValidator(QRegExp("[^@]+@[^@]+\.[^@]+")) # self.dockwidget.credential.setValidator(validator) # disable footprint pushbutton self.dockwidget.footprint.setIcon( QIcon(':/images/themes/default/mActionShowSelectedLayers.svg')) self.dockwidget.footprint.setCheckable(True) self.dockwidget.footprint.setDisabled(True) self.dockwidget.downloadButton.setText('Download') self.dockwidget.assetsList.setDefaultText('') # start in first tab self.dockwidget.tabs.setCurrentIndex(0)
class PostNAS_Search: def __init__(self, iface): # 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', 'PostNAS_Search_{}.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 = PostNAS_SearchDialog(iface=self.iface) self.conf = PostNAS_ConfDialog(iface=self.iface) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&PostNAS_Search') self.searchDockWidget = None self.searchDockWidgetArea = Qt.LeftDockWidgetArea # noinspection PyMethodMayBeStatic def tr(self, message): # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('PostNAS_Search', message) def initGui(self): # Create Conf-Action and Menuentry self.confAction = QAction("Einstellungen", self.iface.mainWindow()) self.confAction.setWhatsThis("Konfiguration der PostNAS-Suche") self.confAction.setStatusTip("Konfiguration der PostNAS-Suche") self.confAction.triggered.connect(self.showConf) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.confAction) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.confAction) self.toggleSearchAction = QAction(u"Flurstücksuche", self.iface.mainWindow()) self.toggleSearchAction.setWhatsThis( u"Starten/Schliessen der Flurstücksuche") self.toggleSearchAction.setStatusTip( u"Starten/Schliessen der Flurstücksuche") self.toggleSearchAction.triggered.connect(self.toggleWidget) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.toggleSearchAction) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.toggleSearchAction) self.fulltextindex = QAction(u"Volltextindex erstellen", self.iface.mainWindow()) self.fulltextindex.setWhatsThis( u"Erzeugt einen Volltextindex in der Datenbank um die Suche zu beschleunigen" ) self.fulltextindex.setStatusTip( u"Erzeugt einen Volltextindex in der Datenbank um die Suche zu beschleunigen" ) self.fulltextindex.triggered.connect(self.createFulltextindex) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.fulltextindex) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.fulltextindex) # Create action that will start plugin configuration self.action = QAction( QIcon(":/plugins/PostNAS_Search/search_24x24.png"), u"Flurstücksuche", self.iface.mainWindow()) self.action.setCheckable(True) # connect the action to the run method self.action.triggered.connect(self.toggleWidget) # Add toolbar button and menu item self.iface.addToolBarIcon(self.action) def toggleWidget(self, event): if self.searchDockWidget == None: self.searchDockWidget = QDockWidget(self.iface.mainWindow()) self.searchDockWidget.setWindowTitle(self.tr(u'Suche')) self.searchDockWidget.setWidget(self.dlg) self.searchDockWidget.closeEvent = self.toggleWidget self.iface.addDockWidget(self.searchDockWidgetArea, self.searchDockWidget) self.action.setChecked(True) else: self.searchDockWidgetArea = self.iface.mainWindow().dockWidgetArea( self.searchDockWidget) self.iface.removeDockWidget(self.searchDockWidget) self.searchDockWidget = None self.action.setChecked(False) def showConf(self): dlg = PostNAS_ConfDialog(self) dlg.exec_() def createFulltextindex(self): dlg = PostNAS_CreateFulltextindex(self) dlg.exec_() def unload(self): # Remove the Toolbar Icon self.iface.removeToolBarIcon(self.action) # Remove DockWidget if self.searchDockWidget != None: self.iface.removeDockWidget(self.searchDockWidget) if hasattr(self.iface, "removePluginDatabaseMenu"): self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.confAction) self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.toggleSearchAction) self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.fulltextindex) else: self.iface.removePluginMenu("&PostNAS-Suche", self.confAction) self.iface.removePluginMenu("&PostNAS-Suche", self.toggleSearchAction) self.iface.removePluginMenu("&PostNAS-Suche", self.fulltextindex) if self.confAction: self.confAction.deleteLater() self.confAction = None if self.toggleSearchAction: self.toggleSearchAction.deleteLater() self.toggleSearchAction = None if self.fulltextindex: self.fulltextindex.deleteLater() self.fulltextindex = None
class XYZHubConnector(object): """base plugin""" def __init__(self, iface): """init""" import sys print(sys.version) self.iface = iface self.web_menu = "&{name}".format(name=config.PLUGIN_FULL_NAME) self.hasGuiInitialized = False self.init_modules() self.obj = self def initGui(self): """startup""" parent = self.iface.mainWindow() ######## action, button icon = QIcon("%s/%s" % (config.PLUGIN_DIR,"images/xyz.png")) icon_bbox = QIcon("%s/%s" % (config.PLUGIN_DIR,"images/bbox.svg")) self.action_connect = QAction(icon, "XYZ Hub Connection", parent) self.action_connect.setWhatsThis( QCoreApplication.translate(PLUGIN_NAME, "WhatsThis message" )) self.action_connect.setStatusTip( QCoreApplication.translate(PLUGIN_NAME, "status tip message" )) self.action_sync_edit = QAction( QIcon("%s/%s" % (config.PLUGIN_DIR,"images/sync.svg")), "Push changes to XYZ Hub", parent) self.action_clear_cache = QAction( QIcon("%s/%s" % (config.PLUGIN_DIR,"images/delete.svg")), "Clear cache", parent) # self.action_sync_edit.setVisible(False) # disable magic sync self.edit_buffer.config_ui(self.enable_sync_btn) self.cb_layer_selected(self.iface.activeLayer()) ######## CONNECT action, button self.action_connect.triggered.connect(self.open_connection_dialog) self.action_sync_edit.triggered.connect(self.open_sync_edit_dialog) self.action_clear_cache.triggered.connect( self.open_clear_cache_dialog) ######## Add the toolbar + button self.toolbar = self.iface.addToolBar(PLUGIN_NAME) self.toolbar.setObjectName(config.PLUGIN_FULL_NAME) self.actions_menu = [self.action_connect, self.action_sync_edit, self.action_clear_cache] for a in [self.action_connect, self.action_sync_edit]: self.toolbar.addAction(a) for a in self.actions_menu: self.iface.addPluginToWebMenu(self.web_menu, a) # # uncomment to use menu button # tool_btn = QToolButton(self.toolbar) # tool_btn.setDefaultAction(self.action_connect) # tool_btn.setPopupMode(tool_btn.MenuButtonPopup) # self.xyz_widget_action = self.toolbar.addWidget(tool_btn) # uncomment to use menu button # self.toolbar.addAction(self.action_connect) self.action_help = None progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(0) progress.reset() progress.hide() # progress = self.iface.statusBarIface().children()[2] # will be hidden by qgis self.iface.statusBarIface().addPermanentWidget(progress) self.pb = progress # btn_toggle_edit = self.get_btn_toggle_edit() # btn_toggle_edit.toggled.connect(lambda *a: print("toggled", a)) self.hasGuiInitialized = True # unused def get_btn_toggle_edit(self): text_toggle_edit = "toggle editing" toolbar = self.iface.digitizeToolBar() mapping = dict( (w.text().lower() if hasattr(w,"text") else str(i), w) for i, w in enumerate(toolbar.children()) ) return mapping[text_toggle_edit] def new_session(self): self.con_man.reset() self.edit_buffer.reset() self.pending_delete_qnodes.clear() if self.hasGuiInitialized: self.pb.hide() def init_modules(self): if LOG_TO_FILE: QgsApplication.messageLog().messageReceived.connect(cb_log_qgis) #, Qt.QueuedConnection connect_global_error_signal(self.log_err_traceback) # util.init_module() # parent = self.iface.mainWindow() parent = QgsProject.instance() self.secret = Secret(config.USER_PLUGIN_DIR +"/secret.ini") ######## Init xyz modules self.map_basemap_meta = basemap.load_default_xml() self.auth_manager = AuthManager(config.USER_PLUGIN_DIR +"/auth.ini") self.network = NetManager(parent) self.con_man = LoaderManager() self.con_man.config(self.network) self.edit_buffer = EditBuffer() ######## data flow # self.conn_info = SpaceConnectionInfo() ######## token self.token_config = ServerTokenConfig(config.USER_PLUGIN_DIR +"/token.ini", parent) self.token_config.set_default_servers(net_utils.API_URL) self.token_model = self.token_config.get_token_model() self.server_model = self.token_config.get_server_model() ######## CALLBACK self.con_man.ld_pool.signal.progress.connect( self.cb_progress_busy) #, Qt.QueuedConnection self.con_man.ld_pool.signal.finished.connect( self.cb_progress_done) QgsProject.instance().cleared.connect(self.new_session) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.edit_buffer.remove_layers) # QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.layer_man.remove_layers) # QgsProject.instance().layersAdded.connect( self.edit_buffer.config_connection) self.iface.currentLayerChanged.connect( self.cb_layer_selected) # UNCOMMENT canvas = self.iface.mapCanvas() self.lastRect = bbox_utils.extent_to_rect(bbox_utils.get_bounding_box(canvas)) self.iface.mapCanvas().extentsChanged.connect( self.reload_tile, Qt.QueuedConnection) # handle move, delete xyz layer group self.pending_delete_qnodes = dict() QgsProject.instance().layerTreeRoot().willRemoveChildren.connect(self.cb_qnodes_deleting) QgsProject.instance().layerTreeRoot().removedChildren.connect(self.cb_qnodes_deleted) QgsProject.instance().layerTreeRoot().visibilityChanged.connect(self.cb_qnode_visibility_changed) QgsProject.instance().readProject.connect( self.import_project) self.import_project() def unload_modules(self): # self.con_man.disconnect_ux( self.iface) QgsProject.instance().cleared.disconnect(self.new_session) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.edit_buffer.remove_layers) # QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.layer_man.remove_layers) # QgsProject.instance().layersAdded.disconnect( self.edit_buffer.config_connection) self.edit_buffer.unload_connection() self.con_man.unload() self.iface.currentLayerChanged.disconnect( self.cb_layer_selected) # UNCOMMENT self.iface.mapCanvas().extentsChanged.disconnect( self.reload_tile) QgsProject.instance().layerTreeRoot().willRemoveChildren.disconnect(self.cb_qnodes_deleting) QgsProject.instance().layerTreeRoot().removedChildren.disconnect(self.cb_qnodes_deleted) QgsProject.instance().layerTreeRoot().visibilityChanged.disconnect(self.cb_qnode_visibility_changed) QgsProject.instance().readProject.disconnect( self.import_project) # utils.disconnect_silent(self.iface.currentLayerChanged) self.secret.deactivate() disconnect_global_error_signal() if LOG_TO_FILE: QgsApplication.messageLog().messageReceived.disconnect(cb_log_qgis) # close_file_logger() pass def unload(self): """teardown""" self.unload_modules() # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.toolbar.clear() # remove action from custom toolbar (toolbar still exist) self.toolbar.deleteLater() for a in self.actions_menu: self.iface.removePluginWebMenu(self.web_menu, a) # remove progress self.iface.statusBarIface().removeWidget(self.pb) ############### # Callback ############### def cb_layer_selected(self, qlayer): flag_xyz = True if qlayer is not None and is_xyz_supported_layer(qlayer) else False if flag_xyz: self.edit_buffer.config_connection([qlayer]) self.edit_buffer.enable_ui(qlayer.id()) else: msg = "No XYZHub Layer selected" self.enable_sync_btn(False, msg) # disable magic sync # self.action_sync_edit.setEnabled(flag_xyz) def enable_sync_btn(self, flag, msg=""): msg = msg or ("No changes detected since last push" if not flag else "Push changes") self.action_sync_edit.setToolTip(msg) self.action_sync_edit.setEnabled(flag) ############### # Callback of action (main function) ############### def show_info_msgbar(self, title, msg="", dt=3): self.iface.messageBar().pushMessage( config.TAG_PLUGIN, ": ".join([title,msg]), Qgis.Info, dt ) def show_warning_msgbar(self, title, msg="", dt=3): self.iface.messageBar().pushMessage( config.TAG_PLUGIN, ": ".join([title,msg]), Qgis.Warning, dt ) def show_success_msgbar(self, title, msg="", dt=3): self.iface.messageBar().pushMessage( config.TAG_PLUGIN, ": ".join([title,msg]), Qgis.Success, dt ) def make_cb_success(self, title, msg="", dt=3): def _cb_success_msg(): self.show_success_msgbar(title, msg, dt=dt) return _cb_success_msg def make_cb_success_args(self, title, msg="", dt=3): def _cb_success_msg(args): a, kw = parse_qt_args(args) txt = ". ".join(map(str,a)) self.show_success_msgbar(title, txt, dt=dt) return _cb_success_msg def make_cb_info_args(self, title, msg="", dt=3): def _cb_info_msg(args): a, kw = parse_qt_args(args) txt = ". ".join(map(str,a)) self.show_info_msgbar(title, txt, dt=dt) return _cb_info_msg def cb_handle_error_msg(self, e): err = parse_exception_obj(e) if isinstance(err, ChainInterrupt): e0, idx = err.args[0:2] else: e0 = err if isinstance(e0, (net_handler.NetworkError, net_handler.NetworkTimeout)): ok = self.show_net_err(e0) if ok: return elif isinstance(e0, EmptyXYZSpaceError): ret = exec_warning_dialog("XYZ Hub","Requested query returns no features") return elif isinstance(e0, ManualInterrupt): self.log_err_traceback(e0) return self.show_err_msgbar(err) def show_net_err(self, err): reply_tag, status, reason, body, err_str, url = err.args[:6] if reply_tag in ["count", "statistics"]: # too many error # msg = "Network Error: %s: %s. %s"%(status, reason, err_str) return 1 detail = "\n". join(["Request:", url,"","Response:", body]) msg = ( "%s: %s\n"%(status,reason) + "There was a problem connecting to the server" ) if status in [401,403]: msg += ("\n\n" + "Please input valid token with correct permissions." + "\n" + "Token is generated via " + "<a href='https://xyz.api.here.com/token-ui/'>https://xyz.api.here.com/token-ui/</a>") ret = exec_warning_dialog("Network Error",msg, detail) return 1 def show_err_msgbar(self, err): self.iface.messageBar().pushMessage( config.TAG_PLUGIN, repr(err), Qgis.Warning, 3 ) self.log_err_traceback(err) def log_err_traceback(self, err): msg = format_traceback(err) QgsMessageLog.logMessage( msg, config.TAG_PLUGIN, Qgis.Warning) def cb_progress_busy(self, n_active): if n_active > 1: return self.flag_pb_show=True self.cb_progress_refresh() def cb_progress_done(self): self.flag_pb_show=False self.cb_progress_refresh() def cb_progress_refresh(self): if not hasattr(self,"flag_pb_show"): return pb = self.pb if self.flag_pb_show: pb.show() # print_qgis("show",pb) else: pb.hide() # print_qgis("hide") ############### # Action (main function) ############### # UNUSED def refresh_canvas(self): # self.iface.activeLayer().triggerRepaint() self.iface.mapCanvas().refresh() def previous_canvas_extent(self): self.iface.mapCanvas().zoomToPreviousExtent() # def new_main_dialog(self): parent = self.iface.mainWindow() dialog = MainDialog(parent) dialog.config(self.token_model, self.server_model) # dialog.config_secret(self.secret) auth = self.auth_manager.get_auth() dialog.config_basemap(self.map_basemap_meta, auth) con = self.con_man.make_con("create") con.signal.finished.connect( dialog.btn_use.clicked.emit ) # can be optimized !! con.signal.error.connect( self.cb_handle_error_msg ) con = self.con_man.make_con("list") con.signal.results.connect( make_fun_args(dialog.cb_display_spaces) ) con.signal.error.connect( self.cb_handle_error_msg ) con.signal.error.connect( lambda e: dialog.cb_enable_token_ui() ) con.signal.finished.connect( dialog.cb_enable_token_ui ) con.signal.finished.connect( dialog.ui_valid_token ) con = self.con_man.make_con("edit") con.signal.finished.connect( dialog.btn_use.clicked.emit ) con.signal.error.connect( self.cb_handle_error_msg ) con = self.con_man.make_con("delete") con.signal.results.connect( dialog.btn_use.clicked.emit ) con.signal.error.connect( self.cb_handle_error_msg ) con = self.con_man.make_con("stat") con.signal.results.connect( make_fun_args(dialog.cb_display_space_count) ) con.signal.error.connect( self.cb_handle_error_msg ) ############ clear cache btn dialog.signal_clear_cache.connect( self.open_clear_cache_dialog) ############ add map tile btn dialog.signal_add_basemap.connect( self.add_basemap_layer) ############ btn: new, edit, delete space dialog.signal_new_space.connect(self.start_new_space) dialog.signal_edit_space.connect(self.start_edit_space) dialog.signal_del_space.connect(self.start_delete_space) ############ Use Token btn dialog.signal_use_token.connect( lambda a: self.con_man.finish_fast()) dialog.signal_use_token.connect(self.start_use_token) ############ get count dialog.signal_space_count.connect(self.start_count_feat, Qt.QueuedConnection) # queued -> non-blocking ui ############ connect btn # dialog.signal_space_connect.connect(self.start_load_layer) dialog.signal_space_connect.connect(self.start_loading) dialog.signal_space_tile.connect(self.start_load_tile) ############ upload btn dialog.signal_upload_space.connect(self.start_upload_space) return dialog def start_new_space(self, args): con = self.con_man.get_con("create") con.start_args(args) def start_edit_space(self, args): con = self.con_man.get_con("edit") con.start_args(args) def start_delete_space(self, args): con = self.con_man.get_con("delete") con.start_args(args) def start_use_token(self, args): con = self.con_man.get_con("list") con.start_args(args) def start_count_feat(self, args): con = self.con_man.get_con("stat") con.start_args(args) def start_upload_space(self, args): con_upload = UploadLayerController(self.network, n_parallel=2) self.con_man.add_on_demand_controller(con_upload) # con_upload.signal.finished.connect( self.make_cb_success("Uploading finish") ) con_upload.signal.results.connect( self.make_cb_success_args("Uploading finish", dt=4)) con_upload.signal.error.connect( self.cb_handle_error_msg ) con = InitUploadLayerController(self.network) self.con_man.add_on_demand_controller(con) con.signal.results.connect( con_upload.start_args) con.signal.error.connect( self.cb_handle_error_msg ) con.start_args(args) def start_load_layer(self, args): # create new con # config # run ############ connect btn con_load = LoadLayerController(self.network, n_parallel=1) self.con_man.add_on_demand_controller(con_load) # con_load.signal.finished.connect( self.make_cb_success("Loading finish") ) con_load.signal.results.connect( self.make_cb_success_args("Loading finish") ) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect( self.cb_handle_error_msg ) con_load.start_args(args) # con.signal.results.connect( self.layer_man.add_args) # IMPORTANT def start_load_tile(self, args): # rect = (-180,-90,180,90) # level = 0 a, kw = parse_qt_args(args) kw.update(self.make_tile_params()) # kw["limit"] = 100 ############ connect btn con_load = TileLayerLoader(self.network, n_parallel=1) self.con_man.add_persistent_loader(con_load) # con_load.signal.finished.connect( self.make_cb_success("Tiles loaded") ) con_load.signal.results.connect( self.make_cb_success_args("Tiles loaded", dt=2) ) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect( self.cb_handle_error_msg ) con_load.start_args( make_qt_args(*a, **kw)) def make_tile_params(self, rect=None, level=None): if not rect: canvas = self.iface.mapCanvas() rect = bbox_utils.extent_to_rect( bbox_utils.get_bounding_box(canvas)) level = tile_utils.get_zoom_for_current_map_scale(canvas) schema = "web" kw = dict() kw["tile_schema"] = schema kw["tile_ids"] = tile_utils.bboxToListColRow(*rect,level, schema=schema) return kw def start_loading(self, args): a, kw = parse_qt_args(args) loading_mode = kw.get("loading_mode") try: con_load = self.make_loader_from_mode(loading_mode) except Exception as e: self.show_err_msgbar(e) return if loading_mode == LOADING_MODES.STATIC: con_load.start_args(args) else: kw.update(self.make_tile_params()) con_load.start_args( make_qt_args(*a, **kw)) def iter_checked_xyz_subnode(self): """ iterate through visible xyz nodes (vector layer and group node) """ root = QgsProject.instance().layerTreeRoot() for vl in root.checkedLayers(): if is_xyz_supported_layer(vl): yield vl for g in iter_group_node(root): if (len(g.findLayers()) == 0 and g.isVisible() and is_xyz_supported_node(g)): yield g def iter_all_xyz_node(self): """ iterate through xyz group nodes """ for qnode in self._iter_all_xyz_node(): yield qnode def iter_update_all_xyz_node(self): """ iterate through xyz group nodes, with meta version check and updated. """ for qnode in self._iter_all_xyz_node(fn_node=updated_xyz_node): yield qnode def _iter_all_xyz_node(self, fn_node=lambda a: None): """ iterate through xyz group nodes, with custom function fn_node applied to every node """ root = QgsProject.instance().layerTreeRoot() for g in iter_group_node(root): fn_node(g) if is_xyz_supported_node(g): yield g def extent_action(self, rect0, rect1): diff = [r0 - r1 for r0,r1 in zip(rect0,rect1)] x_sign = diff[0] * diff[2] y_sign = diff[1] * diff[3] if x_sign >= 0 and y_sign >= 0: # same direction return "pan" elif x_sign < 0 and y_sign < 0: return "zoom" elif x_sign * y_sign == 0 and x_sign + y_sign < 0: return "resize" else: return "unknown" def reload_tile(self): canvas = self.iface.mapCanvas() rect = bbox_utils.extent_to_rect(bbox_utils.get_bounding_box(canvas)) ext_action = self.extent_action(rect,self.lastRect) print_qgis("Extent action: ", ext_action,rect) self.lastRect = rect if ext_action not in ["pan", "zoom"]: return level = tile_utils.get_zoom_for_current_map_scale(canvas) kw = self.make_tile_params(rect, level) # kw["limit"] = 100 lst_con = self._get_lst_reloading_con() for con in lst_con: print_qgis(con.status) print_qgis("loading tile", level, rect) con.restart(**kw) def _get_lst_reloading_con(self): """ Return list of loader to be reload, that has + any vlayer in group is visible + and no vlayer in group is in edit mode """ editing_xid = set() unique_xid = set() for qnode in self.iter_checked_xyz_subnode(): xlayer_id = get_customProperty_str(qnode, QProps.UNIQUE_ID) if xlayer_id in editing_xid: continue if hasattr(qnode, "isEditable") and qnode.isEditable(): editing_xid.add(xlayer_id) continue con = self.con_man.get_interactive_loader(xlayer_id) if (con and con.layer and self.is_all_layer_edit_buffer_empty(con.layer) ): unique_xid.add(xlayer_id) else: continue # print_qgis(editing_xid, unique_xid) # print_qgis(unique_xid.difference(editing_xid)) # print_qgis(self.con_man._layer_ptr) return [ self.con_man.get_interactive_loader(xlayer_id) for xlayer_id in unique_xid.difference(editing_xid) ] def is_all_layer_edit_buffer_empty(self, layer: XYZLayer) -> bool: return all( layer_buffer.is_empty() for layer_buffer in ( self.edit_buffer.get_layer_buffer(vlayer.id()) for vlayer in layer.iter_layer() ) if layer_buffer ) def add_basemap_layer(self, args): a, kw = parse_qt_args(args) meta, app_id, app_code, api_key = a self.auth_manager.save(app_id, app_code, api_key) basemap.add_basemap_layer( meta, app_id, app_code, api_key) ############### # import project function ############### def import_project(self): self.init_all_layer_loader() # # restart static loader once # for con in self.con_man.get_all_static_loader(): # # truncate all feature # con.restart() def make_loader_from_mode(self, loading_mode, layer=None): if loading_mode not in LOADING_MODES: raise InvalidLoadingMode(loading_mode) option = dict(zip(LOADING_MODES, [ (LiveTileLayerLoader, self.con_man.add_persistent_loader, self.make_cb_success_args("Tiles loaded", dt=2)), (TileLayerLoader, self.con_man.add_persistent_loader, self.make_cb_success_args("Tiles loaded", dt=2)), (LoadLayerController, self.con_man.add_static_loader, self.make_cb_success_args("Loading finish", dt=3)) ])).get(loading_mode) if not option: return loader_class, fn_register, cb_success_args = option con_load = loader_class(self.network, n_parallel=1, layer=layer) con_load.signal.results.connect( cb_success_args) con_load.signal.error.connect( self.cb_handle_error_msg ) cb_info = self.make_cb_info_args("Loading status", dt=3) con_load.signal.info.connect( cb_info) ptr = fn_register(con_load) return con_load def init_layer_loader(self, qnode): layer = XYZLayer.load_from_qnode(qnode) loading_mode = layer.loader_params.get("loading_mode") if loading_mode not in LOADING_MODES: # # approach 1: backward compatible, import project # # invalid loading mode default to live # old = loading_mode # loading_mode = LOADING_MODES.LIVE # layer.update_loader_params(loading_mode=loading_mode) # save new loading_mode to layer # # TODO prompt user for handling invalid loading mode layer # self.show_info_msgbar("Import XYZ Layer", # "Undefined loading mode: %s, " % old + # "default to %s loading " % (loading_mode) + # "(layer: %s)" % layer.get_name()) # approach 2: not backward compatible, but no data loss self.show_warning_msgbar("Import XYZ Layer", "Undefined loading mode: %s, " % loading_mode + "loading disabled " + "(layer: %s)" % layer.get_name()) return return self.make_loader_from_mode(loading_mode, layer=layer) def init_all_layer_loader(self): cnt = 0 for qnode in self.iter_update_all_xyz_node(): xlayer_id = get_customProperty_str(qnode, QProps.UNIQUE_ID) con = self.con_man.get_loader(xlayer_id) if con: continue try: con = self.init_layer_loader(qnode) if not con: continue cnt += 1 except Exception as e: self.show_err_msgbar(e) # print_qgis(self.con_man._layer_ptr) self.show_success_msgbar("Import XYZ Layer", "%s XYZ Layer imported"%cnt, dt=2) def cb_qnode_visibility_changed(self, qnode): if qnode.isVisible(): return xlayer_id = get_customProperty_str(qnode, QProps.UNIQUE_ID) con = self.con_man.get_interactive_loader(xlayer_id) if con: con.stop_loading() def cb_qnodes_deleting(self, parent, i0, i1): key = (parent,i0,i1) is_parent_root = not parent.parent() lst = parent.children() for i in range(i0, i1+1): qnode = lst[i] if (is_parent_root and is_xyz_supported_node(qnode)): xlayer_id = get_customProperty_str(qnode, QProps.UNIQUE_ID) self.pending_delete_qnodes.setdefault(key, list()).append(xlayer_id) self.con_man.remove_persistent_loader(xlayer_id) # is possible to handle vlayer delete here # instead of handle in layer.py via callbacks def cb_qnodes_deleted(self, parent, i0, i1): key = (parent,i0,i1) for xlayer_id in self.pending_delete_qnodes.pop(key, list()): self.con_man.remove_persistent_loader(xlayer_id) ############### # Open dialog ############### def open_clear_cache_dialog(self): dialog = ConfirmDialog("Delete cache will make loaded layer unusable !!") ret = dialog.exec_() if ret != dialog.Ok: return utils.clear_cache() def open_connection_dialog(self): dialog = self.new_main_dialog() vlayer = self.iface.activeLayer() dialog.set_layer( vlayer) dialog.exec_() self.con_man.finish_fast() # self.startTime = time.time() def open_sync_edit_dialog(self): vlayer = self.iface.activeLayer() layer_buffer = self.edit_buffer.get_layer_buffer(vlayer.id()) lst_added_feat, removed_ids = layer_buffer.get_sync_feat() conn_info = layer_buffer.get_conn_info() # print_qgis("lst_added_feat: ",lst_added_feat) # print_qgis("removed_feat: ", removed_ids) con = EditSyncController(self.network) self.con_man.add_on_demand_controller(con) con.signal.finished.connect( layer_buffer.sync_complete) con.signal.results.connect( self.make_cb_success_args("Sync edit finish") ) con.signal.error.connect( self.cb_handle_error_msg ) con.start(conn_info, layer_buffer, lst_added_feat, removed_ids)
class CreatePoint: """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', 'CreatePoint_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Obtaining the map canvas self.canvas = iface.mapCanvas() def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" icon_path = ':/plugins/Create_Point/icon.png' #create action that will be run by the plugin self.action = QAction("Create Point", self.iface.mainWindow()) self.action.setIcon(QIcon(icon_path)) self.action.setWhatsThis("Create Point") self.action.setStatusTip("Click On Map And Draw Point") # add plugin menu to Vector toolbar self.iface.addPluginToMenu("Create_Point", self.action) # add icon to new menu item in Vector toolbar self.iface.addToolBarIcon(self.action) # connect action to the run method self.action.triggered.connect(self.run) # prepare map tool self.mapTool = Map_Tool(self.iface) #self.iface.mapCanvas().mapToolSet.connect(self.mapToolChanged) def unload(self): """Actions to run when the plugin is unloaded""" # remove menu and icon from the menu self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("Create_Point", self.action) if self.iface.mapCanvas().mapTool() == self.mapTool: self.iface.mapCanvas().unsetMapTool(self.mapTool) del self.mapTool def run(self): #Check Active Layer Present Or Not self.active_point_layer = self.iface.mapCanvas().currentLayer() if not self.active_point_layer: self.iface.messageBar().pushMessage( "Active Layer", "No Active Layer Found Please Select Point Layer", level=Qgis.Warning) else: self.layer_type = self.active_point_layer.geometryType() if self.layer_type == QgsWkbTypes.PointGeometry: self.iface.mapCanvas().setMapTool(self.mapTool) else: self.iface.messageBar().pushMessage( "Active Layer", "Active Layer Is Not Point Type Layer Please Select Point Layer", level=Qgis.Warning)
class ImpEpanet(object): def __init__(self, iface): # Save a reference to the QGIS iface self.iface = iface self.canvas = self.iface.mapCanvas() self.dlg = ExportEpanetInpFilesDialog() self.sections = ['junctions', 'tanks', 'pipes', 'pumps', 'reservoirs', 'valves', 'STATUS', 'PATTERNS', 'CURVES', 'CONTROLS', 'RULES', 'ENERGY', 'REACTIONS', 'REACTIONS_I', 'EMITTERS', 'QUALITY', 'SOURCES', 'MIXING', 'TIMES', 'REPORT', 'OPTIONS'] def initGui(self): # Create action sys.path.append(os.path.dirname(__file__)+'/impcount.py') self.action = QAction(QIcon(":/plugins/ImportEpanetInpFiles/impepanet.png"), "Import Epanet Input File", self.iface.mainWindow()) self.action.setWhatsThis("Import Epanet Input File") self.action.triggered.connect(self.run) self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&ImportEpanetInpFiles", self.action) self.actionexp = QAction(QIcon(":/plugins/ImportEpanetInpFiles/expepanet.png"), "Export Epanet Input File", self.iface.mainWindow()) self.actionexp.setWhatsThis("Export Epanet Input File") self.actionexp.triggered.connect(self.runexp) self.iface.addToolBarIcon(self.actionexp) self.iface.addPluginToMenu("&ImportEpanetInpFiles", self.actionexp) self.dlg.ok_button.clicked.connect(self.ok) self.dlg.cancel_button.clicked.connect(self.cancel) self.dlg.toolButtonOut.clicked.connect(self.toolButtonOut) def unload(self): # Remove the plugin self.iface.removePluginMenu("&ImportEpanetInpFiles", self.action) self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("&ImportEpanetInpFiles", self.actionexp) self.iface.removeToolBarIcon(self.actionexp) def run(self): filePath = QFileDialog.getOpenFileName(self.iface.mainWindow(), "Choose EPANET Input file", os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop'), "Epanet Inp File (*.inp)") if filePath[0] == "": return epa2gis(filePath[0]) self.iface.messageBar().clearWidgets() msgBox = QMessageBox() msgBox.setWindowTitle('ImportEpanetInpFiles') msgBox.setText('Shapefiles have been created successfully in folder "_shapefiles_".') msgBox.exec_() def runexp(self): self.dlg.out.setText('') self.layers = self.canvas.layers() self.layer_list = [] self.layer_list = ['NONE'] [self.layer_list.append(layer.name()) for layer in self.layers] for sect in self.sections: eval('self.dlg.sect_' + sect + '.clear()') eval('self.dlg.sect_' + sect + '.addItems(self.layer_list)') indices = [i for i, s in enumerate(self.layer_list) if sect in s] if indices: if sect == 'REACTIONS': eval('self.dlg.sect_' + sect + '.setCurrentIndex(indices[1])') else: eval('self.dlg.sect_' + sect + '.setCurrentIndex(indices[0])') self.dlg.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) self.dlg.show() def cancel(self): self.layer_list = [] self.layer_list = ['NONE'] for sect in self.sections: exec ('self.dlg.sect_' + sect + '.clear()') self.dlg.close() def toolButtonOut(self): self.outEpanetName = QFileDialog.getSaveFileName(None, 'Save File', os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop'), 'Epanet Inp File (*.inp)') self.dlg.out.setText(self.outEpanetName[0]) def selectOutp(self): msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('Please define Epanet Inp File location.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return True def ok(self): # Here check if select OK button, get the layer fields # Initialize # [JUNCTIONS] if self.dlg.out.text() == '': if self.selectOutp(): return elif os.path.isabs(self.dlg.out.text()) == False: if self.selectOutp(): return self.outEpanetName = self.dlg.out.text() try: f = open(self.outEpanetName, "w") f.close() except: msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('Please define Epanet Inp File location.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return if not self.layers: msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('No layers selected.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return xypipes_id = [] xypipesvert = [] for sect in self.sections: exec('sect' + sect + '=[]') in globals(), locals() exec('xy' + sect + '=[]') in globals(), locals() if eval('self.dlg.sect_' + sect + '.currentText()') != 'NONE': # Get layer field names indLayerName = self.layer_list.index(eval('self.dlg.sect_' + sect + '.currentText()')) - 1 provider = self.layers[indLayerName].dataProvider() fields = provider.fields() field_names = [field.name() for field in fields] for elem in self.layers[indLayerName].getFeatures(): eval('sect' + sect + '.append(dict(zip(field_names, elem.attributes())))') if any(sect in s for s in self.sections[0:5]): geom = elem.geometry() if self.layers[indLayerName].geometryType() == 0: eval('xy' + sect + '.append(geom.asPoint())') elif self.layers[indLayerName].geometryType() == 1: eval('xy' + sect + '.append(geom.asPolyline())') if sect == 'pipes': if len(geom.asPolyline()) > 2: for pp in range(len(geom.asPolyline())-2): xypipes_id.append(elem.attributes()[0]) xypipesvert.append(geom.asPolyline()[pp]) if sect == 'junctions': if 'Elevation' not in locals()['sect' + sect][0].keys(): QMessageBox.warning(QWidget(), "Message", "Elevation field is missing.") # (myDirectory,nameFile) = os.path.split(self.iface.activeLayer().dataProvider().dataSourceUri()) my_directory = '' f = open(self.outEpanetName, 'wt') f.write('[TITLE]\n') f.write('Export input file via plugin ExportEpanetInpFiles. \n\n') f.write('[JUNCTIONS]\n') node_i_ds = [] for i in range(len(locals()['sectjunctions'])): node_i_ds.append(locals()['sectjunctions'][i]['ID']) f.write(locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['sectjunctions'][i]['Elevation']) + '\n') f.write('\n[RESERVOIRS]\n') for i in range(len(locals()['sectreservoirs'])): node_i_ds.append(locals()['sectreservoirs'][i]['ID']) f.write(locals()['sectreservoirs'][i]['ID'] + ' ' + str(locals()['sectreservoirs'][i]['Head']) + '\n') f.write('\n[TANKS]\n') for i in range(len(locals()['secttanks'])): node_i_ds.append(locals()['secttanks'][i]['ID']) if locals()['secttanks'][i]['VolumeCurv'] == None: locals()['secttanks'][i]['VolumeCurv'] = "" f.write(locals()['secttanks'][i]['ID'] + ' ' + str(locals()['secttanks'][i]['Elevation']) + ' ' + str(locals()['secttanks'][i]['InitLevel']) + ' ' + str(locals()['secttanks'][i]['MinLevel']) + ' ' + str(locals()['secttanks'][i]['MaxLevel']) + ' ' + str( locals()['secttanks'][i]['Diameter']) + ' ' + str(locals()['secttanks'][i]['MinVolume']) + ' ' + str(locals()['secttanks'][i]['VolumeCurv']) + ' ' + '\n') f.write('\n[PIPES]\n') for i in range(len(locals()['sectpipes'])): if (locals()['sectpipes'][i]['NodeFrom'] in node_i_ds) and (locals()['sectpipes'][i]['NodeTo'] in node_i_ds): f.write(locals()['sectpipes'][i]['ID'] + ' ' + locals()['sectpipes'][i]['NodeFrom'] + ' ' + locals()['sectpipes'][i]['NodeTo'] + ' ' + str(locals()['sectpipes'][i]['Length']) + ' ' + str( locals()['sectpipes'][i]['Diameter']) + ' ' + str(locals()['sectpipes'][i]['Roughness']) + ' ' + str(locals()['sectpipes'][i]['MinorLoss']) + ' ' + locals()['sectpipes'][i]['Status'] + '\n') f.write('\n[PUMPS]\n') for i in range(len(locals()['sectpumps'])): if locals()['sectpumps'][i]['Curve'] != 'NULL': try: locals()['sectpumps'][i]['Curve'] = 'HEAD ' + locals()['sectpumps'][i]['Curve'] except: locals()['sectpumps'][i]['Curve'] = 'HEAD ' else: locals()['sectpumps'][i]['Curve'] = '' if locals()['sectpumps'][i]['Pattern'] != 'NULL': try: locals()['sectpumps'][i]['Pattern'] = 'PATTERN ' + locals()['sectpumps'][i]['Pattern'] except: locals()['sectpumps'][i]['Pattern'] = "PATTERN " else: locals()['sectpumps'][i]['Pattern'] = '' if locals()['sectpumps'][i]['Power'] != 'NULL': try: locals()['sectpumps'][i]['Power'] = 'POWER ' + locals()['sectpumps'][i]['Power'] except: locals()['sectpumps'][i]['Power'] = "POWER " else: locals()['sectpumps'][i]['Power'] = '' try: f.write(locals()['sectpumps'][i]['ID'] + ' ' + locals()['sectpumps'][i]['NodeFrom'] + ' ' + locals()['sectpumps'][i]['NodeTo'] + ' ' + locals()['sectpumps'][i]['Curve'] + ' ' + str(locals()['sectpumps'][i]['Pattern']) + ' ' + str(locals()['sectpumps'][i]['Power']) + '\n') except: f.write(locals()['sectpumps'][i]['ID'] +'\n') f.write('\n[VALVES]\n') if self.dlg.sect_valves.currentText() != 'NONE': for i in range(len(locals()['sectvalves'])): try: locals()['sectvalves'][i]['NodeFrom'] = locals()['sectvalves'][i]['NodeFrom'] + '' except: locals()['sectvalves'][i]['NodeFrom'] = "" try: locals()['sectvalves'][i]['NodeTo'] = locals()['sectvalves'][i]['NodeTo'] + '' except: locals()['sectvalves'][i]['NodeTo'] = "" f.write("{} {} {} {} {} {} {}\n".format(locals()['sectvalves'][i]['ID'], locals()['sectvalves'][i]['NodeFrom'], locals()['sectvalves'][i]['NodeTo'], str(locals()['sectvalves'][i]['Diameter']), locals()['sectvalves'][i]['Type'], str(locals()['sectvalves'][i]['Setting']), str(locals()['sectvalves'][i]['MinorLoss']))) f.write('\n[DEMANDS]\n') for i in range(len(locals()['sectjunctions'])): for u in range(int((len(locals()['sectjunctions'][i]) - 2) / 2)): if locals()['sectjunctions'][i]['Demand' + str(u + 1)] == 0 and str( locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) == 'None': continue if str(locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) == 'NULL' or str( locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) == 'None': locals()['sectjunctions'][i]['Pattern' + str(u + 1)] = '' f.write(locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['sectjunctions'][i]['Demand' + str(u + 1)]) + ' ' + str(locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) + '\n') f.write('\n[STATUS]\n') for i in range(len(locals()['sectSTATUS'])): f.write("{} {}\n".format(locals()['sectSTATUS'][i]['Link_ID'], locals()['sectSTATUS'][i]['Status/Set'])) f.write('\n[PATTERNS]\n') for i in range(len(locals()['sectPATTERNS'])): f.write("{} {}\n".format(locals()['sectPATTERNS'][i]['Pattern_ID'], locals()['sectPATTERNS'][i]['Multiplier'])) f.write('\n[CURVES]\n') for i in range(len(locals()['sectCURVES'])): f.write(";{}:\n {} {} {}\n".format(locals()['sectCURVES'][i]['Type'], locals()['sectCURVES'][i]['Curve_ID'], str(locals()['sectCURVES'][i]['X-Value']),str(locals()['sectCURVES'][i]['Y-Value']))) f.write('\n[CONTROLS]\n') for i in range(len(locals()['sectCONTROLS'])): f.write("{}\n".format(locals()['sectCONTROLS'][i]['Controls'])) f.write('\n[RULES]\n') for i in range(len(locals()['sectRULES'])): f.write("RULE {}\n {}\n".format(locals()['sectRULES'][i]['Rule_ID'], locals()['sectRULES'][i]['Rule'])) f.write('\n[ENERGY]\n') if locals()['sectENERGY']: try: f.write('Global Efficiency ' + str(locals()['sectENERGY'][0]['GlobalEffi']) + '\n') except: pass try: f.write('Global Price ' + str(locals()['sectENERGY'][0]['GlobalPric']) + '\n') except: pass try: f.write('Demand Charge ' + str(locals()['sectENERGY'][0]['DemCharge']) + '\n') except: pass f.write('\n[REACTIONS]\n') if locals()['sectREACTIONS']: try: f.write('Order Bulk ' + str(locals()['sectREACTIONS'][0]['OrderBulk']) + '\n') except: pass try: f.write('Order Tank ' + str(locals()['sectREACTIONS'][0]['OrderTank']) + '\n') except: pass try: f.write('Order Wall ' + str(locals()['sectREACTIONS'][0]['OrderWall']) + '\n') except: pass try: f.write('Global Bulk ' + str(locals()['sectREACTIONS'][0]['GlobalBulk']) + '\n') except: pass try: f.write('Global Wall ' + str(locals()['sectREACTIONS'][0]['GlobalWall']) + '\n') except: pass try: f.write('Limiting Potential ' + str(locals()['sectREACTIONS'][0]['LimPotent']) + '\n') except: pass try: f.write('Roughness Correlation ' + str(locals()['sectREACTIONS'][0]['RoughCorr']) + '\n') except: pass f.write('\n[REACTIONS]\n') for i in range(len(locals()['sectREACTIONS_I'])): f.write('{} {} {} \n'.format(locals()['sectREACTIONS_I'][i]['Type'], locals()['sectREACTIONS_I'][i]['Pipe/Tank'], str(locals()['sectREACTIONS_I'][i]['Coeff.']))) f.write('\n[EMITTERS]\n') for i in range(len(locals()['sectEMITTERS'])): f.write('{} {}\n'.format(locals()['sectEMITTERS'][i]['Junc_ID'], str(locals()['sectEMITTERS'][i]['Coeff.']))) f.write('\n[SOURCES]\n') for i in range(len(locals()['sectSOURCES'])): try: locals()['sectSOURCES'][i]['Pattern'] = locals()['sectSOURCES'][i]['Pattern'] + '' except: locals()['sectSOURCES'][i]['Pattern'] = '' f.write("{} {} {} {}\n".format(locals()['sectSOURCES'][i]['Node_ID'], locals()['sectSOURCES'][i]['Type'], str(locals()['sectSOURCES'][i]['Strength']), locals()['sectSOURCES'][i]['Pattern'])) f.write('\n[MIXING]\n') for i in range(len(locals()['sectMIXING'])): f.write('{} {} {} \n'.format(locals()['sectMIXING'][i]['Tank_ID'], locals()['sectMIXING'][i]['Model'], str(locals()['sectMIXING'][i]['Fraction']))) f.write('\n[TIMES]\n') if locals()['sectTIMES']: try: f.write('Duration ' + str(locals()['sectTIMES'][0]['Duration']) + '\n') except: pass try: f.write('Hydraulic Timestep ' + str(locals()['sectTIMES'][0]['HydStep']) + '\n') except: pass try: f.write('Quality Timestep ' + str(locals()['sectTIMES'][0]['QualStep']) + '\n') except: pass try: f.write('Pattern Timestep ' + str(locals()['sectTIMES'][0]['PatStep']) + '\n') except: pass try: f.write('Pattern Start ' + str(locals()['sectTIMES'][0]['PatStart']) + '\n') except: pass try: f.write('Report Timestep ' + str(locals()['sectTIMES'][0]['RepStep']) + '\n') except: pass try: f.write('Report Start ' + str(locals()['sectTIMES'][0]['RepStart']) + '\n') except: pass try: f.write('Start ClockTime ' + str(locals()['sectTIMES'][0]['StartClock']) + '\n') except: pass try: f.write('Statistic ' + str(locals()['sectTIMES'][0]['Statistic']) + '\n') except: pass f.write('\n[REPORT]\n') if locals()['sectREPORT']: try: f.write('Status ' + locals()['sectREPORT'][0]['Status'] + '\n') except: pass try: f.write('Summary ' + locals()['sectREPORT'][0]['Summary'] + '\n') except: pass try: f.write('Page ' + locals()['sectREPORT'][0]['Page'] + '\n') except: pass f.write('\n[OPTIONS]\n') if locals()['sectOPTIONS']: try: f.write('Units ' + str(locals()['sectOPTIONS'][0]['Units']) + '\n'); except: pass try: f.write('Headloss ' + str(locals()['sectOPTIONS'][0]['Headloss']) + '\n') except: pass try: f.write('Specific Gravity ' + str(locals()['sectOPTIONS'][0]['SpecGrav']) + '\n') except: pass try: f.write('Viscosity ' + str(locals()['sectOPTIONS'][0]['Viscosity']) + '\n') except: pass try: f.write('Trials ' + str(locals()['sectOPTIONS'][0]['Trials']) + '\n') except: pass try: f.write('Accuracy ' + str(locals()['sectOPTIONS'][0]['Accuracy']) + '\n') except: pass try: f.write('CHECKFREQ ' + str(locals()['sectOPTIONS'][0]['CheckFreq']) + '\n') except: pass try: f.write('MAXCHECK ' + str(locals()['sectOPTIONS'][0]['MaxCheck']) + '\n') except: pass try: f.write('DAMPLIMIT ' + str(locals()['sectOPTIONS'][0]['DampLimit']) + '\n') except: pass try: f.write('Unbalanced ' + str(locals()['sectOPTIONS'][0]['Unbalanced']) + '\n') except: pass try: f.write('Pattern ' + str(locals()['sectOPTIONS'][0]['PatID']) + '\n') except: pass try: f.write('Demand Multiplier ' + str(locals()['sectOPTIONS'][0]['DemMult']) + '\n') except: pass try: f.write('Emitter Exponent ' + str(locals()['sectOPTIONS'][0]['EmitExp']) + '\n') except: pass try: f.write('Quality ' + str(locals()['sectOPTIONS'][0]['Quality']) + '\n') except: pass try: f.write('Diffusivity ' + str(locals()['sectOPTIONS'][0]['Diffusivit']) + '\n') except: pass try: f.write('Tolerance ' + str(locals()['sectOPTIONS'][0]['Tolerance']) + '\n') except: pass f.write('\n[COORDINATES]\n') for i in range(len(locals()['sectjunctions'])): f.write(locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['xyjunctions'][i][0]) + ' ' + str(locals()['xyjunctions'][i][1]) + '\n') for i in range(len(locals()['sectreservoirs'])): f.write(locals()['sectreservoirs'][i]['ID'] + ' ' + str(locals()['xyreservoirs'][i][0]) + ' ' + str(locals()['xyreservoirs'][i][1]) + '\n') for i in range(len(locals()['secttanks'])): f.write(locals()['secttanks'][i]['ID'] + ' ' + str(locals()['xytanks'][i][0]) + ' ' + str(locals()['xytanks'][i][1]) + '\n') f.write('\n[VERTICES]\n') for l in range(len(xypipes_id)): f.write(xypipes_id[l] + ' ' + str(xypipesvert[l][0]) + ' ' + str(xypipesvert[l][1]) + '\n') f.write('\n[END]\n') f.close() self.cancel() msgBox = QMessageBox() msgBox.setWindowTitle('Export Options') msgBox.setText('Export Epanet Inp File "' + self.outEpanetName + '" succesful.') msgBox.exec_()
class HffPlugin_s(object): HOME = os.environ['HFF_HOME'] PARAMS_DICT = { 'SERVER': '', 'HOST': '', 'DATABASE': '', 'PASSWORD': '', 'PORT': '', 'USER': '', 'THUMB_PATH': '', 'THUMB_RESIZE': '', 'EXPERIMENTAL': '' } path_rel = os.path.join(os.sep, HOME, 'HFF_DB_folder', 'config.cfg') conf = open(path_rel, "rb+") data = conf.read() text = (b'THUMB_RESIZE') if text in data: pass else: conf.seek(-3, 2) conf.read(1) conf.write(b"','THUMB_RESIZE' : 'insert path for the image resized'}") conf.close() PARAMS_DICT = eval(data) def __init__(self, iface): self.iface = iface userPluginPath = os.path.dirname(__file__) systemPluginPath = QgsApplication.prefixPath() + "/python/plugins/HFF" # overrideLocale = QgsSettings().value("locale/overrideFlag", QVariant) # .toBool() # if not overrideLocale: # localeFullName = QLocale.system().name() # else: # localeFullName = QgsSettings().value("locale/userLocale", QVariant) # .toString() # if QFileInfo(userPluginPath).exists(): # translationPath = userPluginPath + "/i18n/hff_system__plugin_" + localeFullName + ".qm" # else: # translationPath = systemPluginPath + "/i18n/hff_system__plugin_" + localeFullName + ".qm" # self.localePath = translationPath # if QFileInfo(self.localePath).exists(): # self.translator = QTranslator() # self.translator.load(self.localePath) # QCoreApplication.installTranslator(self.translator) def initGui(self): settings = QgsSettings() icon_paius = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'hfflogo.png')) self.action = QAction(QIcon(icon_paius), "HFF Main Panel", self.iface.mainWindow()) self.action.triggered.connect(self.showHideDockWidget) # dock widget self.dockWidget = HffPluginDialog(self.iface) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget) # TOOLBAR self.toolBar = self.iface.addToolBar("HFF") self.toolBar.setObjectName("HFF") self.toolBar.addAction(self.action) self.dataToolButton = QToolButton(self.toolBar) self.dataToolButton.setPopupMode(QToolButton.MenuButtonPopup) ###### Section dedicated to the basic data entry # add Actions data self.siteToolButton = QToolButton(self.toolBar) self.siteToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_site = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSite.png')) self.actionSite = QAction(QIcon(icon_site), "Site", self.iface.mainWindow()) self.actionSite.setWhatsThis("Site") self.actionSite.triggered.connect(self.runSite) icon_eamena = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'eamena.jpg')) self.actionEamena = QAction(QIcon(icon_eamena), "Eamena", self.iface.mainWindow()) self.actionEamena.setWhatsThis("Eamena") self.actionEamena.triggered.connect(self.runEamena) self.siteToolButton.addActions([self.actionSite, self.actionEamena]) self.siteToolButton.setDefaultAction(self.actionSite) self.toolBar.addWidget(self.siteToolButton) self.toolBar.addSeparator() ###### Section dedicated to the UnderWater data entry # add Actions data icon_UW = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'snorkel.png')) self.actionUW = QAction(QIcon(icon_UW), "Divelog Form", self.iface.mainWindow()) self.actionUW.setWhatsThis("Divelog") self.actionUW.triggered.connect(self.runUW) icon_ANC = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconANC.png')) self.actionANC = QAction(QIcon(icon_ANC), "Anchor", self.iface.mainWindow()) self.actionANC.setWhatsThis("Anchor") self.actionANC.triggered.connect(self.runANC) icon_ART = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'radar.png')) self.actionART = QAction(QIcon(icon_ART), "Artefact", self.iface.mainWindow()) self.actionART.setWhatsThis("Artefact") self.actionART.triggered.connect(self.runART) icon_Pottery = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'pottery.png')) self.actionPottery = QAction(QIcon(icon_Pottery), "Pottery", self.iface.mainWindow()) self.actionPottery.setWhatsThis("Pottery") self.actionPottery.triggered.connect(self.runPottery) self.dataToolButton.addActions([ self.actionUW, self.actionART, self.actionANC, self.actionPottery ]) self.dataToolButton.setDefaultAction(self.actionUW) self.toolBar.addWidget(self.dataToolButton) self.toolBar.addSeparator() ###### Section dedicated to the shipwreck # add Actions documentation self.ShipwreckToolButton = QToolButton(self.toolBar) icon_shipwreck = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'Shipwreck.png')) self.actionShipwreck = QAction(QIcon(icon_shipwreck), "Shipwreck", self.iface.mainWindow()) self.actionShipwreck.setWhatsThis("Shipwreck") self.actionShipwreck.triggered.connect(self.runShipwreck) self.ShipwreckToolButton.addActions([self.actionShipwreck]) self.ShipwreckToolButton.setDefaultAction(self.actionShipwreck) self.toolBar.addWidget(self.ShipwreckToolButton) self.toolBar.addSeparator() ###### Section dedicated to the documentation # add Actions documentation self.docToolButton = QToolButton(self.toolBar) self.docToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_imageViewer = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'photo.png')) self.actionimageViewer = QAction(QIcon(icon_imageViewer), "Media manager", self.iface.mainWindow()) self.actionimageViewer.setWhatsThis("Media manager") self.actionimageViewer.triggered.connect(self.runImageViewer) icon_Directory_export = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'directoryExp.png')) self.actionImages_Directory_export = QAction( QIcon(icon_Directory_export), "Download image", self.iface.mainWindow()) self.actionImages_Directory_export.setWhatsThis("Download image") self.actionImages_Directory_export.triggered.connect( self.runImages_directory_export) icon_excel_exp = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'excel-export.png')) self.actionexcelExp = QAction(QIcon(icon_excel_exp), "Download EXCEL", self.iface.mainWindow()) self.actionexcelExp.setWhatsThis("Download EXCEL") self.actionexcelExp.triggered.connect(self.runPdfexp) self.docToolButton.addActions([ self.actionexcelExp, self.actionimageViewer, self.actionexcelExp, self.actionImages_Directory_export ]) self.docToolButton.setDefaultAction(self.actionimageViewer) #if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.actionImages_Directory_export.setCheckable(True) self.actionexcelExp.setCheckable(True) self.actionimageViewer.setCheckable(True) self.toolBar.addWidget(self.docToolButton) self.toolBar.addSeparator() ###### Section dedicated to the plugin management self.manageToolButton = QToolButton(self.toolBar) self.manageToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_Con = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconConn.png')) self.actionConf = QAction(QIcon(icon_Con), "Config plugin", self.iface.mainWindow()) self.actionConf.setWhatsThis("Config plugin") self.actionConf.triggered.connect(self.runConf) icon_Dbmanagment = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'backup.png')) self.actionDbmanagment = QAction(QIcon(icon_Dbmanagment), "Database manager", self.iface.mainWindow()) self.actionDbmanagment.setWhatsThis("Database manager") self.actionDbmanagment.triggered.connect(self.runDbmanagment) icon_Info = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconInfo.png')) self.actionInfo = QAction(QIcon(icon_Info), "Plugin info", self.iface.mainWindow()) self.actionInfo.setWhatsThis("Plugin info") self.actionInfo.triggered.connect(self.runInfo) self.manageToolButton.addActions( [self.actionConf, self.actionDbmanagment, self.actionInfo]) self.manageToolButton.setDefaultAction(self.actionConf) self.toolBar.addWidget(self.manageToolButton) self.toolBar.addSeparator() # menu self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionUW) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionANC) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionART) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionPottery) self.iface.addPluginToMenu("HFF - Survey UW Archaeological GIS Tools", self.actionShipwreck) self.iface.addPluginToMenu( "HFF - Survey Terrestrial Archaeological GIS Tools", self.actionSite) self.iface.addPluginToMenu( "HFF - Survey Terrestrial Archaeological GIS Tools", self.actionEamena) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionimageViewer) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionexcelExp) self.iface.addPluginToMenu("HFF - Media manager GIS Tools", self.actionImages_Directory_export) self.iface.addPluginToMenu("HFF - Config GIS Tools", self.actionConf) self.iface.addPluginToMenu("HFF - Config GIS Tools", self.actionDbmanagment) self.iface.addPluginToMenu("HFF - Info GIS Tools", self.actionInfo) # MENU self.menu = QMenu("HFF") self.menu.addActions([self.actionSite, self.actionEamena]) self.menu.addSeparator() self.menu.addActions([self.actionShipwreck]) self.menu.addSeparator() self.menu.addActions([ self.actionUW, self.actionART, self.actionANC, self.actionPottery ]) self.menu.addActions([ self.actionimageViewer, self.actionexcelExp, self.actionImages_Directory_export ]) self.menu.addSeparator() self.menu.addActions( [self.actionConf, self.actionDbmanagment, self.actionInfo]) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.menu) ## def runSite(self): pluginGui = hff_system__Site(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runEamena(self): pluginGui = Eamena(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runUW(self): pluginGui = hff_system__UW(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runANC(self): pluginGui = hff_system__ANC(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runART(self): pluginGui = hff_system__ART(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runPottery(self): pluginGui = hff_system__Pottery(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runShipwreck(self): pluginGui = hff_system__Shipwreck(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runConf(self): pluginConfGui = HFF_systemDialog_Config() pluginConfGui.show() self.pluginGui = pluginConfGui # save def runInfo(self): pluginInfoGui = HFF_systemDialog_Info() pluginInfoGui.show() self.pluginGui = pluginInfoGui # save def runImageViewer(self): pluginImageView = Main() pluginImageView.show() self.pluginGui = pluginImageView # save def runImages_directory_export(self): pluginImage_directory_export = hff_system__Images_directory_export() pluginImage_directory_export.show() self.pluginGui = pluginImage_directory_export # save def runDbmanagment(self): pluginDbmanagment = hff_system__dbmanagment(self.iface) pluginDbmanagment.show() self.pluginGui = pluginDbmanagment # save def runPdfexp(self): pluginPdfexp = hff_system__excel_export(self.iface) pluginPdfexp.show() self.pluginGui = pluginPdfexp # save def unload(self): # Remove the plugin self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionUW) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionANC) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionART) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionPottery) self.iface.removePluginMenu("HFF - Survey UW Archaeological GIS Tools", self.actionShipwreck) self.iface.removePluginMenu( "HFF - Survey Terrestrial Archaeological GIS Tools", self.actionSite) self.iface.removePluginMenu( "HFF - Survey Terrestrial Archaeological GIS Tools", self.actionEamena) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionimageViewer) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionImages_Directory_export) self.iface.removePluginMenu("HFF - Media manager GIS Tools", self.actionexcelExp) self.iface.removePluginMenu("HFF - Config GIS Tools", self.actionConf) self.iface.removePluginMenu("HFF - Info GIS Tools", self.actionInfo) self.iface.removePluginMenu("HFF - Config GIS Tools", self.actionDbmanagment) self.iface.removeToolBarIcon(self.actionUW) self.iface.removeToolBarIcon(self.actionART) self.iface.removeToolBarIcon(self.actionANC) self.iface.removeToolBarIcon(self.actionPottery) self.iface.removeToolBarIcon(self.actionShipwreck) self.iface.removeToolBarIcon(self.actionSite) self.iface.removeToolBarIcon(self.actionimageViewer) self.iface.removeToolBarIcon(self.actionImages_Directory_export) self.iface.removeToolBarIcon(self.actionexcelExp) self.iface.removeToolBarIcon(self.actionConf) self.iface.removeToolBarIcon(self.actionInfo) self.iface.removeToolBarIcon(self.actionDbmanagment) self.dockWidget.setVisible(False) self.iface.removeDockWidget(self.dockWidget) # remove tool bar del self.toolBar def showHideDockWidget(self): if self.dockWidget.isVisible(): self.dockWidget.hide() else: self.dockWidget.show()
class qgsazimuth(object): """ Base class for the qgsAzimuth plugin - Provides a means to draw a feature by specifying the angle and distance beetween points. - Supports angles in either the conventional 0.0 - 360.0 clockwise from North or the surveyor's 'Easting' system with bearings plus or minus 90 deg. from North or South - Supports magnetic declination as degrees plus or minus for East or West respectively - supports inputs in feet or the current CRS units """ # just a test to see if mods are taking def __init__(self, iface): self.iface = iface self.canvas = iface.mapCanvas() self.fPath = ( "" ) # set default working directory, updated from config file & by Import/Export self.bands = [] def initGui(self): # create action that will start plugin configuration self.action = QAction( QIcon(":icons/qgsazimuth.png"), "Azimuth and distance", self.iface.mainWindow(), ) self.action.setWhatsThis("Azimuth and distance") self.action.triggered.connect(self.run) self.bandpoint = QgsRubberBand(self.canvas, QgsWkbTypes.PointGeometry) self.bandpoint.setIcon(QgsRubberBand.ICON_CROSS) self.bandpoint.setColor(QColor.fromRgb(255, 50, 255)) self.bandpoint.setWidth(3) self.bandpoint.setIconSize(20) # add toolbar button and menu item self.iface.addPluginToMenu("&Topography", self.action) self.iface.addToolBarIcon(self.action) self.dock = Dock(self.iface.mainWindow()) self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.dock) self.dock.hide() self.pluginGui = self.dock.widget() self.dock.closed.connect(self.cleanup) self.pluginGui.pushButton_vertexAdd.clicked.connect(self.addRow) self.pluginGui.pushButton_vertexInsert.clicked.connect(self.insertRow) self.pluginGui.pushButton_segListRowDel.clicked.connect(self.delRow) self.pluginGui.pushButton_segListLoad.clicked.connect(self.loadList) self.pluginGui.pushButton_segListClear.clicked.connect(self.clearList) self.pluginGui.pushButton_objectDraw.clicked.connect(self.addgeometry) self.pluginGui.pushButton_startCapture.clicked.connect(self.startgetpoint) self.pluginGui.pushButton_segListSave.clicked.connect(self.saveList) self.pluginGui.pushButton_useLast.clicked.connect(self.use_last_vertex) self.pluginGui.pickAngle1_button.clicked.connect(self.select_angle1) self.pluginGui.pickAngle2_button.clicked.connect(self.select_angle2) self.pluginGui.clearMarkers_button.clicked.connect(self.clear_markers) self.pluginGui.copyDiff_button.clicked.connect(self.copy_diff_offset) # self.pluginGui.table_segmentList.cellChanged.connect(self.render_temp_band) self.pluginGui.table_segmentList.setCurrentCell(0, 0) self.tool = GetCoordTool(self.canvas) self.tool.finished.connect(self.getpoint) self.tool.locationChanged.connect(self.pluginGui.update_startpoint) self.tool.locationChanged.connect(self.update_marker_location) self.angletool = LineTool(self.canvas) self.angletool.geometryComplete.connect(self.update_angle1) self.angletool.locationChanged.connect(self.update_marker_location) self.angletool2 = LineTool(self.canvas) self.angletool2.geometryComplete.connect(self.update_angle2) self.angletool2.locationChanged.connect(self.update_marker_location) self.pluginGui.azimuth1_edit.textChanged.connect(self.update_angle_calc) self.pluginGui.azimuth2_edit.textChanged.connect(self.update_angle_calc) self.pluginGui.lineEdit_magNorth.textChanged.connect(self.update_offsetlabel) self.pluginGui.radioButton_defaultNorth.toggled.connect(self.update_offsetlabel) def update_offsetlabel(self, *args): mag = self.mag_dev self.pluginGui.offsetLabel.setText(str(mag)) def copy_diff_offset(self): diff = self.pluginGui.azimuthDiff_edit.text() self.pluginGui.lineEdit_magNorth.setText(diff) def clear_markers(self): self.angletool2.reset() self.angletool.reset() self.pluginGui.azimuth1_edit.setText(str(0)) self.pluginGui.azimuth2_edit.setText(str(0)) def update_angle_calc(self): a1 = self.pluginGui.azimuth1_edit.text() a2 = self.pluginGui.azimuth2_edit.text() a1 = utils.dmsToDd(a1) a2 = utils.dmsToDd(a2) try: a1 = float(a1) a2 = float(a2) except ValueError: self.pluginGui.azimuthDiff_edit.setText("") return diff = a2 - a1 self.pluginGui.azimuthDiff_edit.setText(str(diff)) def select_angle1(self): self.canvas.setMapTool(self.angletool) def update_angle1(self, geometry): az = utils.azimuth_from_line(geometry) az = str(az) self.pluginGui.azimuth1_edit.setText(az) def update_angle2(self, geometry): az = utils.azimuth_from_line(geometry) az = str(az) self.pluginGui.azimuth2_edit.setText(az) def select_angle2(self): self.canvas.setMapTool(self.angletool2) def update_marker_location(self, point): self.bandpoint.setToGeometry(QgsGeometry.fromPointXY(point), None) def unload(self): # remove the plugin menu item and icon self.saveConf() self.iface.removeDockWidget(self.dock) self.iface.removePluginMenu("&Topography", self.action) self.iface.removeToolBarIcon(self.action) self.bandpoint.reset() self.tool.cleanup() self.clear_markers() del self.angletool2 del self.angletool del self.tool del self.bandpoint def run(self): # misc init self.loadConf() # get config data self.clearList() self.setStartAt("0;0;90") # remove previous StartAt point self.pluginGui.lineEdit_crs.setText( self.iface.mapCanvas().mapSettings().destinationCrs().description() ) if self.iface.activeLayer(): self.updatelayertext(self.iface.activeLayer()) self.pluginGui.radioButton_useActiveLayer.setChecked(True) else: self.pluginGui.radioButton_useActiveLayer.setEnabled(False) self.pluginGui.radioButton_useMemoryLayer.setChecked(True) self.iface.currentLayerChanged.connect(self.updatelayertext) if not self.dock.isVisible(): self.dock.show() # for debugging convenience self.notes = self.pluginGui.plainTextEdit_note def cleanup(self): self.tool.cleanup() self.clear_bands() self.saveConf() def updatelayertext(self, layer): if not layer: self.pluginGui.radioButton_useActiveLayer.setEnabled(False) else: self.pluginGui.radioButton_useActiveLayer.setEnabled(True) self.pluginGui.radioButton_useActiveLayer.setText( "Active Layer ({0})".format(layer.name()) ) @property def useactivelayer(self): return self.pluginGui.radioButton_useActiveLayer.isChecked() def render_temp_band(self, *args): """ Render a temp rubber band for showing the user the results """ self.clear_bands() featurelist, vectorlayer = self.create_feature() if not featurelist or not vectorlayer: return for feature in featurelist: band = QgsRubberBand(self.iface.mapCanvas()) if hasattr(band, "setLineStyle"): band.setLineStyle(Qt.DotLine) band.setWidth(4) band.setColor(Qt.darkMagenta) band.setToGeometry(feature.geometry(), vectorlayer) band.show() self.bands.append(band) pass @property def should_open_form(self): return self.pluginGui.checkBox_openForm.isChecked() @should_open_form.setter def should_open_form(self, value): return self.pluginGui.checkBox_openForm.setChecked(value) def addgeometry(self): featurelist, vectorlayer = self.create_feature() if not featurelist or not vectorlayer: return if not self.useactivelayer: QgsProject.instance().addMapLayer(vectorlayer) vectorlayer.startEditing() for feature in featurelist: if self.should_open_form: form = self.iface.getFeatureForm(vectorlayer, feature) form.setMode(QgsAttributeEditorContext.AddFeatureMode) if not form.exec_(): continue else: print(feature.isValid()) print(feature.geometry().asWkt()) error = vectorlayer.addFeature(feature) print(error, feature) if error: log("Error in adding feature") self.iface.mapCanvas().refresh() self.clear_bands() def clear_bands(self): for band in self.bands: band.reset() self.bands = [] def update_draw_button_state(self): x, y, z = self.starting_point() enabled = True if (x == 0 and y == 0 and z == 90) or ( self.pluginGui.table_segmentList.rowCount() == 0 ): enabled = False self.pluginGui.pushButton_objectDraw.setEnabled(enabled) def starting_point(self): # Get starting point coordinates X = float(str(self.pluginGui.lineEdit_vertexX0.text())) Y = float(str(self.pluginGui.lineEdit_vertexY0.text())) Z = float(str(self.pluginGui.lineEdit_vertexZ0.text())) return X, Y, Z @property def angletype(self): if self.pluginGui.radioButton_azimuthAngle.isChecked(): return "azimuth" elif self.pluginGui.radioButton_bearingAngle.isChecked(): return "bearing" elif self.pluginGui.radioButton_polarCoordAngle.isChecked(): return "polor" @angletype.setter def angletype(self, value): if value == "azimuth": self.pluginGui.radioButton_azimuthAngle.setChecked(True) elif value == "bearing": self.pluginGui.radioButton_bearingAngle.setChecked(True) elif value == "polor": self.pluginGui.radioButton_polarCoordAngle.setChecked(True) else: self.pluginGui.radioButton_azimuthAngle.setChecked(True) @property def distanceunits(self): if self.pluginGui.radioButton_defaultUnits.isChecked(): return "default" elif self.pluginGui.radioButton_englishUnits.isChecked(): return "feet" @distanceunits.setter def distanceunits(self, value): if value == "default": self.pluginGui.radioButton_defaultUnits.setChecked(True) elif value == "feet": self.pluginGui.radioButton_englishUnits.setChecked(True) else: self.pluginGui.radioButton_defaultUnits.setChecked(True) @property def angleunit(self): if self.pluginGui.radioButton_degreeUnit.isChecked(): return "degree" elif self.pluginGui.radioButton_gradianUnit.isChecked(): return "gradian" @angleunit.setter def angleunit(self, value): if value == "degree": self.pluginGui.radioButton_degreeUnit.setChecked(True) elif value == "gradian": self.pluginGui.radioButton_gradianUnit.setChecked(True) else: self.pluginGui.radioButton_degreeUnit.setChecked(True) @property def northtype(self): if self.pluginGui.radioButton_magNorth.isChecked(): return "magnetic" else: return "default" @northtype.setter def northtype(self, value): if value == "magnetic": self.pluginGui.radioButton_magNorth.setChecked(True) else: self.pluginGui.radioButton_defaultNorth.setChecked(True) @property def mag_dev(self): if self.pluginGui.radioButton_magNorth.isChecked(): value = str(self.pluginGui.lineEdit_magNorth.text()) try: return float(value) except ValueError: try: if self.pluginGui.radioButton_gradianUnit.isChecked(): value = utils.gradianToDd(value) return float(utils.dmsToDd(value)) except IndexError: return 0.0 elif self.pluginGui.radioButton_defaultNorth.isChecked(): return 0.0 else: return 0.0 @mag_dev.setter def mag_dev(self, value): self.pluginGui.lineEdit_magNorth.setText(str(value)) @property def surveytype(self): if self.pluginGui.radioButton_radialSurvey.isChecked(): surveytype = "radial" elif self.pluginGui.radioButton_boundarySurvey.isChecked(): surveytype = "polygonal" return surveytype @surveytype.setter def surveytype(self, value): if value == "radial": self.pluginGui.radioButton_radialSurvey.setChecked(True) elif value == "polygonal": self.pluginGui.radioButton_boundarySurvey.setChecked(True) else: self.pluginGui.radioButton_boundarySurvey.setChecked(True) def use_last_vertex(self): # Get the last point from the last band x, y, z = 0, 0, 90 arcpoint_count = self.arc_count points = self.get_points(self.surveytype, arcpoint_count) try: point = points[-1] x, y, z = point.x, point.y, point.z except IndexError: # Don't do anything if there is no last point return point = QgsPointXY(x, y) self.pluginGui.update_startpoint(point, z) self.update_marker_location(point) self.clearList() def table_entries(self): """ Return the entries for each row in the table """ rows = self.pluginGui.table_segmentList.rowCount() for row in range(rows): az = self.pluginGui.table_segmentList.item(row, 0).text() dis = float(str(self.pluginGui.table_segmentList.item(row, 1).text())) zen = self.pluginGui.table_segmentList.item(row, 2).text() direction = self.pluginGui.table_segmentList.item(row, 4).text() direction = utils.Direction.resolve(direction) try: radius = float(self.pluginGui.table_segmentList.item(row, 3).text()) except ValueError: radius = None yield az, dis, zen, direction, radius def get_points(self, surveytype, arcpoint_count): """ Return a list of calculated points for the full run. :param surveytype: :return: """ X, Y, Z = self.starting_point() if (X == 0 and Y == 0 and Z == 90) or ( self.pluginGui.table_segmentList.rowCount() == 0 ): return [] vlist = [] vlist.append(utils.Point(X, Y, Z)) # convert segment list to set of vertice for az, dis, zen, direction, radius in self.table_entries(): if self.pluginGui.radioButton_englishUnits.isChecked(): # adjust for input in feet, not meters dis = float(dis) * 0.3048 # checking degree input if self.pluginGui.radioButton_azimuthAngle.isChecked(): if self.pluginGui.radioButton_gradianUnit.isChecked(): az = utils.gradianToDd(az) zen = utils.gradianToDd(zen) else: az = float(utils.dmsToDd(az)) zen = float(utils.dmsToDd(zen)) elif self.pluginGui.radioButton_bearingAngle.isChecked(): az = float(self.bearingToDd(az)) zen = float(self.bearingToDd(zen)) # correct for magnetic compass headings if necessary self.magDev = self.mag_dev az = float(az) + float(self.magDev) # correct for angles outside of 0.0-360.0 while az > 360.0: az = az - 360.0 while az < 0.0: az = az + 360.0 # checking survey type if surveytype == "radial": reference_point = vlist[0] # reference first vertex if surveytype == "polygonal": reference_point = vlist[-1] # reference previous vertex nextpoint = utils.nextvertex(reference_point, dis, az, zen) if radius: # If there is a radius then we are drawing a arc. if self.pluginGui.radioButton_englishUnits.isChecked(): # adjust for input in feet, not meters radius = float(radius) * 0.3048 # Calculate the arc points. points = list( utils.arc_points( reference_point, nextpoint, dis, radius, point_count=arcpoint_count, direction=direction, zenith_angle=zen, ) ) if direction == utils.Direction.ANTICLOCKWISE: points = reversed(points) # Append them to the final points list. vlist.extend(points) vlist.append(nextpoint) return vlist @property def drawing_layer(self): if self.useactivelayer: vectorlayer = self.iface.activeLayer() else: code = self.iface.mapCanvas().mapSettings().destinationCrs().authid() vectorlayer = QgsVectorLayer( "LineString?crs={}".format(code), "tmp_plot", "memory" ) return vectorlayer @property def arc_count(self): """ The number of points to use when drawing arcs """ return self.pluginGui.spin_arclines.value() @arc_count.setter def arc_count(self, value): """ The number of points to use when drawing arcs """ self.pluginGui.spin_arclines.setValue(value) def create_feature(self): vectorlayer = self.drawing_layer # reprojecting to projects SRS arcpoint_count = self.arc_count points = self.get_points(self.surveytype, arcpoint_count) if not points: return None, None vlist = self.reproject(points, vectorlayer) as_segments = self.pluginGui.checkBox_asSegments.isChecked() featurelist = [] geometrytype = vectorlayer.geometryType() if geometrytype == QgsWkbTypes.PointGeometry: points = utils.to_qgspoints(vlist) features = utils.createpoints(points) featurelist.extend(features) elif geometrytype == QgsWkbTypes.LineGeometry: if as_segments: # If the line is to be draw as segments then we loop the pairs and create a line for each one. points_to_join = [] in_arc = False for pair in utils.pairs( vlist, matchtail=self.surveytype == "polygonal" ): start, end = pair[0], pair[1] # If we are not drawing the arc then just add the pair to get a single line if not start.arc_point and not end.arc_point: points_to_join = pair else: # If we are in a arc we need to handle drawing it as one line # which means grabbing each pair until we are finished the arc if not start.arc_point and end.arc_point: points_to_join = [] in_arc = True if start.arc_point and not end.arc_point: points_to_join.append(start) points_to_join.append(end) in_arc = False if in_arc: points_to_join.append(start) points_to_join.append(end) continue pointlist = utils.to_qgspoints( points_to_join, repeatfirst=self.surveytype == "radial" ) feature = utils.createline(pointlist) featurelist.append(feature) else: pointlist = utils.to_qgspoints( vlist, repeatfirst=self.surveytype == "radial" ) feature = utils.createline(pointlist) featurelist.append(feature) elif geometrytype == QgsWkbTypes.PolygonGeometry: polygon = utils.to_qgspoints(vlist) feature = utils.createpolygon([polygon]) if feature: featurelist.append(feature) # Add the fields for the current layer for feature in featurelist: feature.setFields(vectorlayer.fields()) return featurelist, vectorlayer def bearingToDd(self, dms): # allow survey bearings in form: - N 25d 34' 40" E # where minus ('-') sign allows handling bearings given in reverse direction dms = dms.strip() if dms[0] == "-": rev = True dms = dms[1:].strip() else: rev = False baseDir = dms[0].upper() if baseDir in ["N", "S"]: adjDir = dms[-1].upper() bearing = True if baseDir == "N": if adjDir == "E": base = 0.0 adj = "add" elif adjDir == "W": base = 360.0 adj = "sub" else: return 0 elif baseDir == "S": base = 180.0 if adjDir == "E": adj = "sub" elif adjDir == "W": adj = "add" else: return 0 else: bearing = False if self.pluginGui.radioButton_gradianUnit.isChecked(): dd = utils.gradianToDd(dms) else: dd = utils.dmsToDd(dms) if rev: dd = float(dd) + 180.0 if bearing == True: if adj == "add": dd = float(base) + float(dd) elif adj == "sub": dd = float(base) - float(dd) return dd def clearList(self): self.pluginGui.table_segmentList.clearContents() self.pluginGui.table_segmentList.setSortingEnabled(False) self.pluginGui.table_segmentList.setRowCount(0) self.pluginGui.table_segmentList.setCurrentCell( 0, 0 ) # substitute for missing setCurrentRow() self.render_temp_band() # retranslateUi def newVertex(self): # adds a vertex from the gui self.addrow( self.pluginGui.lineEdit_nextAzimuth.text(), self.pluginGui.lineEdit_nextDistance.value(), self.pluginGui.lineEdit_nextVertical.text(), self.pluginGui.spin_radius.value(), ) def addRow(self): # this and following must be split to handle both GUI & FILE inputs az = self.pluginGui.lineEdit_nextAzimuth.text() dist = self.pluginGui.lineEdit_nextDistance.value() zen = self.pluginGui.lineEdit_nextVertical.text() radius = self.pluginGui.spin_radius.value() if radius == 0: radius = None direction = None else: if self.pluginGui.radio_anticlockwise.isChecked(): direction = "anticlockwise" else: direction = "clockwise" self.addrow(az, dist, zen, radius, direction) def addrow(self, az=0, dist=0, zen=90, radius=None, direction=None): # add the vertex to the end of the table row = self.pluginGui.table_segmentList.rowCount() self.pluginGui.table_segmentList.insertRow(row) self.pluginGui.table_segmentList.setItem( row, 0, QTableWidgetItem(str(az).upper()) ) self.pluginGui.table_segmentList.setItem(row, 1, QTableWidgetItem(str(dist))) self.pluginGui.table_segmentList.setItem(row, 2, QTableWidgetItem(str(zen))) self.pluginGui.table_segmentList.setItem(row, 3, QTableWidgetItem(str(radius))) self.pluginGui.table_segmentList.setItem( row, 4, QTableWidgetItem(str(direction)) ) self.render_temp_band() def insertRow(self): az = self.pluginGui.lineEdit_nextAzimuth.text() dist = self.pluginGui.lineEdit_nextDistance.value() zen = self.pluginGui.lineEdit_nextVertical.text() radius = self.pluginGui.spin_radius.value() if radius == 0: radius = None direction = None else: if self.pluginGui.radio_anticlockwise.isChecked(): direction = "anticlockwise" else: direction = "clockwise" # insert the vertext into the table at the current position row = self.pluginGui.table_segmentList.currentRow() self.pluginGui.table_segmentList.insertRow(row) self.pluginGui.table_segmentList.setItem( row, 0, QTableWidgetItem(str(az).upper()) ) self.pluginGui.table_segmentList.setItem(row, 1, QTableWidgetItem(str(dist))) self.pluginGui.table_segmentList.setItem(row, 2, QTableWidgetItem(str(zen))) self.pluginGui.table_segmentList.setItem(row, 3, QTableWidgetItem(str(radius))) self.pluginGui.table_segmentList.setItem( row, 4, QTableWidgetItem(str(direction)) ) self.render_temp_band() def delRow(self): self.pluginGui.table_segmentList.removeRow( self.pluginGui.table_segmentList.currentRow() ) self.render_temp_band() def moveup(self): self.render_temp_band() pass def movedown(self): self.render_temp_band() pass def startgetpoint(self): # point capture tool self.saveTool = self.canvas.mapTool() self.canvas.setMapTool(self.tool) def getpoint(self, pt): self.clear_markers() self.pluginGui.update_startpoint(pt) self.canvas.setMapTool(self.saveTool) def reproject(self, vlist, vectorlayer): renderer = self.canvas.mapSettings() for row, point in enumerate(vlist): new_point = renderer.layerToMapCoordinates( vectorlayer, QgsPointXY(point[0], point[1]) ) # Translate it into our new point with arc_point info new_point = utils.Point( new_point.x(), new_point.y(), arc_point=point.arc_point ) vlist[row] = new_point return vlist def setAngle(self, s): # self.say('processing angleType='+s) if s == "azimuth": self.pluginGui.radioButton_azimuthAngle.setChecked(True) elif s == "bearing": self.pluginGui.radioButton_bearingAngle.setChecked(True) elif s == "polar": self.pluginGui.radioButton_polorCoordAngle.setChecked(True) else: self.say("invalid angle type: " + s) def setHeading(self, s): # self.say('processing headingType='+s) if s == "coordinate_system": self.pluginGui.radioButton_defaultNorth.setChecked(True) elif s == "magnetic": self.pluginGui.radioButton_magNorth.setChecked(True) else: self.say("invalid heading type: " + s) def setDeclination(self, s): # self.say('processing declination='+s) self.pluginGui.lineEdit_magNorth.setText(s) self.magDev = float(s) def setDistanceUnits(self, s): # self.say('processing distance units='+s) if s == "feet": self.pluginGui.radioButton_englishUnits.setChecked(True) else: self.pluginGui.radioButton_defaultUnits.setChecked(True) def setAngleUnit(self, s): if s == "gradian": self.pluginGui.radioButton_gradianUnit.setChecked(True) else: self.pluginGui.radioButton_degreeUnit.setChecked(True) def setStartAt(self, s): # self.say('processing startAt='+s) coords = [float(v) for v in s.split(";")] point = QgsPointXY(coords[0], coords[1]) self.pluginGui.update_startpoint(point, coords[2]) def setSurvey(self, s): # self.say('processing surveyType='+s) if s == "polygonal": self.pluginGui.radioButton_boundarySurvey.setChecked(True) elif s == "radial": self.pluginGui.radioButton_irrSurvey.setChecked(True) else: self.say("invalid survey type: " + s) def say(self, txt): # present a message box on screen warn = QgsMessageViewer() warn.setMessageAsPlainText(txt) warn.showMessage() def tell(self, txt): # write to bottom of Note area at top of screen self.notes.appendPlainText(txt) # --------------------------------------------------------------------------------------------------------------------------------- # File handling # This section deals with saving the user data to disk, and loading it # # format: # line 1: angle=Azimuth|Bearing|Polar # line 2: heading=Coordinate System|Magnetic # line 3: declination=[- ]x.xxd[ xx.x'] [E|W] # line 4: distunits=Default|Feet # line 5: startAt=xxxxx.xxxxx, xxxxxx.xxxxx # line 6: survey=Polygonal|Radial # line 7: [data] # line 8 through end: Azimuth; dist; zen # # note: lines 1 through 5 are optional if hand entered, but will always be generated when 'saved' # --------------------------------------------------------------------------------------------------------------------------------- def loadList(self): self.fileName, _ = QFileDialog.getOpenFileName( None, "Load data separated by ';'", self.fPath, "" ) if not os.path.exists(self.fileName): return 0 # update selected file's folder fInfo = QFileInfo(self.fileName) self.fPath = fInfo.absolutePath() self.saveConf() self.render_temp_band() # get saved data try: f = open(self.fileName) lines = f.readlines() f.close() self.clearList() for line in lines: # remove trailing 'new lines', etc and break into parts parts = ((line.strip()).lower()).split("=") if len(parts) > 1: # self.say("line="+line+'\nparts[0]='+parts[0]+'\nparts[1]='+parts[1]) if parts[0].lower() == "angle": self.setAngle(parts[1].lower()) elif parts[0].lower() == "heading": self.setHeading(parts[1].lower()) elif parts[0].lower() == "declination": self.setDeclination(parts[1].lower()) elif parts[0].lower() == "dist_units": self.setDistanceUnits(parts[1].lower()) elif parts[0].lower() == "angle_unit": self.setAngleUnit(parts[1].lower()) elif parts[0].lower() == "startat": self.setStartAt(parts[1].lower()) elif parts[0].lower() == "survey": self.setSurvey(parts[1].lower()) else: coords = tuple((line.strip()).split(";")) if coords[0].lower() == "[data]": pass else: self.addrow(*coords) except: self.say("Invalid input") def saveList(self): file, _ = QFileDialog.getSaveFileName( None, "Save segment list to file.", self.fileName, "" ) if file == "": return f = open(file, "w") # update selected file's folder fInfo = QFileInfo(file) self.fPath = fInfo.absolutePath() self.saveConf() if self.pluginGui.radioButton_azimuthAngle.isChecked(): s = "Azimuth" elif self.pluginGui.radioButton_bearingAngle.isChecked(): s = "Bearing" f.write("angle=" + s + "\n") if self.pluginGui.radioButton_defaultNorth.isChecked(): s = "Coordinate_System" elif self.pluginGui.radioButton_magNorth.isChecked(): s = "Magnetic" f.write("heading=" + s + "\n") if hasattr(self, "magDev") and self.magDev != 0.0: f.write("declination=" + str(self.magDev) + "\n") if self.pluginGui.radioButton_defaultUnits.isChecked(): s = "Default" elif self.pluginGui.radioButton_englishUnits.isChecked(): s = "Feet" f.write("dist_units=" + s + "\n") if self.pluginGui.radioButton_degreeUnit.isChecked(): s = "degree" elif self.pluginGui.radioButton_gradianUnit.isChecked(): s = "gradian" f.write("angle_unit=" + s + "\n") f.write( "startAt=" + str(self.pluginGui.lineEdit_vertexX0.text()) + ";" + str(self.pluginGui.lineEdit_vertexY0.text()) + ";" + str(self.pluginGui.lineEdit_vertexZ0.text()) + "\n" ) if self.pluginGui.radioButton_boundarySurvey.isChecked(): s = "Polygonal" elif self.pluginGui.radioButton_radialSurvey.isChecked(): s = "Radial" f.write("survey=" + s + "\n") f.write("[data]\n") for row in range(self.pluginGui.table_segmentList.rowCount()): line = ( str(self.pluginGui.table_segmentList.item(row, 0).text()) + ";" + str(self.pluginGui.table_segmentList.item(row, 1).text()) + ";" + str(self.pluginGui.table_segmentList.item(row, 2).text()) + ";" + str(self.pluginGui.table_segmentList.item(row, 3).text()) + ";" + str(self.pluginGui.table_segmentList.item(row, 4).text()) ) f.write(line + "\n") f.close() # ------------------------ def loadConf(self): settings = QSettings() size = settings.value("/Plugin-qgsAzimuth/size", QSize(800, 600), type=QSize) position = settings.value( "/Plugin-qgsAzimuth/position", QPoint(0, 0), type=QPoint ) self.fPath = settings.value("/Plugin-qgsAzimuth/inp_exp_dir", "", type=str) self.angletype = settings.value("/Plugin-qgsAzimuth/angletype", "", type=str) self.should_open_form = settings.value( "/Plugin-qgsAzimuth/open_form", True, type=bool ) self.surverytype = settings.value("/Plugin-qgsAzimuth/type", "", type=str) self.northtype = settings.value("/Plugin-qgsAzimuth/northtype", "", type=str) self.mag_dev = settings.value( "/Plugin-qgsAzimuth/northtype_value", 0.0, type=float ) self.distanceunits = settings.value( "/Plugin-qgsAzimuth/distanceunits", "", type=str ) self.angleunit = settings.value("/Plugin-qgsAzimuth/angleunit", "", type=str) if self.angleunit == "gradian": self.pluginGui.lineEdit_nextVertical.setText("100") self.angletype = settings.value("/Plugin-qgsAzimuth/angletype", "", type=str) self.arc_count = settings.value("/Plugin-qgsAzimuth/arcpoints", 6, type=int) self.pluginGui.resize(size) self.pluginGui.move(position) self.fileName = self.fPath # settings.restoreGeometry(settings.value("Geometry"), QByteArray(), type=QByteArray) def saveConf(self): settings = QSettings() # settings.setValue("Geometry", self.saveGeometry()) settings.setValue("/Plugin-qgsAzimuth/size", self.pluginGui.size()) settings.setValue("/Plugin-qgsAzimuth/position", self.pluginGui.pos()) settings.setValue("/Plugin-qgsAzimuth/inp_exp_dir", self.fPath) settings.setValue("/Plugin-qgsAzimuth/open_form", self.should_open_form) settings.setValue("/Plugin-qgsAzimuth/type", self.surveytype) settings.setValue("/Plugin-qgsAzimuth/northtype", self.northtype) settings.setValue("/Plugin-qgsAzimuth/northtype_value", self.mag_dev) settings.setValue("/Plugin-qgsAzimuth/distanceunits", self.distanceunits) settings.setValue("/Plugin-qgsAzimuth/angleunit", self.angleunit) settings.setValue("/Plugin-qgsAzimuth/angletype", self.angletype) settings.setValue("/Plugin-qgsAzimuth/arcpoints", self.arc_count) def sortedDict(self, adict): keys = list(adict.keys()) keys.sort() return list(map(adict.get, keys))
class MainPlugin(object): def __init__(self, iface): self.name = "groupLayers" self.iface = iface self.project = QgsProject.instance() self.treeBeforeSave = None def initGui(self): self.action = QAction( QIcon(os.path.dirname(os.path.realpath(__file__)) + "/icon.png"), u"Group Layers by similar type (keep visibility)", self.iface.mainWindow() ) self.action.setObjectName("groupAction") self.action.setWhatsThis("Group/ungroup layers by type") self.action.setStatusTip("Group/ungroup layers by type") self.action.setCheckable(True) self.action.triggered.connect(self.run) self.resetAction = QAction("Group and make all layers visible") self.resetAction.triggered.connect(self.run_reset_visibility) # the icon pressed status could be used, but it is already # changed when run method is called, so this is ambiguous # therefore a dedicated boolean status is used self.grouped = False self.groupAdditionalTypes = False self.defSelection = groupHierarchies.keys().__iter__().__next__() self.hierarchyDefinition = groupHierarchies[self.defSelection] # add toolbar button and menu item layersDock = self.iface.mainWindow().findChild(QDockWidget, "Layers") self.layersToolBar = layersDock.widget().layout().itemAt(0).widget() assert isinstance(self.layersToolBar, QToolBar) self.layersToolBar.addAction(self.action) self.menuButton = [btn for btn in self.layersToolBar.children() if isinstance(btn, QToolButton) if self.action in btn.actions()][0] self.buttonMenu = QMenu() self.menuButton.setMenu(self.buttonMenu) self.menuButton.setPopupMode(QToolButton.MenuButtonPopup) self.buttonMenu.addAction(self.action) self.buttonMenu.addAction(self.resetAction) # self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&Group Layers", self.action) self.defSelector = QAction( u"Select hierarchy definitions", self.iface.mainWindow() ) self.defSelector.setObjectName("defSelector") self.defSelector.triggered.connect(self.selectDefs) self.iface.addPluginToMenu("&Group Layers", self.defSelector) # connect hook to reset the plugin state # when a new or existing project is opened self.project.cleared.connect(self.reset_state) self.project.writeProject.connect(self.write) self.project.projectSaved.connect(self.saved) def unload(self): # remove the plugin menu item and icon self.iface.removePluginMenu("&Group Layers", self.action) self.iface.removePluginMenu("&Group Layers", self.defSelector) self.layersToolBar.removeAction(self.action) self.project.cleared.disconnect(self.reset_state) self.project.writeProject.disconnect(self.write) self.project.projectSaved.disconnect(self.saved) try: self.project.layerWasAdded.disconnect(self.add_layer_sync) except Exception: print('could not disconnect add_layer_sync in unload') try: self.project.layerRemoved.disconnect(self.remove_layer_sync) except Exception: print('could not disconnect remove_layer_sync in unload') # self.iface.removeToolBarIcon(self.action) def selectDefs(self): dialog = DefSelectDialog(self.defSelection, self.groupAdditionalTypes) if dialog.exec_(): self.defSelection = dialog.comboBox.currentText() self.hierarchyDefinition = groupHierarchies[self.defSelection] self.groupAdditionalTypes = dialog.checkBox.isChecked() def run(self, checked=False, reset=False): try: if self.grouped: try: self.project.layerWasAdded.disconnect(self.add_layer_sync) except Exception: print('could not disconnect add_layer_sync') try: self.project.layerRemoved.disconnect(self.remove_layer_sync) except Exception: print('could not disconnect remove_layer_sync') self.groupToTree(reset_initial_visibility=reset) self.resetAction.setText("Group and make all layers visible") else: self.treeToGroup(all_visible=reset) self.resetAction.setText("Ungroup and restore initial (ungrouped) visibility") self.project.layerWasAdded.connect(self.add_layer_sync) self.project.layerRemoved.connect(self.remove_layer_sync) except Exception as e: raise(e) finally: # synchronize plugin state with button state in case of exceptions self.grouped = checked def run_reset_visibility(self): self.action.toggle() self.run(checked=self.action.isChecked(), reset=True) def reset_state(self): self.action.setChecked(False) self.grouped = False def write(self): if self.grouped: answer = QMessageBox.question(self.iface.mainWindow(), "Save ungrouped state", "The layers are currently grouped by the " "groupLayers plugin\n\n" "Would you like to save the initial (ungrouped) state?\n" "(save current (grouped) layer tree if answer = NO)", QMessageBox.Yes|QMessageBox.No) if answer == QMessageBox.Yes: self.treeBeforeSave = self.iface.layerTreeCanvasBridge().rootGroup().clone() self.groupToTree(reset_initial_visibility=True) self.iface.messageBar().pushMessage( 'CAUTION: The layer tree has been saved in its original format, ' 'check options if you want to change this behavior.', Qgis.Info ) def saved(self): if self.treeBeforeSave is not None: tempOldTree = self.oldTree self.oldTree = self.treeBeforeSave self.groupToTree(reset_initial_visibility=True) self.oldTree = tempOldTree self.treeBeforeSave = None def add_layer_sync(self, addedLayer): self.oldTree.addLayer(addedLayer) def remove_layer_sync(self, removedLayerId): removedLayer = self.oldTree.findLayer(removedLayerId) self.recursiveRemoveFromGroup(self.oldTree, removedLayer) def recursiveRemoveFromGroup(self, group, layer): group.removeChildNode(layer) for subGroup in group.findGroups(): self.recursiveRemoveFromGroup(subGroup, layer) def initTreeRec(self, hierarchyDefinition, tree): for (k, v) in hierarchyDefinition.items(): if "groupCriteria" in v: tree[k] = {} self.initTreeRec(v["values"], tree[k]) else: tree[k] = [] def treeToGroup(self, all_visible=True): self.layerDict = {} self.treeRoot = self.project.layerTreeRoot() self.initTreeRec(self.hierarchyDefinition['values'], self.layerDict) layerTree = self.iface.layerTreeCanvasBridge().rootGroup() self.oldTree = layerTree.clone() self.parseTreeRec(layerTree) # into self.layerDict self.layerDict = self.cleanTree(self.layerDict) oldLen = len(layerTree.children()) self.layerDictToTree(self.layerDict, layerTree, all_visible) # caution: commented instruction below removes all layers !! # iface.layerTreeCanvasBridge().rootGroup().clear() layerTree.removeChildren(0, oldLen) def groupToTree(self, reset_initial_visibility=True): self.treeRoot = self.project.layerTreeRoot() layerTree = self.iface.layerTreeCanvasBridge().rootGroup() oldLen = len(layerTree.children()) self.insertInto(self.oldTree, layerTree, reset_initial_visibility) layerTree.removeChildren(0, oldLen) def layerDictToTree(self, layerDict, destinationGroup, all_visible): if isinstance(layerDict, dict): for (layerType, layers) in layerDict.items(): grp = destinationGroup.addGroup(layerType) self.layerDictToTree(layers, grp, all_visible) elif isinstance(layerDict, list): for l in layerDict: isVisible = self.treeRoot.findLayer(l).isVisible() node = destinationGroup.addLayer(l) if not all_visible: node.setItemVisibilityChecked(isVisible) else: raise Exception("Tree dictionary has been initialized incorrectly.") def insertInto(self, origin, destination, reset_initial_visibility): for el in origin.children(): if QgsLayerTree.isLayer(el): node = destination.addLayer(el.layer()) node.setItemVisibilityChecked( self.treeRoot.findLayer(el.layer()).isVisible() ) elif QgsLayerTree.isGroup(el): node = destination.addGroup(el.name()) self.insertInto(el, node, reset_initial_visibility) if reset_initial_visibility: # overwrite visibility with previously saved visibility node.setItemVisibilityChecked(el.itemVisibilityChecked()) def parseTreeRec(self, treeLeaf): for el in treeLeaf.children(): if QgsLayerTree.isLayer(el): l = el.layer() self.sortInto(l, self.layerDict, self.hierarchyDefinition) elif QgsLayerTree.isGroup(el): self.parseTreeRec(el) def sortInto(self, layer, destination, definitions): if "groupCriteria" in definitions: groupValue = layer.__getattribute__(definitions["groupCriteria"])() itemFound = False for (label, criteria) in definitions["values"].items(): if groupValue == criteria["value"]: itemFound = True self.sortInto(layer, destination[label], criteria) if not itemFound: if self.groupAdditionalTypes: groupName = "others" else: groupName = str(groupValue) try: destination[groupName].append(layer) except KeyError: destination[groupName] = [layer] else: destination.append(layer) def cleanTree(self, sourceTree): # remove all branches without end leaves if isinstance(sourceTree, dict): groupContents = {} for (layerType, layers) in sourceTree.items(): groupLayers = self.cleanTree(layers) if groupLayers: groupContents[layerType] = groupLayers return groupContents elif isinstance(sourceTree, list): return sourceTree else: raise Exception("Tree dictionary has been initialized incorrectly.")
class SeilaplanPlugin(object): """QGIS Plugin Implementation.""" def __init__(self, iface): # 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] localePath = os.path.join(self.plugin_dir, 'i18n', 'SeilaplanPlugin_{}.qm'.format(locale)) if os.path.exists(localePath): self.translator = QTranslator() self.translator.load(localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.action = None self.progressDialog = None self.dlg = None # try: # import pydevd # pydevd.settrace('localhost', port=53100, # stdoutToServer=True, stderrToServer=True) # except ConnectionRefusedError: # pass # except ImportError: # pass def initGui(self): # Create action that will start plugin configuration self.action = QAction( QIcon(":/plugins/SeilaplanPlugin/icons/icon_app.png"), "SEILAPLAN", self.iface.mainWindow()) self.action.setWhatsThis("SEILAPLAN") # Connect the action to the run method self.action.triggered.connect(self.run) # Add toolbar button and menu item self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&SEILAPLAN", self.action) def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" self.iface.removePluginMenu('&SEILAPLAN', self.action) self.iface.removeToolBarIcon(self.action) def run(self): """Run method that performs all the real work""" # Control variables for possible rerun of algorithm reRun = True reRunProj = None while reRun: # Create seperate threa for calculations so that QGIS stays # responsive workerThread = ProcessingTask() # Initialize dialog window self.dlg = SeilaplanPluginDialog(self.iface, workerThread) # Get available raster from table of content in QGIS self.dlg.updateRasterList() # Load initial values of dialog self.dlg.loadInitialVals() # If this is a rerun of the algorithm the previous user values are # loaded into the GUI if reRunProj: self.dlg.loadProj(reRunProj) self.dlg.show() # Start event loop self.dlg.exec_() reRun = False reRunProj = None # The algorithm is executed in a separate thread. To see progress, # a new gui shows a progress bar. # If all needed data has been input in the gui and the user has # clicked 'ok' if workerThread.state is True: # Initialize gui to show progress self.progressDialog = ProgressDialog(self.iface) self.progressDialog.setThread(workerThread) # Add task to taskmanager of QGIS and start the calculations QgsApplication.taskManager().addTask(workerThread) # Show progress bar self.progressDialog.run() # After calculations have finished and progress gui has been # closed: Check if user wants a rerun if self.progressDialog.reRun: reRun = True reRunProj = workerThread.projInfo['projFile'] del self.progressDialog del workerThread del self.dlg return def reject(self): self.dlg.Reject() def cleanUp(self): pass
class MetaSearchPlugin(object): """base plugin""" def __init__(self, iface): """init""" self.iface = iface self.context = StaticContext() self.action_run = None self.action_help = None self.dialog = None self.web_menu = '&MetaSearch' def initGui(self): """startup""" # run run_icon = QIcon('%s/%s' % (self.context.ppath, 'images/MetaSearch.png')) self.action_run = QAction(run_icon, 'MetaSearch', self.iface.mainWindow()) self.action_run.setWhatsThis(QCoreApplication.translate('MetaSearch', 'MetaSearch plugin')) self.action_run.setStatusTip(QCoreApplication.translate('MetaSearch', 'Search Metadata Catalogues')) self.action_run.triggered.connect(self.run) self.iface.addWebToolBarIcon(self.action_run) self.iface.addPluginToWebMenu(self.web_menu, self.action_run) # help help_icon = QgsApplication.getThemeIcon('/mActionHelpContents.svg') self.action_help = QAction(help_icon, 'Help', self.iface.mainWindow()) self.action_help.setWhatsThis(QCoreApplication.translate('MetaSearch', 'MetaSearch plugin help')) self.action_help.setStatusTip(QCoreApplication.translate('MetaSearch', 'Get Help on MetaSearch')) self.action_help.triggered.connect(self.help) self.iface.addPluginToWebMenu(self.web_menu, self.action_help) # prefab the dialog but not open it yet self.dialog = MetaSearchDialog(self.iface) def unload(self): """teardown""" # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_run) self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.iface.removeWebToolBarIcon(self.action_run) def run(self): """open MetaSearch""" self.dialog.exec_() def help(self): """open help in user's default web browser""" open_url(get_help_url())
class VoGISProfilToolMainDialog(QDialog): def __init__(self, interface, settings): QDialog.__init__(self, interface.mainWindow()) # Set up the user interface from Designer. self.ui = Ui_VoGISProfilToolMain() self.ui.setupUi(self) self.ui.buttonBox.button(QDialogButtonBox.Ok).setText(QApplication.translate("code", "Profil erstellen")) self.ui.buttonBox.button(QDialogButtonBox.Cancel).setText(QApplication.translate("code", "Schließen")) self.ui.grpCadastre.toggled.connect(self._toggleCadastreLayer) self.ui.cmbCadastreLayer.currentIndexChanged.connect(self._updateCadastreLayer) self.settings = settings self.iface = interface self.selectingVisibleRasters = False self.thread = None if self.settings.onlyHektoMode is True: self.ui.IDC_widRaster.hide() self.adjustSize() self.ui.IDC_dblspinDistance.setValue(self.settings.equiDistance) self.ui.IDC_dblspinVertexCnt.setValue(self.settings.vertexCnt) validator = QIntValidator(-32768, 32768, self) self.ui.IDC_tbNoDataExport.setValidator(validator) self.ui.IDC_tbFromX.setText("-30000") self.ui.IDC_tbFromY.setText("240000") self.ui.IDC_tbToX.setText("-20000") self.ui.IDC_tbToY.setText("230000") self.__addRastersToGui() self.__addPolygonsToGui() for line_lyr in self.settings.mapData.lines.lines(): self.ui.IDC_cbLineLayers.addItem(line_lyr.name, line_lyr) if self.settings.mapData.lines.count() < 1: self.ui.IDC_rbDigi.setChecked(True) self.ui.IDC_rbShapeLine.setEnabled(False) #Einstellungen fuer Linie zeichen self.action = QAction( QIcon(":/plugins/vogisprofiltoolmain/icons/icon.png"), "VoGIS-Profiltool", self.iface.mainWindow()) self.action.setWhatsThis("VoGIS-Profiltool") self.canvas = self.iface.mapCanvas() self.tool = ProfiletoolMapTool(self.canvas, self.action) self.savedTool = self.canvas.mapTool() self.polygon = False self.rubberband = QgsRubberBand(self.canvas, self.polygon) self.rubberband.setLineStyle(Qt.SolidLine) self.rubberband.setWidth(4.0) self.rubberband.setColor(QColor(0, 255, 0)) #http://www.qgis.org/api/classQgsRubberBand.html#a6f7cdabfcf69b65dfc6c164ce2d01fab self.pointsToDraw = [] self.dblclktemp = None self.drawnLine = None def accept(self): try: nodata = self.ui.IDC_tbNoDataExport.text() self.settings.nodata_value = int(nodata) if nodata != "" else None QgsMessageLog.logMessage("Maindlg: nodata: {0}".format(self.settings.nodata_value), "VoGis", Qgis.Info) if self.settings.onlyHektoMode is True and self.settings.mapData.rasters.count() > 0: self.settings.onlyHektoMode = False if self.settings.onlyHektoMode is False: if self.settings.mapData.rasters.count() < 1: retVal = QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Keine Rasterebene vorhanden oder sichtbar! Nur hektometrieren?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if retVal == QMessageBox.No: return else: self.settings.onlyHektoMode = True self.settings.createHekto = True if self.__getSettingsFromGui() is False: return if self.settings.onlyHektoMode is False: if len(self.settings.mapData.rasters.selectedRasters()) < 1: QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Kein Raster selektiert!")) return QgsMessageLog.logMessage("modeLine!=line: {0}".format(self.settings.modeLine != enumModeLine.line), "VoGis", Qgis.Info) QgsMessageLog.logMessage("customLine is None: {0}".format(self.settings.mapData.customLine is None), "VoGis", Qgis.Info) if self.settings.modeLine != enumModeLine.line and self.settings.mapData.customLine is None: QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Keine Profillinie vorhanden!")) return if len(self.settings.mapData.polygons.selected_polygons()) > 0 and len(self.settings.mapData.rasters.selectedRasters()) > 1: raster_names = list(raster.name for raster in self.settings.mapData.rasters.selectedRasters()) sel_raster, ok_clicked = QInputDialog.getItem( self.iface.mainWindow(), "DHM?", "Welches DHM soll zur Flächenverschneidung verwendet werden?", raster_names, 0, False ) if ok_clicked is False: return self.settings.intersection_dhm_idx = raster_names.index(sel_raster) QApplication.setOverrideCursor(Qt.WaitCursor) create_profile = CreateProfile(self.iface, self.settings) thread = QThread(self) create_profile.moveToThread(thread) create_profile.finished.connect(self.profiles_finished) create_profile.error.connect(self.profiles_error) create_profile.progress.connect(self.profiles_progress) thread.started.connect(create_profile.create) thread.start(QThread.LowestPriority) self.thread = thread self.create_profile = create_profile self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) except: QApplication.restoreOverrideCursor() ex = "{0}".format(traceback.format_exc()) msg = "Unexpected ERROR:\n\n{0}".format(ex[:2000]) QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", msg) def profiles_finished(self, profiles, intersections, cadastre): QApplication.restoreOverrideCursor() self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) self.thread.quit() self.thread.wait() #QGIS 2.0 http://gis.stackexchange.com/a/58754 http://gis.stackexchange.com/a/57090 self.iface.mainWindow().statusBar().showMessage("VoGIS-Profiltool, {0} Profile".format(len(profiles))) QgsMessageLog.logMessage("Profile Count: {0}".format(len(profiles)), "VoGis", Qgis.Info) if len(profiles) < 1: QApplication.restoreOverrideCursor() QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Es konnten keine Profile erstellt werden.")) return dlg = VoGISProfilToolPlotDialog(self.iface, self.settings, profiles, intersections, cadastre) dlg.show() dlg.exec_() def profiles_error(self, exception_string): QApplication.restoreOverrideCursor() QgsMessageLog.logMessage("Error during profile creation: {0}".format(exception_string), "VoGis", Qgis.Critical) QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", exception_string) def profiles_progress(self, msg): self.iface.mainWindow().statusBar().showMessage(msg) self.ui.IDC_lblCreateStatus.setText(msg) QApplication.processEvents() def reject(self): if not self.thread is None: if self.thread.isRunning(): self.create_profile.abort() return self.rubberband.reset(self.polygon) QDialog.reject(self) def selectVisibleRasters(self): self.refreshRasterList() self.selectingVisibleRasters = True extCanvas = self.iface.mapCanvas().extent() #alle raster in den einstellunge deselektieren for r in self.settings.mapData.rasters.rasters(): r.selected = False #alle raster in der ListView deselektieren for idx in range(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) item.setCheckState(Qt.Unchecked) #Raster im Extent selektieren canvasCrs = self.iface.mapCanvas().mapSettings().destinationCrs() for idx in range(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) raster = item.data(Qt.UserRole) for r in self.settings.mapData.rasters.rasters(): layerCrs = r.grid.crs() ct = QgsCoordinateTransform(layerCrs, canvasCrs, QgsProject.instance()) extent = ct.transform(r.grid.extent()) if extCanvas.intersects(extent): if r.id == raster.id: r.selected = True item.setCheckState(Qt.Checked) self.selectingVisibleRasters = False def lineLayerChanged(self, idx): if self.ui.IDC_rbShapeLine.isChecked() is False: self.ui.IDC_rbShapeLine.setChecked(True) lineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex())) lyr = lineLyr.line if hasattr(lyr, "selectedFeatureCount"): if(lyr.selectedFeatureCount() < 1): self.ui.IDC_chkOnlySelectedFeatures.setChecked(False) else: self.ui.IDC_chkOnlySelectedFeatures.setChecked(True) def valueChangedEquiDistance(self, val): if self.ui.IDC_rbEquiDistance.isChecked() is False: self.ui.IDC_rbEquiDistance.setChecked(True) def valueChangedVertexCount(self, val): if self.ui.IDC_rbVertexCount.isChecked() is False: self.ui.IDC_rbVertexCount.setChecked(True) def lvRasterItemChanged(self, item): if self.selectingVisibleRasters is True: return if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) raster_lyr = item_data self.settings.mapData.rasters.getById(raster_lyr.id).selected = selected def lvPolygonItemChanged(self, item): if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) poly_lyr = item_data self.settings.mapData.polygons.getById(poly_lyr.id).selected = selected def refreshRasterList(self): root = QgsProject.instance().layerTreeRoot() avail_lyrs = root.findLayers() raster_coll = RasterCollection() for lyr in avail_lyrs: if lyr.isVisible(): mapLayer = lyr.layer() lyr_type = mapLayer.type() lyr_name = mapLayer.name() if lyr_type == QgsMapLayer.RasterLayer: if mapLayer.bandCount() < 2: new_raster = Raster(mapLayer.id(), lyr_name, mapLayer) raster_coll.addRaster(new_raster) self.settings.mapData.rasters = raster_coll self.__addRastersToGui() def __addRastersToGui(self): self.ui.IDC_listRasters.clear() check = Qt.Unchecked if self.settings.mapData.rasters.count() == 1: check = Qt.Checked self.settings.mapData.rasters.rasters()[0].selected = True for raster_lyr in self.settings.mapData.rasters.rasters(): item = QListWidgetItem(raster_lyr.name) item.setData(Qt.UserRole, raster_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listRasters.addItem(item) def __addPolygonsToGui(self): self.ui.IDC_listPolygons.clear() self.ui.cmbCadastreLayer.clear() check = Qt.Unchecked for poly_lyr in self.settings.mapData.polygons.polygons(): item = QListWidgetItem(poly_lyr.name) item.setData(Qt.UserRole, poly_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listPolygons.addItem(item) self.ui.cmbCadastreLayer.addItem(poly_lyr.name, poly_lyr.id) def drawLine(self): if self.ui.IDC_rbDigi.isChecked() is False: self.ui.IDC_rbDigi.setChecked(True) self.dblckltemp = None self.rubberband.reset(self.polygon) self.__cleanDigi() self.__activateDigiTool() self.canvas.setMapTool(self.tool) def __createDigiFeature(self, pnts): u = Util(self.iface) f = u.createQgLineFeature(pnts) self.settings.mapData.customLine = f def __lineFinished(self, position): self.showNormal() self.raise_() self.activateWindow() mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) newPoint = QgsPointXY(mapPos.x(), mapPos.y()) self.pointsToDraw.append(newPoint) #launch analyses self.iface.mainWindow().statusBar().showMessage(str(self.pointsToDraw)) if len(self.pointsToDraw) < 2: self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint self.drawnLine = None QMessageBox.warning(self, "VoGIS-Profiltool", QApplication.translate("code", "Profillinie digitalisieren abgebrochen!")) self.drawnLine = self.__createDigiFeature(self.pointsToDraw) self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint def __cleanDigi(self): self.pointsToDraw = [] self.canvas.unsetMapTool(self.tool) self.canvas.setMapTool(self.savedTool) def __activateDigiTool(self): self.tool.moved.connect(self.__moved) self.tool.rightClicked.connect(self.__rightClicked) self.tool.leftClicked.connect(self.__leftClicked) self.tool.doubleClicked.connect(self.__doubleClicked) self.tool.deactivated.connect(self.__deactivateDigiTool) def __deactivateDigiTool(self): # TODO: how to check if not connected??? try: self.tool.moved.disconnect(self.__moved) except: pass try: self.tool.leftClicked.disconnect(self.__leftClicked) except: pass try: self.tool.rightClicked.disconnect(self.__rightClicked) except: pass try: self.tool.doubleClicked.disconnect(self.__doubleClicked) except: pass try: self.iface.mainWindow().statusBar().showMessage("") except: pass def __moved(self, position): if len(self.pointsToDraw) > 0: mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) self.rubberband.reset(self.polygon) newPnt = QgsPointXY(mapPos.x(), mapPos.y()) pnts = self.pointsToDraw + [newPnt] self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(pnts), None) def __rightClicked(self, position): self.__lineFinished(position) def __leftClicked(self, position): mapPos = self.canvas.getCoordinateTransform().toMapCoordinates(position["x"], position["y"]) newPoint = QgsPointXY(mapPos.x(), mapPos.y()) if newPoint == self.dblclktemp: self.dblclktemp = None return else: if len(self.pointsToDraw) == 0: self.rubberband.reset(self.polygon) self.pointsToDraw.append(newPoint) def __doubleClicked(self, position): pass #not in use right now def __lineCancel(self): pass def __getSettingsFromGui(self): self.settings.linesExplode = (self.ui.IDC_chkLinesExplode.checkState() == Qt.Checked) self.settings.linesMerge = (self.ui.IDC_chkLinesMerge.checkState() == Qt.Checked) self.settings.onlySelectedFeatures = (self.ui.IDC_chkOnlySelectedFeatures.checkState() == Qt.Checked) self.settings.equiDistance = self.ui.IDC_dblspinDistance.value() self.settings.vertexCnt = self.ui.IDC_dblspinVertexCnt.value() #self.settings.createHekto = (self.ui.IDC_chkCreateHekto.checkState() == Qt.Checked) self.settings.nodesAndVertices = (self.ui.IDC_chkNodesAndVertices.checkState() == Qt.Checked) self.settings.mapData.selectedLineLyr = (self.ui.IDC_cbLineLayers.itemData(self.ui.IDC_cbLineLayers.currentIndex())) if self.settings.onlySelectedFeatures is True and self.settings.mapData.selectedLineLyr.line.selectedFeatureCount() < 1: QMessageBox.warning(self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", u"Der gewählte Layer hat keine selektierten Elemente.")) return False if self.ui.IDC_rbDigi.isChecked(): self.settings.modeLine = enumModeLine.customLine elif self.ui.IDC_rbShapeLine.isChecked(): self.settings.modeLine = enumModeLine.line else: #self.ui.IDC_rbStraigthLine self.settings.modeLine = enumModeLine.straightLine if self.ui.IDC_rbEquiDistance.isChecked(): self.settings.modeVertices = enumModeVertices.equiDistant else: self.settings.modeVertices = enumModeVertices.vertexCnt if self.ui.IDC_rbStraigthLine.isChecked(): ut = Util(self.iface) if ut.isFloat(self.ui.IDC_tbFromX.text(), QApplication.translate("code", "Rechtswert von")) is False: return False else: fromX = float(self.ui.IDC_tbFromX.text()) if ut.isFloat(self.ui.IDC_tbFromY.text(), QApplication.translate("code", "Hochwert von")) is False: return False else: fromY = float(self.ui.IDC_tbFromY.text()) if ut.isFloat(self.ui.IDC_tbToX.text(), QApplication.translate("code", "Rechtswert nach")) is False: return False else: toX = float(self.ui.IDC_tbToX.text()) if ut.isFloat(self.ui.IDC_tbToY.text(), QApplication.translate("code", "Hochwert nach")) is False: return False else: toY = float(self.ui.IDC_tbToY.text()) fromPnt = QgsPointXY(fromX, fromY) toPnt = QgsPointXY(toX, toY) self.settings.mapData.customLine = ut.createQgLineFeature([fromPnt, toPnt]) return True def _toggleCadastreLayer(self, toggled): if toggled: layerId = self.ui.cmbCadastreLayer.itemData(self.ui.cmbCadastreLayer.currentIndex()) self.settings.mapData.cadastre = layerId else: self.settings.mapData.cadastre = None def _updateCadastreLayer(self, index): if self.ui.grpCadastre.isChecked(): layerId = self.ui.cmbCadastreLayer.itemData(index) self.settings.mapData.cadastre = layerId
class PostNAS_Search: def __init__(self, iface): # 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','PostNAS_Search_{}.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 = PostNAS_SearchDialog(iface=self.iface) self.conf = PostNAS_ConfDialog(iface=self.iface) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&PostNAS_Search') self.searchDockWidget = None self.searchDockWidgetArea = Qt.LeftDockWidgetArea # noinspection PyMethodMayBeStatic def tr(self, message): # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('PostNAS_Search', message) def initGui(self): # Create Conf-Action and Menuentry self.confAction = QAction("Einstellungen", self.iface.mainWindow()) self.confAction.setWhatsThis("Konfiguration der PostNAS-Suche") self.confAction.setStatusTip("Konfiguration der PostNAS-Suche") self.confAction.triggered.connect(self.showConf) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.confAction) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.confAction) self.toggleSearchAction = QAction(u"Flurstücksuche", self.iface.mainWindow()) self.toggleSearchAction.setWhatsThis(u"Starten/Schliessen der Flurstücksuche") self.toggleSearchAction.setStatusTip(u"Starten/Schliessen der Flurstücksuche") self.toggleSearchAction.triggered.connect(self.toggleWidget) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.toggleSearchAction) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.toggleSearchAction) self.fulltextindex = QAction(u"Volltextindex erstellen", self.iface.mainWindow()) self.fulltextindex.setWhatsThis(u"Erzeugt einen Volltextindex in der Datenbank um die Suche zu beschleunigen") self.fulltextindex.setStatusTip(u"Erzeugt einen Volltextindex in der Datenbank um die Suche zu beschleunigen") self.fulltextindex.triggered.connect(self.createFulltextindex) if hasattr(self.iface, "addPluginToDatabaseMenu"): self.iface.addPluginToDatabaseMenu("&PostNAS-Suche", self.fulltextindex) else: self.iface.addPluginToMenu("&PostNAS-Suche", self.fulltextindex) # Create action that will start plugin configuration self.action = QAction(QIcon(":/plugins/PostNAS_Search/search_24x24.png"),u"Flurstücksuche", self.iface.mainWindow()) self.action.setCheckable(True) # connect the action to the run method self.action.triggered.connect(self.toggleWidget) # Add toolbar button and menu item self.iface.addToolBarIcon(self.action) def toggleWidget(self, event): if self.searchDockWidget == None: self.searchDockWidget = QDockWidget(self.iface.mainWindow()) self.searchDockWidget.setWindowTitle(self.tr(u'Suche')) self.searchDockWidget.setWidget(self.dlg) self.searchDockWidget.closeEvent = self.toggleWidget self.iface.addDockWidget(self.searchDockWidgetArea, self.searchDockWidget) self.action.setChecked(True) else: self.searchDockWidgetArea = self.iface.mainWindow().dockWidgetArea(self.searchDockWidget) self.iface.removeDockWidget(self.searchDockWidget) self.searchDockWidget = None self.action.setChecked(False) def showConf(self): dlg = PostNAS_ConfDialog(self) dlg.exec_() def createFulltextindex(self): dlg = PostNAS_CreateFulltextindex(self) dlg.exec_() def unload(self): # Remove the Toolbar Icon self.iface.removeToolBarIcon(self.action) # Remove DockWidget if self.searchDockWidget != None: self.iface.removeDockWidget(self.searchDockWidget) if hasattr(self.iface, "removePluginDatabaseMenu"): self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.confAction) self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.toggleSearchAction) self.iface.removePluginDatabaseMenu("&PostNAS-Suche", self.fulltextindex) else: self.iface.removePluginMenu("&PostNAS-Suche", self.confAction) self.iface.removePluginMenu("&PostNAS-Suche", self.toggleSearchAction) self.iface.removePluginMenu("&PostNAS-Suche", self.fulltextindex) if self.confAction: self.confAction.deleteLater() self.confAction = None if self.toggleSearchAction: self.toggleSearchAction.deleteLater() self.toggleSearchAction = None if self.fulltextindex: self.fulltextindex.deleteLater() self.fulltextindex = None
class BoundlessConnectPlugin(object): def __init__(self, iface): self.iface = iface try: from boundlessconnect.tests import testerplugin from qgistester.tests import addTestModule addTestModule(testerplugin, 'Boundless Connect') except Exception as e: pass self.dockWidget = None readSettings() self.iface.initializationCompleted.connect(self.checkFirstRun) def initGui(self): self.dockWidget = getConnectDockWidget() self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dockWidget) self.dockWidget.hide() utils.setRepositoryUrl() self.actionRunWizard = self.dockWidget.toggleViewAction() self.actionRunWizard.setText('Boundless Connect') self.actionRunWizard.setIcon( QIcon(os.path.join(pluginPath, 'icons', 'connect.svg'))) self.actionRunWizard.setWhatsThis('Boundless Connect') self.actionRunWizard.setObjectName('actionRunWizard') # If Boundless repository is a directory, add menu entry # to start modified Plugin Manager which works with local repositories if utils.isRepositoryInDirectory(): self.actionPluginManager = QAction( 'Manage plugins (local folder)', self.iface.mainWindow()) self.actionPluginManager.setIcon( QIcon(os.path.join(pluginPath, 'icons', 'plugin.svg'))) self.actionPluginManager.setWhatsThis( 'Manage and install plugins from local repository') self.actionPluginManager.setObjectName('actionPluginManager') self.iface.addPluginToMenu( 'Boundless Connect', self.actionPluginManager) self.actionPluginManager.triggered.connect(self.pluginManagerLocal) actions = self.iface.mainWindow().menuBar().actions() for action in actions: if action.menu().objectName() == 'mPluginMenu': menuPlugin = action.menu() separator = menuPlugin.actions()[1] menuPlugin.insertAction(separator, self.actionRunWizard) if utils.isRepositoryInDirectory(): menuPlugin.insertAction(separator, self.actionPluginManager) addSettingsMenu('Boundless Connect') addHelpMenu('Boundless Connect') addAboutMenu('Boundless Connect') # Enable check for updates if it is not enabled utils.addCheckForUpdates() try: from lessons import addLessonsFolder, addGroup folder = os.path.join(os.path.dirname(__file__), "_lessons") addLessonsFolder(folder, "boundlessconnect") group_description = os.path.join(folder, "group.md") addGroup("Boundless Connect plugin", group_description) except: pass def unload(self): actions = self.iface.mainWindow().menuBar().actions() for action in actions: if action.menu().objectName() == 'mPluginMenu': menuPlugin = action.menu() menuPlugin.removeAction(self.actionRunWizard) if utils.isRepositoryInDirectory(): menuPlugin.removeAction(self.actionPluginManager) removeSettingsMenu('Boundless Connect') removeHelpMenu('Boundless Connect') removeAboutMenu('Boundless Connect') self.dockWidget.hide() try: from boundlessconnect.tests import testerplugin from qgistester.tests import removeTestModule removeTestModule(testerplugin, 'Boundless Connect') except Exception as e: pass try: from lessons import removeLessonsFolder folder = os.path.join(pluginPath, '_lessons') removeLessonsFolder(folder) except: pass def checkFirstRun(self): settings = QSettings() firstRun = settings.value('boundlessconnect/firstRun', True, bool) settings.setValue('boundlessconnect/firstRun', False) if self.dockWidget is None: self.dockWidget = getConnectDockWidget() if firstRun: self.dockWidget.show() utils.installFromStandardPath() def installPlugin(self): fileName = askForFiles(self.iface.mainWindow(), 'Open file', exts='zip') if fileName is None: return result = utils.installFromZipFile(fileName) if result is None: self._showMessage('Plugin installed successfully', QgsMessageBar.SUCCESS) else: self._showMessage(result, QgsMessageBar.WARNING) settings.setValue('lastPluginDirectory', QFileInfo(fileName).absoluteDir().absolutePath()) def pluginManagerLocal(self): utils.showPluginManager(False) def _showMessage(self, message, level=QgsMessageBar.INFO): self.iface.messageBar().pushMessage( message, level, self.iface.messageTimeout())
class XYZHubConnector(object): """base plugin""" def __init__(self, iface): """init""" import sys print(sys.version) self.iface = iface self.web_menu = "&XYZ Hub Connector" self.init_modules() self.obj = self def initGui(self): """startup""" parent = self.iface.mainWindow() ######## action, button icon = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/xyz.png")) icon_bbox = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/bbox.svg")) self.action_connect = QAction(icon, "New XYZ Hub Connection", parent) self.action_connect.setWhatsThis( QCoreApplication.translate(PLUGIN_NAME, "WhatsThis message")) self.action_connect.setStatusTip( QCoreApplication.translate(PLUGIN_NAME, "status tip message")) self.action_clear_cache = QAction("Clear cache", parent) self.action_upload = QAction("Upload to New XYZ Geospace", parent) self.action_basemap = QAction("Add HERE Map Tile", parent) self.action_magic_sync = QAction("Magic Sync (EXPERIMENTAL)", parent) self.action_manage = QAction("Manage XYZ Geospace (EXPERIMENTAL)", parent) self.action_edit = QAction("Edit/Delete XYZ Geospace (EXPERIMENTAL)", parent) if self.iface.activeLayer() is None: # self.action_upload.setEnabled(False) self.action_edit.setEnabled(False) self.action_magic_sync.setEnabled(False) # self.action_magic_sync.setVisible(False) # disable magic sync ######## CONNECT action, button self.action_connect.triggered.connect(self.open_connection_dialog) self.action_manage.triggered.connect(self.open_manage_dialog) self.action_edit.triggered.connect(self.open_edit_dialog) self.action_upload.triggered.connect(self.open_upload_dialog) self.action_magic_sync.triggered.connect(self.open_magic_sync_dialog) self.action_clear_cache.triggered.connect(self.open_clear_cache_dialog) self.action_basemap.triggered.connect(self.open_basemap_dialog) ######## Add the toolbar + button self.toolbar = self.iface.addToolBar(PLUGIN_NAME) self.toolbar.setObjectName("XYZ Hub Connector") tool_btn = QToolButton(self.toolbar) self.actions = [ self.action_connect, self.action_upload, self.action_basemap, self.action_clear_cache ] # , self.action_magic_sync, self.action_manage, self.action_edit for a in self.actions: tool_btn.addAction(a) self.iface.addPluginToWebMenu(self.web_menu, a) tool_btn.setDefaultAction(self.action_connect) tool_btn.setPopupMode(tool_btn.MenuButtonPopup) self.xyz_widget_action = self.toolbar.addWidget(tool_btn) self.action_help = None self.action_reload = QAction(icon_bbox, "Reload BBox", parent) self.action_reload.triggered.connect(self.layer_reload_bbox) self.action_reload.setVisible(False) # disable self.toolbar.addAction(self.action_reload) progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(0) progress.reset() progress.hide() # progress = self.iface.statusBarIface().children()[2] # will be hidden by qgis self.iface.statusBarIface().addPermanentWidget(progress) self.pb = progress def init_modules(self): # util.init_module() # parent = self.iface.mainWindow() parent = QgsProject.instance() ######## Init xyz modules self.map_basemap_meta = basemap.load_default_xml() self.auth_manager = AuthManager(config.PLUGIN_DIR + "/auth.ini") self.token_model = GroupTokenModel(parent) # self.layer = LayerManager(parent, self.iface) self.network = NetManager(parent) self.con_man = ControllerManager() self.layer_man = LayerManager() ######## data flow self.conn_info = SpaceConnectionInfo() ######## token print(config.PLUGIN_DIR) self.token_model.load_ini(config.PLUGIN_DIR + "/token.ini") ######## CALLBACK # self.iface.mapCanvas().extentsChanged.connect( self.debug_reload) # self.con_man.connect_ux( self.iface) # canvas ux # self.con_man.signal.canvas_span.connect( self.loader_reload_bbox) self.con_man.ld_pool.signal.progress.connect( self.cb_progress_busy) #, Qt.QueuedConnection self.con_man.ld_pool.signal.finished.connect(self.cb_progress_done) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.layer_man.remove) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.con_man.remove) # self.iface.currentLayerChanged.connect( self.cb_layer_selected) # UNCOMMENT if DEBUG: QgsApplication.messageLog().messageReceived.connect(print_qgis) def unload_modules(self): # self.con_man.disconnect_ux( self.iface) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.layer_man.remove) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.con_man.remove) # utils.disconnect_silent(self.iface.currentLayerChanged) # self.con_man.unload() # del self.con_man # self.iface.mapCanvas().extentsChanged.disconnect( self.debug_reload) close_print_qgis() pass def unload(self): """teardown""" self.unload_modules() # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.toolbar.clear( ) # remove action from custom toolbar (toolbar still exist) self.toolbar.deleteLater() for a in self.actions: self.iface.removePluginWebMenu(self.web_menu, a) ############### # Callback ############### def cb_layer_selected(self, qlayer): flag_xyz = True if qlayer is not None and self.layer.is_xyz_supported_layer( qlayer) else False # disable magic sync # self.action_magic_sync.setEnabled(flag_xyz) flag_layer = True self.action_upload.setEnabled(flag_layer) self.action_edit.setEnabled(flag_layer) ############### # Callback of action (main function) ############### def cb_success_msg(self, msg, info=""): self.iface.messageBar().pushMessage(msg, info, Qgis.Success, 1) def make_cb_success(self, msg, info=""): def _cb_success_msg(): txt = info self.cb_success_msg(msg, txt) return _cb_success_msg def cb_handle_error_msg(self, e): err = parse_exception_obj(e) if isinstance(err, ChainInterrupt): e0, idx = err.args[0:2] if isinstance(e0, net_handler.NetworkError): ok = self.show_net_err_dialog(e0) if ok: return elif isinstance(e0, loader.EmptyXYZSpaceError): ret = exec_warning_dialog( "Warning", "Requested query returns no features") self.show_err_msgbar(err) def show_net_err_dialog(self, err): assert isinstance(err, net_handler.NetworkError) reply_tag, status, reason, body = err.args[:4] if reply_tag in ["count"]: # too many error return 0 msg = ("%s: %s\n" % (status, reason) + "There was a problem connecting to the server") if status == 403: msg += "\n\n" + "Please make sure that the token has WRITE permission" ret = exec_warning_dialog("Network Error", msg, body) return 1 def show_err_msgbar(self, err): self.iface.messageBar().pushMessage(TAG_PLUGIN, repr(err), Qgis.Warning, 5) msg = format_traceback(err) QgsMessageLog.logMessage(msg, TAG_PLUGIN, Qgis.Warning) def cb_progress_busy(self, n_active): if n_active > 1: return self.flag_pb_show = True self.cb_progress_refresh() def cb_progress_done(self): self.flag_pb_show = False self.cb_progress_refresh() def cb_progress_refresh(self): if not hasattr(self, "flag_pb_show"): return pb = self.pb if self.flag_pb_show: pb.show() print_qgis("show", pb) else: pb.hide() print_qgis("hide") ############### # Action (main function) ############### def load_bbox(self, con, args): bbox = bbox_utils.extend_to_bbox( bbox_utils.get_bounding_box(self.iface)) a, kw = parse_qt_args(args) kw["bbox"] = bbox kw["limit"] = 1000 con.start(*a, **kw) def layer_reload_bbox(self): con_bbox_reload = ReloadLayerController_bbox(self.network) self.con_man.add(con_bbox_reload) # con_bbox_reload.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_bbox_reload.signal.finished.connect( self.make_cb_success("Bounding box loading finish")) con_bbox_reload.signal.error.connect(self.cb_handle_error_msg) # TODO: set/get params from vlayer layer_id = self.iface.activeLayer().id() layer = self.layer_man.get(layer_id) self.load_bbox(con_bbox_reload, make_qt_args(layer)) # UNUSED def debug_reload(self): print("debug_reload") def refresh_canvas(self): self.iface.mapCanvas().refresh() # assert False # debug unload module def previous_canvas_extent(self): self.iface.mapCanvas().zoomToPreviousExtent() def open_clear_cache_dialog(self): parent = self.iface.mainWindow() dialog = ConfirmDialog( parent, "Delete cache will make loaded layer unusable !!") ret = dialog.exec_() if ret != dialog.Ok: return utils.clear_cache() def open_connection_dialog(self): parent = self.iface.mainWindow() dialog = ConnectManageSpaceDialog(parent) dialog.config(self.token_model, self.conn_info) ############ edit btn con = EditSpaceController(self.network) self.con_man.add(con) con.signal.finished.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) dialog.signal_edit_space.connect(con.start_args) ############ delete btn con = DeleteSpaceController(self.network) self.con_man.add(con) con.signal.results.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) dialog.signal_del_space.connect(con.start_args) ############ Use Token btn con = LoadSpaceController(self.network) self.con_man.add(con) con.signal.results.connect(make_fun_args(dialog.cb_display_spaces)) con.signal.error.connect(self.cb_handle_error_msg) con.signal.error.connect(lambda e: dialog.cb_enable_token_ui()) con.signal.finished.connect(dialog.cb_enable_token_ui) dialog.signal_use_token.connect(con.start_args) ############ get statisitics con = StatSpaceController(self.network) self.con_man.add(con) con.signal.results.connect(make_fun_args( dialog.cb_display_space_count)) con.signal.error.connect(self.cb_handle_error_msg) dialog.signal_space_count.connect(con.start_args) ############ TODO: bbox btn ############ connect btn con_load = loader.ReloadLayerController(self.network, n_parallel=2) self.con_man.add(con_load) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.finished.connect( self.make_cb_success("Loading finish")) con_load.signal.error.connect(self.cb_handle_error_msg) dialog.signal_space_connect.connect(con_load.start_args) # con.signal.results.connect( self.layer_man.add_args) # IMPORTANT dialog.exec_() # self.startTime = time.time() def open_manage_dialog(self): pass def open_edit_dialog(self): pass def open_upload_dialog(self): vlayer = self.iface.activeLayer() parent = self.iface.mainWindow() dialog = UploadNewSpaceDialog(parent) dialog.config(self.token_model, self.network, vlayer) ############ Use Token btn con = LoadSpaceController(self.network) self.con_man.add(con) con.signal.results.connect(make_fun_args( dialog.cb_set_valid_token)) # finished signal !? con.signal.error.connect(self.cb_handle_error_msg) con.signal.finished.connect(dialog.cb_enable_token_ui) dialog.signal_use_token.connect(con.start_args) con_upload = UploadLayerController(self.network, n_parallel=2) self.con_man.add(con_upload) con_upload.signal.finished.connect( self.make_cb_success("Uploading finish")) con_upload.signal.error.connect(self.cb_handle_error_msg) con = InitUploadLayerController(self.network) self.con_man.add(con) dialog.signal_upload_new_space.connect(con.start_args) con.signal.results.connect(con_upload.start_args) con.signal.error.connect(self.cb_handle_error_msg) dialog.exec_() def open_magic_sync_dialog(self): pass def open_basemap_dialog(self): parent = self.iface.mainWindow() auth = self.auth_manager.get_auth() dialog = BaseMapDialog(parent) dialog.config(self.map_basemap_meta, auth) dialog.signal_add_basemap.connect(self.add_basemap_layer) dialog.exec_() def add_basemap_layer(self, args): a, kw = parse_qt_args(args) meta, app_id, app_code = a self.auth_manager.save(app_id, app_code) basemap.add_basemap_layer(meta, app_id, app_code)
class PdokServicesPlugin(object): def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # docked or dialog, defaults to dialog # 2018 may: RD: deprecating Docked window, as the content is getting to big anyway # if isinstance(QSettings().value("/pdokservicesplugin/docked"), QVariant): # self.docked = QSettings().value("/pdokservicesplugin/docked", QVariant(False)) # else: # self.docked = QSettings().value("/pdokservicesplugin/docked", False) # # # Create the dialog and keep reference # if "True" == self.docked or "true" == self.docked or True is self.docked: # self.dlg = PdokServicesPluginDockWidget() # self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dlg) # else: # self.dlg = PdokServicesPluginDialog(parent=self.iface.mainWindow()) self.dlg = PdokServicesPluginDialog(parent=self.iface.mainWindow()) # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDatabaseFilePath()).path() + "/python/plugins/pdokservicesplugin" # initialize locale localePath = "" if isinstance(QSettings().value("locale/userLocale"), QVariant): locale = QSettings().value("locale/userLocale").value()[0:2] else: locale = QSettings().value("locale/userLocale")[0:2] if QFileInfo(self.plugin_dir).exists(): localePath = self.plugin_dir + "/i18n/pdokservicesplugin_" + locale + ".qm" if QFileInfo(localePath).exists(): self.translator = QTranslator() self.translator.load(localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.currentLayer = None self.SETTINGS_SECTION = '/pdokservicesplugin/' self.pointer = None self.pdokgeocoder = PDOKGeoLocator(self.iface) self.geocoderSourceModel = None def getSettingsValue(self, key, default=''): if QSettings().contains(self.SETTINGS_SECTION + key): key = self.SETTINGS_SECTION + key if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 return str(QSettings().value(key).toString()) else: return str(QSettings().value(key)) else: return default def setSettingsValue(self, key, value): key = self.SETTINGS_SECTION + key if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 QSettings().setValue(key, QVariant(value)) else: QSettings().setValue(key, value) def initGui(self): # Create action that will start plugin configuration self.run_action = QAction(QIcon(":/plugins/pdokservicesplugin/icon.png"), \ u"Pdok Services Plugin", self.iface.mainWindow()) self.servicesLoaded = False # connect the action to the run method # 2018 may: RD: deprecating Docked window, as the content is getting to big anyway # if "True" == self.docked or "true" == self.docked or True == self.docked: # self.run_action.triggered.connect(self.showAndRaise) # self.dlg.radioDocked.setChecked(True) # # docked the dialog is immidiately visible, so should run NOW # else: # self.run_action.triggered.connect(self.run) # self.dlg.radioDocked.setChecked(False) # self.setupfq() self.run_action.triggered.connect(self.run) #self.dlg.radioDocked.setChecked(False) self.setupfq() # Add toolbar button and menu item #self.iface.addToolBarIcon(self.action) self.toolbar = self.iface.addToolBar("PDOK services plugin") self.toolbar.setObjectName("PDOK services plugin") self.toolbar.addAction(self.run_action) self.toolbarSearch = QLineEdit() self.toolbarSearch.setMaximumWidth(200) self.toolbarSearch.setAlignment(Qt.AlignLeft) self.toolbarSearch.setPlaceholderText("PDOK Locatieserver zoek") self.toolbar.addWidget(self.toolbarSearch) self.toolbarSearch.returnPressed.connect(self.searchAddressFromToolbar) # address/point cleanup self.clean_action = QAction(QIcon(":/plugins/pdokservicesplugin/eraser.png"), \ u"Cleanup", self.eraseAddress()) self.toolbar.addAction(self.clean_action) self.clean_action.triggered.connect(self.eraseAddress) self.iface.addPluginToMenu(u"&Pdok Services Plugin", self.run_action) # about self.aboutAction = QAction(QIcon(":/plugins/pdokservicesplugin/help.png"), \ "About", self.iface.mainWindow()) self.aboutAction.setWhatsThis("Pdok Services Plugin About") self.iface.addPluginToMenu(u"&Pdok Services Plugin", self.aboutAction) self.aboutAction.triggered.connect(self.about) self.dlg.ui.btnLoadLayer.clicked.connect(self.loadService) self.dlg.geocoderSearch.returnPressed.connect(self.searchAddress) self.dlg.geocoderSearch.textEdited.connect(self.searchAddress) self.dlg.geocoderSearch.setPlaceholderText("PDOK Locatieserver zoek, bv postcode of postcode huisnummer") self.dlg.geocoderResultSearch.textChanged.connect(self.filterGeocoderResult) self.dlg.geocoderResultSearch.setPlaceholderText("een of meer zoekwoorden uit resultaat") #self.dlg.radioDocked.toggled.connect(self.set_docked) self.dlg.btnCheckPdokJson.clicked.connect(self.checkPdokJson) #self.iface.mapCanvas().renderStarting.connect(self.extentsChanged) ui = self.dlg.ui cbxs = [ui.cbx_gem, ui.cbx_wpl, ui.cbx_weg, ui.cbx_pcd, ui.cbx_adr, ui.cbx_pcl, ui.cbx_hmp] # connect all fq checkboxes with suggest, so upon a change in fq filter we re-search for cbx in cbxs: cbx.stateChanged.connect(self.searchAddress) self.run(True) # for now hiding the pointer as soon as the extent changes #def extentsChanged(self): # self.removePointer() def checkPdokJson(self): myversion = self.getSettingsValue('pdokversion', '1') msgtxt = '' msglvl = 0 # QgsMessageBar.INFO try: response = urllib.request.urlopen('http://www.qgis.nl/pdok.version') str_response = response.read().decode('utf-8') pdokversion = json.loads(str_response) if pdokversion > int(myversion): response = urllib.request.urlopen('http://www.qgis.nl/pdok.json') str_response = response.read().decode('utf-8') pdokjson = json.loads(str_response) with open(self.plugin_dir +'/pdok.json', 'w') as outfile: json.dump(pdokjson, outfile) msgtxt = "De laatste versie is opgehaald en zal worden gebruikt " + \ str(pdokversion) + ' (was ' + myversion +')' self.servicesLoaded = False # reset reading of json self.run() self.setSettingsValue('pdokversion', pdokversion) else: msgtxt = "Geen nieuwere versie beschikbaar dan " + str(pdokversion) except Exception as e: #print e msgtxt = "Fout bij ophalen van service info. Netwerk probleem?" msglvl = 2 # QgsMessageBar.CRITICAL # msg if hasattr(self.iface, 'messageBar'): self.iface.messageBar().pushMessage("PDOK services update", msgtxt, level=msglvl, duration=10) else: # 1.8 QMessageBox.information(self.iface.mainWindow(), "Pdok Services Plugin", msgtxt) # def set_docked(self, foo): # self.setSettingsValue('docked', self.dlg.radioDocked.isChecked()) # #if Qgis.QGIS_VERSION_INT < 10900: # # # qgis <= 1.8 # # QSettings().setValue("/pdokservicesplugin/docked", QVariant(self.dlg.radioDocked.isChecked())) # #else: # # QSettings().setValue("/pdokservicesplugin/docked", self.dlg.radioDocked.isChecked()) def showAndRaise(self): self.dlg.show() self.dlg.raise_() # also remove the pointer self.removePointer() def about(self): infoString = "Written by Richard Duivenvoorde\nEmail - [email protected]\n" infoString += "Company - Zuidt - http://www.zuidt.nl\n" infoString += "Source: https://github.com/rduivenvoorde/pdokservicesplugin" QMessageBox.information(self.iface.mainWindow(), "Pdok Services Plugin About", infoString) def unload(self): self.removePointer() # Remove the plugin menu item and icon self.iface.removePluginMenu(u"&Pdok Services Plugin",self.run_action) del self.toolbarSearch def showService(self, selectedIndexes): if len(selectedIndexes)==0: self.currentLayer = None self.dlg.ui.layerInfo.setHtml('') self.dlg.ui.comboSelectProj.clear() return # needed to scroll To the selected row incase of using the keyboard / arrows self.dlg.servicesView.scrollTo(self.dlg.servicesView.selectedIndexes()[0]) # itemType holds the data (== column 1) self.currentLayer = self.dlg.servicesView.selectedIndexes()[1].data(Qt.UserRole) if isinstance(self.currentLayer, QVariant): self.currentLayer = self.currentLayer.toMap() # QGIS 1.8: QVariants currentLayer = {} for key in list(self.currentLayer.keys()): val = self.currentLayer[key] currentLayer[str(key)]=str(val.toString()) self.currentLayer = currentLayer url = self.currentLayer['url'] title = self.currentLayer['title'] style = '' if 'style' in self.currentLayer: style = self.currentLayer['style'] title = title + ' [' + style + ']' servicetitle = self.currentLayer['servicetitle'] layername = self.currentLayer['layers'] abstract = self.currentLayer['abstract'] stype = self.currentLayer['type'].upper() minscale ='' if 'minscale' in self.currentLayer and self.currentLayer['minscale'] != None and self.currentLayer['minscale'] != '': minscale = "min. schaal 1:"+self.currentLayer['minscale'] maxscale = '' if 'maxscale' in self.currentLayer and self.currentLayer['maxscale'] != None and self.currentLayer['maxscale'] != '': maxscale = "max. schaal 1:"+self.currentLayer['maxscale'] self.dlg.ui.layerInfo.setText('') self.dlg.ui.btnLoadLayer.setEnabled(True) self.dlg.ui.layerInfo.setHtml('<h4>%s</h4><h3>%s</h3><lu><li>%s</li><li> </li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li></lu>' % (servicetitle, title, abstract, stype, url, layername, style, minscale, maxscale)) self.dlg.ui.comboSelectProj.clear() if stype=="WMS": try: crs = self.currentLayer['crs'] except KeyError: crs = 'EPSG:28992' crs = crs.split(',') self.dlg.ui.comboSelectProj.addItems(crs) for i in range(len(crs)): if crs[i] == 'EPSG:28992': self.dlg.ui.comboSelectProj.setCurrentIndex(i) if stype=="WMTS": tilematrixsets = self.currentLayer['tilematrixsets'].split(',') self.dlg.ui.comboSelectProj.addItems(tilematrixsets) for i in range(len(tilematrixsets)): if tilematrixsets[i].startswith('EPSG:28992'): self.dlg.ui.comboSelectProj.setCurrentIndex(i) def loadService(self): if self.currentLayer == None: return servicetype = self.currentLayer['type'] url = self.currentLayer['url'] # some services have an url with query parameters in it, we have to urlencode those: location,query = urllib.parse.splitquery(url) url = location if query != None and query != '': url +=('?'+urllib.parse.quote_plus(query)) title = self.currentLayer['title'] if 'style' in self.currentLayer: style = self.currentLayer['style'] title = title + ' [' + style + ']' else: style = '' # == default for this service layers = self.currentLayer['layers'] # mmm, tricky: we take the first one while we can actually want png/gif or jpeg if servicetype == "wms": imgformat = self.currentLayer['imgformats'].split(',')[0] if self.dlg.ui.comboSelectProj.currentIndex() == -1: crs = 'EPSG:28992' else: crs = self.dlg.ui.comboSelectProj.currentText() if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 uri = url self.iface.addRasterLayer( uri, # service uri title, # name for layer (as seen in QGIS) "wms", # dataprovider key [layers], # array of layername(s) for provider (id's) [""], # array of stylename(s) NOTE: ignoring styles here!!! imgformat, # image format searchstring crs) # crs code searchstring else: # qgis > 1.8 uri = "crs="+crs+"&layers="+layers+"&styles="+style+"&format="+imgformat+"&url="+url; self.iface.addRasterLayer(uri, title, "wms") elif servicetype == "wmts": if Qgis.QGIS_VERSION_INT < 10900: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ("Sorry, dit type layer: '"+servicetype.upper()+"' \nkan niet worden geladen in deze versie van QGIS.\nMisschien kunt u QGIS 2.0 installeren (die kan het WEL)?\nOf is de laag niet ook beschikbaar als wms of wfs?"), QMessageBox.Ok, QMessageBox.Ok) return if self.dlg.ui.comboSelectProj.currentIndex() == -1: tilematrixset = 'EPSG:28992' else: tilematrixset = self.dlg.ui.comboSelectProj.currentText() imgformat = self.currentLayer['imgformats'].split(',')[0] # special case for luchtfoto #if layers=="luchtfoto": # # tileMatrixSet=nltilingschema&crs=EPSG:28992&layers=luchtfoto&styles=&format=image/jpeg&url=http://geodata1.nationaalgeoregister.nl/luchtfoto/wmts/1.0.0/WMTSCapabilities.xml # # {u'layers': u'luchtfoto', u'imgformats': u'image/jpeg', u'title': u'PDOK-achtergrond luchtfoto', u'url': u'http://geodata1.nationaalgeoregister.nl/luchtfoto/wms', u'abstract': u'', u'tilematrixsets': u'nltilingschema', u'type': u'wmts'} # uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=&format="+imgformat+"&url="+url #else: # uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=&format="+imgformat+"&url="+url; #uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=default&format="+imgformat+"&url="+url; if tilematrixset.startswith('EPSG:'): crs=tilematrixset i = crs.find(':', 5) if i > -1: crs=crs[:i] elif tilematrixset.startswith('OGC:1.0'): crs='EPSG:3857' uri = "tileMatrixSet="+tilematrixset+"&crs="+crs+"&layers="+layers+"&styles=default&format="+imgformat+"&url="+url; #print "############ PDOK URI #################" #print uri self.iface.addRasterLayer(uri, title, "wms") elif servicetype == "wfs": location, query = urllib.parse.splitquery(url) #uri = location+"?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME="+layers+"&SRSNAME=EPSG:28992" #uri = location + "?SERVICE=WFS&REQUEST=GetFeature&TYPENAME=" + layers + "&SRSNAME=EPSG:28992" # adding a bbox paramater forces QGIS to NOT cache features but retrieve new features all the time # QGIS will update the BBOX to the right value #uri += "&BBOX=-10000,310000,290000,650000" uri = " pagingEnabled='true' restrictToRequestBBOX='1' srsname='EPSG:28992' typename='"+layers+"' url='"+url+"' version='2.0.0' " self.iface.addVectorLayer(uri, title, "WFS") elif servicetype == "wcs": # cache=AlwaysCache&crs=EPSG:28992&format=GeoTIFF&identifier=ahn25m:ahn25m&url=http://geodata.nationaalgeoregister.nl/ahn25m/wcs uri = '' # cache=AlwaysCache # cache=PreferNetwork # cache=AlwaysNetwork # cache=AlwaysNetwork&crs=EPSG:28992&format=GeoTIFF&identifier=ahn25m:ahn25m&url=http://geodata.nationaalgeoregister.nl/ahn25m/wcs #uri = "cache=AlwaysNetwork&crs=EPSG:28992&format=image/tiff&version=1.1.1&identifier="+layers+"&url="+url # working for ahn1 ahn2 and ahn3: GEOTIFF_FLOAT32 format = 'GEOTIFF_FLOAT32' # working for ahn25m is only image/tiff if layers=='ahn25m': format = 'image/tiff' # we handcrated some wcs layers with 2 different image formats: tiff (RGB) and tiff (float32): if 'imgformats' in self.currentLayer: format = self.currentLayer['imgformats'].split(',')[0] uri = "cache=AlwaysNetwork&crs=EPSG:28992&format="+format+"&version=1.1.2&identifier=" + layers + "&url=" + url #uri = "cache=AlwaysNetwork&crs=EPSG:28992&format=image/tiff&version=1.1.2&identifier=" + layers + "&url=" + url self.iface.addRasterLayer(uri, title, "wcs") else: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ("Sorry, dit type layer: '"+servicetype.upper()+"' \nkan niet worden geladen door de plugin of door QGIS.\nIs het niet beschikbaar als wms, wmts of wfs?"), QMessageBox.Ok, QMessageBox.Ok) return def filterGeocoderResult(self, string): #print "filtering geocoder results: %s" % string self.dlg.geocoderResultView.selectRow(0) self.geocoderProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.geocoderProxyModel.setFilterFixedString(string) def searchAddressFromToolbar(self): self.removePointer() self.geocoderSourceModel.clear() self.geocode() def searchAddress(self): self.removePointer() #print "search geocoder for: %s" % self.dlg.geocoderSearch.text() self.geocoderSourceModel.clear() #self.geocode(self.dlg.geocoderSearch.text()) self.suggest() def eraseAddress(self): """ clean the input and remove the pointer """ self.removePointer() if self.geocoderSourceModel is not None: self.geocoderSourceModel.clear() if self.dlg.geocoderSearch is not None: self.dlg.geocoderSearch.clear() if self.toolbarSearch is not None: self.toolbarSearch.clear() def filterLayers(self, string): # remove selection if one row is selected self.dlg.servicesView.selectRow(0) #self.currentLayer = None self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxyModel.setFilterFixedString(string) #def addSourceRow(self, service, layer): def addSourceRow(self, serviceLayer): # you can attache different "data's" to to an QStandarditem # default one is the visible one: itemType = QStandardItem("%s" % (serviceLayer["type"].upper()) ) # userrole is a free form one: # only attach the data to the first item # service layer = a dict/object with all props of the layer itemType.setData( serviceLayer, Qt.UserRole ) itemType.setToolTip("%s - %s" % (serviceLayer["type"].upper() ,serviceLayer["title"] )) # only wms services have styles (sometimes) layername = serviceLayer["title"] if 'style' in serviceLayer: itemLayername = QStandardItem("%s [%s]" % (serviceLayer["title"], serviceLayer["style"]) ) layername = "%s [%s]" % (serviceLayer["title"], serviceLayer["style"]) else: itemLayername = QStandardItem("%s" % (serviceLayer["title"])) itemLayername.setToolTip("%s - %s" % (serviceLayer["type"].upper() ,serviceLayer["servicetitle"] )) # itemFilter is the item used to search filter in. That is why layername is a combi of layername + filter here itemFilter = QStandardItem("%s %s %s %s" % (serviceLayer["type"], layername, serviceLayer["servicetitle"], serviceLayer["abstract"]) ) itemServicetitle = QStandardItem("%s" % (serviceLayer["servicetitle"])) itemServicetitle.setToolTip("%s - %s" % (serviceLayer["type"].upper() ,serviceLayer["title"] )) self.sourceModel.appendRow( [ itemLayername, itemType, itemServicetitle, itemFilter ] ) # run method that performs all the real work def run(self, hiddenDialog=False): # enable possible remote pycharm debugging #import pydevd #pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) # last viewed/selected tab if QSettings().contains("/pdokservicesplugin/currenttab"): if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 self.dlg.tabs.widget(QSettings().value("/pdokservicesplugin/currenttab").toInt()[0]) else: self.dlg.tabs.widget(int(QSettings().value("/pdokservicesplugin/currenttab"))) if self.servicesLoaded == False: pdokjson = os.path.join(os.path.dirname(__file__), ".", "pdok.json") f = open(pdokjson, 'r', encoding='utf-8') self.pdok = json.load(f) f.close() self.proxyModel = QSortFilterProxyModel() self.sourceModel = QStandardItemModel() self.proxyModel.setSourceModel(self.sourceModel) # filter == search on itemFilter column: self.proxyModel.setFilterKeyColumn(3) self.dlg.servicesView.setModel(self.proxyModel) self.dlg.servicesView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.geocoderProxyModel = QSortFilterProxyModel() self.geocoderSourceModel = QStandardItemModel() self.geocoderProxyModel.setSourceModel(self.geocoderSourceModel) self.geocoderProxyModel.setFilterKeyColumn(0) self.dlg.geocoderResultView.setModel(self.geocoderProxyModel) self.dlg.geocoderResultView.setEditTriggers(QAbstractItemView.NoEditTriggers) #{"services":[ # {"naam":"WMS NHI","url":"http://geodata.nationaalgeoregister.nl/nhi/ows","layers":["dmlinks","dmnodes"],"type":"wms"}, # {"naam":"WMS NHI","url":"http://geodata.nationaalgeoregister.nl/nhi/ows","layers":["dmlinks","dmnodes"],"type":"wms"} # ]} # for service in self.pdok["services"]: # service[layer] was an array if isinstance(service["layers"], str) or isinstance(service["layers"], str): self.addSourceRow(service) self.dlg.layerSearch.textChanged.connect(self.filterLayers) self.dlg.layerSearch.setPlaceholderText("woord uit laagnaam, type of service ") self.dlg.servicesView.selectionModel().selectionChanged.connect(self.showService) self.dlg.servicesView.doubleClicked.connect(self.loadService) # actually I want to load a service when doubleclicked on header # but as I cannot get this to work, let's disable clicking it then self.dlg.servicesView.verticalHeader().setSectionsClickable(False) self.dlg.servicesView.horizontalHeader().setSectionsClickable(False) #self.dlg.geocoderResultView.doubleClicked.connect(self.zoomToAddress) self.dlg.geocoderResultView.selectionModel().selectionChanged.connect(self.zoomToAddress) # hide itemFilter column: self.dlg.servicesView.hideColumn(3) self.servicesLoaded = True; self.sourceModel.setHeaderData(2, Qt.Horizontal, "Service") self.sourceModel.setHeaderData(1, Qt.Horizontal, "Type") self.sourceModel.setHeaderData(0, Qt.Horizontal, "Laagnaam [style]") self.sourceModel.horizontalHeaderItem(2).setTextAlignment(Qt.AlignLeft) self.sourceModel.horizontalHeaderItem(1).setTextAlignment(Qt.AlignLeft) self.sourceModel.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft) #self.dlg.servicesView.verticalHeader().hide() #self.dlg.servicesView.resizeColumnsToContents() self.dlg.servicesView.setColumnWidth(0, 300) # set name to 300px (there are some huge layernames) self.dlg.servicesView.horizontalHeader().setStretchLastSection(True) # show the dialog ? if not hiddenDialog: self.dlg.show() # Run the dialog event loop #result = self.dlg.exec_() if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 QSettings().setValue("/pdokservicesplugin/currenttab", QVariant(self.dlg.tabs.currentIndex())) else: QSettings().setValue("/pdokservicesplugin/currenttab", self.dlg.tabs.currentIndex()) self.removePointer() def setupfq(self): """ Setup the fq checkboxes in the gui, by looking into the settings for the 'pdokservicesplugin/checkedfqs' key, which contains a list of type strings like ['weg','adres'] """ checked_fqs = self.getSettingsValue('checkedfqs', []) #self.info('setup fq: {}'.format(checked_fqs)) if len(checked_fqs) > 0: # else there is not saved state... take gui defaults self.dlg.ui.cbx_gem.setChecked('gemeente' in checked_fqs) self.dlg.ui.cbx_wpl.setChecked('woonplaats' in checked_fqs) self.dlg.ui.cbx_weg.setChecked('weg' in checked_fqs) self.dlg.ui.cbx_pcd.setChecked('postcode' in checked_fqs) self.dlg.ui.cbx_adr.setChecked('adres' in checked_fqs) self.dlg.ui.cbx_pcl.setChecked('perceel' in checked_fqs) self.dlg.ui.cbx_hmp.setChecked('hectometerpaal' in checked_fqs) def createfq(self): """ This creates a fq-string (Filter Query, see https://github.com/PDOK/locatieserver/wiki/Zoekvoorbeelden-Locatieserver) Based on the checkboxes in the dialog. Defaults to '' Example: 'fq=+type:adres+type:gemeente' (only gemeente AND addresses) :return: """ fqlist = [] if self.dlg.ui.cbx_gem.isChecked(): fqlist.append('gemeente') if self.dlg.ui.cbx_wpl.isChecked(): fqlist.append('woonplaats') if self.dlg.ui.cbx_weg.isChecked(): fqlist.append('weg') if self.dlg.ui.cbx_pcd.isChecked(): fqlist.append('postcode') if self.dlg.ui.cbx_adr.isChecked(): fqlist.append('adres') if self.dlg.ui.cbx_pcl.isChecked(): fqlist.append('perceel') if self.dlg.ui.cbx_hmp.isChecked(): fqlist.append('hectometerpaal') self.setSettingsValue('checkedfqs', fqlist) #self.info(self.getSettingsValue('checkedfqs', ['leeg?'])) fq = '' if len(fqlist) > 0: fq = '&fq=+type:' + '+type:'.join(fqlist) return fq def suggest(self): self.dlg.ui.lookupinfo.setHtml('') search_text = self.dlg.geocoderSearch.text() if len(search_text) <= 1: # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "meer input aub: {}".format(search_text) # ), QMessageBox.Ok, QMessageBox.Ok) return # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "zoeken: {}".format(search_text) # ), QMessageBox.Ok, QMessageBox.Ok) results = self.pdokgeocoder.suggest(search_text, self.createfq()) if len(results) == 0: # ignore, as we are suggesting, maybe more characters will reveal something... return for result in results: #print address adrestekst = QStandardItem("%s" % (result["adrestekst"])) adrestekst.setData(result, Qt.UserRole) type = QStandardItem("%s" % (result["type"])) id = QStandardItem("%s" % (result["id"])) score = QStandardItem("%s" % (result["score"])) adrestekst.setData(result, Qt.UserRole) self.geocoderSourceModel.appendRow([adrestekst, type]) self.geocoderSourceModel.setHeaderData(0, Qt.Horizontal, "Resultaat") self.geocoderSourceModel.setHeaderData(1, Qt.Horizontal, "Type") self.geocoderSourceModel.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft) self.dlg.geocoderResultView.resizeColumnsToContents() self.dlg.geocoderResultView.horizontalHeader().setStretchLastSection(True) def geocode(self): self.dlg.geocoderSearch.setText(self.toolbarSearch.text()) self.suggest() if self.dlg.geocoderResultView.model().rowCount()>0: self.dlg.geocoderResultView.selectRow(0) self.zoomToAddress() else: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ "Niets gevonden.\nProbeer een andere spelling, of alleen postcode/huisnummer?\n\nSelecteer meer (Locatieserver) 'typen' in de PdokServicesPlugin dialoog.\n\nOf gebruik de 'PDOK geocoder'-tab in de PdokServicesPlugin dialoog." ), QMessageBox.Ok, QMessageBox.Ok) # def geocode(self): # self.dlg.ui.lookupinfo.setHtml('') # search_text = self.toolbarSearch.text() # addresses = self.pdokgeocoder.search(search_text) # if len(addresses) == 0: # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "Niets gevonden. Probeer een andere spelling of alleen postcode/huisnummer." # ), QMessageBox.Ok, QMessageBox.Ok) # return # for address in addresses: # #print address # adrestekst = QStandardItem("%s" % (address["adrestekst"])) # adrestekst.setData(address, Qt.UserRole) # straat = QStandardItem("%s" % (address["straat"])) # nummer = QStandardItem("%s" % (address["nummer"])) # postcode = QStandardItem("%s" % (address["postcode"])) # plaats = QStandardItem("%s" % (address["plaats"])) # gemeente = QStandardItem("%s" % (address["gemeente"])) # provincie = QStandardItem("%s" % (address["provincie"])) # self.geocoderSourceModel.appendRow([adrestekst, straat, nummer, postcode, plaats, gemeente, provincie]) # # self.dlg.geocoderResultView.selectRow(0) # self.zoomToAddress() # # self.geocoderSourceModel.setHeaderData(0, Qt.Horizontal, "Resultaat") # self.geocoderSourceModel.setHeaderData(1, Qt.Horizontal, "Straat") # self.geocoderSourceModel.setHeaderData(2, Qt.Horizontal, "Nr") # self.geocoderSourceModel.setHeaderData(3, Qt.Horizontal, "Postcode") # self.geocoderSourceModel.setHeaderData(4, Qt.Horizontal, "Plaats") # self.geocoderSourceModel.setHeaderData(5, Qt.Horizontal, "Gemeente") # self.geocoderSourceModel.setHeaderData(6, Qt.Horizontal, "Provincie") # # self.geocoderSourceModel.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(1).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(2).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(3).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(4).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(5).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(6).setTextAlignment(Qt.AlignLeft) # # self.dlg.geocoderResultView.resizeColumnsToContents() # self.dlg.geocoderResultView.horizontalHeader().setStretchLastSection(True) def zoomToAddress(self): # get x,y from data of record self.removePointer() data = self.dlg.geocoderResultView.selectedIndexes()[0].data(Qt.UserRole) if 'centroide_rd' in data: # free OR lookup service geom = QgsGeometry.fromWkt(data['centroide_rd']) adrestekst = data['adrestekst'] else: # no centroid yet, probably only object id, retrieve it via lookup service id = data['id'] data = self.pdokgeocoder.lookup(id) geom = QgsGeometry.fromWkt(data['centroide_rd']) adrestekst = data['adrestekst'] lookup_data= data['data'] lis = '' for key in lookup_data.keys(): lis = lis + '<li>{}: {}</li>'.format(key, lookup_data[key]) self.dlg.ui.lookupinfo.setHtml( '<h4>{}</h4><lu>{}</lu>'.format(adrestekst, lis)) # just always transform from 28992 to mapcanvas crs crs = self.iface.mapCanvas().mapSettings().destinationCrs() crs28992 = QgsCoordinateReferenceSystem() crs28992.createFromId(28992) crsTransform = QgsCoordinateTransform(crs28992, crs, QgsProject.instance()) z = 1587 if adrestekst.lower().startswith('adres'): z = 794 elif adrestekst.lower().startswith('perceel'): z = 794 elif adrestekst.lower().startswith('hectometer'): z = 1587 elif adrestekst.lower().startswith('straat'): z = 3175 elif adrestekst.lower().startswith('postcode'): z = 6350 elif adrestekst.lower().startswith('woonplaats'): z = 25398 elif adrestekst.lower().startswith('gemeente'): z = 50797 elif adrestekst.lower().startswith('provincie'): z = 812750 geom.transform(crsTransform) center = geom.asPoint() self.setPointer(center) # zoom to with center is actually setting a point rectangle and then zoom rect = QgsRectangle(center, center) self.iface.mapCanvas().setExtent(rect) self.iface.mapCanvas().zoomScale(z) self.iface.mapCanvas().refresh() def setPointer(self, point): self.removePointer() self.pointer = QgsVertexMarker(self.iface.mapCanvas()) self.pointer.setColor(QColor(255, 255, 0)) self.pointer.setIconSize(10) self.pointer.setPenWidth(5) self.pointer.setCenter(point) def removePointer(self): if self.pointer is not None: self.iface.mapCanvas().scene().removeItem(self.pointer) def info(self, msg=""): QgsMessageLog.logMessage('{}'.format(msg), 'PDOK-services Plugin', Qgis.Info)
class Plugin(): """The QGIS interface implementation for the InaSAFE plugin. This class acts as the 'glue' between QGIS and our custom logic. It creates a toolbar and menu bar entry and launches the InaSAFE user interface if these are activated. """ def __init__(self, iface): """Class constructor. On instantiation, the plugin instance will be assigned a copy of the QGIS iface object which will allow this plugin to access and manipulate the running QGIS instance that spawned it. :param iface:Quantum GIS iface instance. This instance is automatically passed to the plugin by QGIS when it loads the plugin. :type iface: QgisAppInterface """ # Save reference to the QGIS interface self.iface = iface self.dock_widget = None # Actions self.action_add_layers = None self.action_add_osm_layer = None self.action_add_petabencana_layer = None self.action_batch_runner = None self.action_dock = None self.action_extent_selector = None self.action_field_mapping = None self.action_multi_exposure = None self.action_function_centric_wizard = None self.action_import_dialog = None self.action_keywords_wizard = None self.action_minimum_needs = None self.action_minimum_needs_config = None self.action_multi_buffer = None self.action_options = None self.action_run_tests = None self.action_save_scenario = None self.action_shake_converter = None self.action_show_definitions = None self.action_toggle_rubberbands = None self.action_metadata_converter = None self.translator = None self.toolbar = None self.wizard = None self.actions = [] # list of all QActions we create for InaSAFE self.message_bar_item = None # Flag indicating if toolbar should show only common icons or not self.full_toolbar = False # print self.tr('InaSAFE') # For enable/disable the keyword editor icon self.iface.currentLayerChanged.connect(self.layer_changed) developer_mode = setting('developer_mode', False, expected_type=bool) self.hide_developer_buttons = (inasafe_release_status == 'final' and not developer_mode) # 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('Plugin', message) def add_action(self, action, add_to_toolbar=True, add_to_legend=False): """Add a toolbar icon to the InaSAFE toolbar. :param action: The action that should be added to the toolbar. :type action: QAction :param add_to_toolbar: Flag indicating whether the action should also be added to the InaSAFE toolbar. Defaults to True. :type add_to_toolbar: bool :param add_to_legend: Flag indicating whether the action should also be added to the layer legend menu. Default to False. :type add_to_legend: bool """ # store in the class list of actions for easy plugin unloading self.actions.append(action) self.iface.addPluginToMenu(self.tr('InaSAFE'), action) if add_to_toolbar: self.toolbar.addAction(action) if add_to_legend: # The id is the action name without spaces, tabs ... self.iface.addCustomActionForLayerType(action, self.tr('InaSAFE'), QgsMapLayer.VectorLayer, True) self.iface.addCustomActionForLayerType(action, self.tr('InaSAFE'), QgsMapLayer.RasterLayer, True) def _create_dock_toggle_action(self): """Create action for plugin dockable window (show/hide).""" # pylint: disable=W0201 icon = resources_path('img', 'icons', 'icon.svg') self.action_dock = QAction(QIcon(icon), self.tr('Toggle InaSAFE Dock'), self.iface.mainWindow()) self.action_dock.setObjectName('InaSAFEDockToggle') self.action_dock.setStatusTip(self.tr('Show/hide InaSAFE dock widget')) self.action_dock.setWhatsThis(self.tr('Show/hide InaSAFE dock widget')) self.action_dock.setCheckable(True) self.action_dock.setChecked(True) self.action_dock.triggered.connect(self.toggle_dock_visibility) self.add_action(self.action_dock) # -------------------------------------- # Create action for keywords creation wizard # ------------------------------------- def _create_keywords_wizard_action(self): """Create action for keywords creation wizard.""" icon = resources_path('img', 'icons', 'show-keyword-wizard.svg') self.action_keywords_wizard = QAction( QIcon(icon), self.tr('Keywords Creation Wizard'), self.iface.mainWindow()) self.action_keywords_wizard.setStatusTip( self.tr('Open InaSAFE keywords creation wizard')) self.action_keywords_wizard.setWhatsThis( self.tr('Open InaSAFE keywords creation wizard')) self.action_keywords_wizard.setEnabled(False) self.action_keywords_wizard.triggered.connect( self.show_keywords_wizard) self.add_action(self.action_keywords_wizard, add_to_legend=True) def _create_analysis_wizard_action(self): """Create action for IF-centric wizard.""" icon = resources_path('img', 'icons', 'show-wizard.svg') self.action_function_centric_wizard = QAction( QIcon(icon), self.tr('Impact Function Centric Wizard'), self.iface.mainWindow()) self.action_function_centric_wizard.setStatusTip( self.tr('Open InaSAFE impact function centric wizard')) self.action_function_centric_wizard.setWhatsThis( self.tr('Open InaSAFE impact function centric wizard')) self.action_function_centric_wizard.setEnabled(True) self.action_function_centric_wizard.triggered.connect( self.show_function_centric_wizard) self.add_action(self.action_function_centric_wizard) def _create_options_dialog_action(self): """Create action for options dialog.""" icon = resources_path('img', 'icons', 'configure-inasafe.svg') self.action_options = QAction(QIcon(icon), self.tr('Options'), self.iface.mainWindow()) self.action_options.setStatusTip( self.tr('Open InaSAFE options dialog')) self.action_options.setWhatsThis( self.tr('Open InaSAFE options dialog')) self.action_options.triggered.connect(self.show_options) self.add_action(self.action_options, add_to_toolbar=self.full_toolbar) def _create_minimum_needs_action(self): """Create action for minimum needs dialog.""" icon = resources_path('img', 'icons', 'show-minimum-needs.svg') self.action_minimum_needs = QAction( QIcon(icon), self.tr('Minimum Needs Calculator'), self.iface.mainWindow()) self.action_minimum_needs.setStatusTip( self.tr('Open InaSAFE minimum needs calculator')) self.action_minimum_needs.setWhatsThis( self.tr('Open InaSAFE minimum needs calculator')) self.action_minimum_needs.triggered.connect(self.show_minimum_needs) self.add_action(self.action_minimum_needs, add_to_toolbar=self.full_toolbar) def _create_multi_buffer_action(self): """Create action for multi buffer dialog.""" icon = resources_path('img', 'icons', 'show-multi-buffer.svg') self.action_multi_buffer = QAction(QIcon(icon), self.tr('Multi Buffer'), self.iface.mainWindow()) self.action_multi_buffer.setStatusTip( self.tr('Open InaSAFE multi buffer')) self.action_multi_buffer.setWhatsThis( self.tr('Open InaSAFE multi buffer')) self.action_multi_buffer.triggered.connect(self.show_multi_buffer) self.add_action(self.action_multi_buffer, add_to_toolbar=self.full_toolbar) def _create_minimum_needs_options_action(self): """Create action for global minimum needs dialog.""" icon = resources_path('img', 'icons', 'show-global-minimum-needs.svg') self.action_minimum_needs_config = QAction( QIcon(icon), self.tr('Minimum Needs Configuration'), self.iface.mainWindow()) self.action_minimum_needs_config.setStatusTip( self.tr('Open InaSAFE minimum needs configuration')) self.action_minimum_needs_config.setWhatsThis( self.tr('Open InaSAFE minimum needs configuration')) self.action_minimum_needs_config.triggered.connect( self.show_minimum_needs_configuration) self.add_action(self.action_minimum_needs_config, add_to_toolbar=self.full_toolbar) def _create_shakemap_converter_action(self): """Create action for converter dialog.""" icon = resources_path('img', 'icons', 'show-converter-tool.svg') self.action_shake_converter = QAction(QIcon(icon), self.tr('Shakemap Converter'), self.iface.mainWindow()) self.action_shake_converter.setStatusTip( self.tr('Open InaSAFE Converter')) self.action_shake_converter.setWhatsThis( self.tr('Open InaSAFE Converter')) self.action_shake_converter.triggered.connect( self.show_shakemap_importer) self.add_action(self.action_shake_converter, add_to_toolbar=self.full_toolbar) def _create_batch_runner_action(self): """Create action for batch runner dialog.""" icon = resources_path('img', 'icons', 'show-batch-runner.svg') self.action_batch_runner = QAction(QIcon(icon), self.tr('Batch Runner'), self.iface.mainWindow()) self.action_batch_runner.setStatusTip(self.tr('Open Batch Runner')) self.action_batch_runner.setWhatsThis(self.tr('Open Batch Runner')) self.action_batch_runner.triggered.connect(self.show_batch_runner) self.add_action(self.action_batch_runner, add_to_toolbar=self.full_toolbar) def _create_save_scenario_action(self): """Create action for save scenario dialog.""" icon = resources_path('img', 'icons', 'save-as-scenario.svg') self.action_save_scenario = QAction(QIcon(icon), self.tr('Save Current Scenario'), self.iface.mainWindow()) message = self.tr('Save current scenario to text file') self.action_save_scenario.setStatusTip(message) self.action_save_scenario.setWhatsThis(message) # noinspection PyUnresolvedReferences self.action_save_scenario.triggered.connect(self.save_scenario) self.add_action(self.action_save_scenario, add_to_toolbar=self.full_toolbar) def _create_osm_downloader_action(self): """Create action for import OSM Dialog.""" icon = resources_path('img', 'icons', 'show-osm-download.svg') self.action_import_dialog = QAction( QIcon(icon), self.tr('OpenStreetMap Downloader'), self.iface.mainWindow()) self.action_import_dialog.setStatusTip( self.tr('OpenStreetMap Downloader')) self.action_import_dialog.setWhatsThis( self.tr('OpenStreetMap Downloader')) self.action_import_dialog.triggered.connect(self.show_osm_downloader) self.add_action(self.action_import_dialog, add_to_toolbar=True) def _create_geonode_uploader_action(self): """Create action for Geonode uploader dialog.""" icon = resources_path('img', 'icons', 'geonode.png') label = tr('Geonode Uploader') self.action_geonode = QAction(QIcon(icon), label, self.iface.mainWindow()) self.action_geonode.setStatusTip(label) self.action_geonode.setWhatsThis(label) self.action_geonode.triggered.connect(self.show_geonode_uploader) self.add_action(self.action_geonode, add_to_toolbar=False) def _create_add_osm_layer_action(self): """Create action for import OSM Dialog.""" icon = resources_path('img', 'icons', 'add-osm-tiles-layer.svg') self.action_add_osm_layer = QAction( QIcon(icon), self.tr('Add OpenStreetMap Tile Layer'), self.iface.mainWindow()) self.action_add_osm_layer.setStatusTip( self.tr('Add OpenStreetMap Tile Layer')) self.action_add_osm_layer.setWhatsThis( self.tr('Use this to add an OSM layer to your map. ' 'It needs internet access to function.')) self.action_add_osm_layer.triggered.connect(self.add_osm_layer) self.add_action(self.action_add_osm_layer, add_to_toolbar=True) def _create_show_definitions_action(self): """Create action for showing definitions / help.""" icon = resources_path('img', 'icons', 'show-inasafe-help.svg') self.action_show_definitions = QAction(QIcon(icon), self.tr('InaSAFE Help'), self.iface.mainWindow()) self.action_show_definitions.setStatusTip(self.tr('Show InaSAFE Help')) self.action_show_definitions.setWhatsThis( self. tr('Use this to show a document describing all InaSAFE concepts.')) self.action_show_definitions.triggered.connect(self.show_definitions) self.add_action(self.action_show_definitions, add_to_toolbar=True) def _create_metadata_converter_action(self): """Create action for showing metadata converter dialog.""" icon = resources_path('img', 'icons', 'show-metadata-converter.svg') self.action_metadata_converter = QAction( QIcon(icon), self.tr('InaSAFE Metadata Converter'), self.iface.mainWindow()) self.action_metadata_converter.setStatusTip( self.tr('Convert metadata from version 4.3 to version 3.5.')) self.action_metadata_converter.setWhatsThis( self.tr('Use this tool to convert metadata 4.3 to version 3.5')) self.action_metadata_converter.triggered.connect( self.show_metadata_converter) self.add_action(self.action_metadata_converter, add_to_toolbar=self.full_toolbar) def _create_field_mapping_action(self): """Create action for showing field mapping dialog.""" icon = resources_path('img', 'icons', 'show-mapping-tool.svg') self.action_field_mapping = QAction( QIcon(icon), self.tr('InaSAFE Field Mapping Tool'), self.iface.mainWindow()) self.action_field_mapping.setStatusTip( self.tr('Assign field mapping to layer.')) self.action_field_mapping.setWhatsThis( self.tr('Use this tool to assign field mapping in layer.')) self.action_field_mapping.setEnabled(False) self.action_field_mapping.triggered.connect(self.show_field_mapping) self.add_action(self.action_field_mapping, add_to_toolbar=self.full_toolbar) def _create_multi_exposure_action(self): """Create action for showing the multi exposure tool.""" self.action_multi_exposure = QAction( QIcon(resources_path('img', 'icons', 'show-multi-exposure.svg')), self.tr('InaSAFE Multi Exposure Tool'), self.iface.mainWindow()) self.action_multi_exposure.setStatusTip( self.tr('Open the multi exposure tool.')) self.action_multi_exposure.setWhatsThis( self.tr('Open the multi exposure tool.')) self.action_multi_exposure.setEnabled(True) self.action_multi_exposure.triggered.connect(self.show_multi_exposure) self.add_action(self.action_multi_exposure, add_to_toolbar=self.full_toolbar) def _create_add_petabencana_layer_action(self): """Create action for import OSM Dialog.""" icon = resources_path('img', 'icons', 'add-petabencana-layer.svg') self.action_add_petabencana_layer = QAction( QIcon(icon), self.tr('Add PetaBencana Flood Layer'), self.iface.mainWindow()) self.action_add_petabencana_layer.setStatusTip( self.tr('Add PetaBencana Flood Layer')) self.action_add_petabencana_layer.setWhatsThis( self.tr('Use this to add a PetaBencana layer to your map. ' 'It needs internet access to function.')) self.action_add_petabencana_layer.triggered.connect( self.add_petabencana_layer) self.add_action(self.action_add_petabencana_layer, add_to_toolbar=self.full_toolbar) def _create_rubber_bands_action(self): """Create action for toggling rubber bands.""" icon = resources_path('img', 'icons', 'toggle-rubber-bands.svg') self.action_toggle_rubberbands = QAction( QIcon(icon), self.tr('Toggle Scenario Outlines'), self.iface.mainWindow()) message = self.tr('Toggle rubber bands showing scenario extents.') self.action_toggle_rubberbands.setStatusTip(message) self.action_toggle_rubberbands.setWhatsThis(message) # Set initial state self.action_toggle_rubberbands.setCheckable(True) flag = setting('showRubberBands', False, expected_type=bool) self.action_toggle_rubberbands.setChecked(flag) # noinspection PyUnresolvedReferences self.action_toggle_rubberbands.triggered.connect( self.dock_widget.toggle_rubber_bands) self.add_action(self.action_toggle_rubberbands) def _create_analysis_extent_action(self): """Create action for analysis extent dialog.""" icon = resources_path('img', 'icons', 'set-extents-tool.svg') self.action_extent_selector = QAction(QIcon(icon), self.tr('Set Analysis Area'), self.iface.mainWindow()) self.action_extent_selector.setStatusTip( self.tr('Set the analysis area for InaSAFE')) self.action_extent_selector.setWhatsThis( self.tr('Set the analysis area for InaSAFE')) self.action_extent_selector.triggered.connect( self.show_extent_selector) self.add_action(self.action_extent_selector) def _create_test_layers_action(self): """Create action for adding layers (developer mode, non final only).""" if self.hide_developer_buttons: return icon = resources_path('img', 'icons', 'add-test-layers.svg') self.action_add_layers = QAction(QIcon(icon), self.tr('Add Test Layers'), self.iface.mainWindow()) self.action_add_layers.setStatusTip(self.tr('Add test layers')) self.action_add_layers.setWhatsThis(self.tr('Add test layers')) self.action_add_layers.triggered.connect(self.add_test_layers) self.add_action(self.action_add_layers) def _create_run_test_action(self): """Create action for running tests (developer mode, non final only).""" if self.hide_developer_buttons: return default_package = str(setting('testPackage', 'safe', expected_type=str)) msg = self.tr('Run tests in %s' % default_package) self.test_button = QToolButton() self.test_button.setMenu(QMenu()) self.test_button.setPopupMode(QToolButton.MenuButtonPopup) icon = resources_path('img', 'icons', 'run-tests.svg') self.action_run_tests = QAction(QIcon(icon), msg, self.iface.mainWindow()) self.action_run_tests.setStatusTip(msg) self.action_run_tests.setWhatsThis(msg) self.action_run_tests.triggered.connect(self.run_tests) self.test_button.menu().addAction(self.action_run_tests) self.test_button.setDefaultAction(self.action_run_tests) self.action_select_package = QAction(QIcon(icon), self.tr('Select package'), self.iface.mainWindow()) self.action_select_package.setStatusTip(self.tr('Select Test Package')) self.action_select_package.setWhatsThis(self.tr('Select Test Package')) self.action_select_package.triggered.connect(self.select_test_package) self.test_button.menu().addAction(self.action_select_package) self.toolbar.addWidget(self.test_button) self.add_action(self.action_run_tests, add_to_toolbar=False) self.add_action(self.action_select_package, add_to_toolbar=False) def _create_dock(self): """Create dockwidget and tabify it with the legend.""" # Import dock here as it needs to be imported AFTER i18n is set up from safe.gui.widgets.dock import Dock self.dock_widget = Dock(self.iface) self.dock_widget.setObjectName('InaSAFE-Dock') self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dock_widget) legend_tab = self.iface.mainWindow().findChild(QApplication, 'Legend') if legend_tab: self.iface.mainWindow().tabifyDockWidget(legend_tab, self.dock_widget) self.dock_widget.raise_() # noinspection PyPep8Naming def initGui(self): """Gui initialisation procedure (for QGIS plugin api). .. note:: Don't change the name of this method from initGui! This method is called by QGIS and should be used to set up any graphical user interface elements that should appear in QGIS by default (i.e. before the user performs any explicit action with the plugin). """ self.toolbar = self.iface.addToolBar('InaSAFE') self.toolbar.setObjectName('InaSAFEToolBar') self.dock_widget = None # Now create the actual dock self._create_dock() # And all the menu actions # Configuration Group self._create_dock_toggle_action() self._create_options_dialog_action() self._create_minimum_needs_options_action() self._create_analysis_extent_action() self._create_rubber_bands_action() self._add_spacer_to_menu() self._create_keywords_wizard_action() self._create_analysis_wizard_action() self._add_spacer_to_menu() self._create_field_mapping_action() self._create_multi_exposure_action() self._create_metadata_converter_action() # TODO: temporarily disabled this until we have a fix # issue: https://github.com/inasafe/inasafe/issues/5109 # self._create_osm_downloader_action() self._create_add_osm_layer_action() self._create_add_petabencana_layer_action() self._create_geonode_uploader_action() self._create_shakemap_converter_action() self._create_minimum_needs_action() self._create_multi_buffer_action() self._create_test_layers_action() self._create_run_test_action() self._add_spacer_to_menu() self._create_batch_runner_action() self._create_save_scenario_action() self._add_spacer_to_menu() self._create_show_definitions_action() # Hook up a slot for when the dock is hidden using its close button # or view-panels # self.dock_widget.visibilityChanged.connect(self.toggle_inasafe_action) # Also deal with the fact that on start of QGIS dock may already be # hidden. self.action_dock.setChecked(self.dock_widget.isVisible()) self.iface.initializationCompleted.connect( partial(self.show_welcome_message)) def _add_spacer_to_menu(self): """Create a spacer to the menu to separate action groups.""" separator = QAction(self.iface.mainWindow()) separator.setSeparator(True) self.iface.addPluginToMenu(self.tr('InaSAFE'), separator) @staticmethod def clear_modules(): """Unload inasafe functions and try to return QGIS to before InaSAFE. .. todo:: I think this function can be removed. TS. """ # next lets force remove any inasafe related modules modules = [] for module in sys.modules: if 'inasafe' in module: # Check if it is really one of our modules i.e. exists in the # plugin directory tokens = module.split('.') path = '' for myToken in tokens: path += os.path.sep + myToken parent = os.path.abspath( os.path.join(__file__, os.path.pardir, os.path.pardir)) full_path = os.path.join(parent, path + '.py') if os.path.exists(os.path.abspath(full_path)): LOGGER.debug('Removing: %s' % module) modules.append(module) for module in modules: del (sys.modules[module]) for module in sys.modules: if 'inasafe' in module: print(module) # Lets also clean up all the path additions that were made package_path = os.path.abspath( os.path.join(os.path.dirname(__file__), os.path.pardir)) LOGGER.debug('Path to remove: %s' % package_path) # We use a list comprehension to ensure duplicate entries are removed LOGGER.debug(sys.path) sys.path = [y for y in sys.path if package_path not in y] LOGGER.debug(sys.path) def unload(self): """GUI breakdown procedure (for QGIS plugin api). .. note:: Don't change the name of this method from unload! This method is called by QGIS and should be used to *remove* any graphical user interface elements that should appear in QGIS. """ # Remove the plugin menu item and icon if self.wizard: self.wizard.deleteLater() for myAction in self.actions: self.iface.removePluginMenu(self.tr('InaSAFE'), myAction) self.iface.removeToolBarIcon(myAction) self.iface.removeCustomActionForLayerType(myAction) self.iface.mainWindow().removeDockWidget(self.dock_widget) self.iface.mainWindow().removeToolBar(self.toolbar) self.dock_widget.setVisible(False) self.dock_widget.destroy() self.iface.currentLayerChanged.disconnect(self.layer_changed) # Unload QGIS expressions loaded by the plugin. for qgis_expression in list(qgis_expressions().keys()): QgsExpression.unregisterFunction(qgis_expression) def toggle_inasafe_action(self, checked): """Check or un-check the toggle inaSAFE toolbar button. This slot is called when the user hides the inaSAFE panel using its close button or using view->panels. :param checked: True if the dock should be shown, otherwise False. :type checked: bool """ self.action_dock.setChecked(checked) # Run method that performs all the real work def toggle_dock_visibility(self): """Show or hide the dock widget.""" if self.dock_widget.isVisible(): self.dock_widget.setVisible(False) else: self.dock_widget.setVisible(True) self.dock_widget.raise_() def add_test_layers(self): """Add standard test layers.""" from safe.test.utilities import load_standard_layers load_standard_layers() rect = QgsRectangle(106.806, -6.195, 106.837, -6.167) self.iface.mapCanvas().setExtent(rect) def select_test_package(self): """Select the test package.""" default_package = 'safe' user_package = str( setting('testPackage', default_package, expected_type=str)) test_package, _ = QInputDialog.getText( self.iface.mainWindow(), self.tr('Select the python test package'), self.tr('Select the python test package'), QLineEdit.Normal, user_package) if test_package == '': test_package = default_package set_setting('testPackage', test_package) msg = self.tr('Run tests in %s' % test_package) self.action_run_tests.setWhatsThis(msg) self.action_run_tests.setText(msg) def run_tests(self): """Run unit tests in the python console.""" from qgis.PyQt.QtWidgets import QDockWidget main_window = self.iface.mainWindow() action = main_window.findChild(QAction, 'mActionShowPythonDialog') action.trigger() package = str(setting('testPackage', 'safe', expected_type=str)) for child in main_window.findChildren(QDockWidget, 'PythonConsole'): if child.objectName() == 'PythonConsole': child.show() for widget in child.children(): if 'PythonConsoleWidget' in str(widget.__class__): # print "Console widget found" shell = widget.shell shell.runCommand( 'from inasafe.test_suite import test_package') shell.runCommand('test_package(\'%s\')' % package) break def show_extent_selector(self): """Show the extent selector widget for defining analysis extents.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.extent_selector_dialog import ExtentSelectorDialog widget = ExtentSelectorDialog( self.iface, self.iface.mainWindow(), extent=self.dock_widget.extent.user_extent, crs=self.dock_widget.extent.crs) widget.clear_extent.connect( self.dock_widget.extent.clear_user_analysis_extent) widget.extent_defined.connect( self.dock_widget.define_user_analysis_extent) # This ensures that run button state is updated on dialog close widget.extent_selector_closed.connect( self.dock_widget.validate_impact_function) # Needs to be non modal to support hide -> interact with map -> show widget.show() # non modal def show_minimum_needs(self): """Show the minimum needs dialog.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.minimum_needs.needs_calculator_dialog import ( NeedsCalculatorDialog) dialog = NeedsCalculatorDialog(self.iface.mainWindow()) dialog.exec_() def show_minimum_needs_configuration(self): """Show the minimum needs dialog.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.minimum_needs.needs_manager_dialog import ( NeedsManagerDialog) dialog = NeedsManagerDialog(parent=self.iface.mainWindow(), dock=self.dock_widget) dialog.exec_() # modal def show_options(self): """Show the options dialog.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.options_dialog import OptionsDialog dialog = OptionsDialog(iface=self.iface, parent=self.iface.mainWindow()) dialog.show_option_dialog() if dialog.exec_(): # modal self.dock_widget.read_settings() from safe.gui.widgets.message import getting_started_message send_static_message(self.dock_widget, getting_started_message()) # Issue #4734, make sure to update the combobox after update the # InaSAFE option self.dock_widget.get_layers() def show_welcome_message(self): """Show the welcome message.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.options_dialog import OptionsDialog # Do not show by default show_message = False previous_version = StrictVersion(setting('previous_version')) current_version = StrictVersion(inasafe_version) # Set previous_version to the current inasafe_version set_setting('previous_version', inasafe_version) if setting('always_show_welcome_message', expected_type=bool): # Show if it the setting said so show_message = True elif previous_version < current_version: # Always show if the user installed new version show_message = True # Allow to disable welcome message when running automated tests if os.environ.get('INASAFE_DISABLE_WELCOME_MESSAGE', False): show_message = False if show_message: dialog = OptionsDialog(iface=self.iface, parent=self.iface.mainWindow()) dialog.show_welcome_dialog() if dialog.exec_(): # modal self.dock_widget.read_settings() def show_keywords_wizard(self): """Show the keywords creation wizard.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.wizard.wizard_dialog import WizardDialog if self.iface.activeLayer() is None: return # Don't break an existing wizard session if accidentally clicked if self.wizard and self.wizard.isVisible(): return # Prevent spawning multiple copies since the IFCW is non modal if not self.wizard: self.wizard = WizardDialog(self.iface.mainWindow(), self.iface, self.dock_widget) self.wizard.set_keywords_creation_mode() self.wizard.exec_() # modal def show_function_centric_wizard(self): """Show the function centric wizard.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.wizard.wizard_dialog import WizardDialog # Don't break an existing wizard session if accidentally clicked if self.wizard and self.wizard.isVisible(): return # Prevent spawning multiple copies since it is non modal if not self.wizard: self.wizard = WizardDialog(self.iface.mainWindow(), self.iface, self.dock_widget) self.wizard.set_function_centric_mode() # non-modal in order to hide for selecting user extent self.wizard.show() def show_shakemap_importer(self): """Show the converter dialog.""" # import here only so that it is AFTER i18n set up from safe.gui.tools.shake_grid.shakemap_converter_dialog import ( ShakemapConverterDialog) dialog = ShakemapConverterDialog(self.iface.mainWindow(), self.iface, self.dock_widget) dialog.exec_() # modal def show_multi_buffer(self): """Show the multi buffer tool.""" from safe.gui.tools.multi_buffer_dialog import (MultiBufferDialog) dialog = MultiBufferDialog(self.iface.mainWindow(), self.iface, self.dock_widget) dialog.exec_() # modal def show_osm_downloader(self): """Show the OSM buildings downloader dialog.""" from safe.gui.tools.osm_downloader_dialog import OsmDownloaderDialog dialog = OsmDownloaderDialog(self.iface.mainWindow(), self.iface) # otherwise dialog is never deleted dialog.setAttribute(Qt.WA_DeleteOnClose, True) dialog.show() # non modal def show_geonode_uploader(self): """Show the Geonode uploader dialog.""" from safe.gui.tools.geonode_uploader import GeonodeUploaderDialog dialog = GeonodeUploaderDialog(self.iface.mainWindow()) dialog.show() # non modal def add_osm_layer(self): """Add OSM tile layer to the map. This uses a gdal wrapper around the OSM tile service - see the WorldOSM.gdal file for how it is constructed. """ path = resources_path('osm', 'WorldOSM.gdal') layer = QgsRasterLayer(path, self.tr('OpenStreetMap')) project = QgsProject.instance() # Try to add it as the last layer in the list # False flag prevents layer being added to legend project.addMapLayer(layer, False) root = QgsProject.instance().layerTreeRoot() index = len(root.findLayers()) + 1 # LOGGER.info('Inserting layer %s at position %s' % ( # layer.source(), index)) root.insertLayer(index, layer) project.addMapLayer(layer) def show_definitions(self): """Show InaSAFE Definitions (a report showing all key metadata).""" from safe.utilities.help import show_help from safe.gui.tools.help import definitions_help show_help(definitions_help.definitions_help()) def show_field_mapping(self): """Show InaSAFE Field Mapping.""" from safe.gui.tools.field_mapping_dialog import FieldMappingDialog dialog = FieldMappingDialog( parent=self.iface.mainWindow(), iface=self.iface, ) if dialog.exec_(): # modal LOGGER.debug('Show field mapping accepted') self.dock_widget.layer_changed(self.iface.activeLayer()) else: LOGGER.debug('Show field mapping not accepted') def show_metadata_converter(self): """Show InaSAFE Metadata Converter.""" from safe.gui.tools.metadata_converter_dialog import ( MetadataConverterDialog) dialog = MetadataConverterDialog( parent=self.iface.mainWindow(), iface=self.iface, ) dialog.exec_() def show_multi_exposure(self): """Show InaSAFE Multi Exposure.""" from safe.gui.tools.multi_exposure_dialog import MultiExposureDialog dialog = MultiExposureDialog(self.iface.mainWindow(), self.iface) dialog.exec_() # modal def add_petabencana_layer(self): """Add petabencana layer to the map. This uses the PetaBencana API to fetch the latest floods in JK. See https://data.petabencana.id/floods """ from safe.gui.tools.peta_bencana_dialog import PetaBencanaDialog dialog = PetaBencanaDialog(self.iface.mainWindow(), self.iface) dialog.show() # non modal def show_batch_runner(self): """Show the batch runner dialog.""" from safe.gui.tools.batch.batch_dialog import BatchDialog dialog = BatchDialog(parent=self.iface.mainWindow(), iface=self.iface, dock=self.dock_widget) dialog.exec_() # modal def save_scenario(self): """Save current scenario to text file.""" from safe.gui.tools.save_scenario import SaveScenarioDialog dialog = SaveScenarioDialog(iface=self.iface, dock=self.dock_widget) dialog.save_scenario() def layer_changed(self, layer): """Enable or disable keywords editor icon when active layer changes. :param layer: The layer that is now active. :type layer: QgsMapLayer """ if not layer: enable_keyword_wizard = False elif not hasattr(layer, 'providerType'): enable_keyword_wizard = False elif layer.providerType() == 'wms': enable_keyword_wizard = False else: enable_keyword_wizard = True try: if layer: if is_raster_layer(layer): enable_field_mapping_tool = False else: keywords = KeywordIO().read_keywords(layer) keywords_version = keywords.get('keyword_version') if not keywords_version: supported = False else: supported = ( is_keyword_version_supported(keywords_version)) if not supported: enable_field_mapping_tool = False else: layer_purpose = keywords.get('layer_purpose') if not layer_purpose: enable_field_mapping_tool = False else: if layer_purpose == layer_purpose_exposure['key']: layer_subcategory = keywords.get('exposure') elif layer_purpose == layer_purpose_hazard['key']: layer_subcategory = keywords.get('hazard') else: layer_subcategory = None field_groups = get_field_groups( layer_purpose, layer_subcategory) if len(field_groups) == 0: # No field group, disable field mapping tool. enable_field_mapping_tool = False else: enable_field_mapping_tool = True else: enable_field_mapping_tool = False except (KeywordNotFoundError, NoKeywordsFoundError, MetadataReadError): # No keywords, disable field mapping tool. enable_field_mapping_tool = False self.action_keywords_wizard.setEnabled(enable_keyword_wizard) self.action_field_mapping.setEnabled(enable_field_mapping_tool) def shortcut_f7(self): """Executed when user press F7 - will show the shakemap importer.""" self.show_shakemap_importer()
class midv_tolkn: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(QFile.decodeName(__file__)) self.db = None def initGui(self): # Create actions icon = QIcon(os.path.join(self.plugin_dir, "icons", "midv_tolkn.png")) self.actionloadthelayers = QAction(QIcon(":/plugins/midv_tolkn/icons/load_layers_domains.png"), "Ladda tolkningslager t QGIS", self.iface.mainWindow()) self.actionloadthelayers.setWhatsThis("Laddar tolkningslager för gvmagasin m.m. till QGIS") self.actionloadthelayers.triggered.connect(lambda x: self.load_the_layers()) self.actionNewDB = QAction(QIcon(":/plugins/midv_tolkn/icons/create_new.png"), "Skapa en ny tolkningsdatabas", self.iface.mainWindow()) self.actionNewDB.triggered.connect(lambda x: self.new_db()) self.actionVacuumDB = QAction(QIcon(":/plugins/midv_tolkn/icons/vacuum.png"), "Packa (vacuum) tolkn-db", self.iface.mainWindow()) self.actionVacuumDB.setWhatsThis("Perform database vacuuming") self.actionVacuumDB.triggered.connect(lambda x: self.vacuum_db()) self.actionZipDB = QAction(QIcon(":/plugins/midv_tolkn/icons/zip.png"), "Backup av tolknings-databas", self.iface.mainWindow()) self.actionZipDB.setWhatsThis("En komprimerad zip-fil kommer att skapas i samma dir som tolknings-databasen.") self.actionZipDB.triggered.connect(lambda x: self.zip_db()) self.actionUpgradeDB = QAction(QIcon(":/plugins/midv_tolkn/icons/create_new.png"), "Uppgradera tolknings-databas", self.iface.mainWindow()) self.actionUpgradeDB.setWhatsThis("Uppgradera en befintlig tolknings-databas till ny databas-struktur.") self.actionUpgradeDB.triggered.connect(lambda x: self.upgrade_db()) #self.actionabout = QAction(QIcon(":/plugins/midv_tolkn/icons/about.png"), "Information", self.iface.mainWindow()) #self.actionabout.triggered.connect(lambda x: self.about) # Add button self.iface.addToolBarIcon(self.actionloadthelayers) # Add plugins menu items self.midv_menu = None # Midvatten-plugin-menyn self.menu = None # sub-menyn "Tolkningar" # Check if Midvatten-menyn existerar och get it for child in self.iface.mainWindow().menuBar().children(): if isinstance(child,QMenu): if child.title() == "Midvatten": # Put here your menu name self.midv_menu = child # If the Midvatten menu does not exist, create it! self.owns_midv_menu = False #indicator that this plugin must not clean up the midvatten menu if not self.midv_menu: self.owns_midv_menu = True #indicator that this plugin must clean up the midvatten menu self.midv_menu = QMenu( "Midvatten", self.iface.mainWindow().menuBar() ) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.midv_menu) # check if there is a sub-menu Tolkningar for childchild in self.midv_menu.children(): if isinstance(childchild,QMenu): if childchild.title() == "&Tolkningar": # Put here your menu name print('found sub-menu Tolkningar') self.menu = childchild # If the tolkning submenu does not exist, create it if not self.menu: print('will add Tolkningar submenu') self.menu_separator1 = self.midv_menu.addSeparator() self.menu = QMenu(QCoreApplication.translate("Midvatten", "&Tolkningar")) self.midv_menu.addMenu(self.menu) self.menu_separator2 = self.midv_menu.addSeparator() self.menu.addAction(self.actionloadthelayers) self.menu.addAction(self.actionNewDB) self.menu.addAction(self.actionVacuumDB) self.menu.addAction(self.actionZipDB) self.menu.addAction(self.actionUpgradeDB) #self.menu.addAction(self.actionabout) def unload(self): # remove tool bar button self.iface.removeToolBarIcon(self.actionloadthelayers) # Remove the plugin menu items and icons try: self.midv_menu.removeAction(self.menu.menuAction()) self.midv_menu.removeAction(self.menu_separator1) self.midv_menu.removeAction(self.menu_separator2) except: pass if self.owns_midv_menu: #indicator that this plugin must clean up the midvatten menu menubar = self.midv_menu.parentWidget() menubar.removeAction(self.midv_menu.menuAction()) self.midv_menu.deleteLater() def about(self): utils.pop_up_info(msg='This feature is not yet implemented',title='Hold on...') def load_data_domains(self): #utils.pop_up_info(msg='This feature is not yet implemented',title='Hold on...') #return QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) err_flag = utils.verify_msettings_loaded_and_layer_edit_mode(qgis.utils.iface, self.ms)#verify midv settings are loaded if err_flag == 0: conn_ok, dd_tables = utils.sql_load_fr_db("select name from sqlite_master where name like 'zz_%'") if not conn_ok: return d_domain_tables = [str(dd_table[0]) for dd_table in dd_tables] err_flag = utils.verify_msettings_loaded_and_layer_edit_mode(qgis.utils.iface, self.ms, d_domain_tables)#verify none of the tables are already loaded and in edit mode if err_flag == 0: LoadLayers(qgis.utils.iface, self.ms.settingsdict,'Midvatten_data_domains') QApplication.restoreOverrideCursor()#now this long process is done and the cursor is back as normal def load_the_layers(self): LoadLayers(qgis.utils.iface,self.db) def new_db(self, set_locale=False): if not set_locale: set_locale = utils.getcurrentlocale() filenamepath = os.path.join(os.path.dirname(__file__),"metadata.txt" ) iniText = QSettings(filenamepath , QSettings.IniFormat) verno = str(iniText.value('version')) from .create_tolkn_db import newdb newdbinstance = newdb(verno, set_locale=set_locale) if not newdbinstance.dbpath=='': self.db = newdbinstance.dbpath def upgrade_db(self, set_locale=False): from_db = None #get full path to the original db to be updated if self.db: use_current_db = utils.Askuser("YesNo","""Do you want to upgrade %s?"""%self.db,'Current database?') if use_current_db.result == 0: from_db = None elif use_current_db.result == 1: from_db = self.db elif use_current_db.result == '': return if not from_db: from_db = QFileDialog.getOpenFileName(None, 'Ange tolknings-db som ska exporteras','',"Spatialite (*.sqlite)")[0] if not from_db: QApplication.restoreOverrideCursor() return None #get EPSG in the original db EPSG = utils.sql_load_fr_db("""SELECT srid FROM geom_cols_ref_sys WHERE Lower(f_table_name) = Lower('gvmag') AND Lower(f_geometry_column) = Lower('geometry')""",from_db) #preparations to create new db of new design if not set_locale: set_locale = utils.getcurrentlocale() filenamepath = os.path.join(os.path.dirname(__file__),"metadata.txt" ) iniText = QSettings(filenamepath , QSettings.IniFormat) verno = str(iniText.value('version')) #now create database of the updated design from .create_tolkn_db import newdb newdbinstance = newdb(verno, user_select_CRS=False, EPSG_code = EPSG[1][0][0], set_locale=set_locale) #transfer data to the new database foo = utils.UpgradeDatabase(from_db,newdbinstance.dbpath, EPSG) #set new database as the current db and load these layers if not newdbinstance.dbpath=='': self.db = newdbinstance.dbpath self.load_the_layers() def vacuum_db(self): force_another_db = False if self.db: use_current_db = utils.Askuser("YesNo","""Vill du packa %s?"""%self.db,'Which database?') if use_current_db.result == 1: dbpath = self.db force_another_db = True elif use_current_db.result == 0: force_another_db = True elif use_current_db.result == '': return if not self.db or force_another_db: dbpath = QFileDialog.getOpenFileName(None, 'Ange db som ska packas','',"Spatialite (*.sqlite)")[0] QApplication.setOverrideCursor(Qt.WaitCursor) utils.sql_alter_db(dbpath,'vacuum') QApplication.restoreOverrideCursor() def zip_db(self): force_another_db = False dbpath=None if self.db: use_current_db = utils.Askuser("YesNo",'Vill du göra backup av %s?'%self.db,'Which database?') if use_current_db.result == 1: dbpath = self.db force_another_db = False elif use_current_db.result == 0: force_another_db = True elif use_current_db.result == '': return if not self.db or force_another_db: dbpath = QFileDialog.getOpenFileName(None, 'Ange db som du vill skapa backup utav','',"Spatialite (*.sqlite)")[0] if dbpath: QApplication.setOverrideCursor(Qt.WaitCursor) connection = utils.dbconnection(dbpath) connection.connect2db() connection.conn.cursor().execute("begin immediate") file_path = os.path.realpath(dbpath) dir_path = os.path.dirname(file_path) current_dir = dir_path.split(os.sep)[-1] bkupname = dbpath + datetime.datetime.now().strftime('%Y%m%dT%H%M') + '.zip' zf = zipfile.ZipFile(bkupname, mode='w') zf.write(dbpath,os.path.basename(dbpath), compress_type=compression) #compression will depend on if zlib is found or not zf.close() connection.conn.rollback() connection.closedb() self.iface.messageBar().pushMessage("Information","Database backup was written to " + bkupname, 1,duration=15) QApplication.restoreOverrideCursor()
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): 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: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToVectorMenu(self.menu, action) self.actions.append(action) # Connect all actions self.dlg.dirOldButton.clicked.connect(self.select_oldDir) self.dlg.dirNewButton.clicked.connect(self.select_newDir) self.dlg.dirResultButton.clicked.connect(self.select_dirResult) self.dlg.mengdertilcsvButton.clicked.connect(self.getStats) self.dlg.selectdir_MButton.clicked.connect(self.select_output_dirM) self.dlg.skrivtilcsvButton.clicked.connect(self.exportLayers) self.dlg.compareButton.clicked.connect(self.comparefiles) self.dlg.comboBox.currentIndexChanged[str].connect( self.comboBox_itemChanged) self.dlg.addButton.clicked.connect(self.addItem) self.dlg.removeButton.clicked.connect(self.removeItem) self.dlg.clearButton.clicked.connect(self.clearSelection) self.dlg.kommuneCheck.toggled.connect(self.kommuneSelected) self.dlg.checkBox_fritekst.toggled.connect( self.comp_checkbox_handler_free) self.dlg.checkBox_nvdbid.toggled.connect( self.comp_checkbox_handler_nvdbid) self.dlg.checkBox_objekt.toggled.connect( self.comp_checkbox_handler_object) self.dlg.kontraktCheck.toggled.connect(self.kontraktSelected) self.dlg.fylkeBox.currentIndexChanged[str].connect(self.getKommune) self.dlg.fylkeBox.currentIndexChanged[str].connect(self.getKontrakt) self.dlg.fylkeBox.currentIndexChanged.connect( self.fylkeBox_itemChanged) self.dlg.kommuneBox.currentIndexChanged[str].connect( self.kommuneBox_itemChanged) self.dlg.kontraktBox.currentIndexChanged[str].connect( self.kontraktBox_itemChanged) self.dlg.mergeButton.clicked.connect(self.mergeLayers) self.dlg.selectdirButton.clicked.connect(self.select_output_dir) self.dlg.kjorButton.clicked.connect(self.runTask) self.dlg.saveButton.clicked.connect(self.saveAsPreset) self.dlg.vegsystemBox.currentIndexChanged[str].connect( self.vegsystemBox_itemChanged) self.dlg.searchTable.doubleClicked.connect(self.searchPreset) self.dlg.deleteButton.clicked.connect(self.deletePreset) self.dlg.statsButton.clicked.connect(self.loadStats) self.dlg.folderButton.clicked.connect(self.openFolder) getAllAreaData() getAllObjectData() getAllPresetData() self.dlg.vegsystemBox.addItems(returnVegreferanseData()) return action
class tableManager: def __init__(self, iface): self.iface = iface #i18n pluginPath = QFileInfo( os.path.realpath(__file__)).path() # patch by Régis Haubourg localeName = QLocale.system().name() if QFileInfo(pluginPath).exists(): self.localePath = pluginPath + "/i18n/tablemanager_" + localeName + ".qm" if QFileInfo(self.localePath).exists(): self.translator = QTranslator() self.translator.load(self.localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) def setCurrentTheme(self, theThemeName): """ Set icons to the current theme """ self.action.setIcon(self.getThemeIcon("tableManagerIcon.png")) def getThemeIcon(self, theName): """ get the icon from the best available theme """ myCurThemePath = QgsApplication.activeThemePath( ) + "/plugins/" + theName myDefThemePath = QgsApplication.defaultThemePath( ) + "/plugins/" + theName myQrcThemePath = ":/plugins/tablemanager/icons/" + QgsApplication.themeName( ) + "/" + theName myQrcPath = ":/plugins/tablemanager/icons/" + theName if QFile.exists(myCurThemePath): return QIcon(myCurThemePath) elif QFile.exists(myDefThemePath): return QIcon(myDefThemePath) elif QFile.exists(myQrcThemePath): return QIcon(myQrcThemePath) elif QFile.exists(myQrcPath): return QIcon(myQrcPath) else: return QIcon() def initGui(self): # create action self.action = QAction( self.getThemeIcon("tableManagerIcon.png"), QCoreApplication.translate('TableManager', 'Table manager'), self.iface.mainWindow()) #self.action = QAction(QIcon(':/plugins/tableManager/icons/tableManagerIcon.png'), QCoreApplication.translate('TableManager','Table manager'), self.iface.mainWindow()) self.action.setWhatsThis( QCoreApplication.translate('TableManager', 'Manages attribute table structure')) self.action.triggered.connect(self.run) self.iface.currentThemeChanged.connect(self.setCurrentTheme) # add toolbar button and menu item if hasattr(self.iface, 'addVectorToolBarIcon'): self.iface.addVectorToolBarIcon(self.action) else: self.iface.addToolBarIcon(self.action) if hasattr(self.iface, 'addPluginToVectorMenu'): self.iface.addPluginToVectorMenu(u"&Table Manager", self.action) else: self.iface.addPluginToMenu(u"&Table Manager", self.action) def unload(self): # remove the plugin menu item and icon if hasattr(self.iface, 'removePluginVectorMenu'): self.iface.removePluginVectorMenu(u"&Table Manager", self.action) else: self.iface.removePluginMenu(u"&Table Manager", self.action) if hasattr(self.iface, 'removeVectorToolBarIcon'): self.iface.removeVectorToolBarIcon(self.action) else: self.iface.removeToolBarIcon(self.action) def run(self): # create and show a configuration dialog or something similar layer = self.iface.activeLayer() if layer == None or layer.type() != layer.VectorLayer: QMessageBox.warning( self.iface.mainWindow(), QCoreApplication.translate('TableManager', 'Table manager'), QCoreApplication.translate('TableManager', 'Please select a vector layer')) elif layer.isEditable(): QMessageBox.warning( self.iface.mainWindow(), QCoreApplication.translate('TableManager', 'Table manager'), QCoreApplication.translate( 'TableManager', 'The selected layer is currently in editing mode.\nPlease exit this mode before managing the table.' )) else: dialoga = tablemanager.tableManager_gui.TableManager(self.iface) dialoga.exec_()
class PdokServicesPlugin(object): def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # docked or dialog, defaults to dialog # 2018 may: RD: deprecating Docked window, as the content is getting to big anyway # if isinstance(QSettings().value("/pdokservicesplugin/docked"), QVariant): # self.docked = QSettings().value("/pdokservicesplugin/docked", QVariant(False)) # else: # self.docked = QSettings().value("/pdokservicesplugin/docked", False) # # # Create the dialog and keep reference # if "True" == self.docked or "true" == self.docked or True is self.docked: # self.dlg = PdokServicesPluginDockWidget() # self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dlg) # else: # self.dlg = PdokServicesPluginDialog(parent=self.iface.mainWindow()) self.dlg = PdokServicesPluginDialog(parent=self.iface.mainWindow()) # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDatabaseFilePath( )).path() + "/python/plugins/pdokservicesplugin" # initialize locale localePath = "" if isinstance(QSettings().value("locale/userLocale"), QVariant): locale = QSettings().value("locale/userLocale").value()[0:2] else: locale = QSettings().value("locale/userLocale")[0:2] if QFileInfo(self.plugin_dir).exists(): localePath = self.plugin_dir + "/i18n/pdokservicesplugin_" + locale + ".qm" if QFileInfo(localePath).exists(): self.translator = QTranslator() self.translator.load(localePath) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self.currentLayer = None self.SETTINGS_SECTION = '/pdokservicesplugin/' self.pointer = None self.pdokgeocoder = PDOKGeoLocator(self.iface) self.geocoderSourceModel = None def getSettingsValue(self, key, default=''): if QSettings().contains(self.SETTINGS_SECTION + key): key = self.SETTINGS_SECTION + key if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 return str(QSettings().value(key).toString()) else: return str(QSettings().value(key)) else: return default def setSettingsValue(self, key, value): key = self.SETTINGS_SECTION + key if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 QSettings().setValue(key, QVariant(value)) else: QSettings().setValue(key, value) def initGui(self): # Create action that will start plugin configuration runIcon = QIcon(os.path.join(self.plugin_dir, 'icon_add_service.svg')) self.run_action = QAction(runIcon, \ "PDOK Services plugin", self.iface.mainWindow()) self.servicesLoaded = False # connect the action to the run method # 2018 may: RD: deprecating Docked window, as the content is getting to big anyway # if "True" == self.docked or "true" == self.docked or True == self.docked: # self.run_action.triggered.connect(self.showAndRaise) # self.dlg.radioDocked.setChecked(True) # # docked the dialog is immidiately visible, so should run NOW # else: # self.run_action.triggered.connect(self.run) # self.dlg.radioDocked.setChecked(False) # self.setupfq() self.run_action.triggered.connect(self.run) #self.dlg.radioDocked.setChecked(False) self.setupfq() # Add toolbar button and menu item #self.iface.addToolBarIcon(self.action) self.toolbar = self.iface.addToolBar("PDOK services plugin") self.toolbar.setObjectName("PDOK services plugin") self.toolbar.addAction(self.run_action) self.toolbarSearch = QLineEdit() self.toolbarSearch.setMaximumWidth(200) self.toolbarSearch.setAlignment(Qt.AlignLeft) self.toolbarSearch.setPlaceholderText("PDOK Locatieserver zoek") self.toolbar.addWidget(self.toolbarSearch) self.toolbarSearch.returnPressed.connect(self.searchAddressFromToolbar) # address/point cleanup eraserIcon = QIcon( os.path.join(self.plugin_dir, 'icon_remove_cross.svg')) self.clean_action = QAction(eraserIcon, \ "Cleanup", self.eraseAddress()) self.toolbar.addAction(self.clean_action) self.clean_action.triggered.connect(self.eraseAddress) self.clean_action.setEnabled(False) self.iface.addPluginToMenu(u"&Pdok Services Plugin", self.run_action) # about self.aboutAction = QAction(QIcon(":/plugins/pdokservicesplugin/icon_help.png"), \ "About", self.iface.mainWindow()) self.aboutAction.setWhatsThis("Pdok Services Plugin About") self.iface.addPluginToMenu(u"&Pdok Services Plugin", self.aboutAction) self.aboutAction.triggered.connect(self.about) self.dlg.ui.btnLoadLayer.clicked.connect(self.loadService) self.dlg.geocoderSearch.returnPressed.connect(self.searchAddress) self.dlg.geocoderSearch.textEdited.connect(self.searchAddress) self.dlg.geocoderSearch.setPlaceholderText( "PDOK Locatieserver zoek, bv postcode of postcode huisnummer") self.dlg.geocoderResultSearch.textChanged.connect( self.filterGeocoderResult) self.dlg.geocoderResultSearch.setPlaceholderText( "een of meer zoekwoorden uit resultaat") #self.dlg.radioDocked.toggled.connect(self.set_docked) self.dlg.btnCheckPdokJson.clicked.connect(self.checkPdokJson) #self.iface.mapCanvas().renderStarting.connect(self.extentsChanged) ui = self.dlg.ui cbxs = [ ui.cbx_gem, ui.cbx_wpl, ui.cbx_weg, ui.cbx_pcd, ui.cbx_adr, ui.cbx_pcl, ui.cbx_hmp ] # connect all fq checkboxes with suggest, so upon a change in fq filter we re-search for cbx in cbxs: cbx.stateChanged.connect(self.searchAddress) self.run(True) # for now hiding the pointer as soon as the extent changes #def extentsChanged(self): # self.removePointer() def checkPdokJson(self): myversion = self.getSettingsValue('pdokversion', '1') msgtxt = '' msglvl = 0 # QgsMessageBar.INFO try: response = urllib.request.urlopen( 'http://www.qgis.nl/pdok.version') str_response = response.read().decode('utf-8') pdokversion = json.loads(str_response) if pdokversion > int(myversion): response = urllib.request.urlopen( 'http://www.qgis.nl/pdok.json') str_response = response.read().decode('utf-8') pdokjson = json.loads(str_response) with open(self.plugin_dir + '/pdok.json', 'w') as outfile: json.dump(pdokjson, outfile) msgtxt = "De laatste versie is opgehaald en zal worden gebruikt " + \ str(pdokversion) + ' (was ' + myversion +')' self.servicesLoaded = False # reset reading of json self.run() self.setSettingsValue('pdokversion', pdokversion) else: msgtxt = "Geen nieuwere versie beschikbaar dan " + str( pdokversion) except Exception as e: #print e msgtxt = "Fout bij ophalen van service info. Netwerk probleem?" msglvl = 2 # QgsMessageBar.CRITICAL # msg if hasattr(self.iface, 'messageBar'): self.iface.messageBar().pushMessage("PDOK services update", msgtxt, level=msglvl, duration=10) else: # 1.8 QMessageBox.information(self.iface.mainWindow(), "Pdok Services Plugin", msgtxt) # def set_docked(self, foo): # self.setSettingsValue('docked', self.dlg.radioDocked.isChecked()) # #if Qgis.QGIS_VERSION_INT < 10900: # # # qgis <= 1.8 # # QSettings().setValue("/pdokservicesplugin/docked", QVariant(self.dlg.radioDocked.isChecked())) # #else: # # QSettings().setValue("/pdokservicesplugin/docked", self.dlg.radioDocked.isChecked()) def showAndRaise(self): self.dlg.show() self.dlg.raise_() # also remove the pointer self.removePointer() def about(self): infoString = "Written by Richard Duivenvoorde\nEmail - [email protected]\n" infoString += "Company - Zuidt - http://www.zuidt.nl\n" infoString += "Source: https://github.com/rduivenvoorde/pdokservicesplugin" QMessageBox.information(self.iface.mainWindow(), "Pdok Services Plugin About", infoString) def unload(self): self.removePointer() # Remove the plugin menu item and icon self.iface.removePluginMenu("&Pdok Services Plugin", self.run_action) self.iface.removePluginMenu("&Pdok Services Plugin", self.aboutAction) del self.toolbarSearch del self.run_action del self.aboutAction def showService(self, selectedIndexes): if len(selectedIndexes) == 0: self.currentLayer = None self.dlg.ui.layerInfo.setHtml('') self.dlg.ui.comboSelectProj.clear() return # needed to scroll To the selected row incase of using the keyboard / arrows self.dlg.servicesView.scrollTo( self.dlg.servicesView.selectedIndexes()[0]) # itemType holds the data (== column 1) self.currentLayer = self.dlg.servicesView.selectedIndexes()[1].data( Qt.UserRole) if isinstance(self.currentLayer, QVariant): self.currentLayer = self.currentLayer.toMap() # QGIS 1.8: QVariants currentLayer = {} for key in list(self.currentLayer.keys()): val = self.currentLayer[key] currentLayer[str(key)] = str(val.toString()) self.currentLayer = currentLayer url = self.currentLayer['url'] title = self.currentLayer['title'] style = '' if 'style' in self.currentLayer: style = self.currentLayer['style'] title = title + ' [' + style + ']' servicetitle = self.currentLayer['servicetitle'] layername = self.currentLayer['layers'] abstract = self.currentLayer['abstract'] stype = self.currentLayer['type'].upper() minscale = '' if 'minscale' in self.currentLayer and self.currentLayer[ 'minscale'] != None and self.currentLayer['minscale'] != '': minscale = "min. schaal 1:" + self.currentLayer['minscale'] maxscale = '' if 'maxscale' in self.currentLayer and self.currentLayer[ 'maxscale'] != None and self.currentLayer['maxscale'] != '': maxscale = "max. schaal 1:" + self.currentLayer['maxscale'] self.dlg.ui.layerInfo.setText('') self.dlg.ui.btnLoadLayer.setEnabled(True) self.dlg.ui.layerInfo.setHtml( '<h4>%s</h4><h3>%s</h3><lu><li>%s</li><li> </li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li></lu>' % (servicetitle, title, abstract, stype, url, layername, style, minscale, maxscale)) self.dlg.ui.comboSelectProj.clear() if stype == "WMS": try: crs = self.currentLayer['crs'] except KeyError: crs = 'EPSG:28992' crs = crs.split(',') self.dlg.ui.comboSelectProj.addItems(crs) for i in range(len(crs)): if crs[i] == 'EPSG:28992': self.dlg.ui.comboSelectProj.setCurrentIndex(i) if stype == "WMTS": tilematrixsets = self.currentLayer['tilematrixsets'].split(',') self.dlg.ui.comboSelectProj.addItems(tilematrixsets) for i in range(len(tilematrixsets)): if tilematrixsets[i].startswith('EPSG:28992'): self.dlg.ui.comboSelectProj.setCurrentIndex(i) def loadService(self): if self.currentLayer == None: return servicetype = self.currentLayer['type'] url = self.currentLayer['url'] # some services have an url with query parameters in it, we have to urlencode those: location, query = urllib.parse.splitquery(url) url = location if query != None and query != '': url += ('?' + urllib.parse.quote_plus(query)) title = self.currentLayer['title'] if 'style' in self.currentLayer: style = self.currentLayer['style'] title = title + ' [' + style + ']' else: style = '' # == default for this service layers = self.currentLayer['layers'] # mmm, tricky: we take the first one while we can actually want png/gif or jpeg if servicetype == "wms": imgformat = self.currentLayer['imgformats'].split(',')[0] if self.dlg.ui.comboSelectProj.currentIndex() == -1: crs = 'EPSG:28992' else: crs = self.dlg.ui.comboSelectProj.currentText() if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 uri = url self.iface.addRasterLayer( uri, # service uri title, # name for layer (as seen in QGIS) "wms", # dataprovider key [layers], # array of layername(s) for provider (id's) ["" ], # array of stylename(s) NOTE: ignoring styles here!!! imgformat, # image format searchstring crs) # crs code searchstring else: # qgis > 1.8 uri = "crs=" + crs + "&layers=" + layers + "&styles=" + style + "&format=" + imgformat + "&url=" + url self.iface.addRasterLayer(uri, title, "wms") elif servicetype == "wmts": if Qgis.QGIS_VERSION_INT < 10900: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( "Sorry, dit type layer: '" + servicetype.upper() + "' \nkan niet worden geladen in deze versie van QGIS.\nMisschien kunt u QGIS 2.0 installeren (die kan het WEL)?\nOf is de laag niet ook beschikbaar als wms of wfs?" ), QMessageBox.Ok, QMessageBox.Ok) return if self.dlg.ui.comboSelectProj.currentIndex() == -1: tilematrixset = 'EPSG:28992' else: tilematrixset = self.dlg.ui.comboSelectProj.currentText() imgformat = self.currentLayer['imgformats'].split(',')[0] # special case for luchtfoto #if layers=="luchtfoto": # # tileMatrixSet=nltilingschema&crs=EPSG:28992&layers=luchtfoto&styles=&format=image/jpeg&url=http://geodata1.nationaalgeoregister.nl/luchtfoto/wmts/1.0.0/WMTSCapabilities.xml # # {u'layers': u'luchtfoto', u'imgformats': u'image/jpeg', u'title': u'PDOK-achtergrond luchtfoto', u'url': u'http://geodata1.nationaalgeoregister.nl/luchtfoto/wms', u'abstract': u'', u'tilematrixsets': u'nltilingschema', u'type': u'wmts'} # uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=&format="+imgformat+"&url="+url #else: # uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=&format="+imgformat+"&url="+url; #uri = "tileMatrixSet="+tilematrixsets+"&crs=EPSG:28992&layers="+layers+"&styles=default&format="+imgformat+"&url="+url; if tilematrixset.startswith('EPSG:'): crs = tilematrixset i = crs.find(':', 5) if i > -1: crs = crs[:i] elif tilematrixset.startswith('OGC:1.0'): crs = 'EPSG:3857' uri = "tileMatrixSet=" + tilematrixset + "&crs=" + crs + "&layers=" + layers + "&styles=default&format=" + imgformat + "&url=" + url #print "############ PDOK URI #################" #print uri self.iface.addRasterLayer(uri, title, "wms") elif servicetype == "wfs": location, query = urllib.parse.splitquery(url) #uri = location+"?SERVICE=WFS&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME="+layers+"&SRSNAME=EPSG:28992" #uri = location + "?SERVICE=WFS&REQUEST=GetFeature&TYPENAME=" + layers + "&SRSNAME=EPSG:28992" # adding a bbox paramater forces QGIS to NOT cache features but retrieve new features all the time # QGIS will update the BBOX to the right value #uri += "&BBOX=-10000,310000,290000,650000" uri = " pagingEnabled='true' restrictToRequestBBOX='1' srsname='EPSG:28992' typename='" + layers + "' url='" + url + "' version='2.0.0' " self.iface.addVectorLayer(uri, title, "WFS") elif servicetype == "wcs": # cache=AlwaysCache&crs=EPSG:28992&format=GeoTIFF&identifier=ahn25m:ahn25m&url=http://geodata.nationaalgeoregister.nl/ahn25m/wcs uri = '' # cache=AlwaysCache # cache=PreferNetwork # cache=AlwaysNetwork # cache=AlwaysNetwork&crs=EPSG:28992&format=GeoTIFF&identifier=ahn25m:ahn25m&url=http://geodata.nationaalgeoregister.nl/ahn25m/wcs #uri = "cache=AlwaysNetwork&crs=EPSG:28992&format=image/tiff&version=1.1.1&identifier="+layers+"&url="+url # working for ahn1 ahn2 and ahn3: GEOTIFF_FLOAT32 format = 'GEOTIFF_FLOAT32' # working for ahn25m is only image/tiff if layers == 'ahn25m': format = 'image/tiff' # we handcrated some wcs layers with 2 different image formats: tiff (RGB) and tiff (float32): if 'imgformats' in self.currentLayer: format = self.currentLayer['imgformats'].split(',')[0] uri = "cache=AlwaysNetwork&crs=EPSG:28992&format=" + format + "&version=1.1.2&identifier=" + layers + "&url=" + url #uri = "cache=AlwaysNetwork&crs=EPSG:28992&format=image/tiff&version=1.1.2&identifier=" + layers + "&url=" + url self.iface.addRasterLayer(uri, title, "wcs") else: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( "Sorry, dit type layer: '" + servicetype.upper() + "' \nkan niet worden geladen door de plugin of door QGIS.\nIs het niet beschikbaar als wms, wmts of wfs?" ), QMessageBox.Ok, QMessageBox.Ok) return def filterGeocoderResult(self, string): #print "filtering geocoder results: %s" % string self.dlg.geocoderResultView.selectRow(0) self.geocoderProxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.geocoderProxyModel.setFilterFixedString(string) def searchAddressFromToolbar(self): self.removePointer() self.geocoderSourceModel.clear() self.geocode() def searchAddress(self): self.removePointer() #print "search geocoder for: %s" % self.dlg.geocoderSearch.text() self.geocoderSourceModel.clear() #self.geocode(self.dlg.geocoderSearch.text()) self.suggest() def eraseAddress(self): """ clean the input and remove the pointer """ self.removePointer() if self.geocoderSourceModel is not None: self.geocoderSourceModel.clear() if self.dlg.geocoderSearch is not None: self.dlg.geocoderSearch.clear() if self.toolbarSearch is not None: self.toolbarSearch.clear() def filterLayers(self, string): # remove selection if one row is selected self.dlg.servicesView.selectRow(0) #self.currentLayer = None self.proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxyModel.setFilterFixedString(string) #def addSourceRow(self, service, layer): def addSourceRow(self, serviceLayer): # you can attache different "data's" to to an QStandarditem # default one is the visible one: itemType = QStandardItem("%s" % (serviceLayer["type"].upper())) # userrole is a free form one: # only attach the data to the first item # service layer = a dict/object with all props of the layer itemType.setData(serviceLayer, Qt.UserRole) itemType.setToolTip( "%s - %s" % (serviceLayer["type"].upper(), serviceLayer["title"])) # only wms services have styles (sometimes) layername = serviceLayer["title"] if 'style' in serviceLayer: itemLayername = QStandardItem( "%s [%s]" % (serviceLayer["title"], serviceLayer["style"])) layername = "%s [%s]" % (serviceLayer["title"], serviceLayer["style"]) else: itemLayername = QStandardItem("%s" % (serviceLayer["title"])) itemLayername.setToolTip( "%s - %s" % (serviceLayer["type"].upper(), serviceLayer["servicetitle"])) # itemFilter is the item used to search filter in. That is why layername is a combi of layername + filter here itemFilter = QStandardItem( "%s %s %s %s" % (serviceLayer["type"], layername, serviceLayer["servicetitle"], serviceLayer["abstract"])) itemServicetitle = QStandardItem("%s" % (serviceLayer["servicetitle"])) itemServicetitle.setToolTip( "%s - %s" % (serviceLayer["type"].upper(), serviceLayer["title"])) self.sourceModel.appendRow( [itemLayername, itemType, itemServicetitle, itemFilter]) # run method that performs all the real work def run(self, hiddenDialog=False): # enable possible remote pycharm debugging #import pydevd #pydevd.settrace('localhost', port=5678, stdoutToServer=True, stderrToServer=True) # last viewed/selected tab if QSettings().contains("/pdokservicesplugin/currenttab"): if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 self.dlg.tabs.widget(QSettings().value( "/pdokservicesplugin/currenttab").toInt()[0]) else: self.dlg.tabs.widget( int(QSettings().value("/pdokservicesplugin/currenttab"))) if self.servicesLoaded == False: pdokjson = os.path.join(os.path.dirname(__file__), ".", "pdok.json") f = open(pdokjson, 'r', encoding='utf-8') self.pdok = json.load(f) f.close() self.proxyModel = QSortFilterProxyModel() self.sourceModel = QStandardItemModel() self.proxyModel.setSourceModel(self.sourceModel) # filter == search on itemFilter column: self.proxyModel.setFilterKeyColumn(3) self.dlg.servicesView.setModel(self.proxyModel) self.dlg.servicesView.setEditTriggers( QAbstractItemView.NoEditTriggers) self.geocoderProxyModel = QSortFilterProxyModel() self.geocoderSourceModel = QStandardItemModel() self.geocoderProxyModel.setSourceModel(self.geocoderSourceModel) self.geocoderProxyModel.setFilterKeyColumn(0) self.dlg.geocoderResultView.setModel(self.geocoderProxyModel) self.dlg.geocoderResultView.setEditTriggers( QAbstractItemView.NoEditTriggers) #{"services":[ # {"naam":"WMS NHI","url":"http://geodata.nationaalgeoregister.nl/nhi/ows","layers":["dmlinks","dmnodes"],"type":"wms"}, # {"naam":"WMS NHI","url":"http://geodata.nationaalgeoregister.nl/nhi/ows","layers":["dmlinks","dmnodes"],"type":"wms"} # ]} # for service in self.pdok["services"]: # service[layer] was an array if isinstance(service["layers"], str) or isinstance( service["layers"], str): self.addSourceRow(service) self.dlg.layerSearch.textChanged.connect(self.filterLayers) self.dlg.layerSearch.setPlaceholderText( "woord uit laagnaam, type of service ") self.dlg.servicesView.selectionModel().selectionChanged.connect( self.showService) self.dlg.servicesView.doubleClicked.connect(self.loadService) # actually I want to load a service when doubleclicked on header # but as I cannot get this to work, let's disable clicking it then self.dlg.servicesView.verticalHeader().setSectionsClickable(False) self.dlg.servicesView.horizontalHeader().setSectionsClickable( False) #self.dlg.geocoderResultView.doubleClicked.connect(self.zoomToAddress) self.dlg.geocoderResultView.selectionModel( ).selectionChanged.connect(self.zoomToAddress) # hide itemFilter column: self.dlg.servicesView.hideColumn(3) self.servicesLoaded = True self.sourceModel.setHeaderData(2, Qt.Horizontal, "Service") self.sourceModel.setHeaderData(1, Qt.Horizontal, "Type") self.sourceModel.setHeaderData(0, Qt.Horizontal, "Laagnaam [style]") self.sourceModel.horizontalHeaderItem(2).setTextAlignment(Qt.AlignLeft) self.sourceModel.horizontalHeaderItem(1).setTextAlignment(Qt.AlignLeft) self.sourceModel.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft) #self.dlg.servicesView.verticalHeader().hide() #self.dlg.servicesView.resizeColumnsToContents() self.dlg.servicesView.setColumnWidth( 0, 300) # set name to 300px (there are some huge layernames) self.dlg.servicesView.horizontalHeader().setStretchLastSection(True) # show the dialog ? if not hiddenDialog: self.dlg.show() # Run the dialog event loop #result = self.dlg.exec_() if Qgis.QGIS_VERSION_INT < 10900: # qgis <= 1.8 QSettings().setValue("/pdokservicesplugin/currenttab", QVariant(self.dlg.tabs.currentIndex())) else: QSettings().setValue("/pdokservicesplugin/currenttab", self.dlg.tabs.currentIndex()) self.removePointer() def setupfq(self): """ Setup the fq checkboxes in the gui, by looking into the settings for the 'pdokservicesplugin/checkedfqs' key, which contains a list of type strings like ['weg','adres'] """ checked_fqs = self.getSettingsValue('checkedfqs', []) #self.info('setup fq: {}'.format(checked_fqs)) if len(checked_fqs ) > 0: # else there is not saved state... take gui defaults self.dlg.ui.cbx_gem.setChecked('gemeente' in checked_fqs) self.dlg.ui.cbx_wpl.setChecked('woonplaats' in checked_fqs) self.dlg.ui.cbx_weg.setChecked('weg' in checked_fqs) self.dlg.ui.cbx_pcd.setChecked('postcode' in checked_fqs) self.dlg.ui.cbx_adr.setChecked('adres' in checked_fqs) self.dlg.ui.cbx_pcl.setChecked('perceel' in checked_fqs) self.dlg.ui.cbx_hmp.setChecked('hectometerpaal' in checked_fqs) def createfq(self): """ This creates a fq-string (Filter Query, see https://github.com/PDOK/locatieserver/wiki/Zoekvoorbeelden-Locatieserver) Based on the checkboxes in the dialog. Defaults to '' Example: 'fq=+type:adres+type:gemeente' (only gemeente AND addresses) :return: """ fqlist = [] if self.dlg.ui.cbx_gem.isChecked(): fqlist.append('gemeente') if self.dlg.ui.cbx_wpl.isChecked(): fqlist.append('woonplaats') if self.dlg.ui.cbx_weg.isChecked(): fqlist.append('weg') if self.dlg.ui.cbx_pcd.isChecked(): fqlist.append('postcode') if self.dlg.ui.cbx_adr.isChecked(): fqlist.append('adres') if self.dlg.ui.cbx_pcl.isChecked(): fqlist.append('perceel') if self.dlg.ui.cbx_hmp.isChecked(): fqlist.append('hectometerpaal') self.setSettingsValue('checkedfqs', fqlist) #self.info(self.getSettingsValue('checkedfqs', ['leeg?'])) fq = '' if len(fqlist) > 0: fq = '&fq=+type:' + '+type:'.join(fqlist) return fq def suggest(self): self.dlg.ui.lookupinfo.setHtml('') search_text = self.dlg.geocoderSearch.text() if len(search_text) <= 1: # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "meer input aub: {}".format(search_text) # ), QMessageBox.Ok, QMessageBox.Ok) return # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "zoeken: {}".format(search_text) # ), QMessageBox.Ok, QMessageBox.Ok) results = self.pdokgeocoder.suggest(search_text, self.createfq()) if len(results) == 0: # ignore, as we are suggesting, maybe more characters will reveal something... return for result in results: #print address adrestekst = QStandardItem("%s" % (result["adrestekst"])) adrestekst.setData(result, Qt.UserRole) type = QStandardItem("%s" % (result["type"])) id = QStandardItem("%s" % (result["id"])) score = QStandardItem("%s" % (result["score"])) adrestekst.setData(result, Qt.UserRole) self.geocoderSourceModel.appendRow([adrestekst, type]) self.geocoderSourceModel.setHeaderData(0, Qt.Horizontal, "Resultaat") self.geocoderSourceModel.setHeaderData(1, Qt.Horizontal, "Type") self.geocoderSourceModel.horizontalHeaderItem(0).setTextAlignment( Qt.AlignLeft) self.dlg.geocoderResultView.resizeColumnsToContents() self.dlg.geocoderResultView.horizontalHeader().setStretchLastSection( True) def geocode(self): self.dlg.geocoderSearch.setText(self.toolbarSearch.text()) self.suggest() if self.dlg.geocoderResultView.model().rowCount() > 0: self.dlg.geocoderResultView.selectRow(0) self.zoomToAddress() else: QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ "Niets gevonden.\nProbeer een andere spelling, of alleen postcode/huisnummer?\n\nSelecteer meer (Locatieserver) 'typen' in de PdokServicesPlugin dialoog.\n\nOf gebruik de 'PDOK geocoder'-tab in de PdokServicesPlugin dialoog." ), QMessageBox.Ok, QMessageBox.Ok) # def geocode(self): # self.dlg.ui.lookupinfo.setHtml('') # search_text = self.toolbarSearch.text() # addresses = self.pdokgeocoder.search(search_text) # if len(addresses) == 0: # QMessageBox.warning(self.iface.mainWindow(), "PDOK plugin", ( \ # "Niets gevonden. Probeer een andere spelling of alleen postcode/huisnummer." # ), QMessageBox.Ok, QMessageBox.Ok) # return # for address in addresses: # #print address # adrestekst = QStandardItem("%s" % (address["adrestekst"])) # adrestekst.setData(address, Qt.UserRole) # straat = QStandardItem("%s" % (address["straat"])) # nummer = QStandardItem("%s" % (address["nummer"])) # postcode = QStandardItem("%s" % (address["postcode"])) # plaats = QStandardItem("%s" % (address["plaats"])) # gemeente = QStandardItem("%s" % (address["gemeente"])) # provincie = QStandardItem("%s" % (address["provincie"])) # self.geocoderSourceModel.appendRow([adrestekst, straat, nummer, postcode, plaats, gemeente, provincie]) # # self.dlg.geocoderResultView.selectRow(0) # self.zoomToAddress() # # self.geocoderSourceModel.setHeaderData(0, Qt.Horizontal, "Resultaat") # self.geocoderSourceModel.setHeaderData(1, Qt.Horizontal, "Straat") # self.geocoderSourceModel.setHeaderData(2, Qt.Horizontal, "Nr") # self.geocoderSourceModel.setHeaderData(3, Qt.Horizontal, "Postcode") # self.geocoderSourceModel.setHeaderData(4, Qt.Horizontal, "Plaats") # self.geocoderSourceModel.setHeaderData(5, Qt.Horizontal, "Gemeente") # self.geocoderSourceModel.setHeaderData(6, Qt.Horizontal, "Provincie") # # self.geocoderSourceModel.horizontalHeaderItem(0).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(1).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(2).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(3).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(4).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(5).setTextAlignment(Qt.AlignLeft) # self.geocoderSourceModel.horizontalHeaderItem(6).setTextAlignment(Qt.AlignLeft) # # self.dlg.geocoderResultView.resizeColumnsToContents() # self.dlg.geocoderResultView.horizontalHeader().setStretchLastSection(True) def zoomToAddress(self): # get x,y from data of record self.removePointer() data = self.dlg.geocoderResultView.selectedIndexes()[0].data( Qt.UserRole) if 'centroide_rd' in data: # free OR lookup service geom = QgsGeometry.fromWkt(data['centroide_rd']) adrestekst = data['adrestekst'] else: # no centroid yet, probably only object id, retrieve it via lookup service id = data['id'] data = self.pdokgeocoder.lookup(id) geom = QgsGeometry.fromWkt(data['centroide_rd']) adrestekst = data['adrestekst'] lookup_data = data['data'] lis = '' for key in lookup_data.keys(): lis = lis + '<li>{}: {}</li>'.format(key, lookup_data[key]) self.dlg.ui.lookupinfo.setHtml('<h4>{}</h4><lu>{}</lu>'.format( adrestekst, lis)) # just always transform from 28992 to mapcanvas crs crs = self.iface.mapCanvas().mapSettings().destinationCrs() crs28992 = QgsCoordinateReferenceSystem() crs28992.createFromId(28992) crsTransform = QgsCoordinateTransform(crs28992, crs, QgsProject.instance()) z = 1587 if adrestekst.lower().startswith('adres'): z = 794 elif adrestekst.lower().startswith('perceel'): z = 794 elif adrestekst.lower().startswith('hectometer'): z = 1587 elif adrestekst.lower().startswith('straat'): z = 3175 elif adrestekst.lower().startswith('postcode'): z = 6350 elif adrestekst.lower().startswith('woonplaats'): z = 25398 elif adrestekst.lower().startswith('gemeente'): z = 50797 elif adrestekst.lower().startswith('provincie'): z = 812750 geom.transform(crsTransform) center = geom.asPoint() self.setPointer(center) # zoom to with center is actually setting a point rectangle and then zoom rect = QgsRectangle(center, center) self.iface.mapCanvas().setExtent(rect) self.iface.mapCanvas().zoomScale(z) self.iface.mapCanvas().refresh() def setPointer(self, point): self.removePointer() self.pointer = QgsVertexMarker(self.iface.mapCanvas()) self.pointer.setColor(QColor(255, 255, 0)) self.pointer.setIconSize(10) self.pointer.setPenWidth(5) self.pointer.setCenter(point) self.clean_action.setEnabled(True) def removePointer(self): if self.pointer is not None: self.iface.mapCanvas().scene().removeItem(self.pointer) self.clean_action.setEnabled(False) def info(self, msg=""): QgsMessageLog.logMessage('{}'.format(msg), 'PDOK-services Plugin', Qgis.Info)
class XYZHubConnector(object): """base plugin""" def __init__(self, iface): """init""" import sys print(sys.version) self.iface = iface self.web_menu = "&XYZ Hub Connector" self.init_modules() self.obj = self def initGui(self): """startup""" parent = self.iface.mainWindow() ######## action, button icon = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/xyz.png")) icon_bbox = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/bbox.svg")) self.action_connect = QAction(icon, "XYZ Hub Connection", parent) self.action_connect.setWhatsThis( QCoreApplication.translate(PLUGIN_NAME, "WhatsThis message")) self.action_connect.setStatusTip( QCoreApplication.translate(PLUGIN_NAME, "status tip message")) self.action_magic_sync = QAction("Magic Sync (EXPERIMENTAL)", parent) if self.iface.activeLayer() is None: self.action_magic_sync.setEnabled(False) # self.action_magic_sync.setVisible(False) # disable magic sync ######## CONNECT action, button self.action_connect.triggered.connect(self.open_connection_dialog) self.action_magic_sync.triggered.connect(self.open_magic_sync_dialog) ######## Add the toolbar + button self.toolbar = self.iface.addToolBar(PLUGIN_NAME) self.toolbar.setObjectName("XYZ Hub Connector") self.actions = [self.action_connect] for a in self.actions: self.iface.addPluginToWebMenu(self.web_menu, a) # # uncomment to use menu button # tool_btn = QToolButton(self.toolbar) # for a in self.actions: # tool_btn.addAction(a) # tool_btn.setDefaultAction(self.action_connect) # tool_btn.setPopupMode(tool_btn.MenuButtonPopup) # self.xyz_widget_action = self.toolbar.addWidget(tool_btn) # uncomment to use menu button self.toolbar.addAction(self.action_connect) self.action_help = None progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(0) progress.reset() progress.hide() # progress = self.iface.statusBarIface().children()[2] # will be hidden by qgis self.iface.statusBarIface().addPermanentWidget(progress) self.pb = progress def init_modules(self): # util.init_module() # parent = self.iface.mainWindow() parent = QgsProject.instance() self.secret = Secret(config.USER_PLUGIN_DIR + "/secret.ini") ######## Init xyz modules self.map_basemap_meta = basemap.load_default_xml() self.auth_manager = AuthManager(config.USER_PLUGIN_DIR + "/auth.ini") self.token_model = GroupTokenModel(parent) # self.layer = LayerManager(parent, self.iface) self.network = NetManager(parent) self.con_man = LoaderManager() self.con_man.config(self.network) self.layer_man = LayerManager() ######## data flow # self.conn_info = SpaceConnectionInfo() ######## token self.token_model.load_ini(config.USER_PLUGIN_DIR + "/token.ini") ######## CALLBACK self.con_man.ld_pool.signal.progress.connect( self.cb_progress_busy) #, Qt.QueuedConnection self.con_man.ld_pool.signal.finished.connect(self.cb_progress_done) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.layer_man.remove) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.con_man.remove) # self.iface.currentLayerChanged.connect( self.cb_layer_selected) # UNCOMMENT if LOG_TO_FILE: QgsApplication.messageLog().messageReceived.connect(cb_log_qgis) def unload_modules(self): # self.con_man.disconnect_ux( self.iface) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.layer_man.remove) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.con_man.remove) # utils.disconnect_silent(self.iface.currentLayerChanged) # self.iface.mapCanvas().extentsChanged.disconnect( self.debug_reload) self.secret.deactivate() # close_file_logger() pass def unload(self): """teardown""" self.unload_modules() # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.toolbar.clear( ) # remove action from custom toolbar (toolbar still exist) self.toolbar.deleteLater() for a in self.actions: self.iface.removePluginWebMenu(self.web_menu, a) ############### # Callback ############### def cb_layer_selected(self, qlayer): flag_xyz = True if qlayer is not None and self.layer.is_xyz_supported_layer( qlayer) else False # disable magic sync # self.action_magic_sync.setEnabled(flag_xyz) ############### # Callback of action (main function) ############### def cb_success_msg(self, msg, info=""): self.iface.messageBar().pushMessage(msg, info, Qgis.Success, 5) def make_cb_success(self, msg, info=""): def _cb_success_msg(): txt = info self.cb_success_msg(msg, txt) return _cb_success_msg def make_cb_success_args(self, msg, info=""): def _cb_success_msg(args): a, kw = parse_qt_args(args) txt = ". ".join(map(str, a)) self.cb_success_msg(msg, txt) return _cb_success_msg def cb_handle_error_msg(self, e): err = parse_exception_obj(e) if isinstance(err, ChainInterrupt): e0, idx = err.args[0:2] if isinstance( e0, (net_handler.NetworkError, net_handler.NetworkTimeout)): ok = self.show_net_err(e0) if ok: return elif isinstance(e0, EmptyXYZSpaceError): ret = exec_warning_dialog( "XYZ Hub", "Requested query returns no features") return self.show_err_msgbar(err) def show_net_err(self, err): reply_tag, status, reason, body, err_str, url = err.args[:6] if reply_tag in ["count", "statistics"]: # too many error # msg = "Network Error: %s: %s. %s"%(status, reason, err_str) return 1 detail = "\n".join(["Request:", url, "", "Response:", body]) msg = ("%s: %s\n" % (status, reason) + "There was a problem connecting to the server") if status == 403: msg += "\n\n" + "Please make sure that the token has WRITE permission" ret = exec_warning_dialog("Network Error", msg, detail) return 1 def show_err_msgbar(self, err): self.iface.messageBar().pushMessage(TAG_PLUGIN, repr(err), Qgis.Warning, 3) msg = format_traceback(err) QgsMessageLog.logMessage(msg, TAG_PLUGIN, Qgis.Warning) def cb_progress_busy(self, n_active): if n_active > 1: return self.flag_pb_show = True self.cb_progress_refresh() def cb_progress_done(self): self.flag_pb_show = False self.cb_progress_refresh() def cb_progress_refresh(self): if not hasattr(self, "flag_pb_show"): return pb = self.pb if self.flag_pb_show: pb.show() # print_qgis("show",pb) else: pb.hide() # print_qgis("hide") ############### # Action (main function) ############### # unused def load_bbox(self, con, args): bbox = bbox_utils.extend_to_bbox( bbox_utils.get_bounding_box(self.iface)) a, kw = parse_qt_args(args) kw["bbox"] = bbox kw["limit"] = 1000 con.start(*a, **kw) # UNUSED def refresh_canvas(self): # self.iface.activeLayer().triggerRepaint() self.iface.mapCanvas().refresh() def previous_canvas_extent(self): self.iface.mapCanvas().zoomToPreviousExtent() # def new_main_dialog(self): parent = self.iface.mainWindow() dialog = MainDialog(parent) dialog.config(self.token_model) dialog.config_secret(self.secret) auth = self.auth_manager.get_auth() dialog.config_basemap(self.map_basemap_meta, auth) con = self.con_man.make_con("create") con.signal.finished.connect( dialog.btn_use.clicked.emit) # can be optimized !! con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("list") con.signal.results.connect(make_fun_args(dialog.cb_display_spaces)) con.signal.error.connect(self.cb_handle_error_msg) con.signal.error.connect(lambda e: dialog.cb_enable_token_ui()) con.signal.finished.connect(dialog.cb_enable_token_ui) con = self.con_man.make_con("edit") con.signal.finished.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("delete") con.signal.results.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("stat") con.signal.results.connect(make_fun_args( dialog.cb_display_space_count)) con.signal.error.connect(self.cb_handle_error_msg) ############ clear cache btn dialog.signal_clear_cache.connect(self.open_clear_cache_dialog) ############ add map tile btn dialog.signal_add_basemap.connect(self.add_basemap_layer) ############ btn: new, edit, delete space dialog.signal_new_space.connect(self.start_new_space) dialog.signal_edit_space.connect(self.start_edit_space) dialog.signal_del_space.connect(self.start_delete_space) ############ Use Token btn dialog.signal_use_token.connect(lambda a: self.con_man.finish_fast()) dialog.signal_use_token.connect(self.start_use_token) ############ get count dialog.signal_space_count.connect( self.start_count_feat, Qt.QueuedConnection) # queued -> non-blocking ui ############ connect btn dialog.signal_space_connect.connect(self.start_load_layer) ############ upload btn dialog.signal_upload_space.connect(self.start_upload_space) return dialog def start_new_space(self, args): con = self.con_man.get_con("create") con.start_args(args) def start_edit_space(self, args): con = self.con_man.get_con("edit") con.start_args(args) def start_delete_space(self, args): con = self.con_man.get_con("delete") con.start_args(args) def start_use_token(self, args): con = self.con_man.get_con("list") con.start_args(args) def start_count_feat(self, args): con = self.con_man.get_con("stat") con.start_args(args) def start_upload_space(self, args): con_upload = UploadLayerController(self.network, n_parallel=2) self.con_man.add_background(con_upload) # con_upload.signal.finished.connect( self.make_cb_success("Uploading finish") ) con_upload.signal.results.connect( self.make_cb_success_args("Uploading finish")) con_upload.signal.error.connect(self.cb_handle_error_msg) con = InitUploadLayerController(self.network) self.con_man.add_background(con) con.signal.results.connect(con_upload.start_args) con.signal.error.connect(self.cb_handle_error_msg) con.start_args(args) def start_load_layer(self, args): # create new con # config # run ############ connect btn con_load = LoadLayerController(self.network, n_parallel=1) self.con_man.add_background(con_load) # con_load.signal.finished.connect( self.make_cb_success("Loading finish") ) con_load.signal.results.connect( self.make_cb_success_args("Loading finish")) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect(self.cb_handle_error_msg) con_load.start_args(args) # con.signal.results.connect( self.layer_man.add_args) # IMPORTANT def add_basemap_layer(self, args): a, kw = parse_qt_args(args) meta, app_id, app_code = a self.auth_manager.save(app_id, app_code) basemap.add_basemap_layer(meta, app_id, app_code) ############### # Open dialog ############### def open_clear_cache_dialog(self): dialog = ConfirmDialog( "Delete cache will make loaded layer unusable !!") ret = dialog.exec_() if ret != dialog.Ok: return utils.clear_cache() def open_connection_dialog(self): dialog = self.new_main_dialog() vlayer = self.iface.activeLayer() dialog.set_layer(vlayer) dialog.exec_() self.con_man.finish_fast() # self.startTime = time.time() # not used def open_magic_sync_dialog(self): pass
class ImpEpanet(object): def __init__(self, iface): # Save a reference to the QGIS iface self.iface = iface self.canvas = self.iface.mapCanvas() self.dlg = ExportEpanetInpFilesDialog() self.sections = [ 'junctions', 'tanks', 'pipes', 'pumps', 'reservoirs', 'valves', 'STATUS', 'PATTERNS', 'CURVES', 'CONTROLS', 'RULES', 'ENERGY', 'REACTIONS', 'REACTIONS_I', 'EMITTERS', 'QUALITY', 'SOURCES', 'MIXING', 'TIMES', 'REPORT', 'OPTIONS' ] def initGui(self): # Create action sys.path.append(os.path.dirname(__file__) + '/impcount.py') self.action = QAction( QIcon(":/plugins/ImportEpanetInpFiles/impepanet.png"), "Import Epanet Input File", self.iface.mainWindow()) self.action.setWhatsThis("Import Epanet Input File") self.action.triggered.connect(self.run) self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&ImportEpanetInpFiles", self.action) self.actionexp = QAction( QIcon(":/plugins/ImportEpanetInpFiles/expepanet.png"), "Export Epanet Input File", self.iface.mainWindow()) self.actionexp.setWhatsThis("Export Epanet Input File") self.actionexp.triggered.connect(self.runexp) self.iface.addToolBarIcon(self.actionexp) self.iface.addPluginToMenu("&ImportEpanetInpFiles", self.actionexp) self.dlg.ok_button.clicked.connect(self.ok) self.dlg.cancel_button.clicked.connect(self.cancel) self.dlg.toolButtonOut.clicked.connect(self.toolButtonOut) def unload(self): # Remove the plugin self.iface.removePluginMenu("&ImportEpanetInpFiles", self.action) self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu("&ImportEpanetInpFiles", self.actionexp) self.iface.removeToolBarIcon(self.actionexp) def run(self): filePath = QFileDialog.getOpenFileName( self.iface.mainWindow(), "Choose EPANET Input file", os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop'), "Epanet Inp File (*.inp)") if filePath[0] == "": return epa2gis(filePath[0]) self.iface.messageBar().clearWidgets() msgBox = QMessageBox() msgBox.setWindowTitle('ImportEpanetInpFiles') msgBox.setText( 'Shapefiles have been created successfully in folder "_shapefiles_".' ) msgBox.exec_() def runexp(self): self.dlg.out.setText('') self.layers = self.canvas.layers() self.layer_list = [] self.layer_list = ['NONE'] [self.layer_list.append(layer.name()) for layer in self.layers] for sect in self.sections: eval('self.dlg.sect_' + sect + '.clear()') eval('self.dlg.sect_' + sect + '.addItems(self.layer_list)') indices = [i for i, s in enumerate(self.layer_list) if sect in s] if indices: if sect == 'REACTIONS': eval('self.dlg.sect_' + sect + '.setCurrentIndex(indices[1])') else: eval('self.dlg.sect_' + sect + '.setCurrentIndex(indices[0])') self.dlg.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) self.dlg.show() def cancel(self): self.layer_list = [] self.layer_list = ['NONE'] for sect in self.sections: exec('self.dlg.sect_' + sect + '.clear()') self.dlg.close() def toolButtonOut(self): self.outEpanetName = QFileDialog.getSaveFileName( None, 'Save File', os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop'), 'Epanet Inp File (*.inp)') self.dlg.out.setText(self.outEpanetName[0]) def selectOutp(self): msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('Please define Epanet Inp File location.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return True def ok(self): # Here check if select OK button, get the layer fields # Initialize # [JUNCTIONS] if self.dlg.out.text() == '': if self.selectOutp(): return elif os.path.isabs(self.dlg.out.text()) == False: if self.selectOutp(): return self.outEpanetName = self.dlg.out.text() try: f = open(self.outEpanetName, "w") f.close() except: msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('Please define Epanet Inp File location.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return if not self.layers: msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle('Warning') msgBox.setText('No layers selected.') msgBox.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint) msgBox.exec_() return xypipes_id = [] xypipesvert = [] for sect in self.sections: exec('sect' + sect + '=[]') in globals(), locals() exec('xy' + sect + '=[]') in globals(), locals() if eval('self.dlg.sect_' + sect + '.currentText()') != 'NONE': # Get layer field names indLayerName = self.layer_list.index( eval('self.dlg.sect_' + sect + '.currentText()')) - 1 provider = self.layers[indLayerName].dataProvider() fields = provider.fields() field_names = [field.name() for field in fields] for elem in self.layers[indLayerName].getFeatures(): eval('sect' + sect + '.append(dict(zip(field_names, elem.attributes())))') if any(sect in s for s in self.sections[0:5]): geom = elem.geometry() if self.layers[indLayerName].geometryType() == 0: eval('xy' + sect + '.append(geom.asPoint())') elif self.layers[indLayerName].geometryType() == 1: eval('xy' + sect + '.append(geom.asPolyline())') if sect == 'pipes': if len(geom.asPolyline()) > 2: for pp in range( len(geom.asPolyline()) - 2): xypipes_id.append(elem.attributes()[0]) xypipesvert.append( geom.asPolyline()[pp]) if sect == 'junctions': if 'Elevation' not in locals()['sect' + sect][0].keys(): QMessageBox.warning(QWidget(), "Message", "Elevation field is missing.") # (myDirectory,nameFile) = os.path.split(self.iface.activeLayer().dataProvider().dataSourceUri()) my_directory = '' f = open(self.outEpanetName, 'wt') f.write('[TITLE]\n') f.write('Export input file via plugin ExportEpanetInpFiles. \n\n') f.write('[JUNCTIONS]\n') node_i_ds = [] for i in range(len(locals()['sectjunctions'])): node_i_ds.append(locals()['sectjunctions'][i]['ID']) f.write(locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['sectjunctions'][i]['Elevation']) + '\n') f.write('\n[RESERVOIRS]\n') for i in range(len(locals()['sectreservoirs'])): node_i_ds.append(locals()['sectreservoirs'][i]['ID']) f.write(locals()['sectreservoirs'][i]['ID'] + ' ' + str(locals()['sectreservoirs'][i]['Head']) + '\n') f.write('\n[TANKS]\n') for i in range(len(locals()['secttanks'])): node_i_ds.append(locals()['secttanks'][i]['ID']) if locals()['secttanks'][i]['VolumeCurv'] == None: locals()['secttanks'][i]['VolumeCurv'] = "" f.write(locals()['secttanks'][i]['ID'] + ' ' + str(locals()['secttanks'][i]['Elevation']) + ' ' + str(locals()['secttanks'][i]['InitLevel']) + ' ' + str(locals()['secttanks'][i]['MinLevel']) + ' ' + str(locals()['secttanks'][i]['MaxLevel']) + ' ' + str(locals()['secttanks'][i]['Diameter']) + ' ' + str(locals()['secttanks'][i]['MinVolume']) + ' ' + str(locals()['secttanks'][i]['VolumeCurv']) + ' ' + '\n') f.write('\n[PIPES]\n') for i in range(len(locals()['sectpipes'])): if (locals()['sectpipes'][i]['NodeFrom'] in node_i_ds) and (locals()['sectpipes'][i]['NodeTo'] in node_i_ds): f.write(locals()['sectpipes'][i]['ID'] + ' ' + locals()['sectpipes'][i]['NodeFrom'] + ' ' + locals()['sectpipes'][i]['NodeTo'] + ' ' + str(locals()['sectpipes'][i]['Length']) + ' ' + str(locals()['sectpipes'][i]['Diameter']) + ' ' + str(locals()['sectpipes'][i]['Roughness']) + ' ' + str(locals()['sectpipes'][i]['MinorLoss']) + ' ' + locals()['sectpipes'][i]['Status'] + '\n') f.write('\n[PUMPS]\n') for i in range(len(locals()['sectpumps'])): if locals()['sectpumps'][i]['Curve'] != 'NULL': try: locals()['sectpumps'][i]['Curve'] = 'HEAD ' + locals( )['sectpumps'][i]['Curve'] except: locals()['sectpumps'][i]['Curve'] = 'HEAD ' else: locals()['sectpumps'][i]['Curve'] = '' if locals()['sectpumps'][i]['Pattern'] != 'NULL': try: locals()['sectpumps'][i]['Pattern'] = 'PATTERN ' + locals( )['sectpumps'][i]['Pattern'] except: locals()['sectpumps'][i]['Pattern'] = "PATTERN " else: locals()['sectpumps'][i]['Pattern'] = '' if locals()['sectpumps'][i]['Power'] != 'NULL': try: locals()['sectpumps'][i]['Power'] = 'POWER ' + locals( )['sectpumps'][i]['Power'] except: locals()['sectpumps'][i]['Power'] = "POWER " else: locals()['sectpumps'][i]['Power'] = '' try: f.write(locals()['sectpumps'][i]['ID'] + ' ' + locals()['sectpumps'][i]['NodeFrom'] + ' ' + locals()['sectpumps'][i]['NodeTo'] + ' ' + locals()['sectpumps'][i]['Curve'] + ' ' + str(locals()['sectpumps'][i]['Pattern']) + ' ' + str(locals()['sectpumps'][i]['Power']) + '\n') except: f.write(locals()['sectpumps'][i]['ID'] + '\n') f.write('\n[VALVES]\n') if self.dlg.sect_valves.currentText() != 'NONE': for i in range(len(locals()['sectvalves'])): try: locals()['sectvalves'][i]['NodeFrom'] = locals( )['sectvalves'][i]['NodeFrom'] + '' except: locals()['sectvalves'][i]['NodeFrom'] = "" try: locals()['sectvalves'][i]['NodeTo'] = locals( )['sectvalves'][i]['NodeTo'] + '' except: locals()['sectvalves'][i]['NodeTo'] = "" f.write("{} {} {} {} {} {} {}\n".format( locals()['sectvalves'][i]['ID'], locals()['sectvalves'][i]['NodeFrom'], locals()['sectvalves'][i]['NodeTo'], str(locals()['sectvalves'][i]['Diameter']), locals()['sectvalves'][i]['Type'], str(locals()['sectvalves'][i]['Setting']), str(locals()['sectvalves'][i]['MinorLoss']))) f.write('\n[DEMANDS]\n') for i in range(len(locals()['sectjunctions'])): for u in range(int((len(locals()['sectjunctions'][i]) - 2) / 2)): if locals( )['sectjunctions'][i]['Demand' + str(u + 1)] == 0 and str( locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) == 'None': continue if str(locals()['sectjunctions'][i] ['Pattern' + str(u + 1)]) == 'NULL' or str( locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) == 'None': locals()['sectjunctions'][i]['Pattern' + str(u + 1)] = '' f.write( locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['sectjunctions'][i]['Demand' + str(u + 1)]) + ' ' + str(locals()['sectjunctions'][i]['Pattern' + str(u + 1)]) + '\n') f.write('\n[STATUS]\n') for i in range(len(locals()['sectSTATUS'])): f.write("{} {}\n".format( locals()['sectSTATUS'][i]['Link_ID'], locals()['sectSTATUS'][i]['Status/Set'])) f.write('\n[PATTERNS]\n') for i in range(len(locals()['sectPATTERNS'])): f.write("{} {}\n".format( locals()['sectPATTERNS'][i]['Pattern_ID'], locals()['sectPATTERNS'][i]['Multiplier'])) f.write('\n[CURVES]\n') for i in range(len(locals()['sectCURVES'])): f.write(";{}:\n {} {} {}\n".format( locals()['sectCURVES'][i]['Type'], locals()['sectCURVES'][i]['Curve_ID'], str(locals()['sectCURVES'][i]['X-Value']), str(locals()['sectCURVES'][i]['Y-Value']))) f.write('\n[CONTROLS]\n') for i in range(len(locals()['sectCONTROLS'])): f.write("{}\n".format(locals()['sectCONTROLS'][i]['Controls'])) f.write('\n[RULES]\n') for i in range(len(locals()['sectRULES'])): f.write("RULE {}\n {}\n".format( locals()['sectRULES'][i]['Rule_ID'], locals()['sectRULES'][i]['Rule'])) f.write('\n[ENERGY]\n') if locals()['sectENERGY']: try: f.write('Global Efficiency ' + str(locals()['sectENERGY'][0]['GlobalEffi']) + '\n') except: pass try: f.write('Global Price ' + str(locals()['sectENERGY'][0]['GlobalPric']) + '\n') except: pass try: f.write('Demand Charge ' + str(locals()['sectENERGY'][0]['DemCharge']) + '\n') except: pass f.write('\n[REACTIONS]\n') if locals()['sectREACTIONS']: try: f.write('Order Bulk ' + str(locals()['sectREACTIONS'][0]['OrderBulk']) + '\n') except: pass try: f.write('Order Tank ' + str(locals()['sectREACTIONS'][0]['OrderTank']) + '\n') except: pass try: f.write('Order Wall ' + str(locals()['sectREACTIONS'][0]['OrderWall']) + '\n') except: pass try: f.write('Global Bulk ' + str(locals()['sectREACTIONS'][0]['GlobalBulk']) + '\n') except: pass try: f.write('Global Wall ' + str(locals()['sectREACTIONS'][0]['GlobalWall']) + '\n') except: pass try: f.write('Limiting Potential ' + str(locals()['sectREACTIONS'][0]['LimPotent']) + '\n') except: pass try: f.write('Roughness Correlation ' + str(locals()['sectREACTIONS'][0]['RoughCorr']) + '\n') except: pass f.write('\n[REACTIONS]\n') for i in range(len(locals()['sectREACTIONS_I'])): f.write('{} {} {} \n'.format( locals()['sectREACTIONS_I'][i]['Type'], locals()['sectREACTIONS_I'][i]['Pipe/Tank'], str(locals()['sectREACTIONS_I'][i]['Coeff.']))) f.write('\n[EMITTERS]\n') for i in range(len(locals()['sectEMITTERS'])): f.write('{} {}\n'.format( locals()['sectEMITTERS'][i]['Junc_ID'], str(locals()['sectEMITTERS'][i]['Coeff.']))) f.write('\n[SOURCES]\n') for i in range(len(locals()['sectSOURCES'])): try: locals()['sectSOURCES'][i]['Pattern'] = locals( )['sectSOURCES'][i]['Pattern'] + '' except: locals()['sectSOURCES'][i]['Pattern'] = '' f.write("{} {} {} {}\n".format( locals()['sectSOURCES'][i]['Node_ID'], locals()['sectSOURCES'][i]['Type'], str(locals()['sectSOURCES'][i]['Strength']), locals()['sectSOURCES'][i]['Pattern'])) f.write('\n[MIXING]\n') for i in range(len(locals()['sectMIXING'])): f.write('{} {} {} \n'.format( locals()['sectMIXING'][i]['Tank_ID'], locals()['sectMIXING'][i]['Model'], str(locals()['sectMIXING'][i]['Fraction']))) f.write('\n[TIMES]\n') if locals()['sectTIMES']: try: f.write('Duration ' + str(locals()['sectTIMES'][0]['Duration']) + '\n') except: pass try: f.write('Hydraulic Timestep ' + str(locals()['sectTIMES'][0]['HydStep']) + '\n') except: pass try: f.write('Quality Timestep ' + str(locals()['sectTIMES'][0]['QualStep']) + '\n') except: pass try: f.write('Pattern Timestep ' + str(locals()['sectTIMES'][0]['PatStep']) + '\n') except: pass try: f.write('Pattern Start ' + str(locals()['sectTIMES'][0]['PatStart']) + '\n') except: pass try: f.write('Report Timestep ' + str(locals()['sectTIMES'][0]['RepStep']) + '\n') except: pass try: f.write('Report Start ' + str(locals()['sectTIMES'][0]['RepStart']) + '\n') except: pass try: f.write('Start ClockTime ' + str(locals()['sectTIMES'][0]['StartClock']) + '\n') except: pass try: f.write('Statistic ' + str(locals()['sectTIMES'][0]['Statistic']) + '\n') except: pass f.write('\n[REPORT]\n') if locals()['sectREPORT']: try: f.write('Status ' + locals()['sectREPORT'][0]['Status'] + '\n') except: pass try: f.write('Summary ' + locals()['sectREPORT'][0]['Summary'] + '\n') except: pass try: f.write('Page ' + locals()['sectREPORT'][0]['Page'] + '\n') except: pass f.write('\n[OPTIONS]\n') if locals()['sectOPTIONS']: try: f.write('Units ' + str(locals()['sectOPTIONS'][0]['Units']) + '\n') except: pass try: f.write('Headloss ' + str(locals()['sectOPTIONS'][0]['Headloss']) + '\n') except: pass try: f.write('Specific Gravity ' + str(locals()['sectOPTIONS'][0]['SpecGrav']) + '\n') except: pass try: f.write('Viscosity ' + str(locals()['sectOPTIONS'][0]['Viscosity']) + '\n') except: pass try: f.write('Trials ' + str(locals()['sectOPTIONS'][0]['Trials']) + '\n') except: pass try: f.write('Accuracy ' + str(locals()['sectOPTIONS'][0]['Accuracy']) + '\n') except: pass try: f.write('CHECKFREQ ' + str(locals()['sectOPTIONS'][0]['CheckFreq']) + '\n') except: pass try: f.write('MAXCHECK ' + str(locals()['sectOPTIONS'][0]['MaxCheck']) + '\n') except: pass try: f.write('DAMPLIMIT ' + str(locals()['sectOPTIONS'][0]['DampLimit']) + '\n') except: pass try: f.write('Unbalanced ' + str(locals()['sectOPTIONS'][0]['Unbalanced']) + '\n') except: pass try: f.write('Pattern ' + str(locals()['sectOPTIONS'][0]['PatID']) + '\n') except: pass try: f.write('Demand Multiplier ' + str(locals()['sectOPTIONS'][0]['DemMult']) + '\n') except: pass try: f.write('Emitter Exponent ' + str(locals()['sectOPTIONS'][0]['EmitExp']) + '\n') except: pass try: f.write('Quality ' + str(locals()['sectOPTIONS'][0]['Quality']) + '\n') except: pass try: f.write('Diffusivity ' + str(locals()['sectOPTIONS'][0]['Diffusivit']) + '\n') except: pass try: f.write('Tolerance ' + str(locals()['sectOPTIONS'][0]['Tolerance']) + '\n') except: pass f.write('\n[COORDINATES]\n') for i in range(len(locals()['sectjunctions'])): f.write(locals()['sectjunctions'][i]['ID'] + ' ' + str(locals()['xyjunctions'][i][0]) + ' ' + str(locals()['xyjunctions'][i][1]) + '\n') for i in range(len(locals()['sectreservoirs'])): f.write(locals()['sectreservoirs'][i]['ID'] + ' ' + str(locals()['xyreservoirs'][i][0]) + ' ' + str(locals()['xyreservoirs'][i][1]) + '\n') for i in range(len(locals()['secttanks'])): f.write(locals()['secttanks'][i]['ID'] + ' ' + str(locals()['xytanks'][i][0]) + ' ' + str(locals()['xytanks'][i][1]) + '\n') f.write('\n[VERTICES]\n') for l in range(len(xypipes_id)): f.write(xypipes_id[l] + ' ' + str(xypipesvert[l][0]) + ' ' + str(xypipesvert[l][1]) + '\n') f.write('\n[END]\n') f.close() self.cancel() msgBox = QMessageBox() msgBox.setWindowTitle('Export Options') msgBox.setText('Export Epanet Inp File "' + self.outEpanetName + '" succesful.') msgBox.exec_()
class PyArchInitPlugin(object): HOME = os.environ['PYARCHINIT_HOME'] PARAMS_DICT = { 'SERVER': '', 'HOST': '', 'DATABASE': '', 'PASSWORD': '', 'PORT': '', 'USER': '', 'THUMB_PATH': '', 'EXPERIMENTAL': '' } path_rel = os.path.join(os.sep, HOME, 'pyarchinit_DB_folder', 'config.cfg') conf = open(path_rel, "r") data = conf.read() conf.close() PARAMS_DICT = eval(data) # TODO: find a better way to settings config # if 'EXPERIMENTAL' in PARAMS_DICT: # PARAMS_DICT['EXPERIMENTAL'] = 'No' # f = open(path_rel, "w") # f.write(str(PARAMS_DICT)) # f.close() def __init__(self, iface): self.iface = iface userPluginPath = os.path.dirname(__file__) systemPluginPath = QgsApplication.prefixPath( ) + "/python/plugins/pyarchinit" overrideLocale = QgsSettings().value("locale/overrideFlag", QVariant) # .toBool() if not overrideLocale: localeFullName = QLocale.system().name() else: localeFullName = QgsSettings().value("locale/userLocale", QVariant) # .toString() if QFileInfo(userPluginPath).exists(): translationPath = userPluginPath + "/i18n/pyarchinit_plugin_" + localeFullName + ".qm" else: translationPath = systemPluginPath + "/i18n/pyarchinit_plugin_" + localeFullName + ".qm" self.localePath = translationPath if QFileInfo(self.localePath).exists(): self.translator = QTranslator() self.translator.load(self.localePath) QCoreApplication.installTranslator(self.translator) def initGui(self): settings = QgsSettings() icon_paius = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'pai_us.png')) self.action = QAction(QIcon(icon_paius), "pyArchInit Main Panel", self.iface.mainWindow()) self.action.triggered.connect(self.showHideDockWidget) # dock widget self.dockWidget = PyarchinitPluginDialog(self.iface) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockWidget) # TOOLBAR self.toolBar = self.iface.addToolBar("pyArchInit") self.toolBar.setObjectName("pyArchInit") self.toolBar.addAction(self.action) self.dataToolButton = QToolButton(self.toolBar) self.dataToolButton.setPopupMode(QToolButton.MenuButtonPopup) ###### Section dedicated to the basic data entry # add Actions data icon_site = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSite.png')) self.actionSite = QAction(QIcon(icon_site), "Siti", self.iface.mainWindow()) self.actionSite.setWhatsThis("Siti") self.actionSite.triggered.connect(self.runSite) icon_US = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSus.png')) self.actionUS = QAction(QIcon((icon_US)), u"US", self.iface.mainWindow()) self.actionUS.setWhatsThis(u"US") self.actionUS.triggered.connect(self.runUS) icon_Finds = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconFinds.png')) self.actionInr = QAction(QIcon(icon_Finds), "Reperti", self.iface.mainWindow()) self.actionInr.setWhatsThis("Reperti") self.actionInr.triggered.connect(self.runInr) icon_camp_exp = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'champion.png')) self.actionCampioni = QAction(QIcon(icon_camp_exp), "Campioni", self.iface.mainWindow()) self.actionCampioni.setWhatsThis("Campioni") self.actionCampioni.triggered.connect(self.runCampioni) icon_Lapidei = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconAlma.png')) self.actionLapidei = QAction(QIcon(icon_Lapidei), "Lapidei", self.iface.mainWindow()) self.actionLapidei.setWhatsThis("Lapidei") self.actionLapidei.triggered.connect(self.runLapidei) self.dataToolButton.addActions([ self.actionSite, self.actionUS, self.actionInr, self.actionCampioni, self.actionLapidei ]) self.dataToolButton.setDefaultAction(self.actionSite) self.toolBar.addWidget(self.dataToolButton) self.toolBar.addSeparator() ###### Section dedicated to the interpretations # add Actions interpretation self.interprToolButton = QToolButton(self.toolBar) self.interprToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_per = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconPer.png')) self.actionPer = QAction(QIcon(icon_per), "Periodizzazione", self.iface.mainWindow()) self.actionPer.setWhatsThis("Periodizzazione") self.actionPer.triggered.connect(self.runPer) icon_Struttura = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconStrutt.png')) self.actionStruttura = QAction(QIcon(icon_Struttura), "Strutture", self.iface.mainWindow()) self.actionPer.setWhatsThis("Strutture") self.actionStruttura.triggered.connect(self.runStruttura) self.interprToolButton.addActions( [self.actionStruttura, self.actionPer]) self.interprToolButton.setDefaultAction(self.actionStruttura) self.toolBar.addWidget(self.interprToolButton) self.toolBar.addSeparator() ###### Section dedicated to the funerary archaeology # add Actions funerary archaeology self.funeraryToolButton = QToolButton(self.toolBar) self.funeraryToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_Schedaind = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconIND.png')) self.actionSchedaind = QAction(QIcon(icon_Schedaind), "Individui", self.iface.mainWindow()) self.actionSchedaind.setWhatsThis("Individui") self.actionSchedaind.triggered.connect(self.runSchedaind) icon_Tafonomia = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconGrave.png')) self.actionTafonomia = QAction(QIcon(icon_Tafonomia), "Tafonomica/Sepolture", self.iface.mainWindow()) self.actionTafonomia.setWhatsThis("Tafonomica/Sepolture") self.actionTafonomia.triggered.connect(self.runTafonomia) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': icon_Detsesso = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconSesso.png')) self.actionDetsesso = QAction(QIcon(icon_Detsesso), "Determinazione Sesso", self.iface.mainWindow()) self.actionDetsesso.setWhatsThis("Determinazione del sesso") self.actionDetsesso.triggered.connect(self.runDetsesso) icon_Deteta = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconEta.png')) self.actionDeteta = QAction(QIcon(icon_Deteta), u"Determinazione dell'età", self.iface.mainWindow()) self.actionSchedaind.setWhatsThis(u"Determinazione dell'età") self.actionDeteta.triggered.connect(self.runDeteta) self.funeraryToolButton.addActions( [self.actionSchedaind, self.actionTafonomia]) self.funeraryToolButton.setDefaultAction(self.actionSchedaind) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.funeraryToolButton.addActions( [self.actionDetsesso, self.actionDeteta]) self.toolBar.addWidget(self.funeraryToolButton) self.toolBar.addSeparator() ###### Section dedicated to the topographical research if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.topoToolButton = QToolButton(self.toolBar) self.topoToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_UT = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconUT.png')) self.actionUT = QAction(QIcon(icon_UT), u"Unità Topografiche", self.iface.mainWindow()) self.actionUT.setWhatsThis(u"Unità Topografiche") self.actionUT.triggered.connect(self.runUT) self.topoToolButton.addActions([self.actionUT]) self.topoToolButton.setDefaultAction(self.actionUT) self.toolBar.addWidget(self.topoToolButton) self.toolBar.addSeparator() ###### Section dedicated to the documentation # add Actions documentation self.docToolButton = QToolButton(self.toolBar) self.docToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_documentazione = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'icondoc.png')) self.actionDocumentazione = QAction(QIcon(icon_documentazione), "Scheda Documentazione", self.iface.mainWindow()) self.actionDocumentazione.setWhatsThis("Documentazione") self.actionDocumentazione.triggered.connect(self.runDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': icon_imageViewer = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'photo.png')) self.actionimageViewer = QAction(QIcon(icon_imageViewer), "Gestione immagini", self.iface.mainWindow()) self.actionimageViewer.setWhatsThis("Gestione immagini") self.actionimageViewer.triggered.connect(self.runImageViewer) icon_Directory_export = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'directoryExp.png')) self.actionImages_Directory_export = QAction( QIcon(icon_Directory_export), "Esportazione immagini", self.iface.mainWindow()) self.actionImages_Directory_export.setWhatsThis( "Esportazione immagini") self.actionImages_Directory_export.triggered.connect( self.runImages_directory_export) icon_pdf_exp = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'pdf-icon.png')) self.actionpdfExp = QAction(QIcon(icon_pdf_exp), "Esportazione PDF", self.iface.mainWindow()) self.actionpdfExp.setWhatsThis("Esportazione PDF") self.actionpdfExp.triggered.connect(self.runPdfexp) self.docToolButton.addActions([self.actionDocumentazione]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.docToolButton.addActions([ self.actionpdfExp, self.actionimageViewer, self.actionpdfExp, self.actionImages_Directory_export ]) self.docToolButton.setDefaultAction(self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.actionImages_Directory_export.setCheckable(True) self.actionpdfExp.setCheckable(True) self.actionimageViewer.setCheckable(True) self.toolBar.addWidget(self.docToolButton) self.toolBar.addSeparator() ###### Section dedicated to elaborations if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.elabToolButton = QToolButton(self.toolBar) self.elabToolButton.setPopupMode(QToolButton.MenuButtonPopup) # add Actions elaboration icon_Archeozoology = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconMegacero.png')) self.actionArcheozoology = QAction(QIcon(icon_Archeozoology), "Statistiche Archeozoologiche", self.iface.mainWindow()) self.actionArcheozoology.setWhatsThis( "Statistiche Archeozoologiche") self.actionArcheozoology.triggered.connect(self.runArcheozoology) icon_GisTimeController = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconTimeControll.png')) self.actionGisTimeController = QAction( QIcon(icon_GisTimeController), "Time Manager", self.iface.mainWindow()) self.actionGisTimeController.setWhatsThis("Time Manager") self.actionGisTimeController.triggered.connect( self.runGisTimeController) icon_Comparision = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'comparision.png')) self.actionComparision = QAction(QIcon(icon_Comparision), "Comparazione immagini", self.iface.mainWindow()) self.actionComparision.setWhatsThis("Comparazione immagini") self.actionComparision.triggered.connect(self.runComparision) self.elabToolButton.addActions([ self.actionArcheozoology, self.actionComparision, self.actionGisTimeController ]) self.elabToolButton.setDefaultAction(self.actionArcheozoology) self.toolBar.addWidget(self.elabToolButton) self.toolBar.addSeparator() ###### Section dedicated to the plugin management self.manageToolButton = QToolButton(self.toolBar) self.manageToolButton.setPopupMode(QToolButton.MenuButtonPopup) icon_thesaurus = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'thesaurusicon.png')) self.actionThesaurus = QAction(QIcon(icon_thesaurus), "Thesaurus sigle", self.iface.mainWindow()) self.actionThesaurus.setWhatsThis("Thesaurus sigle") self.actionThesaurus.triggered.connect(self.runThesaurus) icon_Con = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconConn.png')) self.actionConf = QAction(QIcon(icon_Con), "Configurazione plugin", self.iface.mainWindow()) self.actionConf.setWhatsThis("Configurazione plugin") self.actionConf.triggered.connect(self.runConf) icon_Dbmanagment = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'backup.png')) self.actionDbmanagment = QAction(QIcon(icon_Dbmanagment), "Gestione database", self.iface.mainWindow()) self.actionDbmanagment.setWhatsThis("Gestione database") self.actionDbmanagment.triggered.connect(self.runDbmanagment) icon_Info = '{}{}'.format( filepath, os.path.join(os.sep, 'resources', 'icons', 'iconInfo.png')) self.actionInfo = QAction(QIcon(icon_Info), "Plugin info", self.iface.mainWindow()) self.actionInfo.setWhatsThis("Plugin info") self.actionInfo.triggered.connect(self.runInfo) self.manageToolButton.addActions([ self.actionConf, self.actionThesaurus, self.actionDbmanagment, self.actionInfo ]) self.manageToolButton.setDefaultAction(self.actionConf) self.toolBar.addWidget(self.manageToolButton) self.toolBar.addSeparator() # menu self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionSite) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionUS) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionInr) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionCampioni) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionLapidei) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionStruttura) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionPer) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionSchedaind) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionTafonomia) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDetsesso) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDeteta) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionUT) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionimageViewer) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionpdfExp) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionImages_Directory_export) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionArcheozoology) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionComparision) self.iface.addPluginToMenu( "&pyArchInit - Archaeological GIS Tools", self.actionGisTimeController) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionConf) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionThesaurus) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionDbmanagment) self.iface.addPluginToMenu("&pyArchInit - Archaeological GIS Tools", self.actionInfo) # MENU self.menu = QMenu("pyArchInit") # self.pyarchinitSite = pyarchinit_Site(self.iface) self.menu.addActions([ self.actionSite, self.actionUS, self.actionInr, self.actionCampioni, self.actionLapidei ]) self.menu.addSeparator() self.menu.addActions([self.actionPer, self.actionStruttura]) self.menu.addSeparator() self.menu.addActions([self.actionTafonomia, self.actionSchedaind]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([self.actionDetsesso, self.actionDeteta]) self.menu.addSeparator() if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([self.actionUT]) self.menu.addActions([self.actionDocumentazione]) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([ self.actionimageViewer, self.actionpdfExp, self.actionImages_Directory_export ]) self.menu.addSeparator() if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.menu.addActions([ self.actionArcheozoology, self.actionComparision, self.actionGisTimeController ]) self.menu.addSeparator() self.menu.addActions([ self.actionConf, self.actionThesaurus, self.actionDbmanagment, self.actionInfo ]) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.menu) ## def runSite(self): pluginGui = pyarchinit_Site(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runPer(self): pluginGui = pyarchinit_Periodizzazione(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runStruttura(self): pluginGui = pyarchinit_Struttura(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runUS(self): pluginGui = pyarchinit_US(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runInr(self): pluginGui = pyarchinit_Inventario_reperti(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runCampioni(self): pluginGui = pyarchinit_Campioni(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runLapidei(self): pluginGui = pyarchinit_Inventario_Lapidei(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runGisTimeController(self): pluginGui = pyarchinit_Gis_Time_Controller(self.iface) pluginGui.show() self.pluginGui = pluginGui # save def runConf(self): pluginConfGui = pyArchInitDialog_Config() pluginConfGui.show() self.pluginGui = pluginConfGui # save def runInfo(self): pluginInfoGui = pyArchInitDialog_Info() pluginInfoGui.show() self.pluginGui = pluginInfoGui # save def runImageViewer(self): pluginImageView = Main() pluginImageView.show() self.pluginGui = pluginImageView # save def runTafonomia(self): pluginTafonomia = pyarchinit_Tafonomia(self.iface) pluginTafonomia.show() self.pluginGui = pluginTafonomia # save def runSchedaind(self): pluginIndividui = pyarchinit_Schedaind(self.iface) pluginIndividui.show() self.pluginGui = pluginIndividui # save def runDetsesso(self): pluginSesso = pyarchinit_Detsesso(self.iface) pluginSesso.show() self.pluginGui = pluginSesso # save def runDeteta(self): pluginEta = pyarchinit_Deteta(self.iface) pluginEta.show() self.pluginGui = pluginEta # save def runArcheozoology(self): pluginArchezoology = pyarchinit_Archeozoology(self.iface) pluginArchezoology.show() self.pluginGui = pluginArchezoology # save def runUT(self): pluginUT = pyarchinit_UT(self.iface) pluginUT.show() self.pluginGui = pluginUT # save def runImages_directory_export(self): pluginImage_directory_export = pyarchinit_Images_directory_export() pluginImage_directory_export.show() self.pluginGui = pluginImage_directory_export # save def runComparision(self): pluginComparision = Comparision() pluginComparision.show() self.pluginGui = pluginComparision # save def runDbmanagment(self): pluginDbmanagment = pyarchinit_dbmanagment(self.iface) pluginDbmanagment.show() self.pluginGui = pluginDbmanagment # save def runPdfexp(self): pluginPdfexp = pyarchinit_pdf_export(self.iface) pluginPdfexp.show() self.pluginGui = pluginPdfexp # save def runThesaurus(self): pluginThesaurus = pyarchinit_Thesaurus(self.iface) pluginThesaurus.show() self.pluginGui = pluginThesaurus # save def runDocumentazione(self): pluginDocumentazione = pyarchinit_Documentazione(self.iface) pluginDocumentazione.show() self.pluginGui = pluginDocumentazione # save def unload(self): # Remove the plugin self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionSite) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionPer) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionStruttura) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionUS) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionInr) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionCampioni) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionLapidei) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionSchedaind) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionTafonomia) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDetsesso) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionDeteta) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionTafonomia) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionArcheozoology) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionUT) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionimageViewer) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionImages_Directory_export) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionpdfExp) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionComparision) self.iface.removePluginMenu( "&pyArchInit - Archaeological GIS Tools", self.actionGisTimeController) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionConf) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionThesaurus) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionInfo) self.iface.removePluginMenu("&pyArchInit - Archaeological GIS Tools", self.actionDbmanagment) self.iface.removeToolBarIcon(self.actionSite) self.iface.removeToolBarIcon(self.actionPer) self.iface.removeToolBarIcon(self.actionStruttura) self.iface.removeToolBarIcon(self.actionUS) self.iface.removeToolBarIcon(self.actionInr) self.iface.removeToolBarIcon(self.actionCampioni) self.iface.removeToolBarIcon(self.actionLapidei) self.iface.removeToolBarIcon(self.actionTafonomia) self.iface.removeToolBarIcon(self.actionSchedaind) self.iface.removeToolBarIcon(self.actionDocumentazione) if self.PARAMS_DICT['EXPERIMENTAL'] == 'Si': self.iface.removeToolBarIcon(self.actionDetsesso) self.iface.removeToolBarIcon(self.actionDeteta) self.iface.removeToolBarIcon(self.actionArcheozoology) self.iface.removeToolBarIcon(self.actionUT) # self.iface.removeToolBarIcon(self.actionUpd) self.iface.removeToolBarIcon(self.actionimageViewer) self.iface.removeToolBarIcon(self.actionImages_Directory_export) self.iface.removeToolBarIcon(self.actionpdfExp) self.iface.removeToolBarIcon(self.actionComparision) self.iface.removeToolBarIcon(self.actionGisTimeController) self.iface.removeToolBarIcon(self.actionConf) self.iface.removeToolBarIcon(self.actionThesaurus) self.iface.removeToolBarIcon(self.actionInfo) self.iface.removeToolBarIcon(self.actionDbmanagment) self.dockWidget.setVisible(False) self.iface.removeDockWidget(self.dockWidget) # remove tool bar del self.toolBar def showHideDockWidget(self): if self.dockWidget.isVisible(): self.dockWidget.hide() else: self.dockWidget.show()
class AffineUI: def __init__(self, iface): self.ui = uic.loadUi(self.here / "ui.ui") self.iface = iface self.affine_namespace = Affine(self.ui) @property def here(self): return pathlib.Path(__file__).parent @property def project(self): return QgsProject.instance() def initGui(self): icon = QIcon(str(self.here / "icon.svg")) self.action = QAction(icon, "Affine Transformation...", self.iface.mainWindow()) self.action.setWhatsThis("Configuration for test plugin") self.action.triggered.connect(self.run) self.iface.addToolBarIcon(self.action) self.iface.addPluginToVectorMenu("&Geoprocessing Tools", self.action) self.ui.pushButtonRun.clicked.connect(self.affine) self.ui.pushButtonInvert.clicked.connect(self.invert) self.ui.pushButtonClose.clicked.connect(self.finish) def unload(self): self.iface.removePluginVectorMenu("&Geoprocessing Tools", self.action) self.iface.removeToolBarIcon(self.action) def run(self): self.ui.comboBoxLayer.clear() for name, layer in self.project.mapLayers().items(): if layer.type() == 0: self.ui.comboBoxLayer.addItem(name) self.ui.show() def affine(self): warn = QgsMessageViewer() layer_name = self.ui.comboBoxLayer.currentText() vlayer = self.project.mapLayers().get(layer_name) if vlayer is None: warn.setMessageAsPlainText("Select a layer to transform") warn.showMessage() return if not vlayer.isEditable(): warn.setMessageAsPlainText("Layer not in edit mode") warn.showMessage() return if self.ui.radioButtonWholeLayer.isChecked(): vlayer.selectAll() if vlayer.geometryType() == QgsWkbTypes.PolygonGeometry: start = 1 else: start = 0 v = self.affine_namespace for fid in vlayer.selectedFeatureIds(): feature = vlayer.getFeature(fid) geometry = feature.geometry() for i in itertools.count(start=start): vertex = geometry.vertexAt(i) if vertex == QgsPoint(0, 0): break # matrix form: x' = A x + b # x' = a x + b y + tx # y' = c x + d y + ty newx = v.a * vertex.x() + v.b * vertex.y() + v.tx newy = v.c * vertex.x() + v.d * vertex.y() + v.ty vlayer.moveVertex(newx, newy, fid, i) if self.ui.checkBoxZoomToLayer.isChecked(): self.iface.mapCanvas().zoomToSelected() def invert(self): # matrix form: x' = A x + b # --> x = A^-1 x' - A^-1 b # A^-1 = [d -b; -c a] / det A # only valid if det A = a d - b c != 0 v = self.affine_namespace det = v.a * v.d - v.b * v.c if det == 0: warn = QgsMessageViewer() warn.setMessageAsPlainText("Transformation is not invertable") warn.showMessage() return v.a, v.b, v.c, v.d = v.d / det, -v.b / det, -v.c / det, v.a / det v.tx, v.ty = -v.a * v.tx - v.b * v.ty, -v.c * v.tx - v.d * v.ty def finish(self): self.ui.close()
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 InaSAFE 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
class midv_tolkn: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(QFile.decodeName(__file__)) self.db = None def initGui(self): # Create actions icon = QIcon(os.path.join(self.plugin_dir, "icons", "midv_tolkn.png")) self.actionloadthelayers = QAction( QIcon( os.path.join(self.plugin_dir, 'icons', 'load_layers_domains.png')), "Ladda tolkningslager t QGIS", self.iface.mainWindow()) self.actionloadthelayers.setWhatsThis( "Laddar tolkningslager för gvmagasin m.m. till QGIS") self.actionloadthelayers.triggered.connect( lambda x: self.load_the_layers()) self.actionNewDB = QAction( QIcon(os.path.join(self.plugin_dir, 'icons', 'create_new.png')), "Skapa en ny tolkningsdatabas", self.iface.mainWindow()) self.actionNewDB.triggered.connect(lambda x: self.new_db()) self.actionVacuumDB = QAction( QIcon(os.path.join(self.plugin_dir, 'icons', 'vacuum.png')), "Packa (vacuum) tolkn-db", self.iface.mainWindow()) self.actionVacuumDB.setWhatsThis("Perform database vacuuming") self.actionVacuumDB.triggered.connect(lambda x: self.vacuum_db()) self.actionZipDB = QAction( QIcon(os.path.join(self.plugin_dir, 'icons', 'zip.png')), "Backup av tolknings-databas", self.iface.mainWindow()) self.actionZipDB.setWhatsThis( "En komprimerad zip-fil kommer att skapas i samma dir som tolknings-databasen." ) self.actionZipDB.triggered.connect(lambda x: self.zip_db()) self.actionUpgradeDB = QAction( QIcon(os.path.join(self.plugin_dir, 'icons', 'create_new.png')), "Uppgradera tolknings-databas", self.iface.mainWindow()) self.actionUpgradeDB.setWhatsThis( "Uppgradera en befintlig tolknings-databas till ny databas-struktur." ) self.actionUpgradeDB.triggered.connect(lambda x: self.upgrade_db()) #self.actionabout = QAction(QIcon(":/plugins/midv_tolkn/icons/about.png"), "Information", self.iface.mainWindow()) #self.actionabout.triggered.connect(lambda x: self.about) # Add button self.iface.addToolBarIcon(self.actionloadthelayers) # Add plugins menu items self.midv_menu = None # Midvatten-plugin-menyn self.menu = None # sub-menyn "Tolkningar" # Check if Midvatten-menyn existerar och get it for child in self.iface.mainWindow().menuBar().children(): if isinstance(child, QMenu): if child.title() == "Midvatten": # Put here your menu name self.midv_menu = child # If the Midvatten menu does not exist, create it! self.owns_midv_menu = False #indicator that this plugin must not clean up the midvatten menu if not self.midv_menu: self.owns_midv_menu = True #indicator that this plugin must clean up the midvatten menu self.midv_menu = QMenu("Midvatten", self.iface.mainWindow().menuBar()) menuBar = self.iface.mainWindow().menuBar() menuBar.addMenu(self.midv_menu) # check if there is a sub-menu Tolkningar for childchild in self.midv_menu.children(): if isinstance(childchild, QMenu): if childchild.title( ) == "&Tolkningar": # Put here your menu name print('found sub-menu Tolkningar') self.menu = childchild # If the tolkning submenu does not exist, create it if not self.menu: print('will add Tolkningar submenu') self.menu_separator1 = self.midv_menu.addSeparator() self.menu = QMenu( QCoreApplication.translate("Midvatten", "&Tolkningar")) self.midv_menu.addMenu(self.menu) self.menu_separator2 = self.midv_menu.addSeparator() self.menu.addAction(self.actionloadthelayers) self.menu.addAction(self.actionNewDB) self.menu.addAction(self.actionVacuumDB) self.menu.addAction(self.actionZipDB) self.menu.addAction(self.actionUpgradeDB) #self.menu.addAction(self.actionabout) def unload(self): # remove tool bar button self.iface.removeToolBarIcon(self.actionloadthelayers) # Remove the plugin menu items and icons try: self.midv_menu.removeAction(self.menu.menuAction()) self.midv_menu.removeAction(self.menu_separator1) self.midv_menu.removeAction(self.menu_separator2) except: pass if self.owns_midv_menu: #indicator that this plugin must clean up the midvatten menu menubar = self.midv_menu.parentWidget() menubar.removeAction(self.midv_menu.menuAction()) self.midv_menu.deleteLater() def about(self): utils.pop_up_info(msg='This feature is not yet implemented', title='Hold on...') def load_data_domains(self): #utils.pop_up_info(msg='This feature is not yet implemented',title='Hold on...') #return QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) err_flag = utils.verify_msettings_loaded_and_layer_edit_mode( qgis.utils.iface, self.ms) #verify midv settings are loaded if err_flag == 0: conn_ok, dd_tables = utils.sql_load_fr_db( "select name from sqlite_master where name like 'zz_%'") if not conn_ok: return d_domain_tables = [str(dd_table[0]) for dd_table in dd_tables] err_flag = utils.verify_msettings_loaded_and_layer_edit_mode( qgis.utils.iface, self.ms, d_domain_tables ) #verify none of the tables are already loaded and in edit mode if err_flag == 0: LoadLayers(qgis.utils.iface, self.ms.settingsdict, 'Midvatten_data_domains') QApplication.restoreOverrideCursor( ) #now this long process is done and the cursor is back as normal def load_the_layers(self): LoadLayers(qgis.utils.iface, self.db) def new_db(self, set_locale=False): if not set_locale: set_locale = utils.getcurrentlocale() filenamepath = os.path.join(os.path.dirname(__file__), "metadata.txt") iniText = QSettings(filenamepath, QSettings.IniFormat) verno = str(iniText.value('version')) from .create_tolkn_db import newdb newdbinstance = newdb(verno, set_locale=set_locale) if not newdbinstance.dbpath == '': self.db = newdbinstance.dbpath def upgrade_db(self, set_locale=False): from_db = None #get full path to the original db to be updated if self.db: use_current_db = utils.Askuser( "YesNo", """Do you want to upgrade %s?""" % self.db, 'Current database?') if use_current_db.result == 0: from_db = None elif use_current_db.result == 1: from_db = self.db elif use_current_db.result == '': return if not from_db: from_db = QFileDialog.getOpenFileName( None, 'Ange tolknings-db som ska exporteras', '', "Spatialite (*.sqlite)")[0] if not from_db: QApplication.restoreOverrideCursor() return None #get EPSG in the original db EPSG = utils.sql_load_fr_db( """SELECT srid FROM geom_cols_ref_sys WHERE Lower(f_table_name) = Lower('gvmag') AND Lower(f_geometry_column) = Lower('geometry')""", from_db) #preparations to create new db of new design if not set_locale: set_locale = utils.getcurrentlocale() filenamepath = os.path.join(os.path.dirname(__file__), "metadata.txt") iniText = QSettings(filenamepath, QSettings.IniFormat) verno = str(iniText.value('version')) #now create database of the updated design from .create_tolkn_db import newdb newdbinstance = newdb(verno, user_select_CRS=False, EPSG_code=EPSG[1][0][0], set_locale=set_locale) #transfer data to the new database foo = utils.UpgradeDatabase(from_db, newdbinstance.dbpath, EPSG) #set new database as the current db and load these layers if not newdbinstance.dbpath == '': self.db = newdbinstance.dbpath self.load_the_layers() def vacuum_db(self): force_another_db = False if self.db: use_current_db = utils.Askuser("YesNo", """Vill du packa %s?""" % self.db, 'Which database?') if use_current_db.result == 1: dbpath = self.db force_another_db = True elif use_current_db.result == 0: force_another_db = True elif use_current_db.result == '': return if not self.db or force_another_db: dbpath = QFileDialog.getOpenFileName(None, 'Ange db som ska packas', '', "Spatialite (*.sqlite)")[0] QApplication.setOverrideCursor(Qt.WaitCursor) utils.sql_alter_db(dbpath, 'vacuum') QApplication.restoreOverrideCursor() def zip_db(self): force_another_db = False dbpath = None if self.db: use_current_db = utils.Askuser( "YesNo", 'Vill du göra backup av %s?' % self.db, 'Which database?') if use_current_db.result == 1: dbpath = self.db force_another_db = False elif use_current_db.result == 0: force_another_db = True elif use_current_db.result == '': return if not self.db or force_another_db: dbpath = QFileDialog.getOpenFileName( None, 'Ange db som du vill skapa backup utav', '', "Spatialite (*.sqlite)")[0] if dbpath: QApplication.setOverrideCursor(Qt.WaitCursor) connection = utils.dbconnection(dbpath) connection.connect2db() connection.conn.cursor().execute("begin immediate") file_path = os.path.realpath(dbpath) dir_path = os.path.dirname(file_path) current_dir = dir_path.split(os.sep)[-1] bkupname = dbpath + datetime.datetime.now().strftime( '%Y%m%dT%H%M') + '.zip' zf = zipfile.ZipFile(bkupname, mode='w') zf.write(dbpath, os.path.basename(dbpath), compress_type=compression ) #compression will depend on if zlib is found or not zf.close() connection.conn.rollback() connection.closedb() self.iface.messageBar().pushMessage( "Information", "Database backup was written to " + bkupname, 1, duration=15) QApplication.restoreOverrideCursor()
class XYZHubConnector(object): """base plugin""" def __init__(self, iface): """init""" import sys print(sys.version) self.iface = iface self.web_menu = "&XYZ Hub Connector" self.init_modules() self.obj = self def initGui(self): """startup""" parent = self.iface.mainWindow() ######## action, button icon = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/xyz.png")) icon_bbox = QIcon("%s/%s" % (config.PLUGIN_DIR, "images/bbox.svg")) self.action_connect = QAction(icon, "XYZ Hub Connection", parent) self.action_connect.setWhatsThis( QCoreApplication.translate(PLUGIN_NAME, "WhatsThis message")) self.action_connect.setStatusTip( QCoreApplication.translate(PLUGIN_NAME, "status tip message")) self.action_sync_edit = QAction( QIcon("%s/%s" % (config.PLUGIN_DIR, "images/sync.svg")), "Push changes to XYZ Hub", parent) self.action_clear_cache = QAction( QIcon("%s/%s" % (config.PLUGIN_DIR, "images/delete.svg")), "Clear cache", parent) # self.action_sync_edit.setVisible(False) # disable magic sync self.edit_buffer.config_ui(self.enable_sync_btn) self.cb_layer_selected(self.iface.activeLayer()) ######## CONNECT action, button self.action_connect.triggered.connect(self.open_connection_dialog) self.action_sync_edit.triggered.connect(self.open_sync_edit_dialog) self.action_clear_cache.triggered.connect(self.open_clear_cache_dialog) ######## Add the toolbar + button self.toolbar = self.iface.addToolBar(PLUGIN_NAME) self.toolbar.setObjectName("XYZ Hub Connector") self.actions_menu = [ self.action_connect, self.action_sync_edit, self.action_clear_cache ] for a in [self.action_connect, self.action_sync_edit]: self.toolbar.addAction(a) for a in self.actions_menu: self.iface.addPluginToWebMenu(self.web_menu, a) # # uncomment to use menu button # tool_btn = QToolButton(self.toolbar) # tool_btn.setDefaultAction(self.action_connect) # tool_btn.setPopupMode(tool_btn.MenuButtonPopup) # self.xyz_widget_action = self.toolbar.addWidget(tool_btn) # uncomment to use menu button # self.toolbar.addAction(self.action_connect) self.action_help = None progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(0) progress.reset() progress.hide() # progress = self.iface.statusBarIface().children()[2] # will be hidden by qgis self.iface.statusBarIface().addPermanentWidget(progress) self.pb = progress def init_modules(self): if LOG_TO_FILE: QgsApplication.messageLog().messageReceived.connect( cb_log_qgis) #, Qt.QueuedConnection # util.init_module() # parent = self.iface.mainWindow() parent = QgsProject.instance() self.secret = Secret(config.USER_PLUGIN_DIR + "/secret.ini") ######## Init xyz modules self.map_basemap_meta = basemap.load_default_xml() self.auth_manager = AuthManager(config.USER_PLUGIN_DIR + "/auth.ini") self.token_model = GroupTokenModel(parent) self.network = NetManager(parent) self.con_man = LoaderManager() self.con_man.config(self.network) self.edit_buffer = EditBuffer() ######## data flow # self.conn_info = SpaceConnectionInfo() ######## token self.token_model.load_ini(config.USER_PLUGIN_DIR + "/token.ini") ######## CALLBACK self.con_man.ld_pool.signal.progress.connect( self.cb_progress_busy) #, Qt.QueuedConnection self.con_man.ld_pool.signal.finished.connect(self.cb_progress_done) QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.edit_buffer.remove_layers) # QgsProject.instance().layersWillBeRemoved["QStringList"].connect( self.layer_man.remove_layers) # QgsProject.instance().layersAdded.connect( self.edit_buffer.config_connection) self.iface.currentLayerChanged.connect( self.cb_layer_selected) # UNCOMMENT self.iface.mapCanvas().extentsChanged.connect(self.reload_tile, Qt.QueuedConnection) QgsProject.instance().readProject.connect(self.import_project) self.import_project() def unload_modules(self): # self.con_man.disconnect_ux( self.iface) QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.edit_buffer.remove_layers) # QgsProject.instance().layersWillBeRemoved["QStringList"].disconnect( self.layer_man.remove_layers) # QgsProject.instance().layersAdded.disconnect( self.edit_buffer.config_connection) self.edit_buffer.unload_connection() self.iface.currentLayerChanged.disconnect( self.cb_layer_selected) # UNCOMMENT self.iface.mapCanvas().extentsChanged.disconnect(self.reload_tile) # utils.disconnect_silent(self.iface.currentLayerChanged) self.secret.deactivate() if LOG_TO_FILE: QgsApplication.messageLog().messageReceived.disconnect(cb_log_qgis) # close_file_logger() pass def unload(self): """teardown""" self.unload_modules() # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.toolbar.clear( ) # remove action from custom toolbar (toolbar still exist) self.toolbar.deleteLater() for a in self.actions_menu: self.iface.removePluginWebMenu(self.web_menu, a) # remove progress self.iface.statusBarIface().removeWidget(self.pb) ############### # Callback ############### def cb_layer_selected(self, qlayer): flag_xyz = True if qlayer is not None and is_xyz_supported_layer( qlayer) else False if flag_xyz: self.edit_buffer.config_connection([qlayer]) self.edit_buffer.enable_ui(qlayer.id()) else: msg = "No XYZHub Layer selected" self.enable_sync_btn(False, msg) # disable magic sync # self.action_sync_edit.setEnabled(flag_xyz) def enable_sync_btn(self, flag, msg=""): msg = msg or ("No changes detected since last push" if not flag else "Push changes") self.action_sync_edit.setToolTip(msg) self.action_sync_edit.setEnabled(flag) ############### # Callback of action (main function) ############### def cb_success_msg(self, title, msg="", dt=5): self.iface.messageBar().pushMessage(config.TAG_PLUGIN, ": ".join([title, msg]), Qgis.Success, dt) def make_cb_success(self, title, msg="", dt=5): def _cb_success_msg(): self.cb_success_msg(title, msg, dt=dt) return _cb_success_msg def make_cb_success_args(self, title, msg="", dt=5): def _cb_success_msg(args): a, kw = parse_qt_args(args) txt = ". ".join(map(str, a)) self.cb_success_msg(title, txt, dt=dt) return _cb_success_msg def cb_handle_error_msg(self, e): err = parse_exception_obj(e) if isinstance(err, ChainInterrupt): e0, idx = err.args[0:2] else: e0 = err if isinstance(e0, (net_handler.NetworkError, net_handler.NetworkTimeout)): ok = self.show_net_err(e0) if ok: return elif isinstance(e0, EmptyXYZSpaceError): ret = exec_warning_dialog("XYZ Hub", "Requested query returns no features") return self.show_err_msgbar(err) def show_net_err(self, err): reply_tag, status, reason, body, err_str, url = err.args[:6] if reply_tag in ["count", "statistics"]: # too many error # msg = "Network Error: %s: %s. %s"%(status, reason, err_str) return 1 detail = "\n".join(["Request:", url, "", "Response:", body]) msg = ("%s: %s\n" % (status, reason) + "There was a problem connecting to the server") if status in [401, 403]: msg += ( "\n\n" + "Please input valid token with correct permissions." + "\n" + "Token is generated via " + "<a href='https://xyz.api.here.com/token-ui/'>https://xyz.api.here.com/token-ui/</a>" ) ret = exec_warning_dialog("Network Error", msg, detail) return 1 def show_err_msgbar(self, err): self.iface.messageBar().pushMessage("Error", repr(err), Qgis.Warning, 3) msg = format_traceback(err) QgsMessageLog.logMessage(msg, config.TAG_PLUGIN, Qgis.Warning) def cb_progress_busy(self, n_active): if n_active > 1: return self.flag_pb_show = True self.cb_progress_refresh() def cb_progress_done(self): self.flag_pb_show = False self.cb_progress_refresh() def cb_progress_refresh(self): if not hasattr(self, "flag_pb_show"): return pb = self.pb if self.flag_pb_show: pb.show() # print_qgis("show",pb) else: pb.hide() # print_qgis("hide") ############### # Action (main function) ############### # UNUSED def refresh_canvas(self): # self.iface.activeLayer().triggerRepaint() self.iface.mapCanvas().refresh() def previous_canvas_extent(self): self.iface.mapCanvas().zoomToPreviousExtent() # def new_main_dialog(self): parent = self.iface.mainWindow() dialog = MainDialog(parent) dialog.config(self.token_model) dialog.config_secret(self.secret) auth = self.auth_manager.get_auth() dialog.config_basemap(self.map_basemap_meta, auth) con = self.con_man.make_con("create") con.signal.finished.connect( dialog.btn_use.clicked.emit) # can be optimized !! con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("list") con.signal.results.connect(make_fun_args(dialog.cb_display_spaces)) con.signal.error.connect(self.cb_handle_error_msg) con.signal.error.connect(lambda e: dialog.cb_enable_token_ui()) con.signal.finished.connect(dialog.cb_enable_token_ui) con = self.con_man.make_con("edit") con.signal.finished.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("delete") con.signal.results.connect(dialog.btn_use.clicked.emit) con.signal.error.connect(self.cb_handle_error_msg) con = self.con_man.make_con("stat") con.signal.results.connect(make_fun_args( dialog.cb_display_space_count)) con.signal.error.connect(self.cb_handle_error_msg) ############ clear cache btn dialog.signal_clear_cache.connect(self.open_clear_cache_dialog) ############ add map tile btn dialog.signal_add_basemap.connect(self.add_basemap_layer) ############ btn: new, edit, delete space dialog.signal_new_space.connect(self.start_new_space) dialog.signal_edit_space.connect(self.start_edit_space) dialog.signal_del_space.connect(self.start_delete_space) ############ Use Token btn dialog.signal_use_token.connect(lambda a: self.con_man.finish_fast()) dialog.signal_use_token.connect(self.start_use_token) ############ get count dialog.signal_space_count.connect( self.start_count_feat, Qt.QueuedConnection) # queued -> non-blocking ui ############ connect btn dialog.signal_space_connect.connect(self.start_load_layer) dialog.signal_space_tile.connect(self.start_load_tile) ############ upload btn dialog.signal_upload_space.connect(self.start_upload_space) return dialog def start_new_space(self, args): con = self.con_man.get_con("create") con.start_args(args) def start_edit_space(self, args): con = self.con_man.get_con("edit") con.start_args(args) def start_delete_space(self, args): con = self.con_man.get_con("delete") con.start_args(args) def start_use_token(self, args): con = self.con_man.get_con("list") con.start_args(args) def start_count_feat(self, args): con = self.con_man.get_con("stat") con.start_args(args) def start_upload_space(self, args): con_upload = UploadLayerController(self.network, n_parallel=2) self.con_man.add_background(con_upload) # con_upload.signal.finished.connect( self.make_cb_success("Uploading finish") ) con_upload.signal.results.connect( self.make_cb_success_args("Uploading finish")) con_upload.signal.error.connect(self.cb_handle_error_msg) con = InitUploadLayerController(self.network) self.con_man.add_background(con) con.signal.results.connect(con_upload.start_args) con.signal.error.connect(self.cb_handle_error_msg) con.start_args(args) def start_load_layer(self, args): # create new con # config # run ############ connect btn con_load = LoadLayerController(self.network, n_parallel=1) self.con_man.add_background(con_load) # con_load.signal.finished.connect( self.make_cb_success("Loading finish") ) con_load.signal.results.connect( self.make_cb_success_args("Loading finish")) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect(self.cb_handle_error_msg) con_load.start_args(args) # con.signal.results.connect( self.layer_man.add_args) # IMPORTANT def start_load_tile(self, args): canvas = self.iface.mapCanvas() rect = bbox_utils.extend_to_rect(bbox_utils.get_bounding_box(canvas)) level = tile_utils.get_zoom_for_current_map_scale(canvas) # rect = (-180,-90,180,90) # level = 0 a, kw = parse_qt_args(args) kw["tile_schema"] = "here" kw["tile_ids"] = tile_utils.bboxToListColRow(*rect, level) # kw["limit"] = 100 ############ connect btn con_load = TileLayerLoader(self.network, n_parallel=1) self.con_man.add_layer(con_load) # con_load.signal.finished.connect( self.make_cb_success("Tiles loaded") ) con_load.signal.results.connect( self.make_cb_success_args("Tiles loaded", dt=2)) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect(self.cb_handle_error_msg) con_load.start_args(make_qt_args(*a, **kw)) def reload_tile(self): canvas = self.iface.mapCanvas() rect = bbox_utils.extend_to_rect(bbox_utils.get_bounding_box(canvas)) level = tile_utils.get_zoom_for_current_map_scale(canvas) kw = dict() kw["tile_schema"] = "here" kw["tile_ids"] = tile_utils.bboxToListColRow(*rect, level) # kw["limit"] = 100 unique_con = set() lst_con = list() for qnode in [ vl for vl in QgsProject.instance().layerTreeRoot().checkedLayers( ) if is_xyz_supported_layer(vl) ] + [ g for g in QgsProject.instance().layerTreeRoot().findGroups() if len(g.children()) == 0 and g.isVisible() and is_xyz_supported_node(g) ]: xlayer_id = qnode.customProperty("xyz-hub-id") con = self.con_man.get_from_xyz_layer(xlayer_id) if con is None: continue if con in unique_con: continue lst_con.append(con) unique_con.add(con) # print_qgis(lst_con) # print_qgis(self.con_man._layer_ptr) for con in lst_con: print_qgis(con.status) print_qgis("loading tile", level, rect) con.restart(**kw) def add_basemap_layer(self, args): a, kw = parse_qt_args(args) meta, app_id, app_code = a self.auth_manager.save(app_id, app_code) basemap.add_basemap_layer(meta, app_id, app_code) ############### # import project function ############### def import_project(self): self.init_tile_loader() def init_tile_loader(self): cnt = 0 for qnode in [ g for g in QgsProject.instance().layerTreeRoot().findGroups() if is_xyz_supported_node(g) ]: try: layer = XYZLayer.load_from_qnode(qnode) con_load = TileLayerLoader(self.network, n_parallel=1, layer=layer) ptr = self.con_man.add_layer(con_load) # con_load.signal.finished.connect( self.make_cb_success("Tiles loaded") ) con_load.signal.results.connect( self.make_cb_success_args("Tiles loaded", dt=2)) # con_load.signal.finished.connect( self.refresh_canvas, Qt.QueuedConnection) con_load.signal.error.connect(self.cb_handle_error_msg) cnt += 1 except: pass # print_qgis(self.con_man._layer_ptr) self.cb_success_msg("Import XYZ Layer", "%s XYZ Layer imported" % cnt, dt=2) ############### # Open dialog ############### def open_clear_cache_dialog(self): dialog = ConfirmDialog( "Delete cache will make loaded layer unusable !!") ret = dialog.exec_() if ret != dialog.Ok: return utils.clear_cache() def open_connection_dialog(self): dialog = self.new_main_dialog() vlayer = self.iface.activeLayer() dialog.set_layer(vlayer) dialog.exec_() self.con_man.finish_fast() # self.startTime = time.time() def open_sync_edit_dialog(self): vlayer = self.iface.activeLayer() layer_buffer = self.edit_buffer.get_layer_buffer(vlayer.id()) lst_added_feat, removed_ids = layer_buffer.get_sync_feat() conn_info = layer_buffer.get_conn_info() # print_qgis("lst_added_feat: ",lst_added_feat) # print_qgis("removed_feat: ", removed_ids) con = EditSyncController(self.network) self.con_man.add_background(con) con.signal.finished.connect(layer_buffer.sync_complete) con.signal.results.connect( self.make_cb_success_args("Sync edit finish")) con.signal.error.connect(self.cb_handle_error_msg) con.start(conn_info, layer_buffer, lst_added_feat, removed_ids)
class PointConnector(object): """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', 'PointConnector_{}.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 = PointConnectorDialog() # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Point Connector') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'PointConnector') self.toolbar.setObjectName(u'PointConnector') self.addedLayers = 1 # 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('PointConnector', 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 InaSAFE 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.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): self.action = QAction(QIcon(":/plugins/PointConnector/icon.png"), "PointConnector", self.iface.mainWindow()) self.action.setWhatsThis("Connect points") self.action.setStatusTip("Connect points following a from-to list") self.action.triggered.connect(self.run) if hasattr(self.iface, "addPluginToVectorMenu"): self.iface.addVectorToolBarIcon(self.action) self.iface.addPluginToVectorMenu("&PointConnector", self.action) else: self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu("&PointConnector", self.action) def unload(self): self.iface.removePluginVectorMenu("&PointConnector", self.action) self.iface.removeVectorToolBarIcon(self.action) self.iface.removeToolBarIcon(self.action) def run(self): self.dlg.populateComboBox() # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result == 1: # create layers dict #layers = QgsProject.instance().mapLayers() layers = {} for name, layer in QgsProject.instance().mapLayers().items(): layers[layer.name()] = layer #choose point-source chosenPoint = self.dlg.pointsComboBox.currentText() if chosenPoint != 'Choose layer...': point_layer = layers[chosenPoint] else: pointPath = self.dlg.pointPathLineEdit.text() point_layer = QgsVectorLayer( pointPath, 'points', 'ogr') #shp-file with attribute field name try: p = open(pointPath, 'r') p.close() except IOError: QMessageBox.information( None, "Error", "Shape-file not found. Check file path.") return point_name_index = 0 # choose csv-source lines_list = [] chosenCsv = self.dlg.csvComboBox.currentText() if chosenCsv != 'Choose layer...': csv_layer = layers[chosenCsv] csv_features = csv_layer.getFeatures() for line in csv_features: attrs = line.attributes() lines_list.append(((str(attrs[0])), str(attrs[1]))) else: csvPath = self.dlg.csvPathLineEdit.text() # test if csv is valid try: f = codecs.open(csvPath, 'r', 'utf-8-sig') for line in f: pass f = codecs.open(csvPath, 'r', 'utf-8-sig') except UnicodeDecodeError: try: f = open(csvPath, 'r') re.search('\\\\', f) == None except: QMessageBox.information( None, "Error", "PointConnector can not read csv-file. Try saving it with utf-8 encoding or import it as a layer." ) return except IOError: QMessageBox.information( None, "Error", "Csv-file not found. Check file path or select a csv-layer." ) return #creating lines list from file for line in f: line = line.splitlines() for s in line[:1]: s = tuple(s.split(',')) lines_list.append(s) f.close() point_layer_crs = point_layer.crs().authid() lines_layer = QgsVectorLayer( 'LineString?crs=' + point_layer_crs, 'PointConnector lines ' + str(self.addedLayers), 'memory') pr = lines_layer.dataProvider() lines_layer.startEditing() pr.addAttributes([ QgsField('id', QVariant.Int), QgsField('from', QVariant.String), QgsField('to', QVariant.String) ]) #creating point coordinate dict points = point_layer.getFeatures() points_dict = {} #Progress bar widget progressMessageBar = iface.messageBar().createMessage( "Building point database...") progress = QProgressBar() progress.setMaximum(point_layer.featureCount()) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) i = 0 for p in points: geom = p.geometry() attrs = p.attributes() p = geom.asPoint() key = attrs[point_name_index] points_dict[str( key)] = p #attrs[point_name_index] = name field i += 1 progress.setValue(i) iface.messageBar().clearWidgets() QgsProject.instance().addMapLayer(point_layer) #Progress bar widget progressMessageBar = iface.messageBar().createMessage( "Drawing lines...") progress = QProgressBar() progress.setMaximum(len(lines_list)) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) #Drawing the lines i = 1 not_processed_list = [] for line in lines_list: if (line[0] in list(points_dict.keys()) and line[1] in list(points_dict.keys())): frPoint = points_dict[line[0]] toPoint = points_dict[line[1]] attrs = [i, line[0], line[1]] new_line = QgsGeometry.fromPolyline( [QgsPoint(frPoint), QgsPoint(toPoint)]) feat = QgsFeature() feat.setGeometry(new_line) feat.setAttributes(attrs) (res, outFeats) = pr.addFeatures([feat]) lines_layer.commitChanges() if res != True: pass i += 1 progress.setValue(i) else: not_processed_list.append(line) progress.setValue(i) iface.messageBar().clearWidgets() # add lines layer to canvas QgsProject.instance().addMapLayer(lines_layer) self.addedLayers += 1 if not not_processed_list: QMessageBox.information(None, 'Success', 'All lines drawn without error') else: QMessageBox.information( None, 'Error', str(len(not_processed_list)) + ' out of ' + str(len(lines_list)) + ' line(s) not drawn.')
class GimpSelectionFeaturePlugin(QObject): def __init__(self, iface): super().__init__() self.iface = iface self.name = u"&Gimp Selection Feature" self.dock = self.exitsPluginGimp = None self.translate = Translate( 'gimpselectionfeature' ) def initGui(self): def setExistsPluginGimp(): def getDirPluginGimp(): dirPlugin = None mask = r".*gimp.[0-9]+.[0-9]+/%s" % nameDirPlugin # Linux Format for root, dirs, files in os.walk( dirHome ): if re.match( mask, root.replace('\\', '/'), re.IGNORECASE ): dirPlugin = root break return dirPlugin def copyNewPlugin(): shutil.copy2( gimpPlugin, gimpPluginInstall ) if sys.platform != 'win32': # Add executable st = os.stat( gimpPluginInstall ) os.chmod( gimpPluginInstall, st.st_mode | stat.S_IEXEC ) dirHome = os.path.expanduser('~') nameDirPlugin = "plug-ins" dirPluginGimp = getDirPluginGimp() if dirPluginGimp is None: msg = "Not found diretory 'GIMP' or 'GIMP {}' in '{}'".format( nameDirPlugin, dirHome ) self.exitsPluginGimp = { 'isOk': False, 'msg': msg } return namePlugin = 'socket_server_selection.py' gimpPlugin = os.path.join( os.path.dirname(__file__), namePlugin ) gimpPluginInstall = os.path.join( dirPluginGimp, namePlugin ) if not os.path.exists( gimpPluginInstall ) or not filecmp.cmp( gimpPlugin, gimpPluginInstall ): copyNewPlugin() self.exitsPluginGimp = { 'isOk': True } name = "Gimp Selection Feature" about = QCoreApplication.translate('GimpSelectionFeature', 'Adding selected area in GIMP how a feature in shapefile') icon = QIcon( os.path.join( os.path.dirname(__file__), 'gimpselectionfeature.svg' ) ) self.action = QAction( icon, name, self.iface.mainWindow() ) self.action.setObjectName( name.replace(' ', '') ) self.action.setWhatsThis( about ) self.action.setStatusTip( about ) self.action.setCheckable( True ) self.action.triggered.connect( self.run ) self.iface.addRasterToolBarIcon( self.action ) self.iface.addPluginToRasterMenu( self.name, self.action ) setExistsPluginGimp() if not self.exitsPluginGimp['isOk']: return self.dock = DockWidgetGimpSelectionFeature( self.iface ) self.iface.addDockWidget( Qt.RightDockWidgetArea , self.dock ) self.dock.visibilityChanged.connect( self.dockVisibilityChanged ) def unload(self): self.iface.removeRasterToolBarIcon( self.action ) self.iface.removePluginRasterMenu( self.name, self.action ) if self.exitsPluginGimp['isOk']: self.dock.close() del self.dock self.dock = None del self.action @pyqtSlot() def run(self): if not self.exitsPluginGimp['isOk']: ( t, m ) = ( GimpSelectionFeature.nameModulus, self.exitsPluginGimp['msg'] ) self.iface.messageBar().pushMessage( t, m, Qgis.Critical, 5 ) self.action.setChecked( False ) return if self.dock.isVisible(): self.dock.hide() else: self.dock.show() @pyqtSlot(bool) def dockVisibilityChanged(self, visible): self.action.setChecked( visible )
class QgisMapBiomasAPI: """Plugin implementation """ def __init__(self, iface): """ Constructor Args: iface (qgis.gui.QgisInterface): a reference to the QGIS GUI interface """ self.iface = iface self.plugin_dir = os.path.dirname(__file__) self.locale = QSettings().value('locale/userLocale')[0:2] self.dockwidget = None self.action = None self.name = 'MapBiomas API' self.about = 'MapBiomas API for QGIS' self.token = None self.biome = None self.state = None # initialize locale locale_path = os.path.join( self.plugin_dir, 'i18n', '{}_{}.qm'.format('mapbiomas-api', self.locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) def tr(self, msg): return QCoreApplication.translate("QgisMapBiomasAPI", msg) def initProcessing(self): self.provider = Provider() QgsApplication.processingRegistry().addProvider(self.provider) def initGui(self): """ This method is called by QGIS when the main GUI starts up or when the plugin is enabled in the Plugin Manager. Only want to register the menu items and toolbar buttons here, and connects action with run method. """ self.initProcessing() icon = QIcon(os.path.join(self.plugin_dir, 'icon.png')) self.action = QAction(icon, self.name, self.iface.mainWindow()) self.action.setWhatsThis(self.about) self.action.setStatusTip(self.about) self.action.setCheckable(True) self.action.triggered.connect(self.run) # for plugin menu/toolbar self.iface.addToolBarIcon(self.action) self.iface.addPluginToMenu(self.name, self.action) def unload(self): """ Will be executed when the plugin is disabled. Either in the Plugin Manager or when QGIS shuts down. It removes the previously defined QAction object from the menu and remove the plugin icon from the toolbar. """ # for plugin menu/toolbar self.iface.removeToolBarIcon(self.action) self.iface.removePluginMenu(self.name, self.action) if self.dockwidget is not None: # disconnect triggers here self.dockwidget.pushButton.clicked.disconnect(self.do_something) self.dockwidget.checkBoxStartDetected.toggled[bool].disconnect( self.dockwidget.startDetectedAt.setEnabled) self.dockwidget.checkBoxEndDetected.toggled[bool].disconnect( self.dockwidget.endDetectedAt.setEnabled) self.dockwidget.checkBoxStartPublished.toggled[bool].disconnect( self.dockwidget.startPublishedAt.setEnabled) self.dockwidget.checkBoxEndPublished.toggled[bool].disconnect( self.dockwidget.endPublishedAt.setEnabled) self.dockwidget.close() self.dockwidget.visibilityChanged.disconnect( self.visibility_changed) self.iface.removeDockWidget(self.dockwidget) del self.dockwidget # remove processing provider QgsApplication.processingRegistry().removeProvider(self.provider) def run(self): """ Executes the custom plugin functionality. This method is called by the previously defined QAction object (callback), which went into the toolbar icon and the menu entry. """ if self.dockwidget is None: self.dockwidget = DockMapBiomasApi() self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockwidget) self.dockwidget.visibilityChanged.connect(self.visibility_changed) self.init() self.dockwidget.show() else: if self.dockwidget.isVisible(): self.dockwidget.hide() else: self.dockwidget.show() def visibility_changed(self, change): """ Change icon checked status with dockwidget visibility """ self.action.setChecked(change) def info(self, msg, level=Qgis.Info, duration=5): """ docstring """ self.iface.messageBar().pushMessage(msg, level, duration) def log(self, msg, level=Qgis.Info): """ docstring """ QgsMessageLog.logMessage(msg, self.name, level) def sign_in(self): """ Creation of an access token in the JWT standard to be used in the Authorization header and populate BIOME and STATE if empty """ err = None email = self.dockwidget.email.text() password = self.dockwidget.password.text() if password and email: try: self.token, err = MapbiomasApi.token({ "email": email, "password": password }) except Exception as e: err = str(e) if self.token is not None: if self.biome is None: self.biome, err = territories.get(self.token, {"category": "BIOME"}) if self.state is None: self.state, err = territories.get(self.token, {"category": "STATE"}) else: err = self.tr('Email and password are required.') return err def get_alerts(self): filters = {} territories = [] if self.dockwidget.BIOME.count: territories.extend( [self.biome[k] for k in self.dockwidget.BIOME.checkedItems()]) if self.dockwidget.STATE.count: territories.extend( [self.state[k] for k in self.dockwidget.STATE.checkedItems()]) if territories: filters["territoryIds"] = territories if self.dockwidget.checkBoxStartDetected.isChecked(): filters["startDetectedAt"] = self.dockwidget.startDetectedAt.date( ).toString('yyyy-MM-dd') if self.dockwidget.checkBoxEndDetected.isChecked(): filters["endDetectedAt"] = self.dockwidget.endDetectedAt.date( ).toString('yyyy-MM-dd') if self.dockwidget.checkBoxStartPublished.isChecked(): filters[ "startPublishedAt"] = self.dockwidget.startPublishedAt.date( ).toString('yyyy-MM-dd') if self.dockwidget.checkBoxEndPublished.isChecked(): filters["endPublishedAt"] = self.dockwidget.endPublishedAt.date( ).toString('yyyy-MM-dd') try: data, err = publishedAlerts.get(self.token, filters) except Exception as e: err = str(e) if err is None: with NamedTemporaryFile("w+t", prefix=self.tr("alerts_"), suffix=".geojson", delete=False) as outfile: json.dump(data, outfile) fn = outfile.name if not "territoryIds" in filters and (len(data["features"]) == publishedAlerts.LIMIT): self.info( self.tr('The number of alerts was limited to {}').format( publishedAlerts.LIMIT)) # add vector layer layer = QgsVectorLayer(fn, 'MapBiomasAPI', 'ogr') if layer.isValid(): locale_style = os.path.join( self.plugin_dir, 'i18n', 'mapbiomas-api_{}.qml'.format(self.locale)) if os.path.exists(locale_style): layer.loadNamedStyle(locale_style) else: layer.loadNamedStyle( os.path.join(self.plugin_dir, 'mapbiomas-api.qml')) QgsProject.instance().addMapLayer(layer) else: self.log("Invalid layer file: {}".format(fn)) self.info( self.tr("Unknown error. Invalid layer. Try it again."), level=Qgis.Critical) elif err == 'Você não tem permissão para realizar esta ação': self.dockwidget.pushButton.setText(self.tr('SIGN IN')) self.dockwidget.options.setDisabled(True) self.dockwidget.mGroupBox.setCollapsed(False) self.info(self.tr("The session has expired. Sign in again."), level=Qgis.Critical) else: self.info(err, level=Qgis.Critical) def do_something(self): """Sign in or get alerts """ if self.dockwidget.pushButton.text() == self.tr('SIGN IN'): err = self.sign_in() if err is None: self.dockwidget.BIOME.addItems(self.biome.keys()) self.dockwidget.STATE.addItems(self.state.keys()) self.dockwidget.pushButton.setText(self.tr('GET ALERTS')) self.dockwidget.options.setEnabled(True) self.dockwidget.mGroupBox.setCollapsed(True) else: self.info(err, level=Qgis.Critical) else: self.get_alerts() def init(self): """ Fill options, default values and connect triggers of the dockwidget """ # connect triggers self.dockwidget.pushButton.clicked.connect(self.do_something) self.dockwidget.checkBoxStartDetected.toggled[bool].connect( self.dockwidget.startDetectedAt.setEnabled) self.dockwidget.checkBoxEndDetected.toggled[bool].connect( self.dockwidget.endDetectedAt.setEnabled) self.dockwidget.checkBoxStartPublished.toggled[bool].connect( self.dockwidget.startPublishedAt.setEnabled) self.dockwidget.checkBoxEndPublished.toggled[bool].connect( self.dockwidget.endPublishedAt.setEnabled) # set defaults self.dockwidget.endDetectedAt.setDate(QDate.currentDate()) self.dockwidget.endPublishedAt.setDate(QDate.currentDate())
def add_action(self, name, icon_path, text, callback, toggle_flag=False, enabled_flag=True, checkable_flag=False, visible_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 name: Objectname of the action. Serves also as key for the stored actions. :type name: str :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 toggle_flag: A flag indicating if the action should connect the toggled or triggered signal by default. Defaults to triggered (False) :type toggle_flag: bool :param checkable_flag: A flag indicating if the action should be checkable by default. Defaults to False. :type checkable: bool :param visible_flag: A flag indicating if the action should be displayed by default. Defaults to True. :type visible: 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.setObjectName(name) if toggle_flag: action.toggled.connect(callback) else: action.triggered.connect(callback) action.setEnabled(enabled_flag) action.setCheckable(checkable_flag) action.setVisible(visible_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[name] = action return action
class VoGISProfilToolMainDialog(QDialog): def __init__(self, interface, settings): QDialog.__init__(self, interface.mainWindow()) # Set up the user interface from Designer. self.ui = Ui_VoGISProfilToolMain() self.ui.setupUi(self) self.ui.buttonBox.button(QDialogButtonBox.Ok).setText( QApplication.translate("code", "Profil erstellen")) self.ui.buttonBox.button(QDialogButtonBox.Cancel).setText( QApplication.translate("code", "Schließen")) self.ui.grpCadastre.toggled.connect(self._toggleCadastreLayer) self.ui.cmbCadastreLayer.currentIndexChanged.connect( self._updateCadastreLayer) self.settings = settings self.iface = interface self.selectingVisibleRasters = False self.thread = None if self.settings.onlyHektoMode is True: self.ui.IDC_widRaster.hide() self.adjustSize() self.ui.IDC_dblspinDistance.setValue(self.settings.equiDistance) self.ui.IDC_dblspinVertexCnt.setValue(self.settings.vertexCnt) validator = QIntValidator(-32768, 32768, self) self.ui.IDC_tbNoDataExport.setValidator(validator) self.ui.IDC_tbFromX.setText("-30000") self.ui.IDC_tbFromY.setText("240000") self.ui.IDC_tbToX.setText("-20000") self.ui.IDC_tbToY.setText("230000") self.__addRastersToGui() self.__addPolygonsToGui() for line_lyr in self.settings.mapData.lines.lines(): self.ui.IDC_cbLineLayers.addItem(line_lyr.name, line_lyr) if self.settings.mapData.lines.count() < 1: self.ui.IDC_rbDigi.setChecked(True) self.ui.IDC_rbShapeLine.setEnabled(False) #Einstellungen fuer Linie zeichen self.action = QAction( QIcon(":/plugins/vogisprofiltoolmain/icons/icon.png"), "VoGIS-Profiltool", self.iface.mainWindow()) self.action.setWhatsThis("VoGIS-Profiltool") self.canvas = self.iface.mapCanvas() self.tool = ProfiletoolMapTool(self.canvas, self.action) self.savedTool = self.canvas.mapTool() self.polygon = False self.rubberband = QgsRubberBand(self.canvas, self.polygon) self.rubberband.setLineStyle(Qt.SolidLine) self.rubberband.setWidth(4.0) self.rubberband.setColor(QColor(0, 255, 0)) #http://www.qgis.org/api/classQgsRubberBand.html#a6f7cdabfcf69b65dfc6c164ce2d01fab self.pointsToDraw = [] self.dblclktemp = None self.drawnLine = None def accept(self): try: nodata = self.ui.IDC_tbNoDataExport.text() self.settings.nodata_value = int(nodata) if nodata != "" else None QgsMessageLog.logMessage( "Maindlg: nodata: {0}".format(self.settings.nodata_value), "VoGis", Qgis.Info) if self.settings.onlyHektoMode is True and self.settings.mapData.rasters.count( ) > 0: self.settings.onlyHektoMode = False if self.settings.onlyHektoMode is False: if self.settings.mapData.rasters.count() < 1: retVal = QMessageBox.warning( self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate( "code", "Keine Rasterebene vorhanden oder sichtbar! Nur hektometrieren?" ), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if retVal == QMessageBox.No: return else: self.settings.onlyHektoMode = True self.settings.createHekto = True if self.__getSettingsFromGui() is False: return if self.settings.onlyHektoMode is False: if len(self.settings.mapData.rasters.selectedRasters()) < 1: QMessageBox.warning( self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Kein Raster selektiert!")) return QgsMessageLog.logMessage( "modeLine!=line: {0}".format( self.settings.modeLine != enumModeLine.line), "VoGis", Qgis.Info) QgsMessageLog.logMessage( "customLine is None: {0}".format( self.settings.mapData.customLine is None), "VoGis", Qgis.Info) if self.settings.modeLine != enumModeLine.line and self.settings.mapData.customLine is None: QMessageBox.warning( self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate("code", "Keine Profillinie vorhanden!")) return if len(self.settings.mapData.polygons.selected_polygons() ) > 0 and len( self.settings.mapData.rasters.selectedRasters()) > 1: raster_names = list( raster.name for raster in self.settings.mapData.rasters.selectedRasters()) sel_raster, ok_clicked = QInputDialog.getItem( self.iface.mainWindow(), "DHM?", "Welches DHM soll zur Flächenverschneidung verwendet werden?", raster_names, 0, False) if ok_clicked is False: return self.settings.intersection_dhm_idx = raster_names.index( sel_raster) QApplication.setOverrideCursor(Qt.WaitCursor) create_profile = CreateProfile(self.iface, self.settings) thread = QThread(self) create_profile.moveToThread(thread) create_profile.finished.connect(self.profiles_finished) create_profile.error.connect(self.profiles_error) create_profile.progress.connect(self.profiles_progress) thread.started.connect(create_profile.create) thread.start(QThread.LowestPriority) self.thread = thread self.create_profile = create_profile self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) except: QApplication.restoreOverrideCursor() ex = "{0}".format(traceback.format_exc()) msg = "Unexpected ERROR:\n\n{0}".format(ex[:2000]) QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", msg) def profiles_finished(self, profiles, intersections, cadastre): QApplication.restoreOverrideCursor() self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True) self.thread.quit() self.thread.wait() #QGIS 2.0 http://gis.stackexchange.com/a/58754 http://gis.stackexchange.com/a/57090 self.iface.mainWindow().statusBar().showMessage( "VoGIS-Profiltool, {0} Profile".format(len(profiles))) QgsMessageLog.logMessage("Profile Count: {0}".format(len(profiles)), "VoGis", Qgis.Info) if len(profiles) < 1: QApplication.restoreOverrideCursor() QMessageBox.warning( self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate( "code", "Es konnten keine Profile erstellt werden.")) return dlg = VoGISProfilToolPlotDialog(self.iface, self.settings, profiles, intersections, cadastre) dlg.show() dlg.exec_() def profiles_error(self, exception_string): QApplication.restoreOverrideCursor() QgsMessageLog.logMessage( "Error during profile creation: {0}".format(exception_string), "VoGis", Qgis.Critical) QMessageBox.critical(self.iface.mainWindow(), "VoGIS-Profiltool", exception_string) def profiles_progress(self, msg): self.iface.mainWindow().statusBar().showMessage(msg) self.ui.IDC_lblCreateStatus.setText(msg) QApplication.processEvents() def reject(self): if not self.thread is None: if self.thread.isRunning(): self.create_profile.abort() return self.rubberband.reset(self.polygon) QDialog.reject(self) def selectVisibleRasters(self): self.refreshRasterList() self.selectingVisibleRasters = True extCanvas = self.iface.mapCanvas().extent() #alle raster in den einstellunge deselektieren for r in self.settings.mapData.rasters.rasters(): r.selected = False #alle raster in der ListView deselektieren for idx in range(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) item.setCheckState(Qt.Unchecked) #Raster im Extent selektieren canvasCrs = self.iface.mapCanvas().mapSettings().destinationCrs() for idx in range(self.ui.IDC_listRasters.count()): item = self.ui.IDC_listRasters.item(idx) raster = item.data(Qt.UserRole) for r in self.settings.mapData.rasters.rasters(): layerCrs = r.grid.crs() ct = QgsCoordinateTransform(layerCrs, canvasCrs, QgsProject.instance()) extent = ct.transform(r.grid.extent()) if extCanvas.intersects(extent): if r.id == raster.id: r.selected = True item.setCheckState(Qt.Checked) self.selectingVisibleRasters = False def lineLayerChanged(self, idx): if self.ui.IDC_rbShapeLine.isChecked() is False: self.ui.IDC_rbShapeLine.setChecked(True) lineLyr = (self.ui.IDC_cbLineLayers.itemData( self.ui.IDC_cbLineLayers.currentIndex())) lyr = lineLyr.line if hasattr(lyr, "selectedFeatureCount"): if (lyr.selectedFeatureCount() < 1): self.ui.IDC_chkOnlySelectedFeatures.setChecked(False) else: self.ui.IDC_chkOnlySelectedFeatures.setChecked(True) def valueChangedEquiDistance(self, val): if self.ui.IDC_rbEquiDistance.isChecked() is False: self.ui.IDC_rbEquiDistance.setChecked(True) def valueChangedVertexCount(self, val): if self.ui.IDC_rbVertexCount.isChecked() is False: self.ui.IDC_rbVertexCount.setChecked(True) def lvRasterItemChanged(self, item): if self.selectingVisibleRasters is True: return if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) raster_lyr = item_data self.settings.mapData.rasters.getById( raster_lyr.id).selected = selected def lvPolygonItemChanged(self, item): if item.checkState() == Qt.Checked: selected = True if item.checkState() == Qt.Unchecked: selected = False item_data = item.data(Qt.UserRole) poly_lyr = item_data self.settings.mapData.polygons.getById(poly_lyr.id).selected = selected def refreshRasterList(self): root = QgsProject.instance().layerTreeRoot() avail_lyrs = root.findLayers() raster_coll = RasterCollection() for lyr in avail_lyrs: if lyr.isVisible(): mapLayer = lyr.layer() lyr_type = mapLayer.type() lyr_name = mapLayer.name() if lyr_type == QgsMapLayer.RasterLayer: if mapLayer.bandCount() < 2: new_raster = Raster(mapLayer.id(), lyr_name, mapLayer) raster_coll.addRaster(new_raster) self.settings.mapData.rasters = raster_coll self.__addRastersToGui() def __addRastersToGui(self): self.ui.IDC_listRasters.clear() check = Qt.Unchecked if self.settings.mapData.rasters.count() == 1: check = Qt.Checked self.settings.mapData.rasters.rasters()[0].selected = True for raster_lyr in self.settings.mapData.rasters.rasters(): item = QListWidgetItem(raster_lyr.name) item.setData(Qt.UserRole, raster_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listRasters.addItem(item) def __addPolygonsToGui(self): self.ui.IDC_listPolygons.clear() self.ui.cmbCadastreLayer.clear() check = Qt.Unchecked for poly_lyr in self.settings.mapData.polygons.polygons(): item = QListWidgetItem(poly_lyr.name) item.setData(Qt.UserRole, poly_lyr) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(check) self.ui.IDC_listPolygons.addItem(item) self.ui.cmbCadastreLayer.addItem(poly_lyr.name, poly_lyr.id) def drawLine(self): if self.ui.IDC_rbDigi.isChecked() is False: self.ui.IDC_rbDigi.setChecked(True) self.dblckltemp = None self.rubberband.reset(self.polygon) self.__cleanDigi() self.__activateDigiTool() self.canvas.setMapTool(self.tool) def __createDigiFeature(self, pnts): u = Util(self.iface) f = u.createQgLineFeature(pnts) self.settings.mapData.customLine = f def __lineFinished(self, position): self.showNormal() self.raise_() self.activateWindow() mapPos = self.canvas.getCoordinateTransform().toMapCoordinates( position["x"], position["y"]) newPoint = QgsPointXY(mapPos.x(), mapPos.y()) self.pointsToDraw.append(newPoint) #launch analyses self.iface.mainWindow().statusBar().showMessage(str(self.pointsToDraw)) if len(self.pointsToDraw) < 2: self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint self.drawnLine = None QMessageBox.warning( self, "VoGIS-Profiltool", QApplication.translate( "code", "Profillinie digitalisieren abgebrochen!")) self.drawnLine = self.__createDigiFeature(self.pointsToDraw) self.__cleanDigi() self.pointsToDraw = [] self.dblclktemp = newPoint def __cleanDigi(self): self.pointsToDraw = [] self.canvas.unsetMapTool(self.tool) self.canvas.setMapTool(self.savedTool) def __activateDigiTool(self): self.tool.moved.connect(self.__moved) self.tool.rightClicked.connect(self.__rightClicked) self.tool.leftClicked.connect(self.__leftClicked) self.tool.doubleClicked.connect(self.__doubleClicked) self.tool.deactivated.connect(self.__deactivateDigiTool) def __deactivateDigiTool(self): # TODO: how to check if not connected??? try: self.tool.moved.disconnect(self.__moved) except: pass try: self.tool.leftClicked.disconnect(self.__leftClicked) except: pass try: self.tool.rightClicked.disconnect(self.__rightClicked) except: pass try: self.tool.doubleClicked.disconnect(self.__doubleClicked) except: pass try: self.iface.mainWindow().statusBar().showMessage("") except: pass def __moved(self, position): if len(self.pointsToDraw) > 0: mapPos = self.canvas.getCoordinateTransform().toMapCoordinates( position["x"], position["y"]) self.rubberband.reset(self.polygon) newPnt = QgsPointXY(mapPos.x(), mapPos.y()) pnts = self.pointsToDraw + [newPnt] self.rubberband.setToGeometry(QgsGeometry.fromPolylineXY(pnts), None) def __rightClicked(self, position): self.__lineFinished(position) def __leftClicked(self, position): mapPos = self.canvas.getCoordinateTransform().toMapCoordinates( position["x"], position["y"]) newPoint = QgsPointXY(mapPos.x(), mapPos.y()) if newPoint == self.dblclktemp: self.dblclktemp = None return else: if len(self.pointsToDraw) == 0: self.rubberband.reset(self.polygon) self.pointsToDraw.append(newPoint) def __doubleClicked(self, position): pass #not in use right now def __lineCancel(self): pass def __getSettingsFromGui(self): self.settings.linesExplode = ( self.ui.IDC_chkLinesExplode.checkState() == Qt.Checked) self.settings.linesMerge = ( self.ui.IDC_chkLinesMerge.checkState() == Qt.Checked) self.settings.onlySelectedFeatures = ( self.ui.IDC_chkOnlySelectedFeatures.checkState() == Qt.Checked) self.settings.equiDistance = self.ui.IDC_dblspinDistance.value() self.settings.vertexCnt = self.ui.IDC_dblspinVertexCnt.value() #self.settings.createHekto = (self.ui.IDC_chkCreateHekto.checkState() == Qt.Checked) self.settings.nodesAndVertices = ( self.ui.IDC_chkNodesAndVertices.checkState() == Qt.Checked) self.settings.mapData.selectedLineLyr = ( self.ui.IDC_cbLineLayers.itemData( self.ui.IDC_cbLineLayers.currentIndex())) if self.settings.onlySelectedFeatures is True and self.settings.mapData.selectedLineLyr.line.selectedFeatureCount( ) < 1: QMessageBox.warning( self.iface.mainWindow(), "VoGIS-Profiltool", QApplication.translate( "code", u"Der gewählte Layer hat keine selektierten Elemente.")) return False if self.ui.IDC_rbDigi.isChecked(): self.settings.modeLine = enumModeLine.customLine elif self.ui.IDC_rbShapeLine.isChecked(): self.settings.modeLine = enumModeLine.line else: #self.ui.IDC_rbStraigthLine self.settings.modeLine = enumModeLine.straightLine if self.ui.IDC_rbEquiDistance.isChecked(): self.settings.modeVertices = enumModeVertices.equiDistant else: self.settings.modeVertices = enumModeVertices.vertexCnt if self.ui.IDC_rbStraigthLine.isChecked(): ut = Util(self.iface) if ut.isFloat(self.ui.IDC_tbFromX.text(), QApplication.translate("code", "Rechtswert von")) is False: return False else: fromX = float(self.ui.IDC_tbFromX.text()) if ut.isFloat(self.ui.IDC_tbFromY.text(), QApplication.translate("code", "Hochwert von")) is False: return False else: fromY = float(self.ui.IDC_tbFromY.text()) if ut.isFloat(self.ui.IDC_tbToX.text(), QApplication.translate("code", "Rechtswert nach")) is False: return False else: toX = float(self.ui.IDC_tbToX.text()) if ut.isFloat(self.ui.IDC_tbToY.text(), QApplication.translate("code", "Hochwert nach")) is False: return False else: toY = float(self.ui.IDC_tbToY.text()) fromPnt = QgsPointXY(fromX, fromY) toPnt = QgsPointXY(toX, toY) self.settings.mapData.customLine = ut.createQgLineFeature( [fromPnt, toPnt]) return True def _toggleCadastreLayer(self, toggled): if toggled: layerId = self.ui.cmbCadastreLayer.itemData( self.ui.cmbCadastreLayer.currentIndex()) self.settings.mapData.cadastre = layerId else: self.settings.mapData.cadastre = None def _updateCadastreLayer(self, index): if self.ui.grpCadastre.isChecked(): layerId = self.ui.cmbCadastreLayer.itemData(index) self.settings.mapData.cadastre = layerId
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.addPluginToWebMenu( self.menu, action) self.actions.append(action) return action
def add_menu_action(self, icon_path: str, text: str, callback: Callable, enabled_flag: bool = True, add_to_menu: bool = True, menu_type: str = None, add_to_toolbar: bool = True, status_tip: str = None, whats_this: str = None, parent: QWidget = None) -> QAction: """ Add a toolbar icon to the toolbar, associating it with an action linked to a function called on click; the action is also added to self.actions['menus'] list. Args: 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. text: Text that should be shown in menu items for this action. callback: Function to be called when the action is triggered. enabled_flag: Whether the action should be enabled by default or not. add_to_menu: Whether the action should be added to the menu. menu_type: Type of menu add the action to, other than the main one (None). add_to_toolbar: Whether the action should also be added to the toolbar. status_tip: Optional text to show in a popup when mouse pointer hovers over the action. whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. parent: Parent Qt widget for the new action Returns: The action that was created. """ if not menu_type: logger.debug("Add action \"%s\" to \"plugin\" toolbar menu" % text) else: logger.debug("Add action \"%s\" to \"%s\" toolbar menu" % (text, menu_type)) icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) # Optionally setup "Status" tip dialog if status_tip is not None: action.setStatusTip(status_tip) # Optionally setup "what's this?" tip dialog if whats_this is not None: action.setWhatsThis(whats_this) # Optionally adds plugin menu icon to Plugins toolbar if add_to_toolbar: self.iface.addToolBarIcon(action) # Add menu items to proper plugin category if add_to_menu: if not menu_type: self.iface.addPluginToMenu(self.menu, action) elif menu_type.lower() == "database": self.iface.addPluginToDatabaseMenu(self.menu, action) elif menu_type.lower() == "raster": self.iface.addPluginToRasterMenu(self.menu, action) elif menu_type.lower() == "vector": self.iface.addPluginToVectorMenu(self.menu, action) elif menu_type.lower() == "web": self.iface.addPluginToWebMenu(self.menu, action) else: logger.error("Invalid menu choice") raise RuntimeError("Invalid choice for action adding: %s" % menu_type) # Updates actions array and return inserted elements self.actions['menus'].append(action) return action
def create_action( icon_path, text, callback, enabled_flag=True, status_tip=None, whats_this=None, parent=None, object_name=None): """ # adapted from RedLayers by E. Ferreguti Create an action. :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 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. :param object_name: Optional name to identify objects during customization :type object_name: str :returns: The action that was created. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) if callback: action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip: action.setStatusTip(status_tip) if whats_this: action.setWhatsThis(whats_this) if object_name: action.setObjectName(object_name) return action
class QgepPlugin(object): """ A plugin for wastewater management http://www.github.com/qgep/QGEP """ # The networkAnalyzer will manage the networklayers and pathfinding network_analyzer = None # Remember not to reopen the dock if there's already one opened profile_dock = None # Wizard wizarddock = None # The layer ids the plugin will need edgeLayer = None nodeLayer = None specialStructureLayer = None networkElementLayer = None profile = None def __init__(self, iface): self.iface = iface self.canvas = iface.mapCanvas() self.nodes = None self.edges = None self.initLogger() setup_i18n() def tr(self, source_text): """ This does not inherit from QObject but for the translation to work (in particular to have translatable strings picked up) we need a tr method. :rtype : unicode :param source_text: The text to translate :return: The translated text """ return QApplication.translate('QgepPlugin', source_text) def initLogger(self): """ Initializes the logger """ self.logger = logging.getLogger(__package__) settings = QSettings() loglevel = settings.value("/QGEP/LogLevel", 'Warning') logfile = settings.value("/QGEP/LogFile", None) if hasattr(self.logger, 'qgepFileHandler'): self.logger.removeHandler(self.logger.qgepFileHandler) del self.logger.qgepFileHandler self.logger.addHandler(QgepQgsLogHandler()) if logfile: log_handler = logging.FileHandler(logfile) fmt = logging.Formatter(LOGFORMAT) log_handler.setFormatter(fmt) self.logger.addHandler(log_handler) self.logger.fileHandler = log_handler if 'Debug' == loglevel: self.logger.setLevel(logging.DEBUG) elif 'Info' == loglevel: self.logger.setLevel(logging.INFO) elif 'Warning' == loglevel: self.logger.setLevel(logging.WARNING) elif 'Error' == loglevel: self.logger.setLevel(logging.ERROR) fp = os.path.join(os.path.abspath(os.path.dirname(__file__)), "metadata.txt") ini_text = QSettings(fp, QSettings.IniFormat) verno = ini_text.value("version") self.logger.info('QGEP plugin version ' + verno + ' started') def initGui(self): """ Called to setup the plugin GUI """ self.network_layer_notifier = QgepLayerNotifier( self.iface.mainWindow(), ['vw_network_node', 'vw_network_segment']) self.wastewater_networkelement_layer_notifier = QgepLayerNotifier( self.iface.mainWindow(), ['vw_wastewater_node', 'vw_qgep_reach']) self.toolbarButtons = [] # Create toolbar button self.profileAction = QAction( QIcon( os.path.join(plugin_root_path(), "icons/wastewater-profile.svg")), self.tr("Profile"), self.iface.mainWindow()) self.profileAction.setWhatsThis(self.tr("Reach trace")) self.profileAction.setEnabled(False) self.profileAction.setCheckable(True) self.profileAction.triggered.connect(self.profileToolClicked) self.downstreamAction = QAction( QIcon( os.path.join(plugin_root_path(), "icons/wastewater-downstream.svg")), self.tr("Downstream"), self.iface.mainWindow()) self.downstreamAction.setWhatsThis(self.tr("Downstream reaches")) self.downstreamAction.setEnabled(False) self.downstreamAction.setCheckable(True) self.downstreamAction.triggered.connect(self.downstreamToolClicked) self.upstreamAction = QAction( QIcon( os.path.join(plugin_root_path(), "icons/wastewater-upstream.svg")), self.tr("Upstream"), self.iface.mainWindow()) self.upstreamAction.setWhatsThis(self.tr("Upstream reaches")) self.upstreamAction.setEnabled(False) self.upstreamAction.setCheckable(True) self.upstreamAction.triggered.connect(self.upstreamToolClicked) self.wizardAction = QAction( QIcon(os.path.join(plugin_root_path(), "icons/wizard.svg")), "Wizard", self.iface.mainWindow()) self.wizardAction.setWhatsThis( self.tr("Create new manholes and reaches")) self.wizardAction.setEnabled(False) self.wizardAction.setCheckable(True) self.wizardAction.triggered.connect(self.wizard) self.connectNetworkElementsAction = QAction( QIcon( os.path.join(plugin_root_path(), "icons/link-wastewater-networkelement.svg")), QApplication.translate('qgepplugin', 'Connect wastewater networkelements'), self.iface.mainWindow()) self.connectNetworkElementsAction.setEnabled(False) self.connectNetworkElementsAction.setCheckable(True) self.connectNetworkElementsAction.triggered.connect( self.connectNetworkElements) self.refreshNetworkTopologyAction = QAction( QIcon(os.path.join(plugin_root_path(), "icons/refresh-network.svg")), "Refresh network topology", self.iface.mainWindow()) self.refreshNetworkTopologyAction.setWhatsThis( self.tr("Refresh network topology")) self.refreshNetworkTopologyAction.setEnabled(False) self.refreshNetworkTopologyAction.setCheckable(False) self.refreshNetworkTopologyAction.triggered.connect( self.refreshNetworkTopologyActionClicked) self.aboutAction = QAction(self.tr('About'), self.iface.mainWindow()) self.aboutAction.triggered.connect(self.about) self.settingsAction = QAction(self.tr('Settings'), self.iface.mainWindow()) self.settingsAction.triggered.connect(self.showSettings) # Add toolbar button and menu item self.toolbar = QToolBar(QApplication.translate('qgepplugin', 'QGEP')) self.toolbar.addAction(self.profileAction) self.toolbar.addAction(self.upstreamAction) self.toolbar.addAction(self.downstreamAction) self.toolbar.addAction(self.wizardAction) self.toolbar.addAction(self.refreshNetworkTopologyAction) self.toolbar.addAction(self.connectNetworkElementsAction) self.iface.addPluginToMenu("&QGEP", self.profileAction) self.iface.addPluginToMenu("&QGEP", self.settingsAction) self.iface.addPluginToMenu("&QGEP", self.aboutAction) self.iface.addToolBar(self.toolbar) # Local array of buttons to enable / disable based on context self.toolbarButtons.append(self.profileAction) self.toolbarButtons.append(self.upstreamAction) self.toolbarButtons.append(self.downstreamAction) self.toolbarButtons.append(self.wizardAction) self.toolbarButtons.append(self.refreshNetworkTopologyAction) self.network_layer_notifier.layersAvailable.connect( self.onLayersAvailable) self.network_layer_notifier.layersUnavailable.connect( self.onLayersUnavailable) # Init the object maintaining the network self.network_analyzer = QgepGraphManager() self.network_analyzer.message_emitted.connect( self.iface.messageBar().pushMessage) # Create the map tool for profile selection self.profile_tool = QgepProfileMapTool(self.iface, self.profileAction, self.network_analyzer) self.profile_tool.profileChanged.connect(self.onProfileChanged) self.upstream_tree_tool = QgepTreeMapTool(self.iface, self.upstreamAction, self.network_analyzer) self.upstream_tree_tool.setDirection("upstream") self.upstream_tree_tool.treeChanged.connect(self.onTreeChanged) self.downstream_tree_tool = QgepTreeMapTool(self.iface, self.downstreamAction, self.network_analyzer) self.downstream_tree_tool.setDirection("downstream") self.downstream_tree_tool.treeChanged.connect(self.onTreeChanged) self.maptool_connect_networkelements = QgepMapToolConnectNetworkElements( self.iface, self.connectNetworkElementsAction) self.wastewater_networkelement_layer_notifier.layersAvailableChanged.connect( self.connectNetworkElementsAction.setEnabled) self.processing_provider = QgepProcessingProvider() QgsApplication.processingRegistry().addProvider( self.processing_provider) def unload(self): """ Called when unloading """ self.toolbar.removeAction(self.profileAction) self.toolbar.removeAction(self.upstreamAction) self.toolbar.removeAction(self.downstreamAction) self.toolbar.removeAction(self.wizardAction) self.toolbar.removeAction(self.refreshNetworkTopologyAction) self.toolbar.removeAction(self.connectNetworkElementsAction) self.toolbar.deleteLater() self.iface.removePluginMenu("&QGEP", self.profileAction) self.iface.removePluginMenu("&QGEP", self.aboutAction) QgsApplication.processingRegistry().removeProvider( self.processing_provider) def onLayersAvailable(self, layers): for b in self.toolbarButtons: b.setEnabled(True) self.network_analyzer.setReachLayer(layers['vw_network_segment']) self.network_analyzer.setNodeLayer(layers['vw_network_node']) def onLayersUnavailable(self): for b in self.toolbarButtons: b.setEnabled(False) def profileToolClicked(self): """ Is executed when the profile button is clicked """ self.openDock() # Set the profile map tool self.profile_tool.setActive() def upstreamToolClicked(self): """ Is executed when the user clicks the upstream search tool """ self.openDock() self.upstream_tree_tool.setActive() def downstreamToolClicked(self): """ Is executed when the user clicks the downstream search tool """ self.openDock() self.downstream_tree_tool.setActive() def refreshNetworkTopologyActionClicked(self): """ Is executed when the user clicks the refreshNetworkTopologyAction tool """ self.network_analyzer.refresh() def wizard(self): """ """ if not self.wizarddock: self.wizarddock = QgepWizard(self.iface.mainWindow(), self.iface) self.logger.debug('Opening Wizard') self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.wizarddock) self.wizarddock.show() def connectNetworkElements(self, checked): self.iface.mapCanvas().setMapTool(self.maptool_connect_networkelements) def openDock(self): """ Opens the dock """ if self.profile_dock is None: self.logger.debug('Open dock') self.profile_dock = QgepProfileDockWidget(self.iface.mainWindow(), self.iface.mapCanvas(), self.iface.addDockWidget) self.profile_dock.closed.connect(self.onDockClosed) self.profile_dock.showIt() self.plotWidget = QgepPlotSVGWidget(self.profile_dock, self.network_analyzer) self.plotWidget.specialStructureMouseOver.connect( self.highlightProfileElement) self.plotWidget.specialStructureMouseOut.connect( self.unhighlightProfileElement) self.plotWidget.reachMouseOver.connect( self.highlightProfileElement) self.plotWidget.reachMouseOut.connect( self.unhighlightProfileElement) self.profile_dock.addPlotWidget(self.plotWidget) self.profile_dock.setTree(self.nodes, self.edges) def onDockClosed(self): # used when Dock dialog is closed """ Gets called when the dock is closed All the cleanup of the dock has to be done here """ self.profile_dock = None def onProfileChanged(self, profile): """ The profile changed: update the plot @param profile: The profile to plot """ self.profile = profile.copy() if self.plotWidget: self.plotWidget.setProfile(profile) def onTreeChanged(self, nodes, edges): if self.profile_dock: self.profile_dock.setTree(nodes, edges) self.nodes = nodes self.edges = edges def highlightProfileElement(self, obj_id): if self.profile is not None: self.profile.highlight(str(obj_id)) def unhighlightProfileElement(self): if self.profile is not None: self.profile.highlight(None) def about(self): from .gui.dlgabout import DlgAbout DlgAbout(self.iface.mainWindow()).exec_() def showSettings(self): settings_dlg = QgepSettingsDialog(self.iface.mainWindow()) settings_dlg.exec_()
class MetaSearchPlugin(object): """base plugin""" def __init__(self, iface): """init""" self.iface = iface self.context = StaticContext() self.action_run = None self.action_help = None self.dialog = None self.web_menu = '&MetaSearch' def initGui(self): """startup""" # run run_icon = QIcon('%s/%s' % (self.context.ppath, 'images/MetaSearch.png')) self.action_run = QAction(run_icon, 'MetaSearch', self.iface.mainWindow()) self.action_run.setWhatsThis(QCoreApplication.translate('MetaSearch', 'MetaSearch plugin')) self.action_run.setStatusTip(QCoreApplication.translate('MetaSearch', 'Search Metadata Catalogs')) self.action_run.triggered.connect(self.run) self.iface.addWebToolBarIcon(self.action_run) self.iface.addPluginToWebMenu(self.web_menu, self.action_run) # help help_icon = QgsApplication.getThemeIcon('/mActionHelpContents.svg') self.action_help = QAction(help_icon, 'Help', self.iface.mainWindow()) self.action_help.setWhatsThis(QCoreApplication.translate('MetaSearch', 'MetaSearch plugin help')) self.action_help.setStatusTip(QCoreApplication.translate('MetaSearch', 'Get Help on MetaSearch')) self.action_help.triggered.connect(self.help) self.iface.addPluginToWebMenu(self.web_menu, self.action_help) # prefab the dialog but not open it yet self.dialog = MetaSearchDialog(self.iface) def unload(self): """teardown""" # remove the plugin menu item and icon self.iface.removePluginWebMenu(self.web_menu, self.action_run) self.iface.removePluginWebMenu(self.web_menu, self.action_help) self.iface.removeWebToolBarIcon(self.action_run) def run(self): """open MetaSearch""" self.dialog.exec_() def help(self): """open help in user's default web browser""" open_url(get_help_url())
class QRAVE: """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 self.tm = QgsApplication.taskManager() self.qproject = QgsProject.instance() self.pluginIsActive = False self.dockwidget = None self.metawidget = None # Populated on load from a URL self.acknowledgements = None # 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', 'QRAVE_{}.qm'.format(locale)) self.settings = Settings(iface=self.iface) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Riverscapes Plugin (QRAVE)') # TODO: We are going to let the user set this up in a future iteration self.toolbar = self.iface.addToolBar(u'QRAVE') self.toolbar.setObjectName(u'QRAVE') 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('QRAVE', message) def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" self.qproject.readProject.connect(self.onProjectLoad) self.openAction = QAction( QIcon(':/plugins/qrave_toolbar/RaveAddIn_16px.png'), self.tr(u'Riverscapes Plugin (QRAVE)'), self.iface.mainWindow()) self.openAction.triggered.connect(self.toggle_widget) self.openAction.setStatusTip('Toggle the project viewer') self.openAction.setWhatsThis('Toggle the project viewer') self.openProjectAction = QAction( QIcon(':/plugins/qrave_toolbar/OpenProject.png'), self.tr(u'Open Riverscapes Project'), self.iface.mainWindow()) self.openProjectAction.triggered.connect(self.projectBrowserDlg) self.openProjectAction.setStatusTip('Open QRAVE project') self.openProjectAction.setWhatsThis('Open QRAVE project') self.helpButton = QToolButton() self.helpButton.setToolButtonStyle(Qt.ToolButtonTextOnly) self.helpButton.setMenu(QMenu()) self.helpButton.setPopupMode(QToolButton.MenuButtonPopup) m = self.helpButton.menu() # TODO: get the local help working # self.helpAction = QAction( # QIcon(':/plugins/qrave_toolbar/Help.png'), # self.tr('Help'), # self.iface.mainWindow() # ) # self.helpAction.triggered.connect(partial(showPluginHelp, None, filename=':/plugins/qrave_toolbar/help/build/html/index')) # self.websiteAction = QAction( # QIcon(':/plugins/qrave_toolbar/RaveAddIn_16px.png'), # self.tr('Website'), # self.iface.mainWindow() # ) # self.websiteAction.triggered.connect(lambda: QDesktopServices.openUrl(QUrl("http://rave.riverscapes.xyz"))) self.helpAction = QAction(QIcon(':/plugins/qrave_toolbar/Help.png'), self.tr('Help'), self.iface.mainWindow()) self.helpAction.triggered.connect(lambda: QDesktopServices.openUrl( QUrl("http://rave.riverscapes.xyz"))) self.raveOptionsAction = QAction( QIcon(':/plugins/qrave_toolbar/Options.png'), self.tr('Settings'), self.iface.mainWindow()) self.raveOptionsAction.triggered.connect(self.options_load) self.net_sync_action = QAction( QIcon(':/plugins/qrave_toolbar/refresh.png'), self.tr('Update resources'), self.iface.mainWindow()) self.net_sync_action.triggered.connect( lambda: self.net_sync_load(force=True)) self.find_resources_action = QAction( QIcon(':/plugins/qrave_toolbar/BrowseFolder.png'), self.tr('Find Resources folder'), self.iface.mainWindow()) self.find_resources_action.triggered.connect(self.locateResources) self.about_action = QAction( QIcon(':/plugins/qrave_toolbar/RaveAddIn_16px.png'), self.tr('About QRAVE'), self.iface.mainWindow()) self.about_action.triggered.connect(self.about_load) m.addAction(self.helpAction) # m.addAction(self.websiteAction) m.addAction(self.raveOptionsAction) m.addAction(self.net_sync_action) m.addSeparator() m.addAction(self.find_resources_action) m.addAction(self.about_action) self.helpButton.setDefaultAction(self.helpAction) self.toolbar.addAction(self.openAction) self.toolbar.addAction(self.openProjectAction) self.toolbar.addWidget(self.helpButton) # Do a check to see if the stored version is different than the current version lastVersion = self.settings.getValue('pluginVersion') # This does a lazy netsync (i.e. it will run it if it feels like it) versionChange = lastVersion != __version__ self.net_sync_load(force=versionChange) if versionChange: QgsMessageLog.logMessage( "Version change detected: {} ==> {}".format( lastVersion, __version__), 'QRAVE', level=Qgis.Info) self.settings.setValue('pluginVersion', __version__) def onProjectLoad(self, doc): # If the project has the plugin enabled then restore it. qrave_enabled, type_conversion_ok = self.qproject.readEntry( CONSTANTS['settingsCategory'], 'enabled') if type_conversion_ok and qrave_enabled == '1': self.toggle_widget(forceOn=True) if self.dockwidget is not None: self.dockwidget.reload_tree() def onClosePlugin(self): """Cleanup necessary items here when plugin dockwidget is closed""" if self.metawidget is not None: self.metawidget.hide() if self.dockwidget is not None: self.dockwidget.hide() # disconnects self.dockwidget.closingPlugin.disconnect(self.onClosePlugin) self.qproject.readProject.disconnect(self.onProjectLoad) # remove this statement if dockwidget is to remain # for reuse if plugin is reopened self.dockwidget = None self.pluginIsActive = False def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" if self.metawidget is not None: self.metawidget.hide() if self.dockwidget is not None: self.dockwidget.hide() for action in self.actions: self.iface.removePluginMenu( self.tr(u'&Riverscapes Plugin (QRAVE)'), action) self.iface.removeToolBarIcon(action) # remove the toolbar del self.toolbar def toggle_widget(self, forceOn=False): """Toggle the widget open and closed when clicking the toolbar""" if not self.pluginIsActive: self.pluginIsActive = True # dockwidget may not exist if: # first run of plugin # removed on close (see self.onClosePlugin method) if self.dockwidget is None: # Create the dockwidget (after translation) and keep reference self.dockwidget = QRAVEDockWidget() self.metawidget = QRAVEMetaWidget() # Hook metadata changes up to the metawidget self.dockwidget.metaChange.connect(self.metawidget.load) # Run a network sync operation to get the latest stuff. Don't force it. # This is just a quick check self.net_sync_load() # connect to provide cleanup on closing of dockwidget self.dockwidget.closingPlugin.connect(self.onClosePlugin) # show the dockwidget self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dockwidget) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.metawidget) self.dockwidget.show() else: if self.dockwidget is not None: if self.dockwidget.isHidden(): self.dockwidget.show() elif forceOn is False: self.dockwidget.hide() # The metawidget always starts hidden if self.metawidget is not None: self.metawidget.hide() if self.dockwidget is not None and not self.dockwidget.isHidden(): self.qproject.writeEntry(CONSTANTS['settingsCategory'], 'enabled', True) else: self.qproject.removeEntry(CONSTANTS['settingsCategory'], 'enabled') def net_sync_load(self, force=False): """ Periodically check for new files """ lastDigestSync = self.settings.getValue('lastDigestSync') lastVersion = self.settings.getValue('pluginVersion') currTime = int(time()) # timestamp in seconds plugin_init = self.settings.getValue('initialized') autoUpdate = self.settings.getValue('autoUpdate') self.netsync = NetSync('Sync QRAVE resource files') perform_sync = False # setting the force flag overrides everything else if force: perform_sync = True # Otherwise you only get a sync if 'autoUpdate' is turned on elif autoUpdate: # If this is an old version or the plugin is uninitialized if not plugin_init or lastVersion != __version__ or self.netsync.need_sync: perform_sync = True # If we haven't checked for more than `digestSyncFreqHours` hours elif isinstance(lastDigestSync, int) \ and ((currTime - lastDigestSync) / 3600) > CONSTANTS['digestSyncFreqHours']: perform_sync = True if perform_sync is False: self.netsync = None return # Trigger the dockwidget to repaint after the netsync if self.dockwidget is not None: self.netsync.taskCompleted.connect(self.dockwidget.reload_tree) # FOR DEBUGGING ONLY. NEVER IN PRODUCTION # self.netsync.run() # COMMENT THIS OUT AND USE THE LINE ABOVE FOR SYNCHRONOUS DEBUGGING self.tm.addTask(self.netsync) def projectBrowserDlg(self): """ Browse for a project directory :return: """ last_browse_path = self.settings.getValue('lastBrowsePath') last_dir = os.path.dirname( last_browse_path) if last_browse_path is not None else None dialog_return = QFileDialog.getOpenFileName( self.dockwidget, "Open a Riverscapes project", last_dir, self.tr("Riverscapes Project files (project.rs.xml)")) if dialog_return is not None and dialog_return[ 0] != "" and os.path.isfile(dialog_return[0]): # We set the proect path in the project settings. This way it will be saved with the QgsProject file if self.dockwidget is None or self.dockwidget.isHidden() is True: self.toggle_widget(forceOn=True) self.dockwidget.add_project(dialog_return[0]) def locateResources(self): """This the OS-agnostic "show in Finder" or "show in explorer" equivalent It should open the folder of the item in question Args: fpath (str): [description] """ qurl = QUrl.fromLocalFile(RESOURCES_DIR) QDesktopServices.openUrl(qurl) def options_load(self): """ Open the options/settings dialog """ dialog = OptionsDialog() if self.dockwidget: dialog.dataChange.connect(self.dockwidget.dataChange) dialog.exec_() def about_load(self): """ Open the About dialog """ dialog = AboutDialog() if self.acknowledgements is None: self.acknowledgements = requests.get( 'http://rave.riverscapes.xyz/dotnetack.html').text dialog.acknowledgements.setText(self.acknowledgements) dialog.exec_()