def setView(self, view, inspectElement=False): """ Public method to connect a view to this inspector. @param view reference to the view object @type WebBrowserView @param inspectElement flag indicating to start a web inspection @type bool """ self.__view = view if not self.isEnabled(): return self.__inspectElement = inspectElement try: self.page().setInspectedPage(self.__view.page()) except AttributeError: # pre Qt 5.11 port = Preferences.getWebBrowser("WebInspectorPort") inspectorUrl = QUrl("http://localhost:{0}".format(port)) from WebBrowser.WebBrowserWindow import WebBrowserWindow self.__reply = WebBrowserWindow.networkManager().get( QNetworkRequest(inspectorUrl.resolved(QUrl("json/list")))) self.__reply.finished.connect(self.__inspectorReplyFinished)
def resolve_url(self, baseurl: QUrl) -> typing.Optional[QUrl]: """Resolve the URL in the element's src/href attribute. Args: baseurl: The URL to base relative URLs on as QUrl. Return: A QUrl with the absolute URL, or None. """ if baseurl.isRelative(): raise ValueError("Need an absolute base URL!") for attr in ['href', 'src']: if attr in self: text = self[attr].strip() break else: return None url = QUrl(text) if not url.isValid(): return None if url.isRelative(): url = baseurl.resolved(url) qtutils.ensure_valid(url) return url
def __inspectorReplyFinished(self): """ Private slot handling the reply. """ # used for pre Qt 5.11 result = str(self.__reply.readAll(), encoding="utf8") self.__reply.deleteLater() self.__reply = None pageUrl = QUrl() try: index = _VIEWS.index(self.__view) except ValueError: index = -1 try: clients = json.loads(result) if len(clients) > index: port = Preferences.getWebBrowser("WebInspectorPort") inspectorUrl = QUrl("http://localhost:{0}".format(port)) client = clients[index] pageUrl = inspectorUrl.resolved( QUrl(client["devtoolsFrontendUrl"])) self.load(pageUrl) pushView(self) self.show() except json.JSONDecodeError: # ignore silently pass
class HttpWindow(QMainWindow): def __init__(self, parent=None): super(HttpWindow, self).__init__(parent) self.title = "OraDocs by littleT" self.left = 10 self.top = 10 self.width = 600 self.height = 400 self.docRoot = "https://oradocs-corp.documents.us2.oraclecloud.com/documents/" self.url = QUrl() self.qnam = QNetworkAccessManager() self.reply = None self.outFile = None self.httpGetId = 0 self.httpRequestAborted = False self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.statusBar().showMessage('Starting ...') # for the menu first create some actions to be added like # File - Exit action exitAction = QAction(QIcon('exit24.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit Application') exitAction.triggered.connect(self.close) # File - open openAction = QAction(QIcon(''), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Opens a file') openAction.triggered.connect(self.openCall) # the help actions helpAction = QAction(QIcon(''), 'Help', self) helpAction.triggered.connect(self.openHelp) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(exitAction) helpMenu = mainMenu.addMenu('&Help') helpMenu.addAction(helpAction) self.urlLineEdit = QLineEdit(self) self.urlLineEdit.setGeometry(5, 250, 590, 20) self.urlLineEdit.setText(self.docRoot) self.downloadButton = QPushButton('Click Me', self) self.downloadButton.move(10, 275) self.downloadButton.clicked.connect(self.onDownloadClick) self.quitButton = QPushButton("Quit", self) self.quitButton.setAutoDefault(False) self.quitButton.clicked.connect(self.close) self.quitButton.move(120, 275) self.logOutput = QTextEdit(self) self.logOutput.setReadOnly(True) # self.logOutput.setLineWrapMode(QTextEdit.NoWrap) self.logOutput.setGeometry(5, 320, 590, 60) self.logOutput.setSizePolicy(self.sizePolicy) self.statusBar().showMessage('waiting for click ...') def openCall(self): QMessageBox.information(self, "Info", "File Open Menu, work in progress") def openHelp(self): QMessageBox.information(self, "Info", "Help Menu, work in progress") def onDownloadClick(self): self.url = QUrl(self.docRoot) self.logOutput.insertPlainText("onclick before startReq -> url %s\n" % self.url.toString()) # start the request self.startRequest(self.url) self.logOutput.insertPlainText("onclick after startReq -> url %s\n" % self.url.toString()) # do we need authorization self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) # do we go ssl errors self.qnam.sslErrors.connect(self.sslErrors) def httpFinished(self): self.logOutput.insertPlainText("httpFinished ...\n") self.logOutput.moveCursor(QTextCursor.End) if self.httpRequestAborted: # if self.outFile is not None: # self.outFile.close() # self.outFile.remove() # self.outFile = None self.logOutput.insertPlainText("httpFinished, httpReqAbr ...\n") self.logOutput.moveCursor(QTextCursor.End) self.reply.deleteLater() # self.outFile.flush() # self.outFile.close() return # maybe updating progress or so # self.progressDialog.hide() # self.outFile.flush() # self.outFile.close() # check for redirection redirectionTarget = self.reply.attribute( QNetworkRequest.RedirectionTargetAttribute) if self.reply.error(): # are we got an error # self.outFile.remove() QMessageBox.information(self, "HTTP", "Download failed %s" % self.reply.errorString) elif redirectionTarget is not None: # self.logOutput.insertPlainText("httpFinished, redirect from %s\n" # % str(self.url)) self.logOutput.moveCursor(QTextCursor.End) # do we got redirected newUrl = self.url.resolved(redirectionTarget) self.logOutput.insertPlainText("httpFinished, redirect \n") # % newUrl.toString()) self.logOutput.moveCursor(QTextCursor.End) #ret = QMessageBox.question(self, "HTTP", "Redirect to %s." % # newUrl.toString(), # QMessageBox.Yes | QMessageBox.No) #if ret == QMessageBox.Yes: # # if we saied yes to redirect set the new URL to redirected one # self.url = newUrl # # the reply needs to be nothing # self.reply = None # # self.outFile.open(QIODevice.WriteOnly) # # self.outFile.resize(0) # # and start over # self.startRequest(self.url) # return # the new url is the redirected one self.url = newUrl # the reply needs to be nothing self.reply = None # and start over self.startRequest(self.url) return else: # fileName = QFileInfo(QUrl(self.urlLineEdit.text()).path()).fileName() # self.statusLabel.setText("Downloaded %s to %s." % (fileName, QDir.currentPath())) # self.statusLabel.setText("Done") self.statusBar().showMessage("Done") self.reply.deleteLater() self.reply = None # self.outFile = None def startRequest(self, url): self.logOutput.insertPlainText("startRequest ...\n") self.logOutput.moveCursor(QTextCursor.End) # get the requested page self.reply = self.qnam.get(QNetworkRequest(url)) # if we are finished self.reply.finished.connect(self.httpFinished) # are we ready to read the stuff # self.reply.readyRead.connect(self.httpReadyRead) # downloading # self.reply.downloadProgress.connect(self.updateDataReadProgress) def slotAuthenticationRequired(self, authenticator): import os from PyQt5 import uic self.logOutput.insertPlainText("Authentication ...\n") self.logOutput.moveCursor(QTextCursor.End) self.logOutput.moveCursor(QTextCursor.End) self.logOutput.insertPlainText(str(authenticator)) ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') self.logOutput.moveCursor(QTextCursor.End) self.logOutput.insertPlainText(str(ui)) dlg = uic.loadUi(ui) dlg.adjustSize() dlg.siteDescription.setText("%s at %s" % (authenticator.realm(), self.url.host())) dlg.userEdit.setText(self.url.userName()) dlg.passwordEdit.setText(self.url.password()) if dlg.exec_() == QDialog.Accepted: authenticator.setUser(dlg.userEdit.text()) authenticator.setPassword(dlg.passwordEdit.text()) def sslErrors(self, reply, errors): errorString = ", ".join([str(error.errorString()) for error in errors]) ret = QMessageBox.warning(self, "HTTP Example", "One or more SSL errors has occurred: %s" % errorString, QMessageBox.Ignore | QMessageBox.Abort) if ret == QMessageBox.Ignore: self.reply.ignoreSslErrors()
if context.file is None: print('{mode}: {msg}'.format(mode=mode, msg=message)) else: print('{mode}: {msg}\t\t\t\tline: {line}, function: {func}, file: {file}'.format( mode=mode, line=context.line, func=context.function, file=context.file, msg=message)) qInstallMessageHandler(qt_message_handler) app = QApplication(sys.argv) base_url = QUrl("{}{}/".format(FILE_PREFIX[system()], str(path.abspath(path.dirname(__file__))).replace('\\', '/'))) icon = QIcon() for size in ICON_SIZES: path = FileIO.removeFilePrefix(base_url.resolved(QUrl("assets/icons/{}x{}.png".format(size, size))).url()) icon.addFile(path, QSize(size, size)) app.setWindowIcon(icon) qmlRegisterSingletonType(base_url.resolved(QUrl("assets/styles/UIStyles.qml")), "StyleSettings", 1, 0, "StyleSettings") qmlRegisterSingletonType(CodeAnalyzer, "CodeAnalyzer", 1, 0, "CodeAnalyzer", CodeAnalyzer.singletonProvider) qmlRegisterType(ExpSyntaxHighlighter, "ExpSyntaxHighlighter", 1, 0, "ExpSyntaxHighlighter") qmlRegisterType(DiffCodeAnalyzer, "DiffCodeAnalyzer", 1, 0, "DiffCodeAnalyzer") qmlRegisterType(ExpAnalyzer, "ExpAnalyzer", 1, 0, "ExpAnalyzer") qmlRegisterType(TreeViewModel, "TreeViewModel", 1, 0, "TreeViewModel") qmlRegisterType(DebuggerWrapper, "Debugger", 1, 0, "Debugger") qmlRegisterType(IOWrapper, "IOWrapper", 1, 0, "IOWrapper") qmlRegisterType(FileIO, "FileIO", 1, 0, "FileIO") qmlRegisterType(FormattedTextWriter, "FormattedTextWriter", 1, 0, "FormattedTextWriter") core = Core()
class Hrobot(QObject): asyncFinished = pyqtSignal() def __init__(self, base_url=None, private=True, profile_name=None, gui=False): super().__init__() self.base_url = QUrl(base_url) self.__interceptor = Interceptor(self) if private: self.__profile = QWebEngineProfile() elif profile_name: self.__profile = QWebEngineProfile(profile_name) else: raise Exception( 'please pass `profile_name` in case of `private` flag set to False' ) self.__profile.setRequestInterceptor(self.__interceptor) self.__page = Page(self.__profile, None) self.__cookie_store = self.__profile.cookieStore() self.__cookie_store.cookieAdded.connect(self.__on_cookie_added) self.__cookies = [] self.__async_result = None self.__loading = False self.__view = QWebEngineView() self.__page.setView(self.__view) self._qt_invocation = QtInvocation(self.__page) self.__channel = QWebChannel(self) self.__channel.registerObject("QtInvocation", self._qt_invocation) self.__page.setWebChannel(self.__channel) self.__page.loadStarted.connect(self.__load_started) self.__page.loadFinished.connect(self.__load_finished) self.__view.loadProgress.connect(self.__prg) self.__page.navigationRequested.connect(self.__navigation_requested) # self._qt_invocation.js_navigation_requested.connect(self.__page._js_gap_eventloop) self.__page.settings().setAttribute( self.__page.settings().LocalContentCanAccessRemoteUrls, True) self.__page.setUrl(QUrl('about:blank')) self.__view.setWindowState(Qt.WindowMaximized) if gui: self.__view.show() def __prg(self, p): print('progress: ', p) def __load_started(self): print('load started') def __load_finished(self, ok): print('load finished', ok) def __node(self, node_id): return Node(self, self.__page, node_id) def __navigation_requested(self): print('navvvvvvvvvvvvv', self.__loading) if not self.__loading: self.__loading = True print('navigation event loop started') loop = QEventLoop() self.__page.loadFinished.connect(loop.quit) loop.exec() print('navigation event loop ended') loop_js = QEventLoop() self._qt_invocation.js_ready.connect(loop_js.quit) self.__register_js() loop_js.exec() self.__loading = False print('js register event loop ended') def __register_js(self): channel_file = QFile(":/qtwebchannel/qwebchannel.js") if channel_file.open(QIODevice.ReadOnly): content = channel_file.readAll() channel_file.close() print('runjssssssssssssssssssssssssssssssssssssssss 1') self.__run_js(content.data().decode()) print('runjssssssssssssssssssssssssssssssssssssssss 2', BASE_APP_PATH) qt_file = QFile( '{0}/extensions/hrobot/v_2_0/qt.js'.format(BASE_APP_PATH)) if qt_file.open(QIODevice.ReadOnly): content = qt_file.readAll() qt_file.close() print('runjssssssssssssssssssssssssssssssssssssssss 3') self.__run_js(content.data().decode()) print('runjssssssssssssssssssssssssssssssssssssssss 4') def __async_callback(self, result): self.__async_result = result self.asyncFinished.emit() print('async js emit') def __run_js(self, script): loop = QEventLoop() self.asyncFinished.connect(loop.quit) self.__page.runJavaScript(script, self.__async_callback) loop.exec() print('run js finished') return self.__async_result def __on_cookie_added(self, cookie): print('on add cookie', cookie.toRawForm(1)) for c in self.__cookies: if c.hasSameIdentifier(cookie): return print('coocke', cookie) print('net cookie', QNetworkCookie(cookie)) self.__cookies.append(QNetworkCookie(cookie)) def set_cookie(self, cookie): self.__cookie_store.setCookie(cookie) def __set_browser_attribute(self, attr, value): self.__page.settings().setAttribute(attr, value) def go_to(self, url: Union[QUrl, str]) -> bool: """ Goes to a given URL. """ url = QUrl(url) if self.base_url: url = self.base_url.resolved(url) loop = QEventLoop() self.__page.loadFinished.connect(loop.exit) self.__page.load(url) return True if loop.exec() else False def go_back(self): self.__view.back() def get_body(self): """ Return the current DOM as HTML. """ loop = QEventLoop() self.asyncFinished.connect(loop.quit) self.__page.toHtml(self.__async_callback) loop.exec() return self.__async_result def get_cookies(self, as_json=False): if as_json: return self.__cookie_to_json() return self.__cookies def __cookie_to_json(self): cookies_list_info = [] for c in self.__cookies: c = QNetworkCookie(c) data = { "name": bytearray(c.name()).decode(), "domain": c.domain(), "value": bytearray(c.value()).decode(), "path": c.path(), "expirationDate": c.expirationDate().toString(Qt.ISODate), "secure": c.isSecure(), "httponly": c.isHttpOnly() } cookies_list_info.append(data) return cookies_list_info def json_to_cookie(self, json_cookie_list): cookies_list_info = [] for json_cookie in json_cookie_list: c = QNetworkCookie() print(json_cookie, '** json_cookie') for k, v in json_cookie.items(): if k == 'path': c.setPath(v) elif k == 'domain': c.setPath(v) elif k == 'expirationDate': print(v, type(v)) qdate = QDateTime(2019, 12, 20, 11, 59, 59) print(qdate) c.setExpirationDate(qdate) elif k == 'httponly': c.setHttpOnly(v) elif k == 'secure': c.setSecure(v) elif k == 'value': c.setValue(v.encode()) elif k == 'name': c.setName(v.encode()) print('c', c.expirationDate()) cookies_list_info.append(c) return cookies_list_info def eval_script(self, script): """ Evaluates a piece of Javascript in the context of the current page and returns its value. """ return self.__run_js(script) def exec_script(self, script): """ Executes a piece of Javascript in the context of the current page. """ self.__run_js(script) def block_url(self, url): raise NotImplementedError def allow_url(self, url): raise NotImplementedError def get_url(self): """ Returns the current location. """ return self.__page.url() def reload(self): self.go_to(self.current_url()) def is_private(self): return self.__page.profile().isOffTheRecord() def set_skip_image_loading(self, value): """ Specifies whether images are automatically loaded in web pages. This is disabled by default.""" # self.browser.set_attribute('auto_load_images', value) self.__set_browser_attribute(self.__page.settings().AutoLoadImages, not value) def save_as_pdf(self, name): loop = QEventLoop() self.__page.pdfPrintingFinished.connect(loop.quit) self.__page.printToPdf(name) loop.exec() def scroll_to_end(self, lazy_load=True): loop = QEventLoop() self._qt_invocation.async_js_finished.connect(loop.quit) self.__run_js( 'Qt.scrollToEnd({0})'.format('true' if lazy_load else 'false')) loop.exec() def find_by_css(self, selector): """ Return the first node matching the given CSSv3 expression or None. """ nodes = self.find_all_by_css(selector) return None if not nodes else nodes[0] def find_by_xpath(self, xpath): """ Return the first node matching the given XPath 2.0 expression or None. """ nodes = self.find_all_by_xpath(xpath) return None if not nodes else nodes[0] def find_all_by_css(self, selector): """ Return all nodes matching the given CSSv3 expression. """ try: return [ self.__node(node_id) for node_id in self.__run_js( Utils.qt_js_prepare('Qt.findCss("{0}")'.format( Utils.normalize_quotes(selector)))).split(",") if node_id ] except AttributeError: return None def find_all_by_xpath(self, xpath): """ Return all nodes matching the given XPath 2.0 expression. """ try: return [ self.__node(node_id) for node_id in self.__run_js( Utils.qt_js_prepare('Qt.findXpath("{0}")'.format( Utils.normalize_quotes(xpath)))).split(",") if node_id ] except AttributeError: return None def wait_until_css(self, selector, timeout=30): node = self.find_by_css(selector) elapsed = 0 while not node: if elapsed > timeout: return None Utils.wait(1000) elapsed += 1 node = self.find_by_css(selector) return node def wait_until_xpath(self, xpath, timeout=30): node = self.find_by_xpath(xpath) elapsed = 0 while not node: if elapsed > timeout: return None Utils.wait(1000) elapsed += 1 node = self.find_by_xpath(xpath) return node def find_by_following_sibling(self, tag, sibling): """ Return first sibling node after the current node """ return self.find_by_xpath("//%s/following-sibling::%s" % (tag, sibling)) def find_all_by_following_sibling(self, tag, sibling): """ Return all sibling nodes after the current node """ return self.find_all_by_xpath("//%s/following-sibling::%s" % (tag, sibling)) def find_by_preceding_sibling(self, tag, sibling): """ Return first sibling node before the current node """ return self.find_by_xpath("//%s/preceding-sibling::%s" % (tag, sibling)) def find_all_by_preceding_sibling(self, tag, sibling): """ Return all sibling nodes before the current node """ return self.find_all_by_xpath("//%s/preceding-sibling::%s" % (tag, sibling)) def find_element_has_attribute(self, tag, attr): """ Return the first node has attr in its attribute or none """ return self.find_by_xpath("//%s[@%s]" % (tag, attr)) def find_elements_has_attribute(self, tag, attr): """ Return all nodes has attr in their attribute or none """ return self.find_all_by_xpath("//%s[@%s]" % (tag, attr)) def find_elements_has_any_attribute(self, tag): """ Return all nodes that has any attribute or none""" return self.find_by_xpath("//%s[@*]" % tag) def find_elements_has_not_attribute(self, tag): """ Return all nodes that has not any attribute or none""" return self.find_by_xpath("//%s[not(@*)]" % tag) def find_by_attribute_value(self, tag, attr, value, normalize_space=True): """ Return first node has attr in its attribute and the value of attr is equal to value.""" if normalize_space: return self.find_by_xpath("//%s[normalize-space(@%s = %s)]" % (tag, attr, value)) else: return self.find_by_xpath("//%s[@%s = %s]" % (tag, attr, value)) def find_all_by_attribute_value(self, tag, attr, value, normalize_space=True): """ Return all nodes has attr in their attribute and the value of attr is equal to value.""" if normalize_space: return self.find_all_by_xpath("//%s[normalize-space(@%s = %s)]" % (tag, attr, value)) else: return self.find_all_by_xpath("//%s[@%s = %s]" % (tag, attr, value)) def find_by_children_number(self, tag, children_number): """ Return first node that number of its children is equal to children_number """ return self.find_all_by_xpath("//*[count(%s)= %s]" % (tag, children_number)) def find_all_by_children_number(self, children_number): """ Return all nodes that number of their children is equal to children_number """ return self.find_all_by_xpath("//*[count(*)= %s]" % children_number) def find_by_name(self, tag_name): """ Return node that name of it is equal to tag_name """ return self.find_all_by_xpath("//*[name()=%s]" % tag_name) def find_by_name_starts_with(self, letter): """ Return node that name of it starts with to letter """ return self.find_all_by_xpath("//*[starts-with(name(), %s)]" % letter) def find_by_name_contains(self, letter): """ Return node that name of it contains letter """ return self.find_all_by_xpath("//*[contains(name(),%s)]" % letter) # this finds excludes any descendants and attribute nodes and namespace nodes. def find_by_following(self, node): """ Return nodes that exist in following of node """ return self.find_all_by_xpath("//%s/following::*" % node) # this finds excludes any descendants and attribute nodes and namespace nodes. def find_by_preceding(self, node): """ Return nodes that exist in preceding of node """ return self.find_all_by_xpath("//%s/preceding::*" % node) def find_element_descendant(self, tag, child_tag='*'): return self.find_by_xpath("%s/descendant::%s" % (tag, child_tag)) def find_elements_descendant(self, tag, child_tag='*'): return self.find_all_by_xpath("%s/descendant::%s" % (tag, child_tag)) def find_all_elements_descendant(self, tag): return self.find_all_by_xpath("//%s/descendant::*" % tag) def find_by_contain_text(self, tag, text): """ Return node that contains text in their text value""" return self.find_by_xpath("//%s[contains(text(), '%s')]" % (tag, text)) def find_all_by_contain_text(self, tag, text): """ Return all nodes that contains text in their text value""" return self.find_all_by_xpath("//%s[contains(text(), '%s')]" % (tag, text))
class HttpWindow(QDialog): def __init__(self, parent=None): super(HttpWindow, self).__init__(parent) self.url = QUrl() self.qnam = QNetworkAccessManager() self.reply = None self.outFile = None self.httpGetId = 0 self.httpRequestAborted = False self.urlLineEdit = QLineEdit('https://www.qt.io') urlLabel = QLabel("&URL:") urlLabel.setBuddy(self.urlLineEdit) self.statusLabel = QLabel( "Please enter the URL of a file you want to download.") self.statusLabel.setWordWrap(True) self.downloadButton = QPushButton("Download") self.downloadButton.setDefault(True) self.quitButton = QPushButton("Quit") self.quitButton.setAutoDefault(False) buttonBox = QDialogButtonBox() buttonBox.addButton(self.downloadButton, QDialogButtonBox.ActionRole) buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole) self.progressDialog = QProgressDialog(self) self.urlLineEdit.textChanged.connect(self.enableDownloadButton) self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) self.qnam.sslErrors.connect(self.sslErrors) self.progressDialog.canceled.connect(self.cancelDownload) self.downloadButton.clicked.connect(self.downloadFile) self.quitButton.clicked.connect(self.close) topLayout = QHBoxLayout() topLayout.addWidget(urlLabel) topLayout.addWidget(self.urlLineEdit) mainLayout = QVBoxLayout() mainLayout.addLayout(topLayout) mainLayout.addWidget(self.statusLabel) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("HTTP") self.urlLineEdit.setFocus() def startRequest(self, url): self.reply = self.qnam.get(QNetworkRequest(url)) self.reply.finished.connect(self.httpFinished) self.reply.readyRead.connect(self.httpReadyRead) self.reply.downloadProgress.connect(self.updateDataReadProgress) def downloadFile(self): self.url = QUrl(self.urlLineEdit.text()) fileInfo = QFileInfo(self.url.path()) fileName = fileInfo.fileName() if not fileName: fileName = 'index.html' if QFile.exists(fileName): ret = QMessageBox.question(self, "HTTP", "There already exists a file called %s in the current " "directory. Overwrite?" % fileName, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return QFile.remove(fileName) self.outFile = QFile(fileName) if not self.outFile.open(QIODevice.WriteOnly): QMessageBox.information(self, "HTTP", "Unable to save the file %s: %s." % (fileName, self.outFile.errorString())) self.outFile = None return self.progressDialog.setWindowTitle("HTTP") self.progressDialog.setLabelText("Downloading %s." % fileName) self.downloadButton.setEnabled(False) self.httpRequestAborted = False self.startRequest(self.url) def cancelDownload(self): self.statusLabel.setText("Download canceled.") self.httpRequestAborted = True if self.reply is not None: self.reply.abort() self.downloadButton.setEnabled(True) def httpFinished(self): if self.httpRequestAborted: if self.outFile is not None: self.outFile.close() self.outFile.remove() self.outFile = None self.reply.deleteLater() self.reply = None self.progressDialog.hide() return self.progressDialog.hide() self.outFile.flush() self.outFile.close() redirectionTarget = self.reply.attribute(QNetworkRequest.RedirectionTargetAttribute) if self.reply.error(): self.outFile.remove() QMessageBox.information(self, "HTTP", "Download failed: %s." % self.reply.errorString()) self.downloadButton.setEnabled(True) elif redirectionTarget is not None: newUrl = self.url.resolved(redirectionTarget) ret = QMessageBox.question(self, "HTTP", "Redirect to %s?" % newUrl.toString(), QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.Yes: self.url = newUrl self.reply.deleteLater() self.reply = None self.outFile.open(QIODevice.WriteOnly) self.outFile.resize(0) self.startRequest(self.url) return else: fileName = QFileInfo(QUrl(self.urlLineEdit.text()).path()).fileName() self.statusLabel.setText("Downloaded %s to %s." % (fileName, QDir.currentPath())) self.downloadButton.setEnabled(True) self.reply.deleteLater() self.reply = None self.outFile = None def httpReadyRead(self): if self.outFile is not None: self.outFile.write(self.reply.readAll()) def updateDataReadProgress(self, bytesRead, totalBytes): if self.httpRequestAborted: return self.progressDialog.setMaximum(totalBytes) self.progressDialog.setValue(bytesRead) def enableDownloadButton(self): self.downloadButton.setEnabled(self.urlLineEdit.text() != '') def slotAuthenticationRequired(self, authenticator): import os from PyQt5 import uic ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') dlg = uic.loadUi(ui) dlg.adjustSize() dlg.siteDescription.setText("%s at %s" % (authenticator.realm(), self.url.host())) dlg.userEdit.setText(self.url.userName()) dlg.passwordEdit.setText(self.url.password()) if dlg.exec_() == QDialog.Accepted: authenticator.setUser(dlg.userEdit.text()) authenticator.setPassword(dlg.passwordEdit.text()) def sslErrors(self, reply, errors): errorString = ", ".join([str(error.errorString()) for error in errors]) ret = QMessageBox.warning(self, "HTTP Example", "One or more SSL errors has occurred: %s" % errorString, QMessageBox.Ignore | QMessageBox.Abort) if ret == QMessageBox.Ignore: self.reply.ignoreSslErrors()
file=context.file, msg=message)) qInstallMessageHandler(qt_message_handler) app = QApplication(sys.argv) base_url = QUrl("{}{}/".format( FILE_PREFIX[system()], str(path.abspath(path.dirname(__file__))).replace('\\', '/'))) icon = QIcon() for size in ICON_SIZES: path = FileIO.removeFilePrefix( base_url.resolved(QUrl("assets/icons/{}x{}.png".format(size, size))).url()) icon.addFile(path, QSize(size, size)) app.setWindowIcon(icon) qmlRegisterSingletonType(base_url.resolved(QUrl("assets/styles/UIStyles.qml")), "StyleSettings", 1, 0, "StyleSettings") qmlRegisterSingletonType(CodeAnalyzer, "CodeAnalyzer", 1, 0, "CodeAnalyzer", CodeAnalyzer.singletonProvider) qmlRegisterType(ExpSyntaxHighlighter, "ExpSyntaxHighlighter", 1, 0, "ExpSyntaxHighlighter") qmlRegisterType(DiffCodeAnalyzer, "DiffCodeAnalyzer", 1, 0, "DiffCodeAnalyzer") qmlRegisterType(ExpAnalyzer, "ExpAnalyzer", 1, 0, "ExpAnalyzer") qmlRegisterType(TreeViewModel, "TreeViewModel", 1, 0, "TreeViewModel") qmlRegisterType(DebuggerWrapper, "Debugger", 1, 0, "Debugger") qmlRegisterType(IOWrapper, "IOWrapper", 1, 0, "IOWrapper") qmlRegisterType(FileIO, "FileIO", 1, 0, "FileIO")
class AppWindow(QMainWindow): def __init__(self): super().__init__() self.docRoot = "https://oradocs-corp.documents.us2.oraclecloud.com/documents/" self.url = QUrl() self.qnam = QNetworkAccessManager() self.reply = None self.outFile = None self.httpGetId = 0 self.httpRequestAborted = False self.gotToken = False self.ui = Ui_MainWindow() self.ui.setupUi(self) # self.ui.setupUi.MainWindow.setTitle("OraDocs") self._connections() def _connections(self): self.ui.logOutput.insertPlainText( "Setting up actions for all menus and such .") self.ui.action_Exit.triggered.connect(self.close) self.ui.action_Open.triggered.connect(self.action_open) self.ui.action_Save.triggered.connect(self.action_save) self.ui.action_SyncAll.triggered.connect(self.action_syncAll) self.ui.action_SyncConnect.triggered.connect(self.action_syncConnect) self.ui.logOutput.insertPlainText(".. done\n") def startRequest(self, url): # just some debugging to see were we are self.ui.logOutput.insertPlainText("startRequest ...\n") # get the URL self.ui.logOutput.insertPlainText("get page ...\n") self.reply = self.qnam.get(QNetworkRequest(url)) # not sure if here correct or better somwhere else # do we need authorization self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) # do we got ssl errors self.qnam.sslErrors.connect(self.sslErrors) # after loading the page do some hadling of the output via the pyslot self.reply.finished.connect(self.httpFinished) # we should be able to read the stuff self.ui.logOutput.insertPlainText("before httpReady ...\n") self.reply.readyRead.connect(self.httpReadyRead) # not sure if the return is needed return def httpFinished(self): # just some debugging self.ui.logOutput.insertPlainText("httpFinished start ...\n") # check for redirection redirectionTarget = self.reply.attribute( QNetworkRequest.RedirectionTargetAttribute) # check for reply results if self.reply.error(): # looks like we got an error # self.outFile.remove() QMessageBox.information( self, "HTTP", "Download failed %s" % self.reply.errorString) elif redirectionTarget is not None: # we got redirected # output where we are going to self.ui.logOutput.insertPlainText("redirect -> %s\n" % str(redirectionTarget)) self.ui.logOutput.moveCursor(QTextCursor.End) # our new URL is that one newUrl = self.url.resolved(redirectionTarget) # debug self.ui.logOutput.insertPlainText("new URL -> %s\n" % newUrl.toString()) self.ui.logOutput.moveCursor(QTextCursor.End) # the new url is the redirected one self.url = newUrl # the reply needs to be nothing self.reply = None # and start over self.startRequest(self.url) return else: # do normal processing self.ui.logOutput.insertPlainText("no-redirect -> %s \n" % self.url.toString()) self.ui.logOutput.moveCursor(QTextCursor.End) self.ui.logOutput.insertPlainText( str(self.reply.header(QNetworkRequest.rawHeader))) # as the last actions in here self.reply.deleteLater() self.reply = None def httpReadyRead(self): # if self.outFile is not None: # self.outFile.write(self.reply.readAll()) self.ui.logOutput.insertPlainText("http Ready\n") self.ui.logOutput.moveCursor(QTextCursor.End) myData = self.reply.readAll() # self.ui.logOutput.insertPlainText(str(myData, 'utf-8')) def AuthenticationRequired(self, authenticator): import os from PyQt5 import uic ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') dlg = uic.loadUi(ui) dlg.adjustSize() dlg.siteDescription.setText("%s at %s" % (authenticator.realm(), self.url.host())) dlg.userEdit.setText(self.url.userName()) dlg.passwordEdit.setText(self.url.password()) if dlg.exec_() == QDialog.Accepted: authenticator.setUser(dlg.userEdit.text()) authenticator.setPassword(dlg.passwordEdit.text()) @pyqtSlot() def action_close(self): # print("closing") self.quit() @pyqtSlot() def action_open(self): # print("open") QMessageBox.information(self, "File Open", "work in progress") @pyqtSlot() def action_save(self): # print("open") QMessageBox.information(self, "File Save", "work in progress") @pyqtSlot() def action_syncAll(self): QMessageBox.information(self, "Sync ALl", "work in progress") @pyqtSlot() # we are starting the the connection actions def action_syncConnect(self): # just some debugging self.ui.logOutput.insertPlainText("syncConnect ...\n") # we start with the root URL self.url = QUrl(self.docRoot) # start the request self.startRequest(self.url) # not sure if here correct or better in httpFinished # do we need authorization self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) # do we got ssl errors self.qnam.sslErrors.connect(self.sslErrors) # just some debugging self.ui.logOutput.insertPlainText( "syncConnect - after start Request\n") # QMessageBox.information(self, "Sync Connect", "work in progress") @pyqtSlot() def slotAuthenticationRequired(self, authenticator): # import os QMessageBox.information(self, "Authentication", "work in progress") def sslErrors(self, reply, errors): QMessageBox.information(self, "SSL error", "work in progress")
class GreaseMonkeyScript(QObject): """ Class implementing the GreaseMonkey script. @signal scriptChanged() emitted to indicate a script change @signal updatingChanged(bool) emitted to indicate a change of the updating state """ DocumentStart = 0 DocumentEnd = 1 DocumentIdle = 2 scriptChanged = pyqtSignal() updatingChanged = pyqtSignal(bool) def __init__(self, manager, path): """ Constructor @param manager reference to the manager object (GreaseMonkeyManager) @param path path of the Javascript file (string) """ super(GreaseMonkeyScript, self).__init__(manager) self.__manager = manager self.__fileWatcher = DelayedFileWatcher(parent=None) self.__name = "" self.__namespace = "GreaseMonkeyNS" self.__description = "" self.__version = "" self.__include = [] self.__exclude = [] self.__require = [] self.__icon = QIcon() self.__iconUrl = QUrl() self.__downloadUrl = QUrl() self.__updateUrl = QUrl() self.__startAt = GreaseMonkeyScript.DocumentEnd self.__script = "" self.__fileName = path self.__enabled = True self.__valid = False self.__noFrames = False self.__updating = False self.__downloaders = [] self.__iconReplies = [] self.__parseScript() self.__fileWatcher.delayedFileChanged.connect( self.__watchedFileChanged) def isValid(self): """ Public method to check the validity of the script. @return flag indicating a valid script (boolean) """ return self.__valid def name(self): """ Public method to get the name of the script. @return name of the script (string) """ return self.__name def nameSpace(self): """ Public method to get the name space of the script. @return name space of the script (string) """ return self.__namespace def fullName(self): """ Public method to get the full name of the script. @return full name of the script (string) """ return "{0}/{1}".format(self.__namespace, self.__name) def description(self): """ Public method to get the description of the script. @return description of the script (string) """ return self.__description def version(self): """ Public method to get the version of the script. @return version of the script (string) """ return self.__version def icon(self): """ Public method to get the icon of the script. @return script icon @rtype QIcon """ return self.__icon def iconUrl(self): """ Public method to get the icon URL of the script. @return icon URL of the script (QUrl) """ return QUrl(self.__iconUrl) def downloadUrl(self): """ Public method to get the download URL of the script. @return download URL of the script (QUrl) """ return QUrl(self.__downloadUrl) def updateUrl(self): """ Public method to get the update URL of the script. @return update URL of the script (QUrl) """ return QUrl(self.__updateUrl) def startAt(self): """ Public method to get the start point of the script. @return start point of the script (DocumentStart or DocumentEnd) """ return self.__startAt def noFrames(self): """ Public method to get the noFrames flag. @return flag indicating to not run on sub frames @rtype bool """ return self.__noFrames def isEnabled(self): """ Public method to check, if the script is enabled. @return flag indicating an enabled state (boolean) """ return self.__enabled and self.__valid def setEnabled(self, enable): """ Public method to enable a script. @param enable flag indicating the new enabled state (boolean) """ self.__enabled = enable def include(self): """ Public method to get the list of included URLs. @return list of included URLs (list of strings) """ return self.__include[:] def exclude(self): """ Public method to get the list of excluded URLs. @return list of excluded URLs (list of strings) """ return self.__exclude[:] def require(self): """ Public method to get the list of required scripts. @return list of required scripts (list of strings) """ return self.__require[:] def fileName(self): """ Public method to get the path of the Javascript file. @return path of the Javascript file (string) """ return self.__fileName def isUpdating(self): """ Public method to get the updating flag. @return updating flag @rtype bool """ return self.__updating @pyqtSlot(str) def __watchedFileChanged(self, fileName): """ Private slot handling changes of the script file. @param fileName path of the script file @type str """ if self.__fileName == fileName: self.__reloadScript() def __parseScript(self): """ Private method to parse the given script and populate the data structure. """ self.__name = "" self.__namespace = "GreaseMonkeyNS" self.__description = "" self.__version = "" self.__include = [] self.__exclude = [] self.__require = [] self.__icon = QIcon() self.__iconUrl = QUrl() self.__downloadUrl = QUrl() self.__updateUrl = QUrl() self.__startAt = GreaseMonkeyScript.DocumentEnd self.__script = "" self.__enabled = True self.__valid = False self.__noFrames = False try: f = open(self.__fileName, "r", encoding="utf-8") fileData = f.read() f.close() except (IOError, OSError): # silently ignore because it shouldn't happen return if self.__fileName not in self.__fileWatcher.files(): self.__fileWatcher.addPath(self.__fileName) rx = QRegExp("// ==UserScript==(.*)// ==/UserScript==") rx.indexIn(fileData) metaDataBlock = rx.cap(1).strip() if metaDataBlock == "": # invalid script file return for line in metaDataBlock.splitlines(): if not line.strip(): continue if not line.startswith("// @"): continue line = line[3:].replace("\t", " ") index = line.find(" ") key = line[:index].strip() if index > 0: value = line[index + 1:].strip() else: value = "" if not key: continue if key == "@name": self.__name = value elif key == "@namespace": self.__namespace = value elif key == "@description": self.__description = value elif key == "@version": self.__version = value elif key in ["@include", "@match"]: self.__include.append(value) elif key in ["@exclude", "@exclude_match"]: self.__exclude.append(value) elif key == "@require": self.__require.append(value) elif key == "@run-at": if value == "document-end": self.__startAt = GreaseMonkeyScript.DocumentEnd elif value == "document-start": self.__startAt = GreaseMonkeyScript.DocumentStart elif value == "document-idle": self.__startAt = GreaseMonkeyScript.DocumentIdle elif key == "@downloadURL" and self.__downloadUrl.isEmpty(): self.__downloadUrl = QUrl(value) elif key == "@updateURL" and self.__updateUrl.isEmpty(): self.__updateUrl = QUrl(value) elif key == "@icon": self.__iconUrl = QUrl(value) elif key == "@noframes": self.__noFrames = True self.__iconUrl = self.__downloadUrl.resolved(self.__iconUrl) if not self.__include: self.__include.append("*") nspace = bytes( QCryptographicHash.hash( QByteArray(self.fullName().encode("utf-8")), QCryptographicHash.Md4).toHex()).decode("ascii") valuesScript = values_js.format(nspace) self.__script = "(function(){{{0}\n{1}\n{2}\n}})();".format( valuesScript, self.__manager.requireScripts(self.__require), fileData) self.__valid = True self.__downloadIcon() self.__downloadRequires() def webScript(self): """ Public method to create a script object. @return prepared script object @rtype QWebEngineScript """ script = QWebEngineScript() script.setSourceCode("{0}\n{1}".format(bootstrap_js, self.__script)) script.setName(self.fullName()) script.setWorldId(WebBrowserPage.SafeJsWorld) script.setRunsOnSubFrames(not self.__noFrames) return script def updateScript(self): """ Public method to updated the script. """ if not self.__downloadUrl.isValid() or self.__updating: return self.__updating = True self.updatingChanged.emit(self.__updating) downloader = GreaseMonkeyDownloader( self.__downloadUrl, self.__manager, GreaseMonkeyDownloader.DownloadMainScript) downloader.updateScript(self.__fileName) downloader.finished.connect( lambda: self.__downloaderFinished(downloader)) downloader.error.connect(lambda: self.__downloaderError(downloader)) self.__downloaders.append(downloader) self.__downloadRequires() def __downloaderFinished(self, downloader): """ Private slot to handle a finished download. @param downloader reference to the downloader object @type GreaseMonkeyDownloader """ if downloader in self.__downloaders: self.__downloaders.remove(downloader) self.__updating = False self.updatingChanged.emit(self.__updating) def __downloaderError(self, downloader): """ Private slot to handle a downloader error. @param downloader reference to the downloader object @type GreaseMonkeyDownloader """ if downloader in self.__downloaders: self.__downloaders.remove(downloader) self.__updating = False self.updatingChanged.emit(self.__updating) def __reloadScript(self): """ Private method to reload the script. """ self.__parseScript() self.__manager.removeScript(self, False) self.__manager.addScript(self) self.scriptChanged.emit() def __downloadRequires(self): """ Private method to download the required scripts. """ for urlStr in self.__require: if not self.__manager.requireScripts([urlStr]): downloader = GreaseMonkeyDownloader( QUrl(urlStr), self.__manager, GreaseMonkeyDownloader.DownloadRequireScript) downloader.finished.connect( lambda: self.__requireDownloaded(downloader)) downloader.error.connect( lambda: self.__requireDownloadError(downloader)) self.__downloaders.append(downloader) def __requireDownloaded(self, downloader): """ Private slot to handle a finished download of a required script. @param downloader reference to the downloader object @type GreaseMonkeyDownloader """ if downloader in self.__downloaders: self.__downloaders.remove(downloader) self.__reloadScript() def __requireDownloadError(self, downloader): """ Private slot to handle a downloader error. @param downloader reference to the downloader object @type GreaseMonkeyDownloader """ if downloader in self.__downloaders: self.__downloaders.remove(downloader) def __downloadIcon(self): """ Private slot to download the script icon. """ if self.__iconUrl.isValid(): request = QNetworkRequest(self.__iconUrl) reply = WebBrowserWindow.networkManager().get(request) reply.finished.connect(lambda: self.__iconDownloaded(reply)) self.__iconReplies.append(reply) def __iconDownloaded(self, reply): """ Private slot to handle a finished download of a script icon. @param reply reference to the network reply @type QNetworkReply """ if reply in self.__iconReplies: self.__iconReplies.remove(reply) reply.deleteLater() if reply.error() == QNetworkReply.NoError: self.__icon = QPixmap.fromImage(QImage.fromData(reply.readAll()))
def getFullPath(path): currentPath = QUrl(QFileInfo(__file__).absolutePath()+'/') return currentPath.resolved(QUrl(path)).toString()
class WebHitTestResult(object): """ Class implementing an object for testing certain aspects of a web page. """ def __init__(self, page, pos): """ Constructor @param page reference to the web page @type WebBrowserPage @param pos position to be tested @type QPoint """ self.__isNull = True self.__isContentEditable = False self.__isContentSelected = False self.__isMediaPaused = False self.__isMediaMuted = False self.__pos = QPoint(pos) self.__baseUrl = QUrl() self.__alternateText = "" self.__boundingRect = QRect() self.__imageUrl = QUrl() self.__linkTitle = "" self.__linkUrl = QUrl() self.__mediaUrl = QUrl() self.__tagName = "" self.__viewportPos = page.mapToViewport(pos) script = """ (function() {{ var e = document.elementFromPoint({0}, {1}); if (!e) return; function isMediaElement(e) {{ return e.tagName.toLowerCase() == 'audio' || e.tagName.toLowerCase() == 'video'; }} function isEditableElement(e) {{ if (e.isContentEditable) return true; if (e.tagName.toLowerCase() == 'input' || e.tagName.toLowerCase() == 'textarea') return e.getAttribute('readonly') != 'readonly'; return false; }} function isSelected(e) {{ var selection = window.getSelection(); if (selection.type != 'Range') return false; return window.getSelection().containsNode(e, true); }} function attributeStr(e, a) {{ return e.getAttribute(a) || ''; }} var res = {{ baseUrl: document.baseURI, alternateText: e.getAttribute('alt'), boundingRect: '', imageUrl: '', contentEditable: isEditableElement(e), contentSelected: isSelected(e), linkTitle: '', linkUrl: '', mediaUrl: '', mediaPaused: false, mediaMuted: false, tagName: e.tagName.toLowerCase() }}; var r = e.getBoundingClientRect(); res.boundingRect = [r.top, r.left, r.width, r.height]; if (e.tagName.toLowerCase() == 'img') res.imageUrl = attributeStr(e, 'src').trim(); if (e.tagName.toLowerCase() == 'a') {{ res.linkTitle = e.text; res.linkUrl = attributeStr(e, 'href').trim(); }} while (e) {{ if (res.linkTitle == '' && e.tagName.toLowerCase() == 'a') res.linkTitle = e.text; if (res.linkUrl == '' && e.tagName.toLowerCase() == 'a') res.linkUrl = attributeStr(e, 'href').trim(); if (res.mediaUrl == '' && isMediaElement(e)) {{ res.mediaUrl = e.currentSrc; res.mediaPaused = e.paused; res.mediaMuted = e.muted; }} e = e.parentElement; }} return res; }})() """.format(self.__viewportPos.x(), self.__viewportPos.y()) self.__populate(page.url(), page.execJavaScript(script)) def updateWithContextMenuData(self, data): """ Public method to update the hit test data with data from the context menu event. @param data context menu data @type QWebEngineContextMenuData """ from PyQt5.QtWebEngineWidgets import QWebEngineContextMenuData if not data.isValid() or data.position() != self.__pos: return self.__linkTitle = data.linkText() self.__linkUrl = data.linkUrl() self.__isContentEditable = data.isContentEditable() self.__isContentSelected = bool(data.selectedText()) if data.mediaType() == QWebEngineContextMenuData.MediaTypeImage: self.__imageUrl = data.mediaUrl() elif data.mediaType() in [ QWebEngineContextMenuData.MediaTypeAudio, QWebEngineContextMenuData.MediaTypeVideo ]: self.__mediaUrl = data.mediaUrl() def baseUrl(self): """ Public method to get the base URL of the page. @return base URL @rtype QUrl """ return self.__baseUrl def alternateText(self): """ Public method to get the alternate text. @return alternate text @rtype str """ return self.__alternateText def boundingRect(self): """ Public method to get the bounding rectangle. @return bounding rectangle @rtype QRect """ return QRect(self.__boundingRect) def imageUrl(self): """ Public method to get the URL of an image. @return image URL @rtype QUrl """ return self.__imageUrl def isContentEditable(self): """ Public method to check for editable content. @return flag indicating editable content @rtype bool """ return self.__isContentEditable def isContentSelected(self): """ Public method to check for selected content. @return flag indicating selected content @rtype bool """ return self.__isContentSelected def isNull(self): """ Public method to test, if the hit test is empty. @return flag indicating an empty object @rtype bool """ return self.__isNull def linkTitle(self): """ Public method to get the title for a link element. @return title for a link element @rtype str """ return self.__linkTitle def linkUrl(self): """ Public method to get the URL for a link element. @return URL for a link element @rtype QUrl """ return self.__linkUrl def mediaUrl(self): """ Public method to get the URL for a media element. @return URL for a media element @rtype QUrl """ return self.__mediaUrl def mediaPaused(self): """ Public method to check, if a media element is paused. @return flag indicating a paused media element @rtype bool """ return self.__isMediaPaused def mediaMuted(self): """ Public method to check, if a media element is muted. @return flag indicating a muted media element @rtype bool """ return self.__isMediaMuted def pos(self): """ Public method to get the position of the hit test. @return position of hit test @rtype QPoint """ return QPoint(self.__pos) def viewportPos(self): """ Public method to get the viewport position. @return viewport position @rtype QPoint """ return QPoint(self.__viewportPos) def tagName(self): """ Public method to get the name of the tested tag. @return name of the tested tag @rtype str """ return self.__tagName def __populate(self, url, res): """ Private method to populate the object. @param url URL of the tested page @type QUrl @param res dictionary with result data from JavaScript @type dict """ if not res: return self.__baseUrl = QUrl(res["baseUrl"]) self.__alternateText = res["alternateText"] self.__imageUrl = QUrl(res["imageUrl"]) self.__isContentEditable = res["contentEditable"] self.__isContentSelected = res["contentSelected"] self.__linkTitle = res["linkTitle"] self.__linkUrl = QUrl(res["linkUrl"]) self.__mediaUrl = QUrl(res["mediaUrl"]) self.__isMediaPaused = res["mediaPaused"] self.__isMediaMuted = res["mediaMuted"] self.__tagName = res["tagName"] rect = res["boundingRect"] if len(rect) == 4: self.__boundingRect = QRect(int(rect[0]), int(rect[1]), int(rect[2]), int(rect[3])) if not self.__imageUrl.isEmpty(): self.__imageUrl = url.resolved(self.__imageUrl) if not self.__linkUrl.isEmpty(): self.__linkUrl = self.__baseUrl.resolved(self.__linkUrl) if not self.__mediaUrl.isEmpty(): self.__mediaUrl = url.resolved(self.__mediaUrl)
class App(QMainWindow): def __init__(self): super().__init__() self.title = "OraDocs by littleT" self.left = 10 self.top = 10 self.width = 600 self.height = 400 self.initUI() self.url = QUrl() self.qnam = QNetworkAccessManager() self.reply = None self.outFile = None self.httpGetId = 0 self.httpRequestAborted = False def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.statusBar().showMessage('Starting ...') # for the menu first create some actions to be added like # File - Exit action exitAction = QAction(QIcon('exit24.png'), 'Exit', self) exitAction.setShortcut('Ctrl+Q') exitAction.setStatusTip('Exit Application') exitAction.triggered.connect(self.close) # File - open openAction = QAction(QIcon(''), '&Open', self) openAction.setShortcut('Ctrl+O') openAction.setStatusTip('Opens a file') openAction.triggered.connect(self.openCall()) # the help actions helpAction = QAction(QIcon(''), 'Help', self) helpAction.triggered.connect(self.openHelp) mainMenu = self.menuBar() fileMenu = mainMenu.addMenu('&File') fileMenu.addAction(openAction) fileMenu.addAction(exitAction) helpMenu = mainMenu.addMenu('&Help') helpMenu.addAction(helpAction) self.logOutput = QTextEdit(self) self.logOutput.setReadOnly(True) # self.logOutput.setLineWrapMode(QTextEdit.NoWrap) self.logOutput.setGeometry(5, 200, 590, 60) self.statusBar().showMessage('waiting for click ...') self.urlLineEdit = QLineEdit(self) # self.textbox.move(5, 300) # self.textbox.resize(590, 20) self.urlLineEdit.setGeometry(5, 325, 590, 20) self.button = QPushButton('Click Me', self) self.button.move(10, 350) self.button.clicked.connect(self.doRequest) def doRequest(self): self.root = "https://oradocs-corp.documents.us2.oraclecloud.com/documents/" # url = "https://www.google.com" self.url = QUrl(self.root) self.httpRequestAborted = False self.startRequest(self.url) self.downloadFile() self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) def startRequest(self, url): self.reply = self.qnam.get(QNetworkRequest(url)) self.reply.finished.connect(self.httpFinished) self.reply.readyRead.connect(self.httpReadyRead) def downloadFile(self): self.url = QUrl(self.urlLineEdit.text()) fileInfo = QFileInfo(self.url.path()) fileName = fileInfo.fileName() if not fileName: fileName = 'index.html' if QFile.exists(fileName): ret = QMessageBox.question(self, "HTTP", "There already exists a file called %s in the current " "directory. Overwrite?" % fileName, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return QFile.remove(fileName) self.outFile = QFile(fileName) if not self.outFile.open(QIODevice.WriteOnly): QMessageBox.information(self, "HTTP", "Unable to save the file %s: %s." % (fileName, self.outFile.errorString())) self.outFile = None return self.progressDialog.setWindowTitle("HTTP") self.progressDialog.setLabelText("Downloading %s." % fileName) self.downloadButton.setEnabled(False) self.httpRequestAborted = False self.startRequest(self.url) def cancelDownload(self): self.statusLabel.setText("Download canceled.") self.httpRequestAborted = True if self.reply is not None: self.reply.abort() self.downloadButton.setEnabled(True) def httpFinished(self): if self.httpRequestAborted: if self.outFile is not None: self.outFile.close() self.outFile.remove() self.outFile = None self.reply.deleteLater() self.reply = None # self.progressDialog.hide() return # self.progressDialog.hide() self.outFile.flush() self.outFile.close() redirectionTarget = self.reply.attribute(QNetworkRequest.RedirectionTargetAttribute) if self.reply.error(): self.outFile.remove() QMessageBox.information(self, "HTTP", "Download failed: %s." % self.reply.errorString()) self.downloadButton.setEnabled(True) elif redirectionTarget is not None: newUrl = self.url.resolved(redirectionTarget) ret = QMessageBox.question(self, "HTTP", "Redirect to %s?" % newUrl.toString(), QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.Yes: self.url = newUrl self.reply.deleteLater() self.reply = None self.outFile.open(QIODevice.WriteOnly) self.outFile.resize(0) self.startRequest(self.url) return else: fileName = QFileInfo(QUrl(self.urlLineEdit.text()).path()).fileName() self.statusLabel.setText("Downloaded %s to %s." % (fileName, QDir.currentPath())) self.downloadButton.setEnabled(True) self.reply.deleteLater() self.reply = None self.outFile = None def httpReadyRead(self): if self.outFile is not None: self.outFile.write(self.reply.readAll()) def updateDataReadProgress(self, bytesRead, totalBytes): if self.httpRequestAborted: return self.progressDialog.setMaximum(totalBytes) self.progressDialog.setValue(bytesRead) def slotAuthenticationRequired(self, authenticator): import os from PyQt5 import uic ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') dlg = uic.loadUi(ui) dlg.adjustSize() dlg.siteDescription.setText("%s at %s" % (authenticator.realm(), self.url.host())) dlg.userEdit.setText(self.url.userName()) dlg.passwordEdit.setText(self.url.password()) if dlg.exec_() == QDialog.Accepted: authenticator.setUser(dlg.userEdit.text()) authenticator.setPassword(dlg.passwordEdit.text()) def sslErrors(self, reply, errors): errorString = ", ".join([str(error.errorString()) for error in errors]) ret = QMessageBox.warning(self, "HTTP Example", "One or more SSL errors has occurred: %s" % errorString, QMessageBox.Ignore | QMessageBox.Abort) if ret == QMessageBox.Ignore: self.reply.ignoreSslErrors() def openCall(self): print("Open Call") def openHelp(self): print("Open Help") @pyqtSlot() def onClick(self): # textboxValue = self.textbox.text() # QMessageBox.question(self, 'Hello World!', "Confirm: " + textboxValue, # QMessageBox.Ok, QMessageBox.Ok) # self.textbox.setText("...") myRet = self.myDocs.doRequest("https://www.google.com") self.logOutput.moveCursor(QTextCursor.End) print(myRet) self.logOutput.insertPlainText(myRet) @pyqtSlot() def processReq(self): if self.nam.bytesAvailable(): self.logOutput.moveCursor(QTextCursor.End) self.logOutput.insertPlainText('We are connected\n') bytes_string = self.nam.readAll() self.nam.deleteLater() @pyqtSlot(QNetworkReply.NetworkError) def processErr(self, code): self.msg.critical(None, "Info", "You are not connected to the Internet.") print(code)