def on_searchPushButton_clicked(self, checked): if self.categoryID != '' and self.categoryID != '-1': merchandising = Merchandising(warnings = False) response = merchandising.execute( 'getMostWatchedItems', { 'categoryId': self.categoryID, 'maxResults': self.ui.spinBox.value() } ) reply = response.reply itemRecommendations = reply.itemRecommendations.item row = self.ui.tableWidget.rowCount() for item in itemRecommendations: self.ui.tableWidget.insertRow(row) imageUrl = 'http://thumbs3.ebaystatic.com/pict/%s4040.jpg' % item.itemId request = QNetworkRequest(QUrl(imageUrl)) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferCache) reply = self.manager.get(request) self.replyMap[reply] = row viewItemURL = QLabel() viewItemURL.setOpenExternalLinks(True) #viewItemURL.setTextInteractionFlags(Qt.TextBrowserInteraction) title = '<a href="%s">%s</a>' % (item.viewItemURL, item.title) viewItemURL.setText(title) self.ui.tableWidget.setCellWidget(row, 1, viewItemURL) self.ui.tableWidget.setItem(row, 2, QTableWidgetItem(item.primaryCategoryName)) self.ui.tableWidget.setItem(row, 3, QTableWidgetItem(item.buyItNowPrice.value)) self.ui.tableWidget.setItem(row, 4, QTableWidgetItem(item.watchCount)) row += 1
def _wrap_request(self, request): req = QNetworkRequest(request) req_id = next(self._request_ids) req.setAttribute(self._REQUEST_ID, req_id) if hasattr(request, 'timeout'): req.timeout = request.timeout return req, req_id
def __downloadFile(self, url, filename, doneMethod=None): """ Private slot to download the given file. @param url URL for the download (string) @param filename local name of the file (string) @param doneMethod method to be called when done """ self.__updateButton.setEnabled(False) self.__downloadButton.setEnabled(False) self.__downloadInstallButton.setEnabled(False) self.__downloadCancelButton.setEnabled(True) self.statusLabel.setText(url) self.__doneMethod = doneMethod self.__downloadURL = url self.__downloadFileName = filename self.__downloadIODevice = QFile(self.__downloadFileName + ".tmp") self.__downloadCancelled = False request = QNetworkRequest(QUrl(url)) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) reply = self.__networkManager.get(request) reply.finished.connect(self.__downloadFileDone) reply.downloadProgress.connect(self.__downloadProgress) self.__replies.append(reply)
def checkPluginUpdatesAvailable(self): """ Public method to check the availability of updates of plug-ins. """ period = Preferences.getPluginManager("UpdatesCheckInterval") if period == 0: return elif period in [1, 2, 3]: lastModified = QFileInfo(self.pluginRepositoryFile).lastModified() if lastModified.isValid() and lastModified.date().isValid(): lastModifiedDate = lastModified.date() now = QDate.currentDate() if period == 1 and lastModifiedDate.day() == now.day(): # daily return elif period == 2 and lastModifiedDate.daysTo(now) < 7: # weekly return elif period == 3 and \ (lastModifiedDate.daysTo(now) < lastModifiedDate.daysInMonth()): # monthly return self.__updateAvailable = False request = QNetworkRequest( QUrl(Preferences.getUI("PluginRepositoryUrl6"))) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) reply = self.__networkManager.get(request) reply.finished.connect(self.__downloadRepositoryFileDone) self.__replies.append(reply)
def _wrap_request(self, request): req = QNetworkRequest(request) req_id = next(self._request_ids) req.setAttribute(self._REQUEST_ID, req_id) for attr in ['timeout', 'track_response_body']: if hasattr(request, attr): setattr(req, attr, getattr(request, attr)) return req, req_id
def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y()) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request)
def get(self, url, cache=True, **kwargs): """Start a download with a link URL. Args: url: The URL to get, as QUrl cache: If set to False, don't cache the response. **kwargs: passed to get_request(). Return: The created DownloadItem. """ if not url.isValid(): urlutils.invalid_url_error(url, "start download") return None req = QNetworkRequest(url) user_agent = websettings.user_agent(url) req.setHeader(QNetworkRequest.UserAgentHeader, user_agent) if not cache: req.setAttribute(QNetworkRequest.CacheSaveControlAttribute, False) return self.get_request(req, **kwargs)
def __downloadFile(self, url, filename, doneMethod=None): """ Private slot to download the given file. @param url URL for the download (string) @param filename local name of the file (string) @param doneMethod method to be called when done """ if self.__networkConfigurationManager.isOnline(): self.__updateButton.setEnabled(False) self.__downloadButton.setEnabled(False) self.__downloadInstallButton.setEnabled(False) self.__downloadCancelButton.setEnabled(True) self.statusLabel.setText(url) self.__doneMethod = doneMethod self.__downloadURL = url self.__downloadFileName = filename self.__downloadIODevice = QFile(self.__downloadFileName + ".tmp") self.__downloadCancelled = False request = QNetworkRequest(QUrl(url)) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) reply = self.__networkManager.get(request) reply.finished.connect(self.__downloadFileDone) reply.downloadProgress.connect(self.__downloadProgress) self.__replies.append(reply) else: E5MessageBox.warning( self, self.tr("Error downloading file"), self.tr( """<p>Could not download the requested file""" """ from {0}.</p><p>Error: {1}</p>""" ).format(url, self.tr("Computer is offline.")))
def __getTranslationModels(self): """ Private method to get the translation models supported by IBM Watson Language Translator. """ apiKey = self.plugin.getPreferences("IbmKey") if not apiKey: E5MessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), self.tr("A valid IBM Watson Language Translator key is" " required.")) return translatorUrl = self.plugin.getPreferences("IbmUrl") if not translatorUrl: E5MessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), self.tr("A valid IBM Watson Language Translator URL is" " required.")) return params = "?version=2018-05-01" url = QUrl(translatorUrl + "/v3/models" + params) extraHeaders = [ (b"Authorization", b"Basic " + QByteArray(b"apikey:" + apiKey.encode("utf-8")).toBase64()) ] request = QNetworkRequest(url) request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) if extraHeaders: for name, value in extraHeaders: request.setRawHeader(name, value) reply = self.__networkManager.get(request) reply.finished.connect( lambda: self.__getTranslationModelsReplyFinished(reply)) self.__replies.append(reply)
def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = "http://tile.openstreetmap.org/%d/%d/%d.png" % ( self.zoom, grab.x(), grab.y(), ) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b"User-Agent", b"Nokia (PyQt) Graphics Dojo 1.0") request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request)
def requestStarted(self, request): # 拦截 # request.fail(QWebEngineUrlRequestJob.RequestDenied) # print('initiator:', request.initiator()) print('requestMethod:', request.requestMethod()) print('requestHeaders:', request.requestHeaders()) url = request.requestUrl() if url.scheme().startswith('myurl'): url.setScheme(url.scheme().replace('myurl', 'http')) print('requestUrl:', url) # 构造真实请求 req = QNetworkRequest(url) req.setAttribute(self.AttrType, request) # 记录 for headerName, headerValue in request.requestHeaders().items(): req.setRawHeader(headerName, headerValue) method = request.requestMethod() # TODO: 这里需要把浏览器内部的cookie获取出来重新设置 if method == b'GET': self._manager.get(req) # TODO: 这里貌似没法得到POST的数据,ajax的请求貌似也有问题 elif method == b'POST': self._manager.post(req)
def createRequest(self, enddate, url, path): """创建网络请求""" req = QNetworkRequest(QUrl(url)) # 日期 req.setAttribute(QNetworkRequest.User + 1, enddate) # 图片储存路径 req.setAttribute(QNetworkRequest.User + 2, path) # 回调函数用于加载图片显示 req.setAttribute(QNetworkRequest.User + 3, self._setPixmap) return req
def _wrap_request(self, request): req = QNetworkRequest(request) req_id = next(self._request_ids) req.setAttribute(self._REQUEST_ID, req_id) if self.disable_browser_caches: # disables the network cache # see http://doc.qt.io/qt-5/qnetworkrequest.html#CacheLoadControl-enum req.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) req.setAttribute(QNetworkRequest.CacheSaveControlAttribute, False) for attr in ['timeout', 'track_request_body', 'track_response_body']: if hasattr(request, attr): setattr(req, attr, getattr(request, attr)) return req, req_id
def _get(self, url): """设置图片或者请求网络图片 :param url: """ if not url: self.onError('') return if url.startswith('http') and not self.loadingTimer.isActive(): url = QUrl(url) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar') request.setRawHeader(b'Author', b'Irony') request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) if qApp._network.cache(): request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferNetwork) request.setAttribute(QNetworkRequest.CacheSaveControlAttribute, True) reply = qApp._network.get(request) self.pradius = 0 self.loadingTimer.start(50) # 显示进度动画 reply.finished.connect(self.onFinished) reply.error.connect(self.onError) return self.pradius = 0 if os.path.exists(url) and os.path.isfile(url): if self.isGif: self._movie = QMovie(url, parent=self) if self._movie.isValid(): self._movie.frameChanged.connect(self._resizeGifPixmap) self._movie.start() else: self._pixmap = QPixmap(url) self._resizePixmap() else: self.onError('')
def get_arrive_time(self, station_id: int): self.__url = QUrl(self.time_arrive_pattern.format(station_id)) request = QNetworkRequest() request.setUrl(self.__url) request.setAttribute(QNetworkRequest.User, (int, station_id)) self.__manager.get(request)
class NetworkMJPGImage(QQuickPaintedItem): def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self._stream_buffer = QByteArray() self._stream_buffer_start_index = -1 self._network_manager = None # type: QNetworkAccessManager self._image_request = None # type: QNetworkRequest self._image_reply = None # type: QNetworkReply self._image = QImage() self._image_rect = QRect() self._source_url = QUrl() self._started = False self._mirror = False self.setAntialiasing(True) ## Ensure that close gets called when object is destroyed def __del__(self) -> None: self.stop() def paint(self, painter: "QPainter") -> None: if self._mirror: painter.drawImage(self.contentsBoundingRect(), self._image.mirrored()) return painter.drawImage(self.contentsBoundingRect(), self._image) def setSourceURL(self, source_url: "QUrl") -> None: self._source_url = source_url self.sourceURLChanged.emit() if self._started: self.start() def getSourceURL(self) -> "QUrl": return self._source_url sourceURLChanged = pyqtSignal() source = pyqtProperty(QUrl, fget=getSourceURL, fset=setSourceURL, notify=sourceURLChanged) def setMirror(self, mirror: bool) -> None: if mirror == self._mirror: return self._mirror = mirror self.mirrorChanged.emit() self.update() def getMirror(self) -> bool: return self._mirror mirrorChanged = pyqtSignal() mirror = pyqtProperty(bool, fget=getMirror, fset=setMirror, notify=mirrorChanged) imageSizeChanged = pyqtSignal() @pyqtProperty(int, notify=imageSizeChanged) def imageWidth(self) -> int: return self._image.width() @pyqtProperty(int, notify=imageSizeChanged) def imageHeight(self) -> int: return self._image.height() @pyqtSlot() def start(self) -> None: self.stop() # Ensure that previous requests (if any) are stopped. if not self._source_url: Logger.log("w", "Unable to start camera stream without target!") return auth_data = "" if self._source_url.userInfo(): # move auth data to basic authorization header auth_data = base64.b64encode( self._source_url.userInfo().encode()).decode("utf-8") authority = self._source_url.authority() self._source_url.setAuthority(authority.rsplit("@", 1)[1]) self._image_request = QNetworkRequest(self._source_url) self._image_request.setAttribute( QNetworkRequest.FollowRedirectsAttribute, True) if auth_data: self._image_request.setRawHeader(b"Authorization", ("basic %s" % auth_data).encode()) if self._source_url.scheme().lower() == "https": # ignore SSL errors (eg for self-signed certificates) ssl_configuration = QSslConfiguration.defaultConfiguration() ssl_configuration.setPeerVerifyMode(QSslSocket.VerifyNone) self._image_request.setSslConfiguration(ssl_configuration) if self._network_manager is None: self._network_manager = QNetworkAccessManager() self._image_reply = self._network_manager.get(self._image_request) self._image_reply.downloadProgress.connect( self._onStreamDownloadProgress) self._started = True @pyqtSlot() def stop(self) -> None: self._stream_buffer = QByteArray() self._stream_buffer_start_index = -1 if self._image_reply: try: try: self._image_reply.downloadProgress.disconnect( self._onStreamDownloadProgress) except Exception: pass if not self._image_reply.isFinished(): self._image_reply.close() except Exception as e: # RuntimeError pass # It can happen that the wrapped c++ object is already deleted. self._image_reply = None self._image_request = None self._network_manager = None self._started = False def _onStreamDownloadProgress(self, bytes_received: int, bytes_total: int) -> None: # An MJPG stream is (for our purpose) a stream of concatenated JPG images. # JPG images start with the marker 0xFFD8, and end with 0xFFD9 if self._image_reply is None: return self._stream_buffer += self._image_reply.readAll() if (len(self._stream_buffer) > 5000000): # No single camera frame should be 5 MB or larger Logger.log( "w", "MJPEG buffer exceeds reasonable size. Restarting stream...") self.stop() # resets stream buffer and start index self.start() return if self._stream_buffer_start_index == -1: self._stream_buffer_start_index = self._stream_buffer.indexOf( b"\xff\xd8") stream_buffer_end_index = self._stream_buffer.lastIndexOf(b"\xff\xd9") # If this happens to be more than a single frame, then so be it; the JPG decoder will # ignore the extra data. We do it like this in order not to get a buildup of frames if self._stream_buffer_start_index != -1 and stream_buffer_end_index != -1: jpg_data = self._stream_buffer[ self._stream_buffer_start_index:stream_buffer_end_index + 2] self._stream_buffer = self._stream_buffer[stream_buffer_end_index + 2:] self._stream_buffer_start_index = -1 self._image.loadFromData(jpg_data) if self._image.rect() != self._image_rect: self.imageSizeChanged.emit() self.update()
class Toolbox(QObject, Extension): DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" DEFAULT_CLOUD_API_VERSION = 1 def __init__(self, parent=None) -> None: super().__init__(parent) self._application = Application.getInstance() self._package_manager = None self._plugin_registry = Application.getInstance().getPluginRegistry() self._sdk_version = None self._cloud_api_version = None self._cloud_api_root = None self._api_url = None # Network: self._get_packages_request = None self._get_showcase_request = None self._download_request = None self._download_reply = None self._download_progress = 0 self._is_downloading = False self._network_manager = None self._request_header = [ b"User-Agent", str.encode("%s/%s (%s %s)" % ( Application.getInstance().getApplicationName(), Application.getInstance().getVersion(), platform.system(), platform.machine(), )) ] self._request_urls = {} self._to_update = [] # Package_ids that are waiting to be updated self._old_plugin_ids = [] # Data: self._metadata = { "authors": [], "packages": [], "plugins_showcase": [], "plugins_available": [], "plugins_installed": [], "materials_showcase": [], "materials_available": [], "materials_installed": [] } # Models: self._models = { "authors": AuthorsModel(self), "packages": PackagesModel(self), "plugins_showcase": PackagesModel(self), "plugins_available": PackagesModel(self), "plugins_installed": PackagesModel(self), "materials_showcase": AuthorsModel(self), "materials_available": PackagesModel(self), "materials_installed": PackagesModel(self) } # These properties are for keeping track of the UI state: # ---------------------------------------------------------------------- # View category defines which filter to use, and therefore effectively # which category is currently being displayed. For example, possible # values include "plugin" or "material", but also "installed". self._view_category = "plugin" # View page defines which type of page layout to use. For example, # possible values include "overview", "detail" or "author". self._view_page = "loading" # Active package refers to which package is currently being downloaded, # installed, or otherwise modified. self._active_package = None self._dialog = None self._restart_required = False # variables for the license agreement dialog self._license_dialog_plugin_name = "" self._license_dialog_license_content = "" self._license_dialog_plugin_file_location = "" self._restart_dialog_message = "" Application.getInstance().initializationFinished.connect( self._onAppInitialized) # Signals: # -------------------------------------------------------------------------- # Downloading changes activePackageChanged = pyqtSignal() onDownloadProgressChanged = pyqtSignal() onIsDownloadingChanged = pyqtSignal() restartRequiredChanged = pyqtSignal() installChanged = pyqtSignal() enabledChanged = pyqtSignal() # UI changes viewChanged = pyqtSignal() detailViewChanged = pyqtSignal() filterChanged = pyqtSignal() metadataChanged = pyqtSignal() showLicenseDialog = pyqtSignal() @pyqtSlot(result=str) def getLicenseDialogPluginName(self) -> str: return self._license_dialog_plugin_name @pyqtSlot(result=str) def getLicenseDialogPluginFileLocation(self) -> str: return self._license_dialog_plugin_file_location @pyqtSlot(result=str) def getLicenseDialogLicenseContent(self) -> str: return self._license_dialog_license_content def openLicenseDialog(self, plugin_name: str, license_content: str, plugin_file_location: str) -> None: self._license_dialog_plugin_name = plugin_name self._license_dialog_license_content = license_content self._license_dialog_plugin_file_location = plugin_file_location self.showLicenseDialog.emit() # This is a plugin, so most of the components required are not ready when # this is initialized. Therefore, we wait until the application is ready. def _onAppInitialized(self) -> None: self._package_manager = Application.getInstance().getPackageManager() self._sdk_version = self._getSDKVersion() self._cloud_api_version = self._getCloudAPIVersion() self._cloud_api_root = self._getCloudAPIRoot() self._api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format( cloud_api_root=self._cloud_api_root, cloud_api_version=self._cloud_api_version, sdk_version=self._sdk_version) self._request_urls = { "authors": QUrl("{base_url}/authors".format(base_url=self._api_url)), "packages": QUrl("{base_url}/packages".format(base_url=self._api_url)), "plugins_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)), "plugins_available": QUrl("{base_url}/packages?package_type=plugin".format( base_url=self._api_url)), "materials_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)), "materials_available": QUrl("{base_url}/packages?package_type=material".format( base_url=self._api_url)) } # Get the API root for the packages API depending on Cura version settings. def _getCloudAPIRoot(self) -> str: if not hasattr(cura, "CuraVersion"): return self.DEFAULT_CLOUD_API_ROOT if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"): return self.DEFAULT_CLOUD_API_ROOT if not cura.CuraVersion.CuraCloudAPIRoot: return self.DEFAULT_CLOUD_API_ROOT return cura.CuraVersion.CuraCloudAPIRoot # Get the cloud API version from CuraVersion def _getCloudAPIVersion(self) -> int: if not hasattr(cura, "CuraVersion"): return self.DEFAULT_CLOUD_API_VERSION if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"): return self.DEFAULT_CLOUD_API_VERSION if not cura.CuraVersion.CuraCloudAPIVersion: return self.DEFAULT_CLOUD_API_VERSION return cura.CuraVersion.CuraCloudAPIVersion # Get the packages version depending on Cura version settings. def _getSDKVersion(self) -> int: if not hasattr(cura, "CuraVersion"): return self._plugin_registry.APIVersion if not hasattr(cura.CuraVersion, "CuraSDKVersion"): return self._plugin_registry.APIVersion if not cura.CuraVersion.CuraSDKVersion: return self._plugin_registry.APIVersion return cura.CuraVersion.CuraSDKVersion @pyqtSlot() def browsePackages(self) -> None: # Create the network manager: # This was formerly its own function but really had no reason to be as # it was never called more than once ever. if self._network_manager: self._network_manager.finished.disconnect(self._onRequestFinished) self._network_manager.networkAccessibleChanged.disconnect( self._onNetworkAccessibleChanged) self._network_manager = QNetworkAccessManager() self._network_manager.finished.connect(self._onRequestFinished) self._network_manager.networkAccessibleChanged.connect( self._onNetworkAccessibleChanged) # Make remote requests: self._makeRequestByType("packages") self._makeRequestByType("authors") self._makeRequestByType("plugins_showcase") self._makeRequestByType("materials_showcase") # Gather installed packages: self._updateInstalledModels() if not self._dialog: self._dialog = self._createDialog("Toolbox.qml") self._dialog.show() # Apply enabled/disabled state to installed plugins self.enabledChanged.emit() def _createDialog(self, qml_name: str) -> Optional[QObject]: Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name) path = os.path.join( PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "resources", "qml", qml_name) dialog = Application.getInstance().createQmlComponent( path, {"toolbox": self}) return dialog def _convertPluginMetadata(self, plugin: dict) -> dict: formatted = { "package_id": plugin["id"], "package_type": "plugin", "display_name": plugin["plugin"]["name"], "package_version": plugin["plugin"]["version"], "sdk_version": plugin["plugin"]["api"], "author": { "author_id": plugin["plugin"]["author"], "display_name": plugin["plugin"]["author"] }, "is_installed": True, "description": plugin["plugin"]["description"] } return formatted @pyqtSlot() def _updateInstalledModels(self) -> None: # This is moved here to avoid code duplication and so that after installing plugins they get removed from the # list of old plugins old_plugin_ids = self._plugin_registry.getInstalledPlugins() installed_package_ids = self._package_manager.getAllInstalledPackageIDs( ) scheduled_to_remove_package_ids = self._package_manager.getToRemovePackageIDs( ) self._old_plugin_ids = [] self._old_plugin_metadata = [] for plugin_id in old_plugin_ids: # Neither the installed packages nor the packages that are scheduled to remove are old plugins if plugin_id not in installed_package_ids and plugin_id not in scheduled_to_remove_package_ids: Logger.log( 'i', 'Found a plugin that was installed with the old plugin browser: %s', plugin_id) old_metadata = self._plugin_registry.getMetaData(plugin_id) new_metadata = self._convertPluginMetadata(old_metadata) self._old_plugin_ids.append(plugin_id) self._old_plugin_metadata.append(new_metadata) all_packages = self._package_manager.getAllInstalledPackagesInfo() if "plugin" in all_packages: self._metadata["plugins_installed"] = all_packages[ "plugin"] + self._old_plugin_metadata self._models["plugins_installed"].setMetadata( self._metadata["plugins_installed"]) self.metadataChanged.emit() if "material" in all_packages: self._metadata["materials_installed"] = all_packages["material"] # TODO: ADD MATERIALS HERE ONCE MATERIALS PORTION OF TOOLBOX IS LIVE self._models["materials_installed"].setMetadata( self._metadata["materials_installed"]) self.metadataChanged.emit() @pyqtSlot(str) def install(self, file_path: str) -> None: self._package_manager.installPackage(file_path) self.installChanged.emit() self._updateInstalledModels() self.metadataChanged.emit() self._restart_required = True self.restartRequiredChanged.emit() @pyqtSlot(str) def uninstall(self, plugin_id: str) -> None: self._package_manager.removePackage(plugin_id, force_add=True) self.installChanged.emit() self._updateInstalledModels() self.metadataChanged.emit() self._restart_required = True self.restartRequiredChanged.emit() ## Actual update packages that are in self._to_update def _update(self) -> None: if self._to_update: plugin_id = self._to_update.pop(0) remote_package = self.getRemotePackage(plugin_id) if remote_package: download_url = remote_package["download_url"] Logger.log("d", "Updating package [%s]..." % plugin_id) self.startDownload(download_url) else: Logger.log( "e", "Could not update package [%s] because there is no remote package info available.", plugin_id) if self._to_update: self._application.callLater(self._update) ## Update a plugin by plugin_id @pyqtSlot(str) def update(self, plugin_id: str) -> None: self._to_update.append(plugin_id) self._application.callLater(self._update) @pyqtSlot(str) def enable(self, plugin_id: str) -> None: self._plugin_registry.enablePlugin(plugin_id) self.enabledChanged.emit() Logger.log("i", "%s was set as 'active'.", plugin_id) self._restart_required = True self.restartRequiredChanged.emit() @pyqtSlot(str) def disable(self, plugin_id: str) -> None: self._plugin_registry.disablePlugin(plugin_id) self.enabledChanged.emit() Logger.log("i", "%s was set as 'deactive'.", plugin_id) self._restart_required = True self.restartRequiredChanged.emit() @pyqtProperty(bool, notify=metadataChanged) def dataReady(self) -> bool: return self._packages_model is not None @pyqtProperty(bool, notify=restartRequiredChanged) def restartRequired(self) -> bool: return self._restart_required @pyqtSlot() def restart(self): CuraApplication.getInstance().windowClosed() def getRemotePackage(self, package_id: str) -> Optional[Dict]: # TODO: make the lookup in a dict, not a loop. canUpdate is called for every item. remote_package = None for package in self._metadata["packages"]: if package["package_id"] == package_id: remote_package = package break return remote_package # Checks # -------------------------------------------------------------------------- @pyqtSlot(str, result=bool) def canUpdate(self, package_id: str) -> bool: if self.isOldPlugin(package_id): return True local_package = self._package_manager.getInstalledPackageInfo( package_id) if local_package is None: return False remote_package = self.getRemotePackage(package_id) if remote_package is None: return False local_version = Version(local_package["package_version"]) remote_version = Version(remote_package["package_version"]) return remote_version > local_version @pyqtSlot(str, result=bool) def canDowngrade(self, package_id: str) -> bool: # If the currently installed version is higher than the bundled version (if present), the we can downgrade # this package. local_package = self._package_manager.getInstalledPackageInfo( package_id) if local_package is None: return False bundled_package = self._package_manager.getBundledPackageInfo( package_id) if bundled_package is None: return False local_version = Version(local_package["package_version"]) bundled_version = Version(bundled_package["package_version"]) return bundled_version < local_version @pyqtSlot(str, result=bool) def isInstalled(self, package_id: str) -> bool: return self._package_manager.isPackageInstalled(package_id) @pyqtSlot(str, result=bool) def isEnabled(self, package_id: str) -> bool: if package_id in self._plugin_registry.getActivePlugins(): return True return False # Check for plugins that were installed with the old plugin browser @pyqtSlot(str, result=bool) def isOldPlugin(self, plugin_id: str) -> bool: if plugin_id in self._old_plugin_ids: return True return False def loadingComplete(self) -> bool: populated = 0 for list in self._metadata.items(): if len(list) > 0: populated += 1 if populated == len(self._metadata.items()): return True return False # Make API Calls # -------------------------------------------------------------------------- def _makeRequestByType(self, type: str) -> None: Logger.log("i", "Toolbox: Requesting %s metadata from server.", type) request = QNetworkRequest(self._request_urls[type]) request.setRawHeader(*self._request_header) self._network_manager.get(request) @pyqtSlot(str) def startDownload(self, url: str) -> None: Logger.log( "i", "Toolbox: Attempting to download & install package from %s.", url) url = QUrl(url) self._download_request = QNetworkRequest(url) if hasattr(QNetworkRequest, "FollowRedirectsAttribute"): # Patch for Qt 5.6-5.8 self._download_request.setAttribute( QNetworkRequest.FollowRedirectsAttribute, True) if hasattr(QNetworkRequest, "RedirectPolicyAttribute"): # Patch for Qt 5.9+ self._download_request.setAttribute( QNetworkRequest.RedirectPolicyAttribute, True) self._download_request.setRawHeader(*self._request_header) self._download_reply = self._network_manager.get( self._download_request) self.setDownloadProgress(0) self.setIsDownloading(True) self._download_reply.downloadProgress.connect(self._onDownloadProgress) @pyqtSlot() def cancelDownload(self) -> None: Logger.log("i", "Toolbox: User cancelled the download of a plugin.") self.resetDownload() def resetDownload(self) -> None: if self._download_reply: try: self._download_reply.downloadProgress.disconnect( self._onDownloadProgress) except TypeError: #Raised when the method is not connected to the signal yet. pass #Don't need to disconnect. self._download_reply.abort() self._download_reply = None self._download_request = None self.setDownloadProgress(0) self.setIsDownloading(False) # Handlers for Network Events # -------------------------------------------------------------------------- def _onNetworkAccessibleChanged( self, network_accessibility: QNetworkAccessManager.NetworkAccessibility ) -> None: if network_accessibility == QNetworkAccessManager.NotAccessible: self.resetDownload() def _onRequestFinished(self, reply: QNetworkReply) -> None: if reply.error() == QNetworkReply.TimeoutError: Logger.log("w", "Got a timeout.") self.setViewPage("errored") self.resetDownload() return if reply.error() == QNetworkReply.HostNotFoundError: Logger.log("w", "Unable to reach server.") self.setViewPage("errored") self.resetDownload() return if reply.operation() == QNetworkAccessManager.GetOperation: for type, url in self._request_urls.items(): if reply.url() == url: if reply.attribute( QNetworkRequest.HttpStatusCodeAttribute) == 200: try: json_data = json.loads( bytes(reply.readAll()).decode("utf-8")) # Check for errors: if "errors" in json_data: for error in json_data["errors"]: Logger.log("e", "%s", error["title"]) return # Create model and apply metadata: if not self._models[type]: Logger.log("e", "Could not find the %s model.", type) break # HACK: Eventually get rid of the code from here... if type is "plugins_showcase" or type is "materials_showcase": self._metadata["plugins_showcase"] = json_data[ "data"]["plugin"]["packages"] self._models["plugins_showcase"].setMetadata( self._metadata["plugins_showcase"]) self._metadata[ "materials_showcase"] = json_data["data"][ "material"]["authors"] self._models["materials_showcase"].setMetadata( self._metadata["materials_showcase"]) else: # ...until here. # This hack arises for multiple reasons but the main # one is because there are not separate API calls # for different kinds of showcases. self._metadata[type] = json_data["data"] self._models[type].setMetadata( self._metadata[type]) # Do some auto filtering # TODO: Make multiple API calls in the future to handle this if type is "packages": self._models[type].setFilter( {"type": "plugin"}) if type is "authors": self._models[type].setFilter( {"package_types": "material"}) self.metadataChanged.emit() if self.loadingComplete() is True: self.setViewPage("overview") return except json.decoder.JSONDecodeError: Logger.log( "w", "Toolbox: Received invalid JSON for %s.", type) break else: self.setViewPage("errored") self.resetDownload() return else: # Ignore any operation that is not a get operation pass def _onDownloadProgress(self, bytes_sent: int, bytes_total: int) -> None: if bytes_total > 0: new_progress = bytes_sent / bytes_total * 100 self.setDownloadProgress(new_progress) if bytes_sent == bytes_total: self.setIsDownloading(False) self._download_reply.downloadProgress.disconnect( self._onDownloadProgress) # Must not delete the temporary file on Windows self._temp_plugin_file = tempfile.NamedTemporaryFile( mode="w+b", suffix=".curapackage", delete=False) file_path = self._temp_plugin_file.name # Write first and close, otherwise on Windows, it cannot read the file self._temp_plugin_file.write(self._download_reply.readAll()) self._temp_plugin_file.close() self._onDownloadComplete(file_path) def _onDownloadComplete(self, file_path: str): Logger.log("i", "Toolbox: Download complete.") package_info = self._package_manager.getPackageInfo(file_path) if not package_info: Logger.log( "w", "Toolbox: Package file [%s] was not a valid CuraPackage.", file_path) return license_content = self._package_manager.getPackageLicense(file_path) if license_content is not None: self.openLicenseDialog(package_info["package_id"], license_content, file_path) return self.install(file_path) return # Getter & Setters for Properties: # -------------------------------------------------------------------------- def setDownloadProgress(self, progress: Union[int, float]) -> None: if progress != self._download_progress: self._download_progress = progress self.onDownloadProgressChanged.emit() @pyqtProperty(int, fset=setDownloadProgress, notify=onDownloadProgressChanged) def downloadProgress(self) -> int: return self._download_progress def setIsDownloading(self, is_downloading: bool) -> None: if self._is_downloading != is_downloading: self._is_downloading = is_downloading self.onIsDownloadingChanged.emit() @pyqtProperty(bool, fset=setIsDownloading, notify=onIsDownloadingChanged) def isDownloading(self) -> bool: return self._is_downloading def setActivePackage(self, package: Dict[str, Any]) -> None: self._active_package = package self.activePackageChanged.emit() @pyqtProperty(QObject, fset=setActivePackage, notify=activePackageChanged) def activePackage(self) -> Optional[Dict[str, Any]]: return self._active_package def setViewCategory(self, category: str = "plugin") -> None: self._view_category = category self.viewChanged.emit() @pyqtProperty(str, fset=setViewCategory, notify=viewChanged) def viewCategory(self) -> str: return self._view_category def setViewPage(self, page: str = "overview") -> None: self._view_page = page self.viewChanged.emit() @pyqtProperty(str, fset=setViewPage, notify=viewChanged) def viewPage(self) -> str: return self._view_page # Expose Models: # -------------------------------------------------------------------------- @pyqtProperty(QObject, notify=metadataChanged) def authorsModel(self) -> AuthorsModel: return self._models["authors"] @pyqtProperty(QObject, notify=metadataChanged) def packagesModel(self) -> PackagesModel: return self._models["packages"] @pyqtProperty(QObject, notify=metadataChanged) def pluginsShowcaseModel(self) -> PackagesModel: return self._models["plugins_showcase"] @pyqtProperty(QObject, notify=metadataChanged) def pluginsInstalledModel(self) -> PackagesModel: return self._models["plugins_installed"] @pyqtProperty(QObject, notify=metadataChanged) def materialsShowcaseModel(self) -> PackagesModel: return self._models["materials_showcase"] @pyqtProperty(QObject, notify=metadataChanged) def materialsInstalledModel(self) -> PackagesModel: return self._models["materials_installed"] # Filter Models: # -------------------------------------------------------------------------- @pyqtSlot(str, str, str) def filterModelByProp(self, modelType: str, filterType: str, parameter: str): if not self._models[modelType]: Logger.log( "w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) return self._models[modelType].setFilter({filterType: parameter}) self.filterChanged.emit() @pyqtSlot() def removeFilters(self, modelType: str): if not self._models[modelType]: Logger.log( "w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", modelType) return self._models[modelType].setFilter({}) self.filterChanged.emit()
def createRequest(self, op, request, outgoingData=None): """ Public method to create a request. @param op the operation to be performed (QNetworkAccessManager.Operation) @param request reference to the request object (QNetworkRequest) @param outgoingData reference to an IODevice containing data to be sent (QIODevice) @return reference to the created reply object (QNetworkReply) """ scheme = request.url().scheme() if scheme == "https" and \ (not SSL_AVAILABLE or not QSslSocket.supportsSsl()): from .NetworkProtocolUnknownErrorReply import \ NetworkProtocolUnknownErrorReply return NetworkProtocolUnknownErrorReply(scheme, self) import Helpviewer.HelpWindow if op == QNetworkAccessManager.PostOperation and \ outgoingData is not None: outgoingDataByteArray = outgoingData.peek(1024 * 1024) Helpviewer.HelpWindow.HelpWindow.passwordManager().post( request, outgoingDataByteArray) reply = None if scheme in self.__schemeHandlers: reply = self.__schemeHandlers[scheme]\ .createRequest(op, request, outgoingData) if reply is not None: return reply # give GreaseMonkey the chance to create a request reply = Helpviewer.HelpWindow.HelpWindow.greaseMonkeyManager()\ .createRequest(op, request, outgoingData) if reply is not None: return reply req = QNetworkRequest(request) if req.rawHeader(b"X-Eric6-UserLoadAction") == QByteArray(b"1"): req.setRawHeader(b"X-Eric6-UserLoadAction", QByteArray()) req.setAttribute(QNetworkRequest.User + 200, "") else: req.setAttribute( QNetworkRequest.User + 200, req.rawHeader(b"Referer")) if hasattr(QNetworkRequest, 'HttpPipeliningAllowedAttribute'): req.setAttribute( QNetworkRequest.HttpPipeliningAllowedAttribute, True) if not self.__acceptLanguage.isEmpty(): req.setRawHeader(b"Accept-Language", self.__acceptLanguage) # AdBlock code if op == QNetworkAccessManager.GetOperation: if self.__adblockNetwork is None: self.__adblockNetwork = \ Helpviewer.HelpWindow.HelpWindow.adBlockManager().network() reply = self.__adblockNetwork.block(req) if reply is not None: reply.setParent(self) return reply # set cache policy if op == QNetworkAccessManager.GetOperation: urlHost = req.url().host() for host in Preferences.getHelp("NoCacheHosts"): if host in urlHost: req.setAttribute( QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) break else: req.setAttribute( QNetworkRequest.CacheLoadControlAttribute, Preferences.getHelp("CachePolicy")) else: req.setAttribute( QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) # Do Not Track feature if self.__doNotTrack: req.setRawHeader(b"DNT", b"1") req.setRawHeader(b"X-Do-Not-Track", b"1") # Send referer header? if not self.__sendReferer and \ req.url().host() not in Preferences.getHelp("SendRefererWhitelist"): req.setRawHeader(b"Referer", b"") reply = QNetworkAccessManager.createRequest( self, op, req, outgoingData) self.requestCreated.emit(op, req, reply) return reply
def createRequest(self, url, callback): """创建网络请求""" req = QNetworkRequest(QUrl(url)) # 回调函数用于加载图片显示 req.setAttribute(QNetworkRequest.User + 3, callback) return req
def _createRequest( self, http_method: str, url: str, headers_dict: Optional[Dict[str, str]] = None, data: Optional[Union[bytes, bytearray]] = None, callback: Optional[Callable[["QNetworkReply"], None]] = None, error_callback: Optional[Callable[ ["QNetworkReply", "QNetworkReply.NetworkError"], None]] = None, download_progress_callback: Optional[Callable[[int, int], None]] = None, upload_progress_callback: Optional[Callable[[int, int], None]] = None, timeout: Optional[float] = None, scope: Optional[HttpRequestScope] = None) -> "HttpRequestData": # Sanity checks if timeout is not None and timeout <= 0: raise ValueError( "Timeout must be a positive number if provided, but [%s] was given" % timeout) request = QNetworkRequest(QUrl(url)) # Make sure that Qt handles redirects if hasattr(QNetworkRequest, "FollowRedirectsAttribute"): # Patch for Qt 5.6-5.8 request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) if hasattr(QNetworkRequest, "RedirectPolicyAttribute"): # Patch for Qt 5.9+ request.setAttribute(QNetworkRequest.RedirectPolicyAttribute, True) # Set headers if headers_dict is not None: for key, value in headers_dict.items(): request.setRawHeader(key.encode("utf-8"), value.encode("utf-8")) if scope is not None: scope.requestHook(request) # Generate a unique request ID request_id = uuid.uuid4().hex # Create the request data request_data = HttpRequestData( request_id, http_method=http_method, request=request, data=data, manager_timeout_callback=self._onRequestTimeout, callback=callback, error_callback=error_callback, download_progress_callback=download_progress_callback, upload_progress_callback=upload_progress_callback, timeout=timeout) with self._request_lock: self._request_queue.append(request_data) # Schedule a call to process pending requests in the queue if not self._process_requests_scheduled: self.callLater(0, self._processNextRequestsInQueue) self._process_requests_scheduled = True return request_data
class Toolbox(QObject, Extension): def __init__(self, parent=None) -> None: super().__init__(parent) self._application = Application.getInstance() self._package_manager = None self._plugin_registry = Application.getInstance().getPluginRegistry() self._packages_version = self._plugin_registry.APIVersion self._api_version = 1 self._api_url = "https://api-staging.ultimaker.com/cura-packages/v{api_version}/cura/v{package_version}".format( api_version = self._api_version, package_version = self._packages_version) # Network: self._get_packages_request = None self._get_showcase_request = None self._download_request = None self._download_reply = None self._download_progress = 0 self._is_downloading = False self._network_manager = None self._request_header = [ b"User-Agent", str.encode( "%s/%s (%s %s)" % ( Application.getInstance().getApplicationName(), Application.getInstance().getVersion(), platform.system(), platform.machine(), ) ) ] self._request_urls = { "authors": QUrl("{base_url}/authors".format(base_url = self._api_url)), "packages": QUrl("{base_url}/packages".format(base_url = self._api_url)), "plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)), "materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)) } # Data: self._metadata = { "authors": [], "packages": [], "plugins_showcase": [], "plugins_installed": [], "materials_showcase": [], "materials_installed": [] } # Models: self._models = { "authors": AuthorsModel(self), "packages": PackagesModel(self), "plugins_showcase": PackagesModel(self), "plugins_available": PackagesModel(self), "plugins_installed": PackagesModel(self), "materials_showcase": AuthorsModel(self), "materials_available": PackagesModel(self), "materials_installed": PackagesModel(self) } # These properties are for keeping track of the UI state: # ---------------------------------------------------------------------- # View category defines which filter to use, and therefore effectively # which category is currently being displayed. For example, possible # values include "plugin" or "material", but also "installed". self._view_category = "plugin" # View page defines which type of page layout to use. For example, # possible values include "overview", "detail" or "author". self._view_page = "loading" # Active package refers to which package is currently being downloaded, # installed, or otherwise modified. self._active_package = None self._dialog = None self._restart_required = False # variables for the license agreement dialog self._license_dialog_plugin_name = "" self._license_dialog_license_content = "" self._license_dialog_plugin_file_location = "" self._restart_dialog_message = "" Application.getInstance().initializationFinished.connect(self._onAppInitialized) # Signals: # -------------------------------------------------------------------------- # Downloading changes activePackageChanged = pyqtSignal() onDownloadProgressChanged = pyqtSignal() onIsDownloadingChanged = pyqtSignal() restartRequiredChanged = pyqtSignal() installChanged = pyqtSignal() enabledChanged = pyqtSignal() # UI changes viewChanged = pyqtSignal() detailViewChanged = pyqtSignal() filterChanged = pyqtSignal() metadataChanged = pyqtSignal() showLicenseDialog = pyqtSignal() @pyqtSlot(result = str) def getLicenseDialogPluginName(self) -> str: return self._license_dialog_plugin_name @pyqtSlot(result = str) def getLicenseDialogPluginFileLocation(self) -> str: return self._license_dialog_plugin_file_location @pyqtSlot(result = str) def getLicenseDialogLicenseContent(self) -> str: return self._license_dialog_license_content def openLicenseDialog(self, plugin_name: str, license_content: str, plugin_file_location: str) -> None: self._license_dialog_plugin_name = plugin_name self._license_dialog_license_content = license_content self._license_dialog_plugin_file_location = plugin_file_location self.showLicenseDialog.emit() # This is a plugin, so most of the components required are not ready when # this is initialized. Therefore, we wait until the application is ready. def _onAppInitialized(self) -> None: self._package_manager = Application.getInstance().getCuraPackageManager() @pyqtSlot() def browsePackages(self) -> None: # Create the network manager: # This was formerly its own function but really had no reason to be as # it was never called more than once ever. if self._network_manager: self._network_manager.finished.disconnect(self._onRequestFinished) self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged) self._network_manager = QNetworkAccessManager() self._network_manager.finished.connect(self._onRequestFinished) self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged) # Make remote requests: self._makeRequestByType("packages") self._makeRequestByType("authors") self._makeRequestByType("plugins_showcase") self._makeRequestByType("materials_showcase") # Gather installed packages: self._updateInstalledModels() if not self._dialog: self._dialog = self._createDialog("Toolbox.qml") self._dialog.show() # Apply enabled/disabled state to installed plugins self.enabledChanged.emit() def _createDialog(self, qml_name: str) -> Optional[QObject]: Logger.log("d", "Toolbox: Creating dialog [%s].", qml_name) path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "resources", "qml", qml_name) dialog = Application.getInstance().createQmlComponent(path, {"toolbox": self}) return dialog @pyqtSlot() def _updateInstalledModels(self) -> None: all_packages = self._package_manager.getAllInstalledPackagesInfo() if "plugin" in all_packages: self._metadata["plugins_installed"] = all_packages["plugin"] self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"]) self.metadataChanged.emit() if "material" in all_packages: self._metadata["materials_installed"] = all_packages["material"] self._models["materials_installed"].setMetadata(self._metadata["materials_installed"]) self.metadataChanged.emit() @pyqtSlot(str) def install(self, file_path: str) -> None: self._package_manager.installPackage(file_path) self.installChanged.emit() self._updateInstalledModels() self.metadataChanged.emit() self._restart_required = True self.restartRequiredChanged.emit() @pyqtSlot(str) def uninstall(self, plugin_id: str) -> None: self._package_manager.removePackage(plugin_id) self.installChanged.emit() self._updateInstalledModels() self.metadataChanged.emit() self._restart_required = True self.restartRequiredChanged.emit() @pyqtSlot(str) def enable(self, plugin_id: str) -> None: self._plugin_registry.enablePlugin(plugin_id) self.enabledChanged.emit() Logger.log("i", "%s was set as 'active'.", plugin_id) self._restart_required = True self.restartRequiredChanged.emit() @pyqtSlot(str) def disable(self, plugin_id: str) -> None: self._plugin_registry.disablePlugin(plugin_id) self.enabledChanged.emit() Logger.log("i", "%s was set as 'deactive'.", plugin_id) self._restart_required = True self.restartRequiredChanged.emit() @pyqtProperty(bool, notify = metadataChanged) def dataReady(self) -> bool: return self._packages_model is not None @pyqtProperty(bool, notify = restartRequiredChanged) def restartRequired(self) -> bool: return self._restart_required @pyqtSlot() def restart(self): self._package_manager._removeAllScheduledPackages() CuraApplication.getInstance().windowClosed() # Checks # -------------------------------------------------------------------------- @pyqtSlot(str, result = bool) def canUpdate(self, package_id: str) -> bool: local_package = self._package_manager.getInstalledPackageInfo(package_id) if local_package is None: return False remote_package = None for package in self._metadata["packages"]: if package["package_id"] == package_id: remote_package = package if remote_package is None: return False local_version = local_package["package_version"] remote_version = remote_package["package_version"] return Version(remote_version) > Version(local_version) @pyqtSlot(str, result = bool) def isInstalled(self, package_id: str) -> bool: return self._package_manager.isPackageInstalled(package_id) @pyqtSlot(str, result = bool) def isEnabled(self, package_id: str) -> bool: if package_id in self._plugin_registry.getActivePlugins(): return True return False def loadingComplete(self) -> bool: populated = 0 for list in self._metadata.items(): if len(list) > 0: populated += 1 if populated == len(self._metadata.items()): return True return False # Make API Calls # -------------------------------------------------------------------------- def _makeRequestByType(self, type: str) -> None: Logger.log("i", "Toolbox: Requesting %s metadata from server.", type) request = QNetworkRequest(self._request_urls[type]) request.setRawHeader(*self._request_header) self._network_manager.get(request) @pyqtSlot(str) def startDownload(self, url: str) -> None: Logger.log("i", "Toolbox: Attempting to download & install package from %s.", url) url = QUrl(url) self._download_request = QNetworkRequest(url) if hasattr(QNetworkRequest, "FollowRedirectsAttribute"): # Patch for Qt 5.6-5.8 self._download_request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) if hasattr(QNetworkRequest, "RedirectPolicyAttribute"): # Patch for Qt 5.9+ self._download_request.setAttribute(QNetworkRequest.RedirectPolicyAttribute, True) self._download_request.setRawHeader(*self._request_header) self._download_reply = self._network_manager.get(self._download_request) self.setDownloadProgress(0) self.setIsDownloading(True) self._download_reply.downloadProgress.connect(self._onDownloadProgress) @pyqtSlot() def cancelDownload(self) -> None: Logger.log("i", "Toolbox: User cancelled the download of a plugin.") self.resetDownload() def resetDownload(self) -> None: if self._download_reply: self._download_reply.abort() self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) self._download_reply = None self._download_request = None self.setDownloadProgress(0) self.setIsDownloading(False) # Handlers for Network Events # -------------------------------------------------------------------------- def _onNetworkAccessibleChanged(self, accessible: int) -> None: if accessible == 0: self.resetDownload() def _onRequestFinished(self, reply: QNetworkReply) -> None: if reply.error() == QNetworkReply.TimeoutError: Logger.log("w", "Got a timeout.") self.setViewPage("errored") self.resetDownload() return if reply.error() == QNetworkReply.HostNotFoundError: Logger.log("w", "Unable to reach server.") self.setViewPage("errored") self.resetDownload() return if reply.operation() == QNetworkAccessManager.GetOperation: for type, url in self._request_urls.items(): if reply.url() == url: try: json_data = json.loads(bytes(reply.readAll()).decode("utf-8")) # Check for errors: if "errors" in json_data: for error in json_data["errors"]: Logger.log("e", "%s", error["title"]) return # Create model and apply metadata: if not self._models[type]: Logger.log("e", "Could not find the %s model.", type) break # HACK: Eventually get rid of the code from here... if type is "plugins_showcase" or type is "materials_showcase": self._metadata["plugins_showcase"] = json_data["data"]["plugin"]["packages"] self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"]) self._metadata["materials_showcase"] = json_data["data"]["material"]["authors"] self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"]) else: # ...until here. # This hack arises for multiple reasons but the main # one is because there are not separate API calls # for different kinds of showcases. self._metadata[type] = json_data["data"] self._models[type].setMetadata(self._metadata[type]) # Do some auto filtering # TODO: Make multiple API calls in the future to handle this if type is "packages": self._models[type].setFilter({"type": "plugin"}) if type is "authors": self._models[type].setFilter({"package_types": "material"}) self.metadataChanged.emit() if self.loadingComplete() is True: self.setViewPage("overview") return except json.decoder.JSONDecodeError: Logger.log("w", "Toolbox: Received invalid JSON for %s.", type) break else: # Ignore any operation that is not a get operation pass def _onDownloadProgress(self, bytes_sent: int, bytes_total: int) -> None: if bytes_total > 0: new_progress = bytes_sent / bytes_total * 100 self.setDownloadProgress(new_progress) if bytes_sent == bytes_total: self.setIsDownloading(False) self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) # Must not delete the temporary file on Windows self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curapackage", delete = False) file_path = self._temp_plugin_file.name # Write first and close, otherwise on Windows, it cannot read the file self._temp_plugin_file.write(self._download_reply.readAll()) self._temp_plugin_file.close() self._onDownloadComplete(file_path) def _onDownloadComplete(self, file_path: str): Logger.log("i", "Toolbox: Download complete.") package_info = self._package_manager.getPackageInfo(file_path) if not package_info: Logger.log("w", "Toolbox: Package file [%s] was not a valid CuraPackage.", file_path) return license_content = self._package_manager.getPackageLicense(file_path) if license_content is not None: self.openLicenseDialog(package_info["package_id"], license_content, file_path) return self.install(file_path) return # Getter & Setters for Properties: # -------------------------------------------------------------------------- def setDownloadProgress(self, progress: Union[int, float]) -> None: if progress != self._download_progress: self._download_progress = progress self.onDownloadProgressChanged.emit() @pyqtProperty(int, fset = setDownloadProgress, notify = onDownloadProgressChanged) def downloadProgress(self) -> int: return self._download_progress def setIsDownloading(self, is_downloading: bool) -> None: if self._is_downloading != is_downloading: self._is_downloading = is_downloading self.onIsDownloadingChanged.emit() @pyqtProperty(bool, fset = setIsDownloading, notify = onIsDownloadingChanged) def isDownloading(self) -> bool: return self._is_downloading def setActivePackage(self, package: Dict[str, Any]) -> None: self._active_package = package self.activePackageChanged.emit() @pyqtProperty(QObject, fset = setActivePackage, notify = activePackageChanged) def activePackage(self) -> Optional[Dict[str, Any]]: return self._active_package def setViewCategory(self, category: str = "plugin") -> None: self._view_category = category self.viewChanged.emit() @pyqtProperty(str, fset = setViewCategory, notify = viewChanged) def viewCategory(self) -> str: return self._view_category def setViewPage(self, page: str = "overview") -> None: self._view_page = page self.viewChanged.emit() @pyqtProperty(str, fset = setViewPage, notify = viewChanged) def viewPage(self) -> str: return self._view_page # Expose Models: # -------------------------------------------------------------------------- @pyqtProperty(QObject, notify = metadataChanged) def authorsModel(self) -> AuthorsModel: return self._models["authors"] @pyqtProperty(QObject, notify = metadataChanged) def packagesModel(self) -> PackagesModel: return self._models["packages"] @pyqtProperty(QObject, notify = metadataChanged) def pluginsShowcaseModel(self) -> PackagesModel: return self._models["plugins_showcase"] @pyqtProperty(QObject, notify = metadataChanged) def pluginsInstalledModel(self) -> PackagesModel: return self._models["plugins_installed"] @pyqtProperty(QObject, notify = metadataChanged) def materialsShowcaseModel(self) -> PackagesModel: return self._models["materials_showcase"] @pyqtProperty(QObject, notify = metadataChanged) def materialsInstalledModel(self) -> PackagesModel: return self._models["materials_installed"] # Filter Models: # -------------------------------------------------------------------------- @pyqtSlot(str, str, str) def filterModelByProp(self, modelType: str, filterType: str, parameter: str): if not self._models[modelType]: Logger.log("w", "Toolbox: Couldn't filter %s model because it doesn't exist.", modelType) return self._models[modelType].setFilter({ filterType: parameter }) self.filterChanged.emit() @pyqtSlot() def removeFilters(self, modelType: str): if not self._models[modelType]: Logger.log("w", "Toolbox: Couldn't remove filters on %s model because it doesn't exist.", modelType) return self._models[modelType].setFilter({}) self.filterChanged.emit()
class ProcessDialog(QDialog): def __init__(self, port, **kwargs): super().__init__() self.setWindowTitle('Cooking your TinyGS station...') self.setFixedWidth(400) self.exception = None esptool.sw.progress.connect(self.update_progress) self.nam = QNetworkAccessManager() self.nrBinFile = QNetworkRequest() self.bin_data = b'' self.setLayout(VLayout(5, 5)) self.actions_layout = QFormLayout() self.actions_layout.setSpacing(5) self.layout().addLayout(self.actions_layout) self._actions = [] self._action_widgets = {} self.port = port self.auto_reset = kwargs.get('auto_reset', False) self.file_path = kwargs.get('file_path') if self.file_path and self.file_path.startswith('http'): self._actions.append('download') self.backup = kwargs.get('backup') if self.backup: self._actions.append('backup') self.backup_size = kwargs.get('backup_size') self.erase = kwargs.get('erase') if self.erase: self._actions.append('erase') if self.file_path: self._actions.append('write') self.create_ui() self.start_process() def create_ui(self): for action in self._actions: pb = QProgressBar() pb.setFixedHeight(35) self._action_widgets[action] = pb self.actions_layout.addRow(action.capitalize(), pb) self.btns = QDialogButtonBox(QDialogButtonBox.Abort) self.btns.rejected.connect(self.abort) self.layout().addWidget(self.btns) self.sb = QStatusBar() self.layout().addWidget(self.sb) def appendBinFile(self): self.bin_data += self.bin_reply.readAll() def saveBinFile(self): if self.bin_reply.error() == QNetworkReply.NoError: self.file_path = self.file_path.split('/')[-1] with open(self.file_path, 'wb') as f: f.write(self.bin_data) self.run_esp() else: raise NetworkError def updateBinProgress(self, recv, total): self._action_widgets['download'].setValue(recv // total * 100) def download_bin(self): self.nrBinFile.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nrBinFile.setUrl(QUrl(self.file_path)) self.bin_reply = self.nam.get(self.nrBinFile) self.bin_reply.readyRead.connect(self.appendBinFile) self.bin_reply.downloadProgress.connect(self.updateBinProgress) self.bin_reply.finished.connect(self.saveBinFile) def show_connection_state(self, state): self.sb.showMessage(state, 0) def run_esp(self): params = { 'file_path': self.file_path, 'auto_reset': self.auto_reset, 'erase': self.erase } if self.backup: backup_size = f'0x{2 ** self.backup_size}00000' params['backup_size'] = backup_size self.esp_thread = QThread() self.esp = ESPWorker(self.port, self._actions, **params) esptool.sw.connection_state.connect(self.show_connection_state) self.esp.waiting.connect(self.wait_for_user) self.esp.done.connect(self.accept) self.esp.error.connect(self.error) self.esp.moveToThread(self.esp_thread) self.esp_thread.started.connect(self.esp.run) self.esp_thread.start() def start_process(self): if 'download' in self._actions: self.download_bin() self._actions = self._actions[1:] else: self.run_esp() def update_progress(self, action, value): self._action_widgets[action].setValue(value) @pyqtSlot() def wait_for_user(self): dlg = QMessageBox.information( self, 'User action required', 'Please power cycle the device, wait a moment and press OK', QMessageBox.Ok | QMessageBox.Cancel) if dlg == QMessageBox.Ok: self.esp.continue_ok() elif dlg == QMessageBox.Cancel: self.esp.abort() self.esp.continue_ok() self.abort() def stop_thread(self): self.esp_thread.wait(2000) self.esp_thread.exit() def accept(self): self.stop_thread() self.done(QDialog.Accepted) def abort(self): self.sb.showMessage('Aborting...', 0) QApplication.processEvents() self.esp.abort() self.stop_thread() self.reject() def error(self, e): self.exception = e self.abort() def closeEvent(self, e): self.stop_thread()
class ProcessDialog(QDialog): def __init__(self, port, **kwargs): super().__init__() self.setWindowTitle('Preparando seu Satélite Educacional...') self.setFixedWidth(600) self.exception = None esptool.sw.progress.connect(self.update_progress) self.nam = QNetworkAccessManager() self.nrDownloads = 0 self.nrBinFile1 = QNetworkRequest() self.bin_data1 = b'' self.nrBinFile2 = QNetworkRequest() self.bin_data2 = b'' self.nrBinFile3 = QNetworkRequest() self.bin_data3 = b'' self.nrBinFile4 = QNetworkRequest() self.bin_data4 = b'' self.setLayout(VLayout(5, 5)) self.actions_layout = QFormLayout() self.actions_layout.setSpacing(5) self.layout().addLayout(self.actions_layout) self._actions = [] self._action_widgets = {} self.port = port self.file_path = kwargs.get('file_url') self.file_pathBoot = kwargs.get('file_urlBoot') self.file_pathBootloader = kwargs.get('file_urlBootloader') self.file_pathPart = kwargs.get('file_urlPart') self._actions.append('download') self.erase = kwargs.get('erase') if self.erase: self._actions.append('erase') if self.file_path: self._actions.append('write') self.create_ui() self.start_process() def create_ui(self): for action in self._actions: pb = QProgressBar() pb.setFixedHeight(35) self._action_widgets[action] = pb self.actions_layout.addRow(action.capitalize(), pb) self.btns = QDialogButtonBox(QDialogButtonBox.Abort) self.btns.rejected.connect(self.abort) self.layout().addWidget(self.btns) self.sb = QStatusBar() self.layout().addWidget(self.sb) def appendBinFile1(self): self.bin_data1 += self.bin_reply1.readAll() def appendBinFile2(self): self.bin_data2 += self.bin_reply2.readAll() def appendBinFile3(self): self.bin_data3 += self.bin_reply3.readAll() def appendBinFile4(self): self.bin_data4 += self.bin_reply4.readAll() def downloadsFinished(self): if self.nrDownloads == 4: self.run_esp() def saveBinFile1(self): if self.bin_reply1.error() == QNetworkReply.NoError: self.file_path = self.file_path.split('/')[-1] with open(self.file_path, 'wb') as f: f.write(self.bin_data1) self.nrDownloads += 1 self.downloadsFinished() else: raise NetworkError def saveBinFile2(self): if self.bin_reply2.error() == QNetworkReply.NoError: self.file_pathBoot = self.file_pathBoot.split('/')[-1] with open(self.file_pathBoot, 'wb') as f: f.write(self.bin_data2) self.nrDownloads += 1 self.downloadsFinished() else: raise NetworkError def saveBinFile3(self): if self.bin_reply3.error() == QNetworkReply.NoError: self.file_pathBootloader = self.file_pathBootloader.split('/')[-1] with open(self.file_pathBootloader, 'wb') as f: f.write(self.bin_data3) self.nrDownloads += 1 self.downloadsFinished() else: raise NetworkError def saveBinFile4(self): if self.bin_reply4.error() == QNetworkReply.NoError: self.file_pathPart = self.file_pathPart.split('/')[-1] with open(self.file_pathPart, 'wb') as f: f.write(self.bin_data4) self.nrDownloads += 1 self.downloadsFinished() else: raise NetworkError def updateBinProgress(self, recv, total): self._action_widgets['download'].setValue(recv // total * 100) def download_bin(self): self.nrBinFile1.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nrBinFile1.setUrl(QUrl(self.file_path)) self.bin_reply1 = self.nam.get(self.nrBinFile1) self.bin_reply1.readyRead.connect(self.appendBinFile1) self.bin_reply1.downloadProgress.connect(self.updateBinProgress) self.bin_reply1.finished.connect(self.saveBinFile1) self.nrBinFile2.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nrBinFile2.setUrl(QUrl(self.file_pathBoot)) self.bin_reply2 = self.nam.get(self.nrBinFile2) self.bin_reply2.readyRead.connect(self.appendBinFile2) self.bin_reply2.finished.connect(self.saveBinFile2) self.nrBinFile3.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nrBinFile3.setUrl(QUrl(self.file_pathBootloader)) self.bin_reply3 = self.nam.get(self.nrBinFile3) self.bin_reply3.readyRead.connect(self.appendBinFile3) self.bin_reply3.finished.connect(self.saveBinFile3) self.nrBinFile4.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) self.nrBinFile4.setUrl(QUrl(self.file_pathPart)) self.bin_reply4 = self.nam.get(self.nrBinFile4) self.bin_reply4.readyRead.connect(self.appendBinFile4) self.bin_reply4.finished.connect(self.saveBinFile4) def show_connection_state(self, state): self.sb.showMessage(state, 0) def run_esp(self): params = { 'file_path': self.file_path, 'file_pathBoot': self.file_pathBoot, 'file_pathBootloader': self.file_pathBootloader, 'file_pathPart': self.file_pathPart, 'erase': self.erase } self.esp_thread = QThread() self.esp = ESPWorker(self.port, self._actions, **params) esptool.sw.connection_state.connect(self.show_connection_state) self.esp.done.connect(self.accept) self.esp.error.connect(self.error) self.esp.moveToThread(self.esp_thread) self.esp_thread.started.connect(self.esp.run) self.esp_thread.start() def start_process(self): if 'download' in self._actions: self.download_bin() self._actions = self._actions[1:] else: self.run_esp() def update_progress(self, action, value): self._action_widgets[action].setValue(value) @pyqtSlot() def stop_thread(self): self.esp_thread.wait(2000) self.esp_thread.exit() def accept(self): self.stop_thread() self.done(QDialog.Accepted) def abort(self): self.sb.showMessage('Aborting...', 0) QApplication.processEvents() self.esp.abort() self.stop_thread() self.reject() def error(self, e): self.exception = e self.abort() def closeEvent(self, e): self.stop_thread()
def createRequest(self, op, request, outgoingData=None): """ Public method to create a request. @param op the operation to be performed (QNetworkAccessManager.Operation) @param request reference to the request object (QNetworkRequest) @param outgoingData reference to an IODevice containing data to be sent (QIODevice) @return reference to the created reply object (QNetworkReply) """ scheme = request.url().scheme() if scheme == "https" and \ (not SSL_AVAILABLE or not QSslSocket.supportsSsl()): from .NetworkProtocolUnknownErrorReply import \ NetworkProtocolUnknownErrorReply return NetworkProtocolUnknownErrorReply(scheme, self) import Helpviewer.HelpWindow if op == QNetworkAccessManager.PostOperation and \ outgoingData is not None: outgoingDataByteArray = outgoingData.peek(1024 * 1024) Helpviewer.HelpWindow.HelpWindow.passwordManager().post( request, outgoingDataByteArray) reply = None if scheme in self.__schemeHandlers: reply = self.__schemeHandlers[scheme]\ .createRequest(op, request, outgoingData) if reply is not None: return reply # give GreaseMonkey the chance to create a request reply = Helpviewer.HelpWindow.HelpWindow.greaseMonkeyManager()\ .createRequest(op, request, outgoingData) if reply is not None: return reply req = QNetworkRequest(request) if req.rawHeader(b"X-Eric6-UserLoadAction") == QByteArray(b"1"): req.setRawHeader(b"X-Eric6-UserLoadAction", QByteArray()) req.setAttribute(QNetworkRequest.User + 200, "") else: req.setAttribute(QNetworkRequest.User + 200, req.rawHeader(b"Referer")) if hasattr(QNetworkRequest, 'HttpPipeliningAllowedAttribute'): req.setAttribute(QNetworkRequest.HttpPipeliningAllowedAttribute, True) if not self.__acceptLanguage.isEmpty(): req.setRawHeader(b"Accept-Language", self.__acceptLanguage) # AdBlock code if op == QNetworkAccessManager.GetOperation: if self.__adblockNetwork is None: self.__adblockNetwork = \ Helpviewer.HelpWindow.HelpWindow.adBlockManager().network() reply = self.__adblockNetwork.block(req) if reply is not None: reply.setParent(self) return reply # set cache policy if op == QNetworkAccessManager.GetOperation: urlHost = req.url().host() for host in Preferences.getHelp("NoCacheHosts"): if host in urlHost: req.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) break else: req.setAttribute(QNetworkRequest.CacheLoadControlAttribute, Preferences.getHelp("CachePolicy")) else: req.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) # Do Not Track feature if self.__doNotTrack: req.setRawHeader(b"DNT", b"1") req.setRawHeader(b"X-Do-Not-Track", b"1") # Send referer header? if not self.__sendReferer and \ req.url().host() not in Preferences.getHelp("SendRefererWhitelist"): req.setRawHeader(b"Referer", b"") reply = QNetworkAccessManager.createRequest(self, op, req, outgoingData) self.requestCreated.emit(op, req, reply) return reply
def GM_xmlhttpRequest(self, details): # we could actually mock a XMLHttpRequest to support progress # signals but who really uses them? # https://wiki.greasespot.net/GM_xmlhttpRequest # qtwebchannel.js calls JSON.stringify in QWebChannel.send() so any # method attributes of arguments (eg {'onload':function(...){...;}) are # stripped. # * handle method, url, headers, data # * figure out what headers we need to automatically set (referer, ...) # * can we use some qt thing (page.get()?) to do ^ # * should probably check how cookies are handled # chrome/tampermonkey sends cookies (for the requested domain, # duh) with GM_xhr requests # https://openuserjs.org/ # https://greasyfork.org/en/scripts # tampermoney on chrome prompts when a script tries to do a # cross-origin request. print("==============================================") print("GM_xmlhttpRequest") print(details) if not 'url' in details: return request_index = details['_qute_gm_request_index'] if not request_index: log.greasemonkey.error(("GM_xmlhttpRequest received request " "without nonce, skipping.")) return if objreg.get('host-blocker').is_blocked(QUrl(details['url'])): return # TODO: url might be relative, need to fix on the JS side. request = QNetworkRequest(QUrl(details['url'])) request.setOriginatingObject(self) # The C++ docs say the default is to not follow any redirects. request.setAttribute(QNetworkRequest.RedirectionTargetAttribute, QNetworkRequest.NoLessSafeRedirectPolicy) # TODO: Ensure these headers are encoded to spec if containing eg # unicodes if 'headers' in details: for k, v in details['headers'].items(): # With this script: https://raw.githubusercontent.com/evazion/translate-pixiv-tags/master/translate-pixiv-tags.user.js # One of the headers it 'X-Twitter-Polling': True, which was # causing the below to error out because v is a bool. Not sure # where that is coming from or what value twitter expects. # That script is patching jquery so try with unpatched jquery # and see what it does. request.setRawHeader(k.encode('ascii'), str(v).encode('ascii')) # TODO: Should we allow xhr to set user-agent? if not request.header(QNetworkRequest.UserAgentHeader): request.setHeader(QNetworkRequest.UserAgentHeader, self.profile.httpUserAgent()) payload = details.get('data', None) if payload: # Should check encoding from content-type header? payload = payload.encode('utf-8') reply = self.nam.sendCustomRequest( request, details.get('method', 'GET').encode('ascii'), payload) if reply.isFinished(): self.handle_xhr_reply(reply, request_index) else: reply.finished.connect( functools.partial(self.handle_xhr_reply, reply, request_index))
def execute_request(self, url, **kwargs): """ Uses QgsNetworkAccessManager and QgsAuthManager. """ method = kwargs.get('http_method', 'get') headers = kwargs.get('headers', {}) # This fixes a weird 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[b'Accept-Encoding'] except KeyError as ke: # only debugging here as after 1st remove it isn't there anymore self.util.msg_log_debug( u'unexpected error deleting request header: {}'.format(ke)) pass # Avoid double quoting form QUrl url = unquote(url) self.util.msg_log_debug(u'http_call request: {} {}'.format( method, url)) class Response: status_code = 200 status_message = 'OK' text = '' ok = True headers = {} reason = '' exception = None def iter_content(self, _): return [self.text] self.http_call_result = Response() url = self.util.remove_newline(url) req = QNetworkRequest() req.setUrl(QUrl(url)) req.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True) for k, v in headers.items(): self.util.msg_log_debug("%s: %s" % (k, v)) try: req.setRawHeader(k, v) except: self.util.msg_log_error( u'FAILED to set header: {} => {}'.format(k, v)) self.util.msg_log_last_exception() if self.settings.authcfg: self.util.msg_log_debug(u'before updateNetworkRequest') QgsApplication.authManager().updateNetworkRequest( req, self.settings.authcfg) self.util.msg_log_debug(u'before updateNetworkRequest') if self.reply is not None and self.reply.isRunning(): self.reply.close() self.util.msg_log_debug(u'getting QgsNetworkAccessManager.instance()') #func = getattr(QgsNetworkAccessManager.instance(), method) #func = QgsNetworkAccessManager().get(req) #manager = QNetworkAccessManager() #event = QEventLoop() #response = manager.get(QNetworkRequest(QUrl(url))) #response.downloadProgress.connect(self.download_progress) #response.finished.connect(event.quit) #event.exec() #response_msg = response.readAll() ##response_msg = str(response_msg) #response_msg = str(response_msg, encoding='utf-8') ##response_msg = response_msg.decode('utf-8') #response.deleteLater() #self.util.msg_log_debug(u'response message:\n{} ...'.format(response_msg[:255])) #self.http_call_result.text = response_msg # in Python3 all strings are unicode, so QString is not defined #return self.http_call_result # Calling the server ... self.util.msg_log_debug('before self.reply = func(req)') #self.reply = func(req) #self.reply = QgsNetworkAccessManager.instance().get(req) method_call = getattr(QgsNetworkAccessManager.instance(), method) self.reply = method_call(req) #self.reply.setReadBufferSize(1024*1024*1024) #self.reply.setReadBufferSize(1024 * 1024 * 1024 * 1024) self.reply.setReadBufferSize(0) self.util.msg_log_debug('after self.reply = func(req)') # Let's log the whole call for debugging purposes: if self.settings.debug: self.util.msg_log_debug("\nSending %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(): try: self.util.msg_log_debug("%s: %s" % (k, v)) except: self.util.msg_log_debug('error logging headers') if self.settings.authcfg: self.util.msg_log_debug("update reply w/ authcfg: {0}".format( self.settings.authcfg)) QgsApplication.authManager().updateNetworkReply( self.reply, self.settings.authcfg) self.util.msg_log_debug('before connecting to events') # connect downloadProgress event try: self.reply.downloadProgress.connect(self.download_progress) #pass except: self.util.msg_log_error( 'error connecting "downloadProgress" event') self.util.msg_log_last_exception() # connect reply finished event try: self.reply.finished.connect(self.reply_finished) #pass except: self.util.msg_log_error( 'error connecting reply "finished" progress event') self.util.msg_log_last_exception() self.util.msg_log_debug('after connecting to events') # Call and block self.event_loop = QEventLoop() try: self.reply.finished.connect(self.event_loop.quit) except: self.util.msg_log_error( 'error connecting reply "finished" progress event to event loop quit' ) self.util.msg_log_last_exception() self.mb_downloaded = 0 # Catch all exceptions (and clean up requests) self.event_loop.exec() # Let's log the whole response for debugging purposes: if self.settings.debug: self.util.msg_log_debug( u'\nGot response [{}/{}] ({} bytes) from:\n{}\nexception:{}'. format(self.http_call_result.status_code, self.http_call_result.status_message, len(self.http_call_result.text), self.reply.url().toString(), self.http_call_result.exception)) headers = { str(h): str(self.reply.rawHeader(h)) for h in self.reply.rawHeaderList() } for k, v in headers.items(): self.util.msg_log_debug("%s: %s" % (k, v)) self.util.msg_log_debug("Payload :\n%s ......" % self.http_call_result.text[:255]) self.reply.close() self.util.msg_log_debug("Deleting reply ...") try: self.reply.deleteLater() except: self.util.msg_log_error('unexpected error deleting QNetworkReply') self.util.msg_log_last_exception() self.reply = None if self.http_call_result.exception is not None: self.util.msg_log_error('http_call_result.exception is not None') self.http_call_result.ok = False # raise self.http_call_result.exception return self.http_call_result