def testFetchBadUrl(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent(QUrl('http://x')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() != QNetworkReply.NoError
def testFetchUrlContent(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent(QUrl('http://localhost:' + str(TestQgsNetworkContentFetcher.port) + '/qgis_local_server/index.html')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() == QNetworkReply.NoError, r.error() html = fetcher.contentAsString() assert 'QGIS' in html
def testFetchEncodedContent(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent(QUrl('http://localhost:' + str(TestQgsNetworkContentFetcher.port) + '/encoded_html.html')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() == QNetworkReply.NoError, r.error() html = fetcher.contentAsString() assert chr(6040) in html
def testDoubleFetch(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent(QUrl('http://www.qgis.org/')) # double fetch - this should happen before previous request finishes fetcher.fetchContent(QUrl('http://localhost:' + str(TestQgsNetworkContentFetcher.port) + '/qgis_local_server/index.html')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() == QNetworkReply.NoError, r.error() html = fetcher.contentAsString() assert 'QGIS' in html
def testFetchUrlContent(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent( QUrl('http://localhost:' + str(TestQgsNetworkContentFetcher.port) + '/qgis_local_server/index.html')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() == QNetworkReply.NoError, r.error() html = fetcher.contentAsString() assert 'QGIS' in html
def testFetchEncodedContent(self): fetcher = QgsNetworkContentFetcher() self.loaded = False fetcher.fetchContent( QUrl('http://localhost:' + str(TestQgsNetworkContentFetcher.port) + '/encoded_html.html')) fetcher.finished.connect(self.contentLoaded) while not self.loaded: app.processEvents() r = fetcher.reply() assert r.error() == QNetworkReply.NoError, r.error() html = fetcher.contentAsString() assert chr(6040) in html
def fetch(self): """ Fetch the JSON file and call the function when it's finished. """ self.fetcher = QgsNetworkContentFetcher() self.fetcher.finished.connect(self.request_finished) self.fetcher.fetchContent(QUrl(self.url))
class VersionChecker: def __init__(self, dialog: QDialog, url): """ Update the dialog when versions has been fetched. """ self.dialog = dialog self.url = url self.fetcher = None self.json = None def fetch(self): """ Fetch the JSON file and call the function when it's finished. """ self.fetcher = QgsNetworkContentFetcher() self.fetcher.finished.connect(self.request_finished) self.fetcher.fetchContent(QUrl(self.url)) def request_finished(self): """ Dispatch the answer to update the GUI. """ content = self.fetcher.contentAsString() if not content: return # Update the UI released_versions = json.loads(content) self.update_lwc_releases(released_versions) self.update_lwc_selector(released_versions) # Cache the file content += '\n' folder = lizmap_user_folder() with open(os.path.join(folder, "released_versions.json"), "w") as output: output.write(content) def update_lwc_selector(self, released_versions: dict): """ Update LWC selector showing outdated versions. """ for i, json_version in enumerate(released_versions): if not json_version['maintained']: index = self.dialog.combo_lwc_version.findData(LwcVersions(json_version['branch'])) text = self.dialog.combo_lwc_version.itemText(index) if i == 0: # If it's the first item in the list AND not maintained, then it's the next LWC version new_text = text + ' - ' + tr('Next') else: new_text = text + ' - ' + tr('Not maintained') self.dialog.combo_lwc_version.setItemText(index, new_text) def update_lwc_releases(self, released_versions: dict): """ Update labels about latest releases. """ template = ( '<a href="https://github.com/3liz/lizmap-web-client/releases/tag/{tag}">' '{tag} - {date}' '</a>') i = 0 for json_version in released_versions: qdate = QDate.fromString( json_version['latest_release_date'], "yyyy-MM-dd") date_string = qdate.toString(QLocale().dateFormat(QLocale.ShortFormat)) if json_version['maintained']: if i == 0: text = template.format( tag=json_version['latest_release_version'], date=date_string, ) self.dialog.lwc_version_latest.setText(text) elif i == 1: text = template.format( tag=json_version['latest_release_version'], date=date_string, ) self.dialog.lwc_version_oldest.setText(text) i += 1
class AutoSuggest(QObject): def __init__(self, geturl_func, parseresult_func, parent = None): QObject.__init__(self, parent) self.geturl_func = geturl_func self.parseresult_func = parseresult_func self.editor = parent self.networkFetcher = QgsNetworkContentFetcher() self.selectedObject = None self.isUnloaded = False self.popup = QTreeWidget(parent) #self.popup.setColumnCount(2) self.popup.setColumnCount(1) self.popup.setUniformRowHeights(True) self.popup.setRootIsDecorated(False) self.popup.setEditTriggers(QTreeWidget.NoEditTriggers) self.popup.setSelectionBehavior(QTreeWidget.SelectRows) self.popup.setFrameStyle(QFrame.Box | QFrame.Plain) self.popup.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.popup.header().hide() self.popup.installEventFilter(self) self.popup.setMouseTracking(True) #self.connect(self.popup, SIGNAL("itemClicked(QTreeWidgetItem*, int)"), # self.doneCompletion) self.popup.itemClicked.connect( self.doneCompletion ) self.popup.setWindowFlags(Qt.Popup) self.popup.setFocusPolicy(Qt.NoFocus) self.popup.setFocusProxy(parent) self.timer = QTimer(self) self.timer.setSingleShot(True) self.timer.setInterval(500) #self.connect(self.timer, SIGNAL("timeout()"), self.autoSuggest) self.timer.timeout.connect( self.autoSuggest ) #self.connect(self.editor, SIGNAL("textEdited(QString)"), self.timer, SLOT("start()")) #self.editor.textEdited.connect( self.timer.start ) self.editor.textEdited.connect( self.timer.start ) #self.editor.textChanged.connect( self.timer.start ) #self.connect(self.networkManager, SIGNAL("finished(QNetworkReply*)"), # self.handleNetworkData) self.networkFetcher.finished.connect( self.handleNetworkData ) def eventFilter(self, obj, ev): if obj != self.popup: return False if ev.type() == QEvent.MouseButtonPress: self.popup.hide() self.editor.setFocus() return True if ev.type() == QEvent.KeyPress: consumed = False key = ev.key() if key == Qt.Key_Enter or key == Qt.Key_Return: self.doneCompletion() consumed = True elif key == Qt.Key_Escape: self.editor.setFocus() self.popup.hide() consumed = True elif key in (Qt.Key_Up, Qt.Key_Down, Qt.Key_Home, Qt.Key_End, Qt.Key_PageUp, Qt.Key_PageDown): pass else: self.editor.setFocus() self.editor.event(ev) self.popup.hide() return consumed return False def showCompletion(self, rows): # Rows is an iterable of tuples like [("text",object1),("text2", object2),...] pal = self.editor.palette() color = pal.color(QPalette.Disabled, QPalette.WindowText) self.popup.setUpdatesEnabled(False) self.popup.clear() if rows is None or len( rows ) < 1: return for row in rows: item = QTreeWidgetItem(self.popup) item.setText(0, row[0]) #item.setText(1, hit['type']) item.setTextAlignment(1, Qt.AlignRight) item.setForeground(1, color) item.setData(2, Qt.UserRole, (row[1],)) # Try immutable py obj #http://stackoverflow.com/questions/9257422/how-to-get-the-original-python-data-from-qvariant self.popup.setCurrentItem(self.popup.topLevelItem(0)) self.popup.resizeColumnToContents(0) #self.popup.resizeColumnToContents(1) self.popup.adjustSize() self.popup.setUpdatesEnabled(True) h = self.popup.sizeHintForRow(0) * min(15, len(rows)) + 3 w = max(self.popup.width(), self.editor.width()) self.popup.resize(w, h) self.popup.move(self.editor.mapToGlobal(QPoint(0, self.editor.height()))) self.popup.setFocus() self.popup.show() def doneCompletion(self): self.timer.stop() self.popup.hide() self.editor.setFocus() item = self.popup.currentItem() if item: self.editor.setText(item.text(0) ) obj = item.data(2, Qt.UserRole) #.toPyObject() self.selectedObject = obj[0] e = QKeyEvent(QEvent.KeyPress, Qt.Key_Enter, Qt.NoModifier) QApplication.postEvent(self.editor, e) e = QKeyEvent(QEvent.KeyRelease, Qt.Key_Enter, Qt.NoModifier) QApplication.postEvent(self.editor, e) def preventSuggest(self): self.timer.stop() def autoSuggest(self): term = self.editor.text() if term: qurl = self.geturl_func( term ) if qurl: # TODO: Cancel existing requests: http://qt-project.org/forums/viewthread/18073 self.networkFetcher.fetchContent(qurl) # QUrl(url))) def handleNetworkData(self): reply = self.networkFetcher.reply() if reply: if reply.error() == QNetworkReply.NoError: content = self.networkFetcher.contentAsString() rows = self.parseresult_func( content ) self.showCompletion( rows ) else: QgsApplication.messageLog().logMessage( 'Server returned: ' + reply.error(), __package__ ) def unload( self ): # Avoid processing events after QGIS shutdown has begun self.popup.removeEventFilter(self) self.isUnloaded = True
class DfConfig(QtCore.QObject): df_con_error = QtCore.pyqtSignal() df_settings_warning = QtCore.pyqtSignal() loaded = QtCore.pyqtSignal() def __init__(self, settings): super(DfConfig, self).__init__() self.settings = settings self.cached_df_qlr_filename = None self.allowed_df_services = {} self.df_qlr_file = None self.background_category = None self.categories = None # Network self._services_network_fetcher = QgsNetworkContentFetcher() self._qlr_network_fetcher = QgsNetworkContentFetcher() self._services_network_fetcher.finished.connect( self._handle_services_response) self._qlr_network_fetcher.finished.connect(self._handle_qlr_response) def begin_load(self): self.cached_df_qlr_filename = ( self.settings.value("cache_path") + hashlib.md5(self.settings.value("token").encode()).hexdigest() + "_dataforsyning_data.qlr") self.allowed_df_services = {} if self.settings.is_set(): try: self._request_services() except Exception as e: log_message(traceback.format_exc()) self.df_con_error.emit() self.background_category = None self.categories = [] self.debug_write_allowed_services() else: self.df_settings_warning.emit() self.background_category = None self.categories = [] def _request_services(self): url_to_get = self.insert_token(DF_SERVICES_URL) self._services_network_fetcher.fetchContent(QUrl(url_to_get)) def _handle_services_response(self): network_reply = self._services_network_fetcher.reply() if network_reply.error(): self.background_category = None self.categories = [] self.df_con_error.emit() log_message( f"Network error getting services from df. Error code : " + str(network_reply.error())) return response = str(network_reply.readAll(), "utf-8") doc = QtXml.QDomDocument() doc.setContent(response) service_types = doc.documentElement().childNodes() i = 0 allowed = {} allowed["any_type"] = {"services": []} while i < service_types.count(): service_type = service_types.at(i) service_type_name = service_type.nodeName() allowed[service_type_name] = {"services": []} services = service_type.childNodes() j = 0 while j < services.count(): service = services.at(j) service_name = service.nodeName() allowed[service_type_name]["services"].append(service_name) allowed["any_type"]["services"].append(service_name) j = j + 1 i = i + 1 self.allowed_df_services = allowed if not allowed["any_type"]["services"]: self.df_con_error.emit() log_message( f"Dataforsyningen returned an empty list of allowed services for token: {self.settings.value('token')}" ) # Go on and get QLR self._get_qlr_file() def _get_qlr_file(self): local_file_exists = os.path.exists(self.cached_df_qlr_filename) if local_file_exists: local_file_time = datetime.datetime.fromtimestamp( os.path.getmtime(self.cached_df_qlr_filename)) use_cached = local_file_time > datetime.datetime.now( ) - FILE_MAX_AGE if use_cached: # Skip requesting remote qlr self._load_config_from_cached_df_qlr() return # Get qlr from DF self._request_df_qlr_file() def _request_df_qlr_file(self): url_to_get = self.settings.value("df_qlr_url") self._qlr_network_fetcher.fetchContent(QUrl(url_to_get)) def _handle_qlr_response(self): network_reply = self._qlr_network_fetcher.reply() if network_reply.error(): log_message("No contact to the configuration at " + self.settings.value("df_qlr_url") + ". Error code : " + str(network_reply.error())) else: response = str(network_reply.readAll(), "utf-8") response = self.insert_token(response) self.write_cached_df_qlr(response) # Now load and use it self._load_config_from_cached_df_qlr() def _load_config_from_cached_df_qlr(self): self.df_qlr_file = QlrFile(self._read_cached_df_qlr()) self.background_category, self.categories = self.get_df_categories() self.loaded.emit() def get_categories(self): return self.categories def get_background_category(self): return self.background_category def get_maplayer_node(self, id): return self.df_qlr_file.get_maplayer_node(id) def get_df_categories(self): df_categories = [] df_background_category = None groups_with_layers = self.df_qlr_file.get_groups_with_layers() for group in groups_with_layers: df_category = {"name": group["name"], "selectables": []} for layer in group["layers"]: if self.user_has_access(layer["service"]): df_category["selectables"].append({ "type": "layer", "source": "df", "name": layer["name"], "id": layer["id"], }) if len(df_category["selectables"]) > 0: df_categories.append(df_category) if group["name"] == "Baggrundskort": df_background_category = df_category return df_background_category, df_categories def user_has_access(self, service_name): return service_name in self.allowed_df_services["any_type"]["services"] def get_custom_categories(self): return [] def _read_cached_df_qlr(self): # return file(unicode(self.cached_df_qlr_filename)).read() f = QFile(self.cached_df_qlr_filename) f.open(QIODevice.ReadOnly) return f.readAll() def write_cached_df_qlr(self, contents): """We only call this function IF we have a new version downloaded""" # Remove old versions file for filename in glob.glob( self.settings.value("cache_path") + "*_dataforsyning_data.qlr"): os.remove(filename) # Write new version with codecs.open(self.cached_df_qlr_filename, "w", "utf-8") as f: f.write(contents) def debug_write_allowed_services(self): try: debug_filename = (self.settings.value("cache_path") + self.settings.value("username") + ".txt") if os.path.exists(debug_filename): os.remove(debug_filename) with codecs.open(debug_filename, "w", "utf-8") as f: f.write( json.dumps( self.allowed_df_services["any_type"]["services"], indent=2).replace("[", "").replace("]", "")) except Exception: pass def insert_token(self, text): result = text replace_vars = {} replace_vars["df_token"] = self.settings.value("token") for i, j in replace_vars.items(): result = result.replace("{{" + str(i) + "}}", str(j)) return result