def sendVote(self, plugin_id, vote): """ send vote via the RPC """ if not plugin_id or not vote: return False url = "http://plugins.qgis.org/plugins/RPC2/" params = {"id": "djangorpc", "method": "plugin.vote", "params": [str(plugin_id), str(vote)]} req = QNetworkRequest(QUrl(url)) req.setRawHeader(b"Content-Type", b"application/json") QgsNetworkAccessManager.instance().post(req, bytes(json.dumps(params), "utf-8")) return True
def sendVote(self, plugin_id, vote): """ send vote via the RPC """ if not plugin_id or not vote: return False url = "http://plugins.qgis.org/plugins/RPC2/" params = "{\"id\":\"djangorpc\",\"method\":\"plugin.vote\",\"params\":[%s,%s]}" % (str(plugin_id), str(vote)) req = QNetworkRequest(QUrl(url)) req.setRawHeader("Content-Type", "application/json") QgsNetworkAccessManager.instance().post(req, params) return True
def sendVote(self, plugin_id, vote): """ send vote via the RPC """ if not plugin_id or not vote: return False url = "http://plugins.qgis.org/plugins/RPC2/" params = "{\"id\":\"djangorpc\",\"method\":\"plugin.vote\",\"params\":[%s,%s]}" % ( str(plugin_id), str(vote)) req = QNetworkRequest(QUrl(url)) req.setRawHeader("Content-Type", "application/json") QgsNetworkAccessManager.instance().post(req, params) return True
def sendVote(self, plugin_id, vote): """ send vote via the RPC """ if not plugin_id or not vote: return False url = "http://plugins.qgis.org/plugins/RPC2/" params = {"id": "djangorpc", "method": "plugin.vote", "params": [str(plugin_id), str(vote)]} req = QNetworkRequest(QUrl(url)) req.setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorClass), "QgsPluginInstaller") req.setAttribute(QNetworkRequest.Attribute(QgsNetworkRequestParameters.AttributeInitiatorRequestId), "sendVote") req.setRawHeader(b"Content-Type", b"application/json") QgsNetworkAccessManager.instance().post(req, bytes(json.dumps(params), "utf-8")) return True
def fetchNext(self): if len(self.queue) == 0: return url = self.queue.pop(0) self.log("fetchNext: %s" % url) request = QNetworkRequest(QUrl(url)) request.setRawHeader("User-Agent", self.userAgent) reply = QgsNetworkAccessManager.instance().get(request) reply.finished.connect(self.replyFinishedSlot) self.requestingUrls.append(url) self.replies.append(reply) return reply
def create_request(self, request_type: str): """Creates a QNetworkRequest() with appropriate headers and URL according to the 'request_type' parameter. :param str request_type: type of request to create. Options: - 'token' - 'search' - 'details' - 'shares' :returns: the QNetworkRequest to send to the Isogeo's API :rtype: QNetworkRequest """ # creating headers (same steps wathever request_type value) header_value = QByteArray() header_name = QByteArray() header_name.append("Authorization") # for token request if request_type == "token": # filling request header with credentials header_value.append("Basic ") header_value.append( base64.b64encode("{}:{}".format(self.app_id, self.app_secret).encode())) # creating the QNetworkRequest from oAuth2 authentication URL request = QNetworkRequest(QUrl(self.api_url_token)) # creating and setting the 'Content-type header' ct_header_value = QByteArray() ct_header_value.append("application/json") request.setHeader(request.ContentTypeHeader, ct_header_value) # for other request_type, setting appropriate url else: if request_type == "shares": url = QUrl("{}/shares".format(self.api_url_base)) elif request_type == "search" or request_type == "details": url = QUrl(self.currentUrl) else: logger.debug( "Unkown request type asked : {}".format(request_type)) raise ValueError return 0 # filling request header with token header_value.append(self.token) request = QNetworkRequest(url) # creating QNetworkRequest from appropriate url request.setRawHeader(header_name, header_value) return request
def send_request_to_isogeo_api(self, token, limit=10): """Send a content url to the Isogeo API. This takes the currentUrl variable and send a request to this url, using the token variable. """ myurl = QUrl(self.currentUrl) request = QNetworkRequest(myurl) request.setRawHeader("Authorization", token) if self.requestStatusClear is True: self.requestStatusClear = False api_reply = self.manager.get(request) api_reply.finished.connect( partial(self.handle_api_reply, answer=api_reply)) else: pass
def api_get_request(self): logger.debug("\n----------------- Sending request -----------------") # creating credentials header crd_header_value = QByteArray() crd_header_value.append(self.token) crd_header_name = QByteArray() crd_header_name.append("Authorization") # creating request rqst = QNetworkRequest(QUrl(self.request_url)) # setting credentials header rqst.setRawHeader(crd_header_name, crd_header_value) # sending request rqst_reply = self.naMngr.get(rqst) rqst_reply.finished.connect(partial(self.api_handle_request, reply=rqst_reply))
def delegate_download(self, action_url, method, headers, data, js_cb_func, js_cb_object_id): """ :param action_url: url to call on ipt api :param method: string like 'POST' :param headers: list of strings :param data: list of dictionaries {name (string) value(string)} :param delegate_download_js_cb: javascript callback :param js_cb_object_id: id of the javascript object to be called back """ # TODO: Accept also methods other than POST if method != 'POST': self.call_js_cb(js_cb_func, js_cb_object_id, None, 1, 'Method %s not allowed' % method) return False if ':' in action_url: qurl = QUrl(action_url) elif action_url.startswith('/'): qurl = QUrl("%s%s" % (self.parent().host, action_url)) else: url = "%s/%s" % ('/'.join([ str(x) for x in self.parent().web_view.url().toEncoded().split( '/')[:-1] ]), action_url) qurl = QUrl(url) manager = self.parent().web_view.page().networkAccessManager() request = QNetworkRequest(qurl) request.setAttribute(REQUEST_ATTRS['instance_finished_cb'], self.manager_finished_cb) request.setAttribute(REQUEST_ATTRS['js_cb_object_id'], js_cb_object_id) request.setAttribute(REQUEST_ATTRS['js_cb_func'], js_cb_func) for header in headers: request.setRawHeader(header['name'], header['value']) multipart = QHttpMultiPart(QHttpMultiPart.FormDataType) for d in data: part = QHttpPart() part.setHeader(QNetworkRequest.ContentDispositionHeader, "form-data; name=\"%s\"" % d['name']) part.setBody(d['value']) multipart.append(part) reply = manager.post(request, multipart) # NOTE: needed to avoid segfault! multipart.setParent(reply) # delete the multiPart with the reply return True
def api_authentification(self): logger.debug("\n------------------ Authentication ------------------") # creating credentials header logger.debug("Creating credentials header") crd_header_value = QByteArray() crd_header_value.append("Basic ") crd_header_value.append( base64.b64encode("{}:{}".format(self.app_id, self.app_secrets).encode())) crd_header_name = QByteArray() crd_header_name.append("Authorization") # creating Content-Type header logger.debug("Creating 'Content-Type' header") ct_header_value = QByteArray() ct_header_value.append("application/json") # creating request token_rqst = QNetworkRequest(QUrl(self.token_url)) logger.debug("Creating token request : {}".format(token_rqst.url())) # setting headers token_rqst.setRawHeader(crd_header_name, crd_header_value) logger.debug("Setting credentials header : {}".format( token_rqst.rawHeader(crd_header_name))) token_rqst.setHeader(token_rqst.ContentTypeHeader, ct_header_value) logger.debug("Setting 'Content-Type' header : {}".format( token_rqst.header(token_rqst.ContentTypeHeader))) # creating data data = QByteArray() data.append(urlencode({"grant_type": "client_credentials"})) logger.debug("Creating data : {}".format(data)) # requesting and handle reply logger.debug("Asking for token") token_reply = self.naMngr.post(token_rqst, data) token_reply.finished.connect( partial(self.api_handle_token, reply=token_reply))
def get_reply(url): qgs_request = QgsBlockingNetworkRequest() request = QNetworkRequest(QUrl(url)) request.setRawHeader(b"User-Agent", b"qgis-pdokservices-plugin") err = qgs_request.get(request, True) if err is QgsBlockingNetworkRequest.NoError: # TODO: add proper error handling QgsMessageLog.logMessage("SERVER ERROR OCCURED", PLUGIN_NAME, level=Qgis.Info) reply = qgs_request.reply() if reply.error() is QNetworkReply.NoError: # TODO: add proper error handling QgsMessageLog.logMessage("SERVER ERROR OCCURED", PLUGIN_NAME, level=Qgis.Info) return reply
def _sync_get(url): global __network_manager if __network_manager is None: __network_manager = QNetworkAccessManager() __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy()) pause = QEventLoop() req = QNetworkRequest(url) req.setRawHeader(b"Accept", b"application/xml") req.setRawHeader(b"Accept-Language", b"fr") reply = __network_manager.get(req) reply.finished.connect(pause.quit) is_ok = [True] def onError(self): is_ok[0] = False pause.quit() reply.error.connect(onError) pause.exec_() return reply, is_ok[0]
def canvasReleaseEvent(self, event): # Make sure the point is transfored to 4326 pt = self.toMapCoordinates(event.pos()) canvasCRS = self.canvas.mapSettings().destinationCrs() transform = QgsCoordinateTransform(canvasCRS, self.epsg4326, QgsProject.instance()) pt = transform.transform(pt.x(), pt.y()) url = '{}?format=json&lat={:f}&lon={:f}&zoom={:d}&addressdetails=0&polygon_text=1'.format( self.settings.reverseURL(), pt.y(), pt.x(), self.settings.levelOfDetail) # print url qurl = QUrl(url) if self.reply is not None: self.reply.finished.disconnect(self.replyFinished) self.reply.abort() self.reply = None request = QNetworkRequest(qurl) request.setRawHeader( b"User-Agent", b"Mozilla/5.0 (Windows NT 6.1: WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" ) request.setRawHeader(b"Connection", b"keep-alive") request.setRawHeader( b"Accept", b"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") self.reply = QgsNetworkAccessManager.instance().get(request) self.reply.finished.connect(self.replyFinished) if not self.reverseGeoCodeDialog.isVisible(): self.show()
def processFreeFormData(self): self.geocodes = {} addresses = [] # Get the text for the Address Query Box an dgo through line by line to geocode it inputtext = str(self.addressTextEdit.toPlainText()) lines = inputtext.splitlines() self.pointLayer = None self.numAddress = 0 self.numErrors = 0 self.totalAddress = 0 # Create a list of all the Addresses. We want to get an accurate count for address in lines: # Get rid of beginning and end space address = address.strip() # Skip any blank lines if not address: continue self.numAddress += 1 addresses.append(address) if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum addresses to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return # Save the total number of addresses because numAddress will be reduced to 0 as processed self.totalAddress = self.numAddress if self.numAddress: self.createPointLayer() maxResults = self.maxResultsSpinBox.value() showDetails = int(self.detailedAddressCheckBox.isChecked()) for address in addresses: # Replace internal spaces with + signs address2 = re.sub('\s+', '+', address) url = '{}?q={}&format=json&limit={}&polygon=0&addressdetails={}'.format( self.settings.searchURL(), address2, maxResults, showDetails) # print url qurl = QUrl(url) request = QNetworkRequest(qurl) request.setRawHeader( b"User-Agent", b"Mozilla/5.0 (Windows NT 6.1: WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" ) request.setRawHeader(b"Connection", b"keep-alive") request.setRawHeader( b"Accept", b"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ) reply = QgsNetworkAccessManager.instance().get(request) self.geocodes[reply] = address reply.finished.connect(self.replyFinished)
def _sync_get(url): global __network_manager if __network_manager is None: __network_manager = QNetworkAccessManager() __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy()) pause = QEventLoop() req = QNetworkRequest(url) req.setRawHeader(b"Accept", b"application/xml") req.setRawHeader(b"Accept-Language", bytes(settings.value("default_language", "fr"), "utf8")) req.setRawHeader(b"User-Agent", bytes(settings.value('http_user_agent', plugin_name()), "utf8")) reply = __network_manager.get(req) reply.finished.connect(pause.quit) is_ok = [True] def onError(self): is_ok[0] = False pause.quit() reply.error.connect(onError) pause.exec_() return reply, is_ok[0]
def _sync_get(url): global __network_manager if __network_manager is None: __network_manager = QNetworkAccessManager() __network_manager.setProxy(QgsNetworkAccessManager.instance().proxy()) pause = QEventLoop() req = QNetworkRequest(url) req.setRawHeader(b"Accept", b"application/xml") req.setRawHeader(b"Accept-Language", bytes(settings.value("default_language", "fr"), "utf8")) req.setRawHeader( b"User-Agent", bytes(settings.value("http_user_agent", plugin_name()), "utf8")) reply = __network_manager.get(req) reply.finished.connect(pause.quit) is_ok = [True] def onError(self): is_ok[0] = False pause.quit() reply.error.connect(onError) pause.exec_() return reply, is_ok[0]
class ConnectDockWidget(BASE, WIDGET): def __init__(self, parent=None, visible=False): super(ConnectDockWidget, self).__init__(parent) self.setupUi(self) self.loggedIn = False self.token = None self.progressBar.hide() self.setVisible(visible) self.setWindowIcon(QIcon(os.path.join(pluginPath, 'icons', 'connect.svg'))) self.svgLogo.load(os.path.join(pluginPath, 'icons', 'connect-logo.svg')) self.lblSmallLogo.setPixmap(QPixmap(os.path.join(pluginPath, 'icons', 'connect.png'))) self.lblSmallLogo.hide() btnOk = self.buttonBox.button(QDialogButtonBox.Ok) btnOk.setText('Login') # setup tab bar self.tabsContent.addTab('Knowledge') self.tabsContent.addTab('Data') self.tabsContent.addTab('Plugins') self.tabsContent.setDocumentMode(True) self.tabsContent.setDrawBase(False) self._toggleCategoriesSelector(True) self.tabsContent.setCurrentIndex(0) self.tabsContent.currentChanged.connect(self.tabChanged) self.buttonBox.helpRequested.connect(self.showHelp) self.buttonBox.accepted.connect(self.logIn) self.btnSignOut.clicked.connect(self.showLogin) self.labelLevel.linkActivated.connect(self.showLogin) self.leSearch.buttonClicked.connect(self.search) self.leSearch.returnPressed.connect(self.search) self.connectWidget.rememberStateChanged.connect(self.updateSettings) self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks) cssFile = os.path.join(pluginPath, "resources", "search.css") with open(cssFile) as f: content = f.read() self.css = content.replace("#PLUGIN_PATH#", QUrl.fromLocalFile(pluginPath).toString()) self.webView.linkClicked.connect(self.linkClicked) for cat, cls in connect.categories.items(): self.cmbContentType.addItem(cls[1], cat) settings = QSettings() settings.beginGroup(reposGroup) self.authId = settings.value(boundlessRepoName + '/authcfg', '') settings.endGroup() if self.authId not in QgsAuthManager.instance().configIds(): self.authId = '' utils.setRepositoryAuth(self.authId) self._toggleSearchControls(True) self.showLogin() def showEvent(self, event): fillCredentials = pluginSetting("rememberCredentials") if self.authId != '' and fillCredentials and not self.loggedIn: authConfig = QgsAuthMethodConfig() if self.authId in QgsAuthManager.instance().configIds(): QgsAuthManager.instance().loadAuthenticationConfig(self.authId, authConfig, True) username = authConfig.config('username') password = authConfig.config('password') else: self.authId = '' utils.setRepositoryAuth(self.authId) self._showMessage('Could not find Connect credentials in the database.', QgsMessageBar.WARNING) username = '' password = '' self.connectWidget.setLogin(username) self.connectWidget.setPassword(password) BASE.showEvent(self, event) def keyPressEvent(self, event): if self.stackedWidget.currentIndex() == 0: if event.key() in [Qt.Key_Return, Qt.Key_Enter]: self.logIn() BASE.keyPressEvent(self, event) def showLogin(self): self.stackedWidget.setCurrentIndex(0) self.webView.setVisible(False) self.webView.setHtml("") self.leSearch.setText("") self.tabsContent.setCurrentIndex(0) self.svgLogo.show() self.lblSmallLogo.hide() connect.resetToken() self.token = None fillCredentials = pluginSetting("rememberCredentials") if fillCredentials: self.connectWidget.setRemember(Qt.Checked) username = "" password = "" if self.authId != "": authConfig = QgsAuthMethodConfig() if self.authId in QgsAuthManager.instance().configIds(): QgsAuthManager.instance().loadAuthenticationConfig(self.authId, authConfig, True) username = authConfig.config("username") password = authConfig.config("password") self.connectWidget.setLogin(username) self.connectWidget.setPassword(password) else: self.connectWidget.setRemember(Qt.Unchecked) self.connectWidget.setLogin("") self.connectWidget.setPassword("") def showHelp(self): webbrowser.open_new("file://{}".format(os.path.join(pluginPath, "docs", "html", "index.html"))) def linkClicked(self, url): name = url.toString() if name == "next": self.search(self.searchPage + 1) elif name == "previous": self.search(self.searchPage - 1) elif name.startswith("canvas"): content = self.searchResults[name] content.addToCanvas(self.roles) elif name.startswith("project"): content = self.searchResults[name] content.addToDefaultProject(self.roles) else: content = self.searchResults[name] content.open(self.roles) def logIn(self): if self.connectWidget.login().strip() == "" or self.connectWidget.password().strip() == "": self._showMessage("Please enter valid Connect credentials " "to use plugin.") return setPluginSetting("rememberCredentials", self.connectWidget.remember()) utils.addBoundlessRepository() self.request = QNetworkRequest(QUrl(authEndpointUrl)) httpAuth = base64.b64encode(b"%s:%s" % (self.connectWidget.login().strip(), self.connectWidget.password().strip())).decode("ascii") self.request.setRawHeader('Authorization', 'Basic {}'.format(httpAuth)) QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) self.token = connect.getToken(self.connectWidget.login().strip(), self.connectWidget.password().strip()) if self.token is None: QApplication.restoreOverrideCursor() QMessageBox.warning(self, "Error!", "Can not get token. Please check you credentials and endpoint URL in plugin settings.") return self.reply = QgsNetworkAccessManager.instance().get(self.request) self.reply.finished.connect(self.requestFinished) def search(self, page=0): if self.tabsContent.currentIndex() == 0: categories = self.cmbContentType.selectedData(Qt.UserRole) if len(categories) == 0: categories = list(connect.categories.keys()) cat = ','.join(categories) self._findContent(cat, page) elif self.tabsContent.currentIndex() == 1: if oauth2_supported(): self._findBasemaps() elif self.tabsContent.currentIndex() == 2: self._findPlugins() self.svgLogo.hide() self.lblSmallLogo.show() def _getSearchHtml(self, body): html = '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <style> {} </style> </head> <body> {} </body> </html>'''.format(self.css, body) return html def _findContent(self, category, page=0): if self.token is None: self._showMessage("Seems you have no Connect token. Login with valid Connect credentials and try again.", QgsMessageBar.WARNING) return text = self.leSearch.text().strip() self.searchPage = page try: self._toggleSearchProgress() results = execute(lambda: connect.search(text, category, self.searchPage, self.token)) if results: self.searchResults = {r.url:r for r in results} body = "<ul>" for r in results: body += "<li>%s</li>" % r.asHtmlEntry(self.roles) body += "</ul>" if len(results) == connect.RESULTS_PER_PAGE: if self.searchPage == 0: body += "<div class='pagination'><div class='next'><a href='next'>Next</a></div></div>" else: body += "<div class='pagination'><div class='prev'><a href='previous'>Prev</a></div><div class='next'><a href='next'>Next</a></div></div>" else: if self.searchPage != 0: body += "<div class='pagination'><div class='prev'><a href='previous'>Prev</a></div></div>" else: body = "" self.webView.setHtml(self._getSearchHtml(body)) self.webView.setVisible(True) self._toggleSearchProgress(False) except Exception as e: self._toggleSearchProgress(False) self.webView.setHtml("") self._showMessage("There has been a problem performing the search:\n{}".format(str(e.args[0])), QgsMessageBar.WARNING) def _findPlugins(self): if self.token is None: self._showMessage("Seems you have no Connect token. Login with valid Connect credentials and try again.", QgsMessageBar.WARNING) return text = self.leSearch.text().strip() try: self._toggleSearchProgress() results = execute(lambda: connect.findAll(text, "PLUG", self.token)) body = "<h1>{} results</h1><hr/>".format(len(results)) if results: self.searchResults = {r.url:r for r in results} body += "<ul>" for r in results: body += "<li>%s</li>" % r.asHtmlEntry(self.roles) body += "</ul>" self.webView.setHtml(self._getSearchHtml(body)) self.webView.setVisible(True) self._toggleSearchProgress(False) except Exception as e: self._toggleSearchProgress(False) self.webView.setHtml("") self._showMessage("There has been a problem performing the search:\n{}".format(str(e.args[0])), QgsMessageBar.WARNING) def _findBasemaps(self): if self.token is None: self._showMessage("Seems you have no Connect token. Login with valid Connect credentials and try again.", QgsMessageBar.WARNING) return text = self.leSearch.text().strip() try: results = execute(lambda: connect.searchBasemaps(text, self.token)) body = "<h1>{} results</h1><hr/>".format(len(results)) if results: self.searchResults = {"canvas"+r.url:r for r in results} self.searchResults.update({"project"+r.url:r for r in results}) body += "<ul>" for r in results: body += "<li>%s</li>" % r.asHtmlEntry(self.roles) body += "</ul>" self.webView.setHtml(self._getSearchHtml(body)) self.webView.setVisible(True) except Exception as e: self._toggleSearchProgress(False) self.webView.setHtml("") self._showMessage("There has been a problem performing the search:\n{}".format(str(e.args[0])), QgsMessageBar.WARNING) def requestFinished(self): QApplication.restoreOverrideCursor() reply = self.sender() visible = True if reply.error() != QNetworkReply.NoError: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 401: msg = 'Your credentials seem invalid.\n' \ 'You will not be able to access any content.\n' \ 'Please enter valid Connect credentials to use plugin.' else: msg = 'An error occurred when validating your ' \ 'credentials. Server responded:\n{}.\n' \ 'You will not be able to access any content.\n' \ 'Please enter valid Connect credentials to use plugin'.format(reply.errorString()) QMessageBox.warning(self, 'Error!', msg) return else: self.btnSignOut.setText("Logout") self.saveOrUpdateAuthId() self.roles = json.loads(str(reply.readAll())) # if this is first login ask if user wants to have basemap settings = QSettings() firstLogin = settings.value('boundlessconnect/firstLogin', True, bool) if firstLogin: settings.setValue('boundlessconnect/firstLogin', False) if oauth2_supported() and basemaputils.canAccessBasemap(self.roles): ret = QMessageBox.question(self, self.tr('Base Maps'), self.tr('Would you like to add Boundless basemap ' 'to your default project? This option can ' 'be disabled at any time in the settings.'), QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.Yes: if self.token is None: self._showMessage("Seems you have no Connect token. Login with valid Connect credentials and try again.", QgsMessageBar.WARNING) return if self.installBaseMap(): pass execute(connect.loadPlugins) self.stackedWidget.setCurrentIndex(1) self.labelLevel.setVisible(visible) self.labelLevel.setText("Logged in as: <b>%s</b>" % self.connectWidget.login()) self.loggedIn = True cat = ",".join(list(connect.categories.keys())) self._findContent(cat) def saveOrUpdateAuthId(self): if self.authId == '': authConfig = QgsAuthMethodConfig('Basic') self.authId = QgsAuthManager.instance().uniqueConfigId() authConfig.setId(self.authId) authConfig.setConfig('username', self.connectWidget.login().strip()) authConfig.setConfig('password', self.connectWidget.password().strip()) authConfig.setName('Boundless Connect Portal') authConfig.setUri(pluginSetting('repoUrl')) if QgsAuthManager.instance().storeAuthenticationConfig(authConfig): utils.setRepositoryAuth(self.authId) else: self._showMessage('Unable to save credentials.', QgsMessageBar.WARNING) else: authConfig = QgsAuthMethodConfig() QgsAuthManager.instance().loadAuthenticationConfig(self.authId, authConfig, True) authConfig.setConfig('username', self.connectWidget.login().strip()) authConfig.setConfig('password', self.connectWidget.password().strip()) QgsAuthManager.instance().updateAuthenticationConfig(authConfig) # also setup OAuth2 configuration if possible if oauth2_supported(): endpointUrl = "{}/token/oauth?version={}".format(pluginSetting("connectEndpoint"), pluginSetting("apiVersion")) setup_oauth(self.connectWidget.login().strip(), self.connectWidget.password().strip(), endpointUrl) def tabChanged(self, index): if index == 0: self._toggleCategoriesSelector(True) self._toggleSearchControls(True) self.webView.setHtml("") categories = self.cmbContentType.selectedData(Qt.UserRole) if len(categories) == 0: categories = list(connect.categories.keys()) cat = ','.join(categories) self._findContent(cat) elif index == 1: self._toggleCategoriesSelector(False) self._toggleSearchControls(oauth2_supported()) self.webView.setHtml("") if oauth2_supported(): self._findBasemaps() elif index == 2: self._toggleCategoriesSelector(False) self._toggleSearchControls(True) self.webView.setHtml("") self._findPlugins() def _toggleCategoriesSelector(self, visible): self.lblCategorySearch.setVisible(visible) self.cmbContentType.setVisible(visible) def _toggleSearchControls(self, enabled): self.leSearch.setEnabled(enabled) self.lblOAuthWarning.setVisible(not enabled) def installBaseMap(self): authcfg = get_oauth_authcfg() if authcfg is None: self._showMessage('Could not find a valid authentication configuration!', QgsMessageBar.WARNING) return False authId = authcfg.id() mapBoxStreets = basemaputils.getMapBoxStreetsMap(self.token) if os.path.isfile(basemaputils.defaultProjectPath()): # default project already exists, make a backup copy backup = basemaputils.defaultProjectPath().replace( '.qgs', '-%s.qgs' % datetime.now().strftime('%Y-%m-%d-%H_%M_%S')) shutil.copy2(basemaputils.defaultProjectPath(), backup) self._showMessage("A backup copy of the previous default project " "has been saved to {}".format(backup)) msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Question) msgBox.setText("A default project already exists. Do you " "wish to add the Boundless basemap to your " "existing default project or create a new " "default project?") btnAdd = msgBox.addButton("Add", QMessageBox.ActionRole) btnCreateNew = msgBox.addButton("Create New", QMessageBox.ActionRole) msgBox.exec_() if msgBox.clickedButton() == btnAdd: if not basemaputils.addToDefaultProject([mapBoxStreets], ["Mapbox Streets"], authId): self._showMessage("Could not update default project with basemap!", QgsMessageBar.WARNING) return False elif msgBox.clickedButton() == btnCreateNew: template = basemaputils.PROJECT_DEFAULT_TEMPLATE prj = basemaputils.createDefaultProject([mapBoxStreets], ["Mapbox Streets"], template, authId) if prj is None or prj == '': self._showMessage("Could not create a valid default project from the template '{}'!".format(template), QgsMessageBar.WARNING) return False if not basemaputils.writeDefaultProject(prj): self._showMessage("Could not write the default project on disk!", QgsMessageBar.WARNING) return False else: # no default project, create one template = basemaputils.PROJECT_DEFAULT_TEMPLATE prj = basemaputils.createDefaultProject([mapBoxStreets], ["Mapbox Streets"], template, authId) if prj is None or prj == '': self._showMessage("Could not create a valid default project from the template '{}'!".format(template), QgsMessageBar.WARNING) return False if not basemaputils.writeDefaultProject(prj): self._showMessage("Could not write the default project on disk!", QgsMessageBar.WARNING) return False self._showMessage("Basemap added to the default project.") return True def updateSettings(self, state): if state == Qt.Checked: setPluginSetting("rememberCredentials", True) else: setPluginSetting("rememberCredentials", False) def _toggleSearchProgress(self, show=True): if show: self.progressBar.setRange(0, 0) self.progressBar.show() else: self.progressBar.setRange(0, 100) self.progressBar.reset() self.progressBar.hide() def _showMessage(self, message, level=QgsMessageBar.INFO): iface.messageBar().pushMessage( message, level, iface.messageTimeout())
def request(self, url, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None): """ Make a network request by calling QgsNetworkAccessManager. redirections argument is ignored and is here only for httplib2 compatibility. """ self.msg_log(u'http_call request: {0}'.format(url)) self.http_call_result = Response({ 'status': 0, 'status_code': 0, 'status_message': '', 'text': '', 'ok': False, 'headers': {}, 'reason': '', 'exception': None, }) req = QNetworkRequest() # Avoid double quoting form QUrl if PYTHON_VERSION >= 3: url = urllib.parse.unquote(url) else: url = urllib2.unquote(url) req.setUrl(QUrl(url)) if self.cookie is not None: if headers is not None: headers['Cookie'] = self.cookie else: headers = {'Cookie': self.cookie} if self.basicauth is not None: if headers is not None: headers['Authorization'] = self.basicauth else: headers = {'Authorization': self.basicauth} if headers is not None: # This fixes a wierd error with compressed content not being correctly # inflated. # If you set the header on the QNetworkRequest you are basically telling # QNetworkAccessManager "I know what I'm doing, please don't do any content # encoding processing". # See: https://bugs.webkit.org/show_bug.cgi?id=63696#c1 try: del headers['Accept-Encoding'] except KeyError: pass for k, v in headers.items(): if PYTHON_VERSION >= 3: if isinstance(k, str): k = k.encode('utf-8') if isinstance(v, str): v = v.encode('utf-8') req.setRawHeader(k, v) if self.authid: self.msg_log("Update request w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkRequest(req, self.authid) if self.reply is not None and self.reply.isRunning(): self.reply.close() if method.lower() == 'delete': func = getattr(QgsNetworkAccessManager.instance(), 'deleteResource') else: func = getattr(QgsNetworkAccessManager.instance(), method.lower()) # Calling the server ... # Let's log the whole call for debugging purposes: self.msg_log("Sending %s request to %s" % (method.upper(), req.url().toString())) headers = {str(h): str(req.rawHeader(h)) for h in req.rawHeaderList()} for k, v in headers.items(): self.msg_log("%s: %s" % (k, v)) if method.lower() in ['post', 'put']: if PYTHON_VERSION >= 3: if isinstance(body, str): body = body.encode('utf-8') self.reply = func(req, body) else: self.reply = func(req) if self.authid: self.msg_log("Update reply w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkReply( self.reply, self.authid) self.reply.sslErrors.connect(self.sslErrors) self.reply.finished.connect(self.replyFinished) # Call and block self.el = QEventLoop() self.reply.finished.connect(self.el.quit) self.reply.downloadProgress.connect(self.downloadProgress) # Catch all exceptions (and clean up requests) try: self.el.exec_() # Let's log the whole response for debugging purposes: self.msg_log("Got response %s %s from %s" % \ (self.http_call_result.status_code, self.http_call_result.status_message, self.reply.url().toString())) headers = { str(h): str(self.reply.rawHeader(h)) for h in self.reply.rawHeaderList() } for k, v in headers.items(): self.msg_log("%s: %s" % (k, v)) if len(self.http_call_result.text) < 1024: self.msg_log("Payload :\n%s" % self.http_call_result.text) else: self.msg_log("Payload is > 1 KB ...") except Exception as e: raise e finally: if self.reply is not None: if self.reply.isRunning(): self.reply.close() self.msg_log("Deleting reply ...") self.reply.deleteLater() self.reply = None else: self.msg_log("Reply was already deleted ...") if not self.http_call_result.ok: if self.http_call_result.exception and not self.exception_class: raise self.http_call_result.exception else: raise self.exception_class(self.http_call_result.reason) return (self.http_call_result, self.http_call_result.text)
def handle_download(self): result_type_codes_download = [ "logfiles", # non-groundwater codes "subgrid_map", "flow-aggregate", "id-mapping", # groundwater codes "results-3di", "aggregate-results-3di", "grid-admin", ] selection_model = self.dialog.downloadResultTableView.selectionModel() proxy_indexes = selection_model.selectedIndexes() if len(proxy_indexes) != 1: pop_up_info("Please select one result.") return proxy_selection_index = proxy_indexes[0] selection_index = self.dialog.download_proxy_model.mapToSource( proxy_selection_index) item = self.downloadable_results.rows[selection_index.row()] to_download = [ r for r in item.results.value if r["result_type"]["code"] in result_type_codes_download ] to_download_urls = [dl["attachment_url"] for dl in to_download] logger.debug(item.name.value) # ask user where to store download directory = QFileDialog.getExistingDirectory(None, "Choose a directory", os.path.expanduser("~")) if not directory: return dir_name = get_valid_filename(item.name.value) self.download_directory = os.path.join(directory, dir_name) # For now, only work with empty directories that we create ourselves. # Because the files are downloaded and processed in chunks, we cannot # guarantee data integrity with existing files. if os.path.exists(self.download_directory): pop_up_info("The directory %s already exists." % self.download_directory) return logger.info("Creating download directory.") os.mkdir(self.download_directory) logger.debug(self.download_directory) CHUNK_SIZE = 16 * 1024 # Important note: QNetworkAccessManager is asynchronous, which means # the downloads are processed asynchronous using callbacks. for url in to_download_urls: request = QNetworkRequest(QUrl(url)) request.setRawHeader(b"username", bytes(self.username, "utf-8")) request.setRawHeader(b"password", bytes(self.password, "utf-8")) request.setAttribute(USER_DOWNLOAD_DIRECTORY, self.download_directory) reply = self.network_manager.get(request) # Get replies in chunks, and process them reply.setReadBufferSize(CHUNK_SIZE) reply.readyRead.connect( self.on_single_download_ready_to_read_chunk) reply.finished.connect(self.on_single_download_finished) pop_up_info("Download started.")
def reverseGeocode(self): layer = self.mMapLayerComboBox.currentLayer() if not layer: self.iface.messageBar().pushMessage( "", "No valid point vector layer to reverse geocode", level=QgsMessageBar.WARNING, duration=2) return self.numAddress = layer.featureCount() self.totalAddress = self.numAddress self.numErrors = 0 if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum geocodes to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return layername = self.layerLineEdit.text() self.pointLayer = QgsVectorLayer("point?crs=epsg:4326", layername, "memory") self.provider = self.pointLayer.dataProvider() self.provider.addAttributes( [QgsField("display_name", QVariant.String)]) self.pointLayer.updateFields() if self.showLabelCheckBox.checkState(): # Display labels label = QgsPalLayerSettings() label.readFromLayer(self.pointLayer) label.enabled = True label.fieldName = 'display_name' label.placement = QgsPalLayerSettings.AroundPoint label.setDataDefinedProperty(QgsPalLayerSettings.Size, True, True, '8', '') label.writeToLayer(self.pointLayer) layerCRS = layer.crs() epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326") transform = QgsCoordinateTransform(layerCRS, epsg4326, QgsProject.instance()) iter = layer.getFeatures() self.geocodes = {} for feature in iter: # already know that this is a point vector layer pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = transform.transform(pt.x(), pt.y()) lat = str(pt.y()) lon = str(pt.x()) url = self.settings.reverseURL( ) + '?format=json&lat=' + lat + '&lon=' + lon + '&zoom=18&addressdetails=0' # print url qurl = QUrl(url) request = QNetworkRequest(qurl) request.setRawHeader( b"User-Agent", b"Mozilla/5.0 (Windows NT 6.1: WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" ) request.setRawHeader(b"Connection", b"keep-alive") request.setRawHeader( b"Accept", b"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ) reply = QgsNetworkAccessManager.instance().get(request) self.geocodes[reply] = pt reply.finished.connect(self.reverseGeoFinished)
def request(self, url, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None, blocking=True): """ Make a network request by calling QgsNetworkAccessManager. redirections argument is ignored and is here only for httplib2 compatibility. """ self.msg_log(u'http_call request: {0}'.format(url)) self.blocking_mode = blocking req = QNetworkRequest() # Avoid double quoting form QUrl url = urllib.parse.unquote(url) req.setUrl(QUrl(url)) if headers is not None: # This fixes a wierd error with compressed content not being correctly # inflated. # If you set the header on the QNetworkRequest you are basically telling # QNetworkAccessManager "I know what I'm doing, please don't do any content # encoding processing". # See: https://bugs.webkit.org/show_bug.cgi?id=63696#c1 try: del headers['Accept-Encoding'] except KeyError: pass for k, v in list(headers.items()): self.msg_log("Setting header %s to %s" % (k, v)) req.setRawHeader(k, v) if self.authid: self.msg_log("Update request w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkRequest(req, self.authid) if self.reply is not None and self.reply.isRunning(): self.reply.close() if method.lower() == 'delete': func = getattr(QgsNetworkAccessManager.instance(), 'deleteResource') else: func = getattr(QgsNetworkAccessManager.instance(), method.lower()) # Calling the server ... # Let's log the whole call for debugging purposes: self.msg_log("Sending %s request to %s" % (method.upper(), req.url().toString())) self.on_abort = False headers = {str(h): str(req.rawHeader(h)) for h in req.rawHeaderList()} for k, v in list(headers.items()): self.msg_log("%s: %s" % (k, v)) if method.lower() in ['post', 'put']: if isinstance(body, file): body = body.read() self.reply = func(req, body) else: self.reply = func(req) if self.authid: self.msg_log("Update reply w/ authid: {0}".format(self.authid)) QgsAuthManager.instance().updateNetworkReply(self.reply, self.authid) # necessary to trap local timout manage by QgsNetworkAccessManager # calling QgsNetworkAccessManager::abortRequest QgsNetworkAccessManager.instance().requestTimedOut.connect(self.requestTimedOut) self.reply.sslErrors.connect(self.sslErrors) self.reply.finished.connect(self.replyFinished) self.reply.downloadProgress.connect(self.downloadProgress) # block if blocking mode otherwise return immediatly # it's up to the caller to manage listeners in case of no blocking mode if not self.blocking_mode: return (None, None) # Call and block self.el = QEventLoop() self.reply.finished.connect(self.el.quit) # Catch all exceptions (and clean up requests) try: self.el.exec_(QEventLoop.ExcludeUserInputEvents) except Exception as e: raise e if self.reply: self.reply.finished.disconnect(self.el.quit) # emit exception in case of error if not self.http_call_result.ok: if self.http_call_result.exception and not self.exception_class: raise self.http_call_result.exception else: raise self.exception_class(self.http_call_result.reason) return (self.http_call_result, self.http_call_result.content)
def request(self, url, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None, blocking=True): """ Make a network request by calling QgsNetworkAccessManager. redirections argument is ignored and is here only for httplib2 compatibility. """ self.msg_log(u'http_call request: {0}'.format(url)) self.blocking_mode = blocking req = QNetworkRequest() # Avoid double quoting form QUrl url = urllib.parse.unquote(url) req.setUrl(QUrl(url)) if headers is not None: # This fixes a wierd error with compressed content not being correctly # inflated. # If you set the header on the QNetworkRequest you are basically telling # QNetworkAccessManager "I know what I'm doing, please don't do any content # encoding processing". # See: https://bugs.webkit.org/show_bug.cgi?id=63696#c1 try: del headers['Accept-Encoding'] except KeyError: pass for k, v in list(headers.items()): self.msg_log("Setting header %s to %s" % (k, v)) if k and v: req.setRawHeader(k.encode(), v.encode()) if self.authid: self.msg_log("Update request w/ authid: {0}".format(self.authid)) self.auth_manager().updateNetworkRequest(req, self.authid) if self.reply is not None and self.reply.isRunning(): self.reply.close() if method.lower() == 'delete': func = getattr(QgsNetworkAccessManager.instance(), 'deleteResource') else: func = getattr(QgsNetworkAccessManager.instance(), method.lower()) # Calling the server ... # Let's log the whole call for debugging purposes: self.msg_log("Sending %s request to %s" % (method.upper(), req.url().toString())) self.on_abort = False headers = {str(h): str(req.rawHeader(h)) for h in req.rawHeaderList()} for k, v in list(headers.items()): self.msg_log("%s: %s" % (k, v)) if method.lower() in ['post', 'put']: if isinstance(body, io.IOBase): body = body.read() if isinstance(body, str): body = body.encode() if isinstance(body, dict): body = str(json.dumps(body)).encode(encoding='utf-8') self.reply = func(req, body) else: self.reply = func(req) if self.authid: self.msg_log("Update reply w/ authid: {0}".format(self.authid)) self.auth_manager().updateNetworkReply(self.reply, self.authid) QgsNetworkAccessManager.instance().setTimeout(int(self.timeout) * 1000) # necessary to trap local timeout manage by QgsNetworkAccessManager # calling QgsNetworkAccessManager::abortRequest QgsNetworkAccessManager.instance().requestTimedOut.connect( self.requestTimedOut) self.reply.sslErrors.connect(self.sslErrors) self.reply.finished.connect(self.replyFinished) self.reply.downloadProgress.connect(self.downloadProgress) # block if blocking mode otherwise return immediatly # it's up to the caller to manage listeners in case of no blocking mode if not self.blocking_mode: return (None, None) # Call and block self.el = QEventLoop() self.reply.finished.connect(self.el.quit) # Catch all exceptions (and clean up requests) try: self.el.exec_(QEventLoop.ExcludeUserInputEvents) except Exception as e: raise e if self.reply: self.reply.finished.disconnect(self.el.quit) # emit exception in case of error if not self.http_call_result.ok: if self.http_call_result.exception and not self.exception_class: raise self.http_call_result.exception else: raise self.exception_class(self.http_call_result.reason) return (self.http_call_result, self.http_call_result.content)
def processAddressTable(self): layer = self.addressMapLayerComboBox.currentLayer() if not layer: self.iface.messageBar().pushMessage( "", "No valid table or vector layer to reverse geocode", level=QgsMessageBar.WARNING, duration=4) return self.numAddress = self.totalAddress = layer.featureCount() if not self.numAddress: self.iface.messageBar().pushMessage("", "No addresses to geocode", level=QgsMessageBar.WARNING, duration=4) return self.numErrors = 0 if self.numAddress > self.settings.maxAddress: self.iface.messageBar().pushMessage( "", "Maximum geocodes to process were exceeded. Please reduce the number and try again.", level=QgsMessageBar.WARNING, duration=4) return maxResults = self.maxResultsSpinBox.value() showDetails = int(self.detailedAddressCheckBox.isChecked()) self.geocodes = {} self.pointLayer = None self.createPointLayer() iter = layer.getFeatures(QgsFeatureRequest().setFlags( QgsFeatureRequest.NoGeometry)) full_address = self.fullAddressComboBox.currentIndex() - 1 street_num = self.numberComboBox.currentIndex() - 1 street_name = self.streetNameComboBox.currentIndex() - 1 city = self.cityComboBox.currentIndex() - 1 county = self.countyComboBox.currentIndex() - 1 state = self.stateComboBox.currentIndex() - 1 country = self.countryComboBox.currentIndex() - 1 postal = self.postalCodeComboBox.currentIndex() - 1 for feature in iter: self.isfirst = True if full_address >= 0: address = feature[full_address].strip() address2 = re.sub('\s+', '+', address) url = self.settings.searchURL() + '?q=' + address2 else: address = ','.join( [str(x) if x else '' for x in feature.attributes()]) url = self.settings.searchURL() + '?' if street_name >= 0: num = '' name = '' if street_num >= 0 and feature[street_num]: num = ('{}'.format(feature[street_num])).strip() if feature[street_name]: name = ('{}'.format(feature[street_name])).strip() street = num + ' ' + name street = street.strip() if street: url += self.formatParam('street', street) if city >= 0: url += self.formatParam('city', feature[city]) if county >= 0: url += self.formatParam('county', feature[county]) if state >= 0: url += self.formatParam('state', feature[state]) if country >= 0: url += self.formatParam('country', feature[country]) if postal >= 0: url += self.formatParam('postalcode', feature[postal]) url += '&format=json&limit={}&polygon=0&addressdetails={}'.format( maxResults, showDetails) # print url qurl = QUrl(url) request = QNetworkRequest(qurl) request.setRawHeader( b"User-Agent", b"Mozilla/5.0 (Windows NT 6.1: WOW64; rv:52.0) Gecko/20100101 Firefox/52.0" ) request.setRawHeader(b"Connection", b"keep-alive") request.setRawHeader( b"Accept", b"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ) reply = QgsNetworkAccessManager.instance().get(request) self.geocodes[reply] = address reply.finished.connect(self.replyFinished)