class BrowserWidget(QWebEngineView): def __init__(self, url, *args, **kwargs): QWebEngineView.__init__(self, *args, **kwargs) self._page = QWebEnginePage(get_profile()) self.setPage(self._page) self.load(url) # Shortcut to manually reload self.reload_shortcut = QShortcut('CTRL+R', self) self.reload_shortcut.activated.connect(self.reload) # Check if pages is correctly loaded self.loadFinished.connect(self._load_finished) # Shortcut to close self.quit_shortcut = QShortcut('CTRL+ALT+DELETE', self) self.quit_shortcut.activated.connect(lambda: self.close()) # Stretch the browser policy = QSizePolicy() policy.setVerticalStretch(1) policy.setHorizontalStretch(1) policy.setVerticalPolicy(QSizePolicy.Preferred) policy.setHorizontalPolicy(QSizePolicy.Preferred) self.setSizePolicy(policy) def load(self, url): self._page.setUrl(url) def _load_finished(self, success): if not success: QTimer.singleShot(5000, self.reload)
class Umbrella(QMainWindow, Ui_MainWindow): #생성자 def __init__(self): super().__init__() self.init_my_location() self.setupUi(self) # 초기화 # self.url = "http://localhost:8080/umbrella" self.url = "http://localhost:8000/umbrella2.html" self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(QUrl(self.url)) self.page.setView(self.webEngineView) chrome_option = Options() chrome_option.add_argument("--headless") chrome_option.add_argument("--mute-audio") self.browser = webdriver.Chrome( chrome_options=chrome_option, executable_path="webdriver/Chrome/chromedriver.exe") self.browser.get(self.url) self.runner = Runner(self.page, self.browser) self.comboBox.addItem("키워드") self.comboBox.addItem("주소") # self.page.featurePermissionRequested.connect(self.setPagePermission) # self.pushButton.clicked.connect(self.map_removeMarkers) # self.pushButton.clicked.connect(lambda: self.map_setLevel(random.randrange(7))) self.pushButton.clicked.connect(lambda: self.runner.coord_to_address( self.my_location_lat, self.my_location_lng, random.randrange(0, 5)) ) # self.pushButton.clicked.connect(lambda: self.getDistance([33.450500,126.569968],[[33.450500,126.569968],[35.404195,126.886323],[39.668777,126.065913]])) # self.pushButton.clicked.connect(self.test_a) # self.pushButton.clicked.connect(self.search) self.lineEdit.returnPressed.connect(self.runner.search) self.page.loadFinished.connect(lambda: self.runner.setMap( self.my_location_lat, self.my_location_lng)) # self.setMap(self.my_location_lat, self.my_location_lng) def init_my_location(self): url = 'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyDQKxbTt0MrFNH85kTJXzickMD5s88UVaI' data = { 'considerIp': True, } result = requests.post(url, data) my_location = json.loads(result.text) # print(my_location) # print("lat : ",my_location.get('location').get('lat')) # print("lon : ",my_location.get('location').get('lng')) self.my_location_lat = str(my_location.get('location').get('lat')) self.my_location_lng = str(my_location.get('location').get('lng'))
async def _alogin(self): """async login method.""" from PyQt5.QtWidgets import QApplication from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage from PyQt5.QtCore import QEventLoop, QUrl app = QApplication(sys.argv) browser = QWebEngineView() profile = QWebEngineProfile() page = QWebEnginePage(profile, browser) loop = asyncio.get_event_loop() browser_closed_event = asyncio.Event(loop=loop) page.windowCloseRequested.connect( lambda event: browser_closed_event.set()) # whenever a page finishes loading, look for the login button page.loadFinished.connect(partial(self.__on_page_loaded, page)) # keep track of cookies cookies = profile.cookieStore() self.__update_cookie_store(cookies) got_auth_event = asyncio.Event(loop=loop) cookies.cookieAdded.connect( partial(self.__on_cookie_added, got_auth_event)) # navigate to the notebook and show the browser page.setUrl(QUrl(self.__notebook_url)) browser.setPage(page) browser.show() # process Qt events until we've got the token or the browser is closed async def poll(): future = asyncio.gather(got_auth_event.wait(), browser_closed_event.wait()) while not got_auth_event.is_set( ) and not browser_closed_event.is_set(): app.processEvents(QEventLoop.AllEvents, 300) await asyncio.wait([future], loop=loop, timeout=0) await poll() if not got_auth_event.is_set(): raise AuthenticationError() return self.__cookies
class TestForm(QMainWindow, Ui_MainWindow) : #생성자 def __init__(self) : super().__init__() self.setupUi(self) # 초기화 self.url = QUrl("http://localhost:8080/umbrella") self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(self.url) self.page.setView(self.webEngineView) self.pushButton_3.clicked.connect(self.translate_ui) def translate_ui(self) : print('aaaaaaaa') self.stackedWidget.setCurrentIndex(1)
def __init__(self, parent=None): super().__init__(parent) layout = QVBoxLayout() self.setLayout(layout) self.profile = QWebEngineProfile() self.store = self.profile.cookieStore() self.brower = QWebEngineView() self.profile.cookieStore().cookieAdded.connect(self.onCookieAdd) page = QWebEnginePage(self.profile, self.brower) page.setUrl(QUrl("https://passport.csdn.net/login?code=public")) self.brower.setPage(page) self.title = QLabel() self.edit = QTextEdit() #self.edit=QCodeEditor() layout.addWidget(self.title) layout.addWidget(self.brower) layout.addWidget(self.edit) layout.setStretchFactor(self.title, 1) layout.setStretchFactor(self.brower, 10) layout.setStretchFactor(self.edit, 10) self.title.setHidden(True) self.edit.setHidden(True) #当edit的内容改动的时候,broswer的内容要同步进行刷新 self.edit.textChanged.connect(self.refreshBrowser) #快捷查找 self.contentSearch = QLineEdit(returnPressed=lambda: self.brower. findText(self.contentSearch.text())) self.contentSearch.setWindowTitle("搜索") self.contentSearch.hide() self.showSearch = QShortcut( "Ctrl+F", self, activated=lambda: (self.contentSearch.show(), self.contentSearch.setFocus()))
class Umbrella(QMainWindow, Ui_MainWindow): def __init__(self): super().__init__() self.init_my_location() self.setupUi(self) # 초기화 # self.url = "http://192.168.0.3:8080/umbrella" self.url = "http://localhost:8080/umbrella.html" self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(QUrl(self.url)) self.page.setView(self.webEngineView) # self.webEngineView2.load(QUrl("http://ncov.mohw.go.kr/bdBoardList_Real.do?brdId=1&brdGubun=11&ncvContSeq=&contSeq=&board_id=&gubun=")) self.appLoaded = False chrome_option = Options() chrome_option.add_argument("--headless") chrome_option.add_argument("--mute-audio") self.browser = webdriver.Chrome( chrome_options=chrome_option, executable_path="resources/chromedriver.exe") self.browser.get(self.url) self.user_uuid = uuid.uuid4() self.runner = Runner(self) self.dc = DataCollector(self) self.dm = DataManager(self) self.itemList = [] self.rowList = [] self.dataChecker = 0 # self.webEngineView2.load(QUrl(self.dc.html_test())) self.initSignal() self.timeSeries = self.dc.get_timeseries() self.comboBox.addItem("-----") for i in sorted(self.timeSeries.keys()): self.comboBox.addItem(i) #테트리스 # self.tboard = Board(self.page_3) # self.tboard.msg2Statusbar.connect(self.test_1) # self.tboard.start() # self.tboard.setStyleSheet("background-color:#ffffff") # self.tboard.setGeometry(460,0,460,820) def test_1(self, msg): if msg == "Game over": self.tboard.initBoard() self.tboard.start() def initSignal(self): #page 변환 self.pushButton_3.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(1)) self.pushButton_4.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(1)) self.intro_button.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(1)) self.pushButton_5.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(1)) self.pushButton__image.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(0)) self.pushButton__image2.clicked.connect( lambda: self.stackedWidget.setCurrentIndex(0)) self.pushButton.clicked.connect(self.runner.map_removeMarkers) #intro 데이터 입력 self.lineEdit.returnPressed.connect( lambda: self.runner.search(self.lineEdit.text().strip())) self.pushButton.clicked.connect( lambda: self.runner.search(self.lineEdit.text().strip())) self.page.loadFinished.connect(lambda: self.runner.setMap( self.my_location_lat, self.my_location_lng)) self.pushButton2.clicked.connect(self.mark_around) self.pushButton3.clicked.connect(lambda: self.runner.setMap( self.my_location_lat, self.my_location_lng)) self.page.urlChanged.connect(self.setButton) self.listWidget.itemActivated.connect(self.activateRow) self.listWidget.itemClicked.connect(self.rowClicked) self.lineEdit.setText( self.runner.coord_to_address(self.my_location_lat, self.my_location_lng, 0)) self.radio1.clicked.connect(lambda: self.setDataChecker(0)) self.radio2.clicked.connect(lambda: self.setDataChecker(2)) self.radio3.clicked.connect(lambda: self.setDataChecker(3)) self.radio4.clicked.connect(lambda: self.setDataChecker(4)) self.widget_1.pressed.connect(self.view_graph) self.widget_2.pressed.connect(self.view_graph) self.widget_3.pressed.connect(self.view_graph) self.widget_4.pressed.connect(self.view_graph) self.comboBox.currentTextChanged.connect(self.show_timeSeries) def show_timeSeries(self, nat): if nat in self.timeSeries.keys(): self.dm.graph_timeseries(self.timeSeries.get(nat)) def view_graph(self): self.stackedWidget.setCurrentIndex(2) def mark_around(self): print("markaround") self.remove_list() if not self.page.url().toString().strip().startswith(self.url): self.page.load(QUrl(self.url)) return self.runner.map_removeMarkers() try: lat, lng = self.runner.map_getCenter() except: print("mark_arount exception") return data = self.dc.get_data_by_latlng(lat, lng, 1000) self.runner.marking(data) self.show_list(data) self.lineEdit.setText(self.runner.coord_to_address(lat, lng, 0)) def setDataChecker(self, num): self.dataChecker = num #표지 def intro(self): data = self.dc.A() #Text self.dm.show_intro_list(data) #그래프 self.dm.intro_graph(data) def init_my_location(self): url = 'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyDQKxbTt0MrFNH85kTJXzickMD5s88UVaI' data = { 'considerIp': True, } result = requests.post(url, data) my_location = json.loads(result.text) self.my_location_lat = str(my_location.get('location').get('lat')) self.my_location_lng = str(my_location.get('location').get('lng')) def setButton(self): if self.page.url().toString().strip().startswith( "http://localhost:8080/umbrella"): self.pushButton2.setText("판매처 탐색") else: self.pushButton2.setText("지도 새로고침") def show_list(self, data): remainP = [ '100개 이상', '30개 이상 100개 미만', '2개 이상 30개 미만', '1개 이하', '판매중지' ] for i in range(len(data)): item = QListWidgetItem(self.listWidget) row = Item(data[i]) rs = data[i].get('remain_stat') if rs == None: row.remain_stat.setStyleSheet('color:red') elif remainP.index(rs) <= 1: row.remain_stat.setStyleSheet('color:green') elif remainP.index(rs) == 2: row.remain_stat.setStyleSheet('color:orange') else: row.remain_stat.setStyleSheet('color:red') item.setWhatsThis(str(i)) item.setSizeHint(row.sizeHint()) self.listWidget.setItemWidget(item, row) self.listWidget.addItem(item) self.itemList.append(item) self.rowList.append(row) def remove_list(self): for i in range(len(self.itemList)): self.itemList[i].setHidden(True) self.itemList = [] self.rowList = [] def activateRow(self, row): self.runner.setMap(self.rowList[int(row.whatsThis())].lat, self.rowList[int(row.whatsThis())].lng) self.runner.info_open(self.rowList[int(row.whatsThis())].code) def rowClicked(self, row): self.runner.info_close_all() self.runner.info_open(self.rowList[int(row.whatsThis())].code)
ip = res.text.split(":") port = ip[1] ip = ip[0] proxy = QtNetwork.QNetworkProxy() # Http访问代理 proxy.setType(QtNetwork.QNetworkProxy.HttpProxy) # 代理ip地址HttpProxy proxy.setHostName(ip) # 端口号 proxy.setPort(int(port)) QtNetwork.QNetworkProxy.setApplicationProxy(proxy) interceptor = TwitchInterceptor() profile = QWebEngineProfile() profile.clearHttpCache() profile.clearAllVisitedLinks() pCookie = profile.cookieStore() pCookie.deleteAllCookies() pCookie.deleteSessionCookies() profile.setRequestInterceptor(interceptor) profile.setPersistentCookiesPolicy(QWebEngineProfile.ForcePersistentCookies) page = QWebEnginePage(profile, view) page.loadFinished.connect(on_done) view.setPage(page) page.setUrl(QUrl(twitch_url)) view.show() sys.exit(app.exec_())
class TeamtoolBrowser(QWidget, design.Ui_Form): def __init__(self, parent=None): super(TeamtoolBrowser, self).__init__(parent) self.setupUi(self) self.browser = QWebEngineView() self.profile = QWebEngineProfile("somestorage", self.browser) self.webpage = QWebEnginePage(self.profile, self.browser) self.browser.setPage(self.webpage) self.initUI() self.eventUI() def eventUI(self): self.btnRefresh.clicked.connect(lambda: self.browse(refresh=True)) self.codeEdit.textChanged.connect(lambda: self.browse(offline=True)) self.fileView.doubleClicked.connect(self.selectFile) self.urlBar.returnPressed.connect(lambda: self.browse()) self.webpage.loadStarted.connect(lambda: self.startLoading()) self.webpage.loadFinished.connect(lambda: self.onLoadFinished()) self.btnPrev.clicked.connect(lambda: self.prev()) self.btnNext.clicked.connect(lambda: self.next()) def prev(self): ''' History: go back ''' self.webpage.page().triggerAction(QWebEnginePage.Back) self.urlBar.setText(self.webpage.url().toString()) def next(self): ''' History: move forward ''' self.webpage.page().triggerAction(QWebEnginePage.Forward) self.urlBar.setText(self.webpage.url().toString()) def startLoading(self): ''' When page starts to load ''' self.loadingAnimation.start() self.labelLoading.setVisible(True) def onLoadFinished(self): ''' When page has finished to load ''' self.loadingAnimation.stop() self.labelLoading.setVisible(False) if self.webpage.history().canGoBack(): self.btnPrev.setEnabled(True) else: self.btnPrev.setEnabled(False) if self.webpage.history().canGoForward(): self.btnNext.setEnabled(True) else: self.btnNext.setEnabled(False) self.urlBar.setText(self.webpage.url().toString()) def browse(self, refresh=False, offline=False): ''' Browse to urlBar URL or render a text/html string ''' # Offline mode, load plaintext html code if offline: self.webpage.setHtml(self.codeEdit.toPlainText()) return # Online mode if refresh: url = self.browser.reload() return url = self.urlBar.text() if not re.match('http://|https://', url, re.I): url = f'http://{url}' # print('===============>', os.path.join('statics/button', 'lock-ssl.png'), QUrl(url).scheme()) if QUrl(url).scheme() == 'https': print('HTTPS') self.httpsicon.setPixmap(self.pixmap_ssl) else: print('HTTP') self.httpsicon.setPixmap(self.pixmap_nossl) print(f'Browse to this URL: {url}') if isinstance(url, str) and url != '': self.webpage.setUrl(QUrl(url)) def selectFile(self, index): ''' Select a file in file system ''' if not self.fileModel.isDir(index) and index.data().lower().endswith( ('.html', '.txt')): with open(self.fileModel.fileInfo(index).absoluteFilePath(), 'r', encoding='utf-8') as f: self.webpage.setHtml(f.read()) else: print('Can not read this file...') def initUI(self): ''' Configuration of widgets ''' self.gLayoutBrowser.addWidget(self.browser) self.loadingAnimation = QMovie('loading.gif') self.loadingAnimation.setScaledSize(QtCore.QSize(24, 24)) self.labelLoading.setMovie(self.loadingAnimation) self.labelLoading.setVisible(False) self.fileModel = QFileSystemModel() self.fileModel.setRootPath(QtCore.QDir.currentPath()) self.fileView.setModel(self.fileModel) self.fileModel.setNameFilters(('.html', '.txt')) self.fileView.setColumnWidth(0, 170) self.fileView.setColumnWidth(1, 50) self.fileView.setColumnWidth(2, 50) self.splitterMain.setStretchFactor(1, 3) self.splitterSidebar.setStretchFactor(0, 1) self.urlBar.setPlaceholderText('Tapez ici votre URL') self.loadPage(online=True) self.pixmap_ssl = QPixmap(os.path.join('static/button', 'lock-ssl.png')) self.pixmap_nossl = QPixmap( os.path.join('static/button', 'lock-nossl.png')) print(f'w: {self.pixmap_ssl.width()} | h: {self.pixmap_ssl.height()}') self.httpsicon.setPixmap(self.pixmap_nossl) self.setGeometry(300, 300, 1280, 720) self.updateTitle() # self.codeEdit = TxtInput([QPushButton('Hello'), QPushButton('World')]) # self.editor = CustomTextEditor(txtInput=self.codeEdit) self.codeEdit = QPlainTextEdit() self.splitterSidebar.addWidget(self.codeEdit) self.show() def loadPage(self, online=True): ''' Load home page ''' if online: self.browser.setUrl(QUrl("https://www.google.com")) return with open('home.html', 'r') as f: html = f.read() self.browser.setHtml(html) def updateTitle(self): title = self.browser.page().title() self.setWindowTitle(f'{title}')
class AuthWidget(QWebEngineView): def __init__(self, parent, config=None, credential_file=None, cookie_persistence=False, log_level=logging.INFO): super(AuthWidget, self).__init__(parent) self.parent = parent self.config = None self.config_file = DEFAULT_CONFIG_FILE self.credential = DEFAULT_CREDENTIAL self.credential_file = None self.cookie_file = None self.cookie_jar = None self.auth_url = None self.authn_session = None self.authn_session_page = None self.authn_cookie_name = None self.authn_expires = time.time() self._success_callback = None self._failure_callback = None self._session = requests.session() self.token = None self.default_profile = QWebEngineProfile("deriva-auth", self) self.private_profile = QWebEngineProfile(self) logging.getLogger().setLevel(log_level) info = "%s v%s [Python: %s (PyQt: %s), %s]" % ( self.__class__.__name__, get_installed_version(VERSION), platform.python_version(), PYQT_VERSION_STR, platform.platform(aliased=True)) logging.info("Initializing authorization provider: %s" % info) self.cookie_persistence = cookie_persistence self._timer = QTimer(self) self._timer.timeout.connect(self._onTimerFired) self.configure(config, credential_file) def configure(self, config, credential_file): self.config = config if config else read_config(self.config_file, create_default=True, default=DEFAULT_CONFIG) self.credential_file = credential_file host = self.config.get("host") if not host: self.set_current_html(ERROR_HTML % "Could not locate hostname parameter in configuration.") return self.auth_url = QUrl() self.auth_url.setScheme(config.get("protocol", "https")) self.auth_url.setHost(host) if config.get("port") is not None: self.auth_url.setPort(config["port"]) self.authn_cookie_name = self.config.get("cookie_name", "webauthn") self.cookie_file = DEFAULT_SESSION_CONFIG.get("cookie_jar") self.cookie_jar = load_cookies_from_file(self.cookie_file) retries = Retry(connect=DEFAULT_SESSION_CONFIG['retry_connect'], read=DEFAULT_SESSION_CONFIG['retry_read'], backoff_factor=DEFAULT_SESSION_CONFIG['retry_backoff_factor'], status_forcelist=DEFAULT_SESSION_CONFIG['retry_status_forcelist']) self._session.mount(self.auth_url.toString() + '/', HTTPAdapter(max_retries=retries)) def set_current_html(self, html): page = QWebEnginePage(self.parent) page.setHtml(html) self.setPage(page) self.update() qApp.processEvents() def authenticated(self): if self.authn_session is None: return False now = time.time() if now >= self.authn_expires: return False return True def login(self): if not (self.auth_url and (self.auth_url.host() and self.auth_url.scheme())): logging.error("Missing or invalid hostname parameter in configuration.") return logging.info("Authenticating with host: %s" % self.auth_url.toString()) qApp.setOverrideCursor(Qt.WaitCursor) self._cleanup() self.authn_session_page = QWebEnginePage(self.private_profile, self.parent) \ if not self.cookie_persistence else QWebEnginePage(self.default_profile, self.parent) self.authn_session_page.profile().setPersistentCookiesPolicy( QWebEngineProfile.ForcePersistentCookies if self.cookie_persistence else QWebEngineProfile.NoPersistentCookies) if self.cookie_persistence: logging.debug("QTWebEngine persistent storage located at: %s" % self.authn_session_page.profile().persistentStoragePath()) self.authn_session_page.profile().cookieStore().cookieAdded.connect(self._onCookieAdded) self.authn_session_page.profile().cookieStore().cookieRemoved.connect(self._onCookieRemoved) self.authn_session_page.loadProgress.connect(self._onLoadProgress) self.authn_session_page.loadFinished.connect(self._onLoadFinished) self.authn_session_page.setUrl(QUrl(self.auth_url.toString() + "/authn/preauth")) self.setPage(self.authn_session_page) def logout(self, delete_cookies=False): if not (self.auth_url and (self.auth_url.host() and self.auth_url.scheme())): return if self.authenticated(): try: logging.info("Logging out of host: %s" % self.auth_url.toString()) if delete_cookies and self.cookie_persistence: self.authn_session_page.profile().cookieStore().deleteAllCookies() self._session.delete(self.auth_url.toString() + "/authn/session") if self.credential_file: creds = read_credential(self.credential_file, create_default=True) host = self.auth_url.host() if creds.get(host): del creds[host] write_credential(self.credential_file, creds) except Exception as e: logging.warning("Logout error: %s" % format_exception(e)) self._cleanup() def setSuccessCallback(self, callback=None): self._success_callback = callback def setFailureCallback(self, callback=None): self._failure_callback = callback def setStatus(self, message): if self.window().statusBar is not None: self.window().statusBar().showMessage(message) def _execSuccessCallback(self): if self._success_callback: self._success_callback(host=self.auth_url.host(), credential=self.credential) def _execFailureCallback(self, message): if self._failure_callback: self._failure_callback(host=self.auth_url.host(), message=message) def _onTimerFired(self): if not self.authenticated(): self.authn_session = None return resp = self._session.put(self.auth_url.toString() + "/authn/session") seconds_remaining = self.authn_session['seconds_remaining'] self.authn_expires = time.time() + seconds_remaining + 1 if resp.ok: logging.trace("webauthn session:\n%s\n", resp.json()) logging.info("Session refreshed for: %s" % self.auth_url.host()) else: logging.warning( "Unable to refresh session for: %s. Server responded: %s" % (self.auth_url.host(), str.format("%s %s: %s" % (resp.status_code, resp.reason, resp.content.decode())))) def _onSessionContent(self, content): try: qApp.restoreOverrideCursor() self.set_current_html(SUCCESS_HTML) try: self.authn_session = json.loads(content) except json.JSONDecodeError: raise RuntimeError("Unable to parse response from server: %s" % content) seconds_remaining = self.authn_session['seconds_remaining'] if not self._timer.isActive(): interval = seconds_remaining // 2 logging.info("Authentication successful for [%s]: credential refresh in %d seconds." % (self.auth_url.toString(), interval)) self._timer.start(interval * 1000) self.authn_expires = time.time() + seconds_remaining + 1 logging.trace("webauthn session:\n%s\n", json.dumps(self.authn_session, indent=2)) QTimer.singleShot(100, self._execSuccessCallback) except (ValueError, Exception) as e: error = format_exception(e) logging.error(error) self.set_current_html(ERROR_HTML % content) self._execFailureCallback(error) def _onPreAuthContent(self, content): try: if not content: logging.debug("no preauth content") return preauth = json.loads(content) logging.trace("webauthn preauth:\n%s\n", json.dumps(preauth, indent=2)) qApp.setOverrideCursor(Qt.WaitCursor) self.authn_session_page.setUrl(QUrl(preauth["redirect_url"])) except (ValueError, Exception) as e: logging.error(format_exception(e)) self.set_current_html(ERROR_HTML % content) def _onLoadFinished(self, result): qApp.restoreOverrideCursor() qApp.processEvents() if not result: self.setPage(self.authn_session_page) logging.debug("Page load error: %s" % self.authn_session_page.url().toDisplayString()) return self.set_current_html(DEFAULT_HTML % self.auth_url.host()) path = self.authn_session_page.url().path() if path == "/authn/preauth": self.authn_session_page.toPlainText(self._onPreAuthContent) elif path == "/authn/session": self.authn_session_page.toPlainText(self._onSessionContent) else: if self.page() != self.authn_session_page: self.page().deleteLater() self.setPage(self.authn_session_page) def _onLoadProgress(self, progress): self.setStatus("Loading page: %s [%d%%]" % (self.page().url().host(), progress)) def _onCookieAdded(self, cookie): cookie_str = str(cookie.toRawForm(QNetworkCookie.NameAndValueOnly), encoding='utf-8') cookie_name = str(cookie.name(), encoding='utf-8') cookie_val = str(cookie.value(), encoding='utf-8') if (cookie_name == self.authn_cookie_name) and (cookie.domain() == self.config.get("host")): logging.trace("%s cookie added:\n\n%s\n\n" % (self.authn_cookie_name, cookie_str)) self.credential["cookie"] = "%s=%s" % (self.authn_cookie_name, cookie_val) host = self.auth_url.host() cred_entry = dict() cred_entry[host] = self.credential if self.credential_file: creds = read_credential(self.credential_file, create_default=True) creds.update(cred_entry) write_credential(self.credential_file, creds) self.token = cookie_val self._session.cookies.set(self.authn_cookie_name, cookie_val, domain=host, path='/') if self.cookie_jar is not None: self.cookie_jar.set_cookie( create_cookie(self.authn_cookie_name, cookie_val, domain=host, path='/', expires=0, discard=False, secure=True)) for path in self.config.get("cookie_jars", DEFAULT_CONFIG["cookie_jars"]): path_dir = os.path.dirname(path) if os.path.isdir(path_dir): logging.debug("Saving cookie jar to: %s" % path) self.cookie_jar.save(path, ignore_discard=True, ignore_expires=True) else: logging.debug("Cookie jar save path [%s] does not exist." % path_dir) def _onCookieRemoved(self, cookie): cookie_str = str(cookie.toRawForm(QNetworkCookie.NameAndValueOnly), encoding='utf-8') cookie_name = str(cookie.name(), encoding='utf-8') if cookie_name == self.authn_cookie_name and cookie.domain() == self.url().host(): logging.trace("%s cookie removed:\n\n%s\n\n" % (self.authn_cookie_name, cookie_str)) if self.cookie_jar: self.cookie_jar.clear(cookie_name, path=cookie.path(), domain=cookie.domain()) def _cleanup(self): self._timer.stop() self.token = None self.authn_session = None self.authn_expires = time.time() if self.authn_session_page: self.authn_session_page.loadProgress.disconnect(self._onLoadProgress) self.authn_session_page.loadFinished.disconnect(self._onLoadFinished) self.authn_session_page.profile().cookieStore().cookieAdded.disconnect(self._onCookieAdded) self.authn_session_page.profile().cookieStore().cookieRemoved.disconnect(self._onCookieRemoved) self.authn_session_page.deleteLater() self.authn_session_page = None
class TestForm(QMainWindow, Ui_MainWindow): #생성자 def __init__(self): super().__init__() self.init_my_location() self.setupUi(self) # 초기화 # self.url = "http://localhost:8080/umbrella" self.url = "http://localhost:8000/umbrella2.html" self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(QUrl(self.url)) self.page.setView(self.webEngineView) chrome_option = Options() #headless 모드 chrome_option.add_argument("--headless") #사운드 뮤트 chrome_option.add_argument("--mute-audio") # webdriver 설정(chrome) --headless self.browser = webdriver.Chrome( chrome_options=chrome_option, executable_path="webdriver/Chrome/chromedriver.exe") self.browser.get(self.url) self.runner = Runner(self.page, self.browser) self.comboBox.addItem("키워드") self.comboBox.addItem("주소") # self.page.featurePermissionRequested.connect(self.setPagePermission) # self.pushButton.clicked.connect(self.map_removeMarkers) # self.pushButton.clicked.connect(lambda: self.map_setLevel(random.randrange(7))) #현재위치 #self.pushButton.clicked.connect(lambda: self.coord_to_address(37.62244036,127.072065, 0)) #거리 self.pushButton.clicked.connect( lambda: self.getDistance([33.450500, 126.569968], [[ 33.450500, 126.569968 ], [35.404195, 126.886323], [39.668777, 126.065913]])) self.pushButton.clicked.connect(lambda: self.runner.coord_to_address( self.my_location_lat, self.my_location_lng, random.randrange(0, 5)) ) # self.pushButton.clicked.connect(lambda: self.getDistance([33.450500,126.569968],[[33.450500,126.569968],[35.404195,126.886323],[39.668777,126.065913]])) # self.pushButton.clicked.connect(self.test_a) # self.pushButton.clicked.connect(self.search) self.lineEdit.returnPressed.connect(self.search) self.page.loadFinished.connect( lambda: self.setMap(self.my_location_lat, self.my_location_lng)) # self.setMap(self.my_location_lat, self.my_location_lng) #아이피로 현재 위치 받아오기(google api 사용) def init_my_location(self): url = 'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyDQKxbTt0MrFNH85kTJXzickMD5s88UVaI' data = { 'considerIp': True, } result = requests.post(url, data) my_location = json.loads(result.text) # print(my_location) # print("lat : ",my_location.get('location').get('lat')) # print("lon : ",my_location.get('location').get('lng')) self.my_location_lat = my_location.get('location').get('lat') self.my_location_lng = my_location.get('location').get('lng') def test_a(self): script = """ return centerX.val() """ centerX = self.run(script) print(centerX) #위치권한 요청이 왔을때 허용해줌 def setPagePermission(self, url, feature): self.page.setFeaturePermission(url, feature, QWebEnginePage.PermissionGrantedByUser) def search(self): search_text = self.lineEdit.text().strip() if self.comboBox.currentIndex() == 0: script = """ removeMarkers(); // 주소-좌표 변환 객체를 생성합니다 var geocoder = new kakao.maps.services.Geocoder(); // 장소 검색 객체를 생성합니다 var ps = new kakao.maps.services.Places(); // 키워드로 장소를 검색합니다 ps.keywordSearch('""" + search_text + """', placesSearchCB); function placesSearchCB (data, status, pagination) { if (status === kakao.maps.services.Status.OK) { // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해 // LatLngBounds 객체에 좌표를 추가합니다 var bounds = new kakao.maps.LatLngBounds(); for (var i=0; i<data.length; i++) { displayMarker(data[i]); bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x)); } // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다 map.setBounds(bounds); } } """ elif self.comboBox.currentIndex(): script = """ removeMarkers(); // 주소-좌표 변환 객체를 생성합니다 var geocoder = new kakao.maps.services.Geocoder(); // 주소로 좌표를 검색합니다 geocoder.addressSearch('""" + search_text + """', function(result, status) { // 정상적으로 검색이 완료됐으면 if (status === kakao.maps.services.Status.OK) { var coords = new kakao.maps.LatLng(result[0].y, result[0].x); // 결과값으로 받은 위치를 마커로 표시합니다 var marker = new kakao.maps.Marker({ map: map, position: coords }); //*** 마커 담기 markerList.push(marker) // 인포윈도우로 장소에 대한 설명을 표시합니다 infowindow.open(map, marker); // 지도의 중심을 결과값으로 받은 위치로 이동시킵니다 map.setCenter(coords); } }); """ else: return self.run(script) #거리 계산하는 메소드 # center에는 기준좌표 [lat, lng] # pointList에는 측정할 좌표 리스트 [ [lat,lng] , [lat,lng] ....... ] #리턴값은 측정한 거리(int값) list ex) [ [0], [218667], [691542] ] #단위는 m def getDistance(self, center, pointList): # center가 None일 경우 # 기본값으로 '내위치'의 좌표 center = center or [self.my_location_lat, self.my_location_lng] script = """ var tmp_point_arr = """ + str(pointList) + """ var tmp_center = """ + str(center) + """ var tmp_div = $('#tmp_div'); var result_arr = new Array(); for(var i=0; i < tmp_point_arr.length; i++){ const polyline = new window.daum.maps.Polyline({ map : map, path : [ new window.daum.maps.LatLng(tmp_center[0], tmp_center[1]), new window.daum.maps.LatLng(tmp_point_arr[i][0], tmp_point_arr[i][1]) ], strokeWeight : 0 }); result_arr.push(polyline.getLength()); } return '['+result_arr.toString()+']'; """ result = list(map(int, eval(self.run(script)))) print(result) for i in result: print(f"거리 : {i}m, type : {type(i)}") return result #좌표로 주소 얻기 idx #0 : 지번주소 #1 : 지번주소 - 시도단위 #2 : 지번주소 - 구 단위 #3 : 지번주소 - 동 단위 #4 : 지번주소 - 우편번호(6자리) #없을경우 "" def coord_to_address(self, lat, lng, idx): if not idx in (0, 1, 2, 3, 4): idx = 0 result = "" print(lat) print(lng) script = """ go_py_result = '대기중' var coord = new kakao.maps.LatLng(""" + str(lat) + """, """ + str( lng) + """); var c2a = function(result, status) { tmp_div.append("result0 -"+result[0].address.address_name); //go_py_result = result[0].address.address_name; var idx = """ + str(idx) + """ if(idx === 0){ go_py_result = result[0].address.address_name; }else if(idx === 1){ go_py_result = result[0].address.region_1depth_name; }else if(idx === 2){ go_py_result = result[0].address.region_2depth_name; }else if(idx === 3){ go_py_result = result[0].address.region_3depth_name; }else if(idx === 4){ go_py_result = result[0].address.zip_code; }else{ go_py_result = result[0].address.address_name; } }; geocoder.coord2Address(coord.getLng(), coord.getLat(), c2a); """ script2 = "return go_py_result;" self.run(script) for i in range(50): result = self.run(script2) if result != "대기중": print("idx : ", idx, "c 2 a : ", result) return result break print("idx : ", idx, "c 2 a : ", result) return "" #지도 확대 레벨 설정 def map_setLevel(self, level): script = """ map.setLevel(""" + str(level) + """) """ self.run(script) #마커 다 지우는 메소드 def map_removeMarkers(self): script = """ removeMarkers(); """ self.run(script) #맵 이동 def setMap(self, lat, lng): script = """ var umbrella_location = new kakao.maps.LatLng(""" + str( lat) + """, """ + str(lng) + """); map.setCenter(umbrella_location); """ self.run(script) #스크립트 실행 def run(self, script): # print("run runJavaScript") self.page.runJavaScript(script) # print("run execute_Script") result = self.browser.execute_script(script) return result def marking(self, data): typeP = ["", "약국", "우체국", "농협"] for item in data: addr = item.get('addr') code = item.get('code') created_at = item.get('created_at') lat = item.get('lat') lng = item.get('lng') name = item.get('name') remain_stat = item.get('remain_stat') stock_at = item.get('stock_at') type = typeP[int(item.get('type'))] print( f"addr = {addr}\ncode = {code}\ncreated_at = {created_at}\nlat = {lat}\nlng = {lng}\nname = {name}\nremain_stat = {remain_stat}\nstock_at = {stock_at}\ntype = {type}" ) script = """ """ self.run(script)
class Umbrella(QMainWindow, Ui_MainWindow) : #생성자 def __init__(self) : super().__init__() self.init_my_location() self.setupUi(self) # 초기화 self.url = "http://localhost:8080/umbrella" # self.url = "http://localhost:8000/umbrella2.html" self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(QUrl(self.url)) self.page.setView(self.webEngineView) self.appLoaded = False chrome_option = Options() chrome_option.add_argument("--headless") chrome_option.add_argument("--mute-audio") self.browser = webdriver.Chrome(chrome_options=chrome_option, executable_path="resources/chromedriver.exe") self.browser.get(self.url) self.runner = Runner(self) self.dc = DataCollector() # self.comboBox.addItem("키워드") # self.comboBox.addItem("주소") self.itemList = [] self.rowList = [] # self.page.featurePermissionRequested.connect(self.setPagePermission) #page 변환 self.pushButton_3.clicked.connect(self.translate_ui) self.pushButton.clicked.connect(self.runner.map_removeMarkers) # self.pushButton.clicked.connect(self.map_removeMarkers) # self.pushButton.clicked.connect(self.runner.map_getLevel) # self.pushButton.clicked.connect(lambda: self.runner.map_setLevel(random.randrange(7))) # self.pushButton.clicked.connect(lambda: self.runner.coord_to_address(self.my_location_lat,self.my_location_lng, random.randrange(0,5))) # self.pushButton.clicked.connect(lambda: self.getDistance([33.450500,126.569968],[[33.450500,126.569968],[35.404195,126.886323],[39.668777,126.065913]])) # self.pushButton.clicked.connect(self.test_a) # self.pushButton.clicked.connect(self.search) self.lineEdit.returnPressed.connect(lambda: self.runner.search(self.lineEdit.text().strip())) self.pushButton.clicked.connect(lambda: self.runner.search(self.lineEdit.text().strip())) self.page.loadFinished.connect(lambda: self.runner.setMap(self.my_location_lat, self.my_location_lng)) # self.setMap(self.my_location_lat, self.my_location_lng) self.pushButton2.clicked.connect(self.mark_around) self.pushButton3.clicked.connect(lambda: self.runner.setMap(self.my_location_lat,self.my_location_lng)) self.page.urlChanged.connect(self.setButton) self.listWidget.itemActivated.connect(self.activateRow) # self.lineEdit.setText(self.runner.coord_to_address(self.my_location_lat,self.my_location_lng, 0)) self.lineEdit.setText(self.runner.coord_to_address(self.my_location_lat,self.my_location_lng, 0)) def translate_ui(self) : print('aaaaaaaa') self.stackedWidget.setCurrentIndex(1) def mark_around(self) : self.remove_list() if not self.page.url().toString().strip().startswith("http://localhost:8080/umbrella") : self.page.load(QUrl(self.url)) return self.runner.map_removeMarkers() lat, lng = self.runner.map_getCenter() data = self.dc.get_data_by_latlng(lat, lng, 1000) self.runner.marking(data) self.show_list(data) self.lineEdit.setText(self.runner.coord_to_address(lat, lng, 0)) def init_my_location(self) : url = 'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyDQKxbTt0MrFNH85kTJXzickMD5s88UVaI' data = { 'considerIp': True, } result = requests.post(url, data) my_location = json.loads(result.text) # print(my_location) # print("lat : ",my_location.get('location').get('lat')) # print("lon : ",my_location.get('location').get('lng')) self.my_location_lat = str(my_location.get('location').get('lat')) self.my_location_lng = str(my_location.get('location').get('lng')) def setButton(self) : if self.page.url().toString().strip().startswith("http://localhost:8080/umbrella") : self.pushButton2.setText("판매처 탐색") else : self.pushButton2.setText("지도 새로고침") def show_list(self, data) : for i in range(len(data)) : item = QListWidgetItem(self.listWidget) row = Item(data[i]) item.setWhatsThis(str(i)) item.setSizeHint(row.sizeHint()) self.listWidget.setItemWidget(item, row) self.listWidget.addItem(item) self.itemList.append(item) self.rowList.append(row) def remove_list(self) : for i in range(len(self.itemList)) : self.itemList[i].setHidden(True) self.itemList = [] self.rowList = [] def activateRow(self, row) : self.runner.setMap(self.rowList[int(row.whatsThis())].lat,self.rowList[int(row.whatsThis())].lng) self.runner.info_open(self.rowList[int(row.whatsThis())].code) # self.runner.map_setLevel(2) pass
class TestForm(QMainWindow, Ui_MainWindow): #생성자 def __init__(self): super().__init__() self.setupUi(self) # 초기화 self.url = QUrl("http://localhost:8080/umbrella") self.webEngineView.load(QUrl(self.url)) self.page = QWebEnginePage() self.page.setUrl(self.url) self.page.setView(self.webEngineView) self.comboBox.addItem("키워드") self.comboBox.addItem("주소") # self.page.featurePermissionRequested.connect(self.setPagePermission) self.pushButton.clicked.connect(self.search) self.lineEdit.returnPressed.connect(self.search) self.init_my_location() self.page.loadFinished.connect( lambda: self.setMap(self.my_location_lat, self.my_location_lng)) # self.setMap(self.my_location_lat, self.my_location_lng) #아이피로 현재 위치 받아오기(google api 사용) def init_my_location(self): url = 'https://www.googleapis.com/geolocation/v1/geolocate?key=AIzaSyDQKxbTt0MrFNH85kTJXzickMD5s88UVaI' data = { 'considerIp': True, } result = requests.post(url, data) my_location = json.loads(result.text) # print(my_location) print("lat : ", my_location.get('location').get('lat')) print("lon : ", my_location.get('location').get('lng')) self.my_location_lat = my_location.get('location').get('lat') self.my_location_lng = my_location.get('location').get('lng') def setMap(self, lat, lng): script = """ var umbrella_location = new kakao.maps.LatLng(""" + str( lat) + """, """ + str(lng) + """); map.setCenter(umbrella_location); """ self.run(script) #위치권한 요청이 왔을때 허용해줌 def setPagePermission(self, url, feature): self.page.setFeaturePermission(url, feature, QWebEnginePage.PermissionGrantedByUser) def search(self): search_text = self.lineEdit.text().strip() if self.comboBox.currentIndex() == 0: script = """ removeMarkers(); // 주소-좌표 변환 객체를 생성합니다 var geocoder = new kakao.maps.services.Geocoder(); // 장소 검색 객체를 생성합니다 var ps = new kakao.maps.services.Places(); // 키워드로 장소를 검색합니다 ps.keywordSearch('""" + search_text + """', placesSearchCB); function placesSearchCB (data, status, pagination) { if (status === kakao.maps.services.Status.OK) { // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해 // LatLngBounds 객체에 좌표를 추가합니다 var bounds = new kakao.maps.LatLngBounds(); for (var i=0; i<data.length; i++) { displayMarker(data[i]); bounds.extend(new kakao.maps.LatLng(data[i].y, data[i].x)); } // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다 map.setBounds(bounds); } } """ elif self.comboBox.currentIndex(): script = """ removeMarkers(); var positions = []; positions=Marker3.main3(); for (var i=0; i<positions.length;i++){ map:map, position:new kakao.maps.LatLng(positions[i].get('lat')+positions[i].get('lng')) } // 주소-좌표 변환 객체를 생성합니다 var geocoder = new kakao.maps.services.Geocoder(); // 주소로 좌표를 검색합니다 geocoder.addressSearch('""" + search_text + """', function(result, status) { // 정상적으로 검색이 완료됐으면 if (status === kakao.maps.services.Status.OK) { var coords = new kakao.maps.LatLng(result[0].y, result[0].x); // 결과값으로 받은 위치를 마커로 표시합니다 var marker = new kakao.maps.Marker({ map: map, position: coords }); //*** 마커 담기 markerList.push(marker) // 인포윈도우로 장소에 대한 설명을 표시합니다 infowindow.open(map, marker); // 지도의 중심을 결과값으로 받은 위치로 이동시킵니다 map.setCenter(coords); } }); """ else: return self.run(script) def run(self, script): self.page.runJavaScript(script)
class Browser(QMainWindow): def __init__(self, mainWin, webview=None): super().__init__(mainWin) self.showFullScreen() self.mainWin = mainWin self.webview = webview self.initUI() def initUI(self): global CREATE_BROWER # print("initUI") # self.setWindowFlags(Qt.FramelessWindowHint) # 去掉标题栏的代码 # 设置窗口标题 # self.setWindowTitle('LingBrowser') # 设置窗口图标 self.setWindowIcon(QIcon(':/icons/logo.png')) self.page = QWebEnginePage() self.page.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True) # 支持视频播放 self.page.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True) self.page.settings().setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True) if self.webview == None: # 初始化一个 tab self.webview = WebView(self) # self必须要有,是将主窗口作为参数,传给浏览器 self.page.setUrl(QUrl(HOME_PAGE)) self.page.windowCloseRequested.connect(self.on_windowCloseRequested) # 页面关闭请求 if CREATE_BROWER: CREATE_BROWER = False self.page.profile().downloadRequested.connect(self.on_downloadRequested) # 页面下载请求 self.t = WebEngineUrlRequestInterceptor() self.page.profile().setRequestInterceptor(self.t) self.webview.setPage(self.page) self.url = self.webview.page().url() self.initToolbar(self.webview) self.setCentralWidget(self.webview) self.center() def on_downloadRequested(self, downloadItem): # print("download..") # print(downloadItem.downloadFileName()) # print('isFinished', downloadItem.isFinished()) # print('isPaused', downloadItem.isPaused()) # print('isSavePageDownload', downloadItem.isSavePageDownload()) # print('path', downloadItem.path()) # print('url', downloadItem.url()) downloadFileName, ok2 = QFileDialog.getSaveFileName(self, "文件保存", downloadItem.path(), "All Files (*)") print(downloadItem.path()) downloadItem.setPath(downloadFileName) downloadItem.accept() downloadItem.finished.connect(self.on_downloadfinished) downloadItem.downloadProgress.connect(self.on_downloadProgress) def on_downloadfinished(self): print() def on_downloadProgress(self, int_1, int_2): rate = str(round(int_1 / int_2, 2) * 100).split(".")[0] self.mainWin.statusBarDownloadLabel.setText("文件下载 " + rate + "%") if int(rate) == 100: self.mainWin.statusBarDownloadLabel.setHidden(True) self.mainWin.statusBar.setHidden(True) else: self.mainWin.statusBarDownloadLabel.setHidden(False) self.mainWin.statusBar.setHidden(False) def on_windowCloseRequested(self): print("close tab") # self.webview.close() # del self.webview # sip.delete(self.webview) # self.webview # self.webview.page().profile().deleteLater() # self.deleteLater() pass def moreMenuShow(self): try: self.contextMenu = QMenu() self.contextMenu.setObjectName("moreMenu") self.contextMenu.setFont(fontawesome("far")) # self.actionA = self.contextMenu.addAction(self.zoom_in_action) # self.actionA = self.contextMenu.addAction(self.zoom_out_action) self.contextMenu.popup( QPoint(self.mainWin.x() + self.more_button.x() - 200, self.mainWin.y() + 75)) # 2菜单显示的位置 QCursor.pos() # print(self.more_button.x()) # print(self.more_button.y()) # print(self.frameGeometry()) # print(self.mainWin.x()) # print(self.mainWin.y()) self.contextMenu.setContentsMargins(25,0,0,0) self.contextMenu.addMenu("打印") self.contextMenu.addSeparator() # 缩放组合 sf_widget = QWidget(self) sf_widget.setProperty("class","qwidget") sf_widget.setObjectName("sf_widget") sf_widget.setContentsMargins(0,0,0,0) # sf_widget.setFixedHeight(20) sf_layout = QHBoxLayout() sf_layout.setContentsMargins(0,0,0,0) sf_widget.setLayout(sf_layout) sf_label = QLabel("缩放") sf_label.setObjectName("sf_item_label") sf_layout.addWidget(sf_label) sf_layout.addWidget(self.zoom_out_button) sf_layout.addWidget(self.sf_label_rate) sf_layout.addWidget(self.zoom_in_button) sf_layout.addWidget(self.full_screen_button) sf_action = QWidgetAction(self) sf_action.setDefaultWidget(sf_widget) self.actionA = self.contextMenu.addAction(sf_action) # self.actionA.triggered.connect(self.actionHandler) sf_layout.setSpacing(0) self.contextMenu.show() except Exception as e: print(e) def initToolbar(self, webview): pass ###使用QToolBar创建导航栏,并使用QAction创建按钮 # 添加导航栏 self.navigation_bar = QToolBar('Navigation') # 锁定导航栏 self.navigation_bar.setMovable(False) # 设定图标的大小 self.navigation_bar.setIconSize(QSize(2, 2)) # 添加导航栏到窗口中 self.addToolBar(self.navigation_bar) # 添加其它配置 self.navigation_bar.setObjectName("navigation_bar") self.navigation_bar.setCursor(Qt.ArrowCursor) # QAction类提供了抽象的用户界面action,这些action可以被放置在窗口部件中 # 添加前进、后退、停止加载和刷新的按钮 self.reload_icon = unichr(0xf2f9) self.stop_icon = unichr(0xf00d) # 后退按钮 self.back_action = QWidgetAction(self) self.back_button = QPushButton(unichr(0xf060), self, clicked=webview.back, font=fontawesome("far"), objectName='back_button') self.back_button.setToolTip("后退") self.back_button.setCursor(Qt.ArrowCursor) self.back_action.setDefaultWidget(self.back_button) # 前进按钮 self.next_action = QWidgetAction(self) self.next_button = QPushButton(unichr(0xf061), self, clicked=webview.forward, font=fontawesome("far"), objectName='next_button') self.next_button.setToolTip("前进") self.next_button.setCursor(Qt.ArrowCursor) self.next_action.setDefaultWidget(self.next_button) # 刷新与停止按钮 self.reload_action = QWidgetAction(self) self.reload_button = QPushButton(self.reload_icon, self, clicked=webview.reload, font=fontawesome("far"), objectName='reload_button') self.reload_button.setToolTip("刷新") self.reload_button.setCursor(Qt.ArrowCursor) self.reload_action.setDefaultWidget(self.reload_button) # 放大按钮 self.zoom_in_button = QPushButton(unichr(0xf067), self, clicked=self.zoom_in_func, font=fontawesome("far"), objectName='zoom_in_btn') self.zoom_in_button.setToolTip("放大") self.zoom_in_button.setCursor(Qt.ArrowCursor) # 缩小按钮 self.zoom_out_button = QPushButton(unichr(0xf068), self, clicked=self.zoom_out_func, font=fontawesome("far"), objectName='zoom_out_btn') self.zoom_out_button.setToolTip("缩小") self.zoom_out_button.setCursor(Qt.ArrowCursor) self.sf_label_rate = QLabel() self.sf_label_rate.setObjectName("sf_label_rate") self.sf_label_rate.setFixedWidth(30) self.sf_label_rate.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter) self.sf_label_rate.setProperty("class","qlabel") self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%") # 全屏按钮 self.full_screen_button = QPushButton(unichr(0xe140), self, clicked=self.full_screen_func, font=fontawesome("boot"), objectName='full_screen_button') self.full_screen_button.setToolTip("全屏") self.full_screen_button.setCursor(Qt.ArrowCursor) # 其它按钮 self.more_action = QWidgetAction(self) self.more_button = QPushButton(unichr(0xe235), self, clicked=self.moreMenuShow, font=fontawesome("boot"), objectName='more_button') self.more_button.setToolTip("页面控制及浏览器核心") self.more_button.setCursor(Qt.ArrowCursor) self.more_action.setDefaultWidget(self.more_button) # 首页按钮 self.index_action = QWidgetAction(self) self.index_button = QPushButton(unichr(0xf015), self, # clicked=self.zoom_out_func, font=fontawesome("far"), objectName='index_button') self.index_button.setToolTip("主页") self.index_button.setCursor(Qt.ArrowCursor) self.index_action.setDefaultWidget(self.index_button) # self.back_button.triggered.connect(webview.back) # self.next_button.triggered.connect(webview.forward) # self.reload_button.triggered.connect(webview.reload) # self.zoom_in_btn.triggered.connect(self.zoom_in_func) # self.zoom_out_btn.triggered.connect(self.zoom_out_func) # 将按钮添加到导航栏上 self.navigation_bar.addAction(self.back_action) self.navigation_bar.addAction(self.next_action) self.navigation_bar.addAction(self.reload_action) self.navigation_bar.addAction(self.index_action) # 添加URL地址栏 self.urlbar = QLineEdit() # 让地址栏能响应回车按键信号 self.urlbar.returnPressed.connect(self.navigate_to_url) # self.navigation_bar.addSeparator() self.navigation_bar.addWidget(self.urlbar) # self.navigation_bar.addSeparator() # self.navigation_bar.addAction(self.zoom_in_action) # self.navigation_bar.addAction(self.zoom_out_action) self.navigation_bar.addAction(self.more_action) # 让浏览器相应url地址的变化 webview.urlChanged.connect(self.renew_urlbar) webview.loadProgress.connect(self.processLoad) webview.loadStarted.connect(self.loadPage) webview.loadFinished.connect(self.loadFinish) webview.titleChanged.connect(self.renew_title) webview.iconChanged.connect(self.renew_icon) self.webBind() webview.show() self.navigation_bar.setIconSize(QSize(20, 20)) self.urlbar.setFont(QFont('SansSerif', 13)) def zoom_in_func(self): self.webview.setZoomFactor(self.webview.zoomFactor() + 0.1) self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%") def zoom_out_func(self): self.webview.setZoomFactor(self.webview.zoomFactor() - 0.1) self.sf_label_rate.setText(str(int(self.webview.zoomFactor()*100))+"%") def full_screen_func(self): self.navigation_bar.setHidden(True) self.mainWin.titleBar.setHidden(True) self.mainWin.showFullScreen() def on_network_call(self, info): print(info) pass def loadPage(self): # print("loadPage") # print(self.webview.objectName()) # self.renew_title("空页面") index = self.mainWin.tabWidget.currentIndex() self.mainWin.tabWidget.setTabIcon(index, QIcon(":icons/earth_128.png")) # self.reload_button.setDefaultWidget(self.stop_button_icon) self.reload_button.setText(self.stop_icon) self.reload_button.setToolTip("停止") def processLoad(self, rate): self.mainWin.statusBarLabelProgress.setValue(rate) self.mainWin.statusBarLabel.setText("网页加载") if rate == 0: self.mainWin.statusBarLabelProgress.setMaximum(0) self.mainWin.statusBarLabelProgress.setMinimum(0) else: self.mainWin.statusBarLabelProgress.setMaximum(0) self.mainWin.statusBarLabelProgress.setMinimum(100) if rate == 100: self.mainWin.statusBarLabelProgress.setHidden(True) self.mainWin.statusBarLabel.setHidden(True) self.mainWin.statusBar.setHidden(True) else: self.mainWin.statusBarLabelProgress.setHidden(False) self.mainWin.statusBarLabel.setHidden(False) self.mainWin.statusBar.setHidden(False) pass def loadFinish(self, isEnd): if isEnd: # print("load finished", isEnd) # self.reload_button.setDefaultWidget(self.reload_button_icon) self.reload_button.setText(self.reload_icon) self.reload_button.setToolTip("刷新") else: # print("load finished", isEnd) # print("load finished",isEnd) pass # index = self.webview.objectName() # title = self.page.title() # print("title", title) try: url = self.page.url().toString() except BaseException as base: url = self.webview.page().url().toString() # self.mainWin.tabWidget.setTabText(int(index), title if title else url) self.urlbar.setText(url) def webBind(self): # print("webBind") # self.back_button.disconnect() # self.next_button.disconnect() # self.stop_button.disconnect() # self.reload_button.disconnect() # self.add_button.disconnect() # self.back_button.triggered.connect(self.webview.back) # self.next_button.triggered.connect(self.webview.forward) # self.stop_button.triggered.connect(self.webview.stop) # self.reload_button.triggered.connect(self.webview.reload) # self.add_button.triggered.connect(self.mainWin.newTab) self.webview.urlChanged.connect(self.renew_urlbar) self.webview.titleChanged.connect(self.renew_title) self.webview.iconChanged.connect(self.renew_icon) def navigate_to_url(self): q = QUrl(self.urlbar.text()) if q.scheme() == '': q.setScheme('http') self.webview.setUrl(q) def renew_urlbar(self, url): # 将当前网页的链接更新到地址栏 # print("renew_urlbar") self.urlbar.setText(url.toString()) self.urlbar.setCursorPosition(0) # print("url", url)f def renew_title(self, title): # 将当前网页的标题更新到标签栏 index = self.webview.objectName() self.mainWin.tabWidget.setTabToolTip(int(index), title) title = " " + title[:11] + ".." if len(title) >= 12 else " " + title self.mainWin.tabWidget.setTabText(int(index), title) pass def renew_icon(self, icon): # 将当前网页的图标更新到标签栏 # print("renew_icon") index = self.webview.objectName() self.mainWin.tabWidget.setTabIcon(int(index), icon) def center(self): # print("center") qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) # 创建tab def create_tab(self, webview): # print("create_tab") self.tab = QWidget() self.mainWin.tabWidget.addTab(self.tab, "新标签页") self.mainWin.tabWidget.setCurrentWidget(self.tab) index = self.mainWin.tabWidget.currentIndex() # self.mainWin.tabWidget.setTabIcon(index, ":icons/logo.png") ##### self.Layout = QVBoxLayout(self.tab) self.Layout.setContentsMargins(0, 0, 0, 0) self.Layout.addWidget(Browser(self.mainWin, webview=webview)) webview.setObjectName(str(index)) self.mainWin.tab_[str(index)] = webview self.tab.setObjectName("tab_" + str(index))
class MainWindow(QMainWindow): error = pyqtSignal(str) def __init__(self): super().__init__() self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowIcon(readIcon) # permalinks of comments we already notified the user of self.permalinks = [] self.quitting = False self.error.connect(self.showError) # Logger self.fileHandler = None self.handler = Handler() self.handler.newMessage.connect(self.logMessage) s = QSettings(orgName, appName) level = s.value('misc/loglevel', defaultLevel, type=int) self.handler.setLevel(logLevels[level]) self.handler.setFormatter(logging.Formatter(logFormat)) logging.getLogger().addHandler(self.handler) self.updateLogger() # Auto search self.model = Model() self.model.statusMessage.connect(self.showStatusMessage) self.model.progress.connect(self.showProgress) self.updateAutoSearch() self.autoSearchPage = QWebEnginePage() self.autoSearchPage.loadFinished.connect(self.searchPageLoaded) self.progressBar = QProgressBar() self.progressBar.setTextVisible(False) self.progressBar.setMaximumWidth(100) self.progressBar.setMinimum(0) self.progressBar.setMaximum(99) self.statusBar().addPermanentWidget(self.progressBar) self.progressBar.hide() self.delegate = ItemDelegate() self.fontSize = 14 self.ui.treeView.setHeaderHidden(True) self.ui.treeView.setIconSize(QSize(40, 40)) self.ui.treeView.setStyleSheet("QTreeView {{font-size: {}pt;}}".format( self.fontSize)) self.ui.treeView.setModel(self.model) self.ui.treeView.setItemDelegate(self.delegate) self.ui.treeView.hideColumn(1) self.ui.treeView.setContextMenuPolicy(Qt.CustomContextMenu) self.ui.treeView.customContextMenuRequested.connect(self.onCustomMenu) bookmarks = s.value('bookmarks/bookmarks_list', '') self.bookmarksList = [ baseUrl(line) for line in bookmarks.split('\n') if baseUrl(line) ] self.bookmarksList = list(dict.fromkeys(self.bookmarksList)) self.bookmarksModel = BookmarksModel(self.bookmarksList) self.bookmarksModel.setSourceModel(self.model) self.ui.bookmarksTreeView.setHeaderHidden(True) self.ui.bookmarksTreeView.setIconSize(QSize(40, 40)) self.ui.bookmarksTreeView.setStyleSheet( "QTreeView {{font-size: {}pt;}}".format(self.fontSize)) self.ui.bookmarksTreeView.setModel(self.bookmarksModel) self.ui.bookmarksTreeView.setItemDelegate(self.delegate) self.ui.bookmarksTreeView.hideColumn(1) self.ui.bookmarksTreeView.setContextMenuPolicy(Qt.CustomContextMenu) self.ui.bookmarksTreeView.customContextMenuRequested.connect( self.onCustomMenu) # Tray icon self.ui.prefsAction.triggered.connect(self.showPrefs) self.ui.refreshAction.triggered.connect(self.refresh) self.ui.quitAction.triggered.connect(self.quit) self.ui.zoomInAction.triggered.connect(self.zoomIn) self.ui.zoomOutAction.triggered.connect(self.zoomOut) minimizeAction = QAction("Mi&nimize", self) minimizeAction.triggered.connect(self.hide) restoreAction = QAction("&Restore", self) restoreAction.triggered.connect(self.show) trayMenu = QMenu(self) trayMenu.addAction(minimizeAction) trayMenu.addAction(restoreAction) trayMenu.addAction(self.ui.prefsAction) trayMenu.addAction(self.ui.refreshAction) trayMenu.addAction(self.ui.quitAction) self.trayIcon = QSystemTrayIcon() self.trayIcon.setContextMenu(trayMenu) self.trayIcon.activated.connect(self.iconActivated) self.trayIcon.setIcon(readIcon) self.trayIcon.setVisible(True) self.ui.webView.loadStarted.connect( lambda self=self: self.ui.urlLineEdit.setText(self.ui.webView.url( ).toString())) self.ui.webView.loadFinished.connect(self.loadFinished) self.ui.urlLineEdit.returnPressed.connect( lambda self=self: self.ui.webView.setUrl( QUrl(self.ui.urlLineEdit.text()))) self.ui.webView.setUrl(stUrl) self.timer = QTimer() self.timer.timeout.connect(self.refresh) self.updateInterval(s.value('misc/interval', defaultInterval, type=int)) self.timer.start() self.messagesPage = QWebEnginePage() self.messagesPage.loadFinished.connect(self.messagesPageLoaded) self.refresh() def zoomIn(self): currentIndex = self.ui.tabWidget.currentIndex() if currentIndex == 0: self.ui.webView.setZoomFactor(self.ui.webView.zoomFactor() + 0.25) elif currentIndex == 1 or currentIndex == 2: if self.fontSize >= 20: return self.fontSize += 1 self.ui.treeView.setStyleSheet( "QTreeView {{font-size: {}pt;}}".format(self.fontSize)) self.ui.bookmarksTreeView.setStyleSheet( "QTreeView {{font-size: {}pt;}}".format(self.fontSize)) elif currentIndex == 3: self.ui.logTextEdit.zoomIn() def zoomOut(self): currentIndex = self.ui.tabWidget.currentIndex() if currentIndex == 0: self.ui.webView.setZoomFactor(self.ui.webView.zoomFactor() - 0.25) elif currentIndex == 1 or currentIndex == 2: if self.fontSize <= 8: return self.fontSize -= 1 self.ui.treeView.setStyleSheet( "QTreeView {{font-size: {}pt;}}".format(self.fontSize)) self.ui.bookmarksTreeView.setStyleSheet( "QTreeView {{font-size: {}pt;}}".format(self.fontSize)) elif currentIndex == 3: self.ui.logTextEdit.zoomOut() def onCustomMenu(self, point): sender = self.sender() index = sender.indexAt(point) urlIndex = index.siblingAtColumn(1) url = str(sender.model().data(urlIndex, role=Qt.DisplayRole)) url = baseUrl(url) if not url: return self.contextMenu = QMenu() action = QAction("Copy url", self.contextMenu) action.triggered.connect( lambda checked, arg=url: QApplication.clipboard().setText(arg)) self.contextMenu.addAction(action) action = QAction("Open in browser", self.contextMenu) action.triggered.connect( lambda checked, self=self, url=url: self.toBrowser(url)) self.contextMenu.addAction(action) action = QAction("Open in default browser", self.contextMenu) action.triggered.connect(lambda checked, arg=url: subprocess.call( [sys.executable, '-m', 'webbrowser', '-t', arg])) self.contextMenu.addAction(action) if url not in self.bookmarksList: enabled = True action = QAction("Add to bookmarks", self.contextMenu) else: enabled = False action = QAction("Remove from bookmarks", self.contextMenu) action.triggered.connect(lambda checked, self=self, url=url, enabled= enabled: self.setBookmarked(url, enabled)) self.contextMenu.addAction(action) action = QAction("Check now", self.contextMenu) action.triggered.connect( lambda checked, self=self, url=url: self.model.checkNow(url)) self.contextMenu.addAction(action) self.contextMenu.exec(sender.viewport().mapToGlobal(point)) def setBookmarked(self, url, enabled): bookmarked = url in self.bookmarksList s = QSettings(orgName, appName) if bookmarked and not enabled: self.bookmarksList.remove(url) elif enabled and not bookmarked: self.bookmarksList.append(url) self.bookmarksModel.invalidate() s.setValue('bookmarks/bookmarks_list', '\n'.join(self.bookmarksList)) def toBrowser(self, url): self.ui.webView.setUrl(QUrl(url)) self.ui.tabWidget.setCurrentIndex(0) def logMessage(self, msg): self.ui.logTextEdit.appendPlainText(msg) def updateLogLevel(self, newLevel): logging.debug('setting log level ' + str(newLevel)) logging.getLogger().setLevel(logLevels[newLevel]) for h in logging.getLogger().handlers: h.setLevel(logLevels[newLevel]) def updateLogger(self): logging.debug("updating logger handlers") s = QSettings(orgName, appName) if self.fileHandler: logging.getLogger().removeHandler(self.fileHandler) self.fileHandler = None if s.value('logfile/enable', False, type=bool): f = s.value('logfile/filename', defaultLogfile) if not os.path.isabs(f): f = os.path.join(baseDir, f) logging.debug('new file handler for ' + f) fileHandler = logging.FileHandler(f) level = s.value('misc/loglevel', defaultLevel, type=int) fileHandler.setLevel(logLevels[level]) fileHandler.setFormatter(logging.Formatter(logFormat)) self.fileHandler = fileHandler logging.getLogger().addHandler(self.fileHandler) def updateAutoSearch(self): s = QSettings(orgName, appName) self.autoSearchEnabled = s.value('autosearch/enable', False, type=bool) haveListStr = s.value('autosearch/have_list', '') haveList = [ line.strip().lower() for line in haveListStr.split('\n') if line.strip() ] wantListStr = s.value('autosearch/want_list', '') wantList = [ line.strip().lower() for line in wantListStr.split('\n') if line.strip() ] self.model.updateLists(haveList, wantList) def searchPageLoaded(self, ok): if not ok: logging.warning('Failed to load URL: ' + stUrl.toString()) return self.autoSearchPage.toHtml(self.model.parseSearchResults) def refresh(self): self.messagesPage.setUrl(messagesUrl) if not self.autoSearchEnabled: return self.autoSearchPage.setUrl(stUrl) for url in self.bookmarksList: self.model.queueUrl(url, False) def updateInterval(self, newInterval): logging.info( 'setting refresh interval: {} minutes'.format(newInterval)) self.timer.setInterval(newInterval * 1000 * 60) def quit(self): self.trayIcon.setVisible(False) self.quitting = True self.model.cancelAll.emit() self.statusBar().showMessage('Waiting for worker threads...') QThreadPool.globalInstance().waitForDone() QApplication.setQuitOnLastWindowClosed(True) self.close() def loadFinished(self, ok): if not ok: logging.warning('failed to load URL: ' + self.ui.webView.url().toString()) return self.ui.urlLineEdit.setText(self.ui.webView.url().toString()) self.ui.urlLineEdit.setCursorPosition(0) if not self.autoSearchEnabled: return url = self.ui.webView.url().toString() if url == stUrl.toString() or url.startswith( 'https://www.steamtrades.com/trades/search'): self.ui.webView.page().toHtml(self.model.parseSearchResults) elif url.startswith('https://www.steamtrades.com/trade/'): self.model.queueUrl(url, False) def messagesPageLoaded(self, ok): if not ok: logging.warning('failed to load URL: ' + self.messagesPage.url().toString()) return self.messagesPage.toHtml(self.checkMessages) def closeEvent(self, event): if not self.quitting: self.hide() event.ignore() else: event.accept() def iconActivated(self, reason): if reason == QSystemTrayIcon.Context or reason == QSystemTrayIcon.Trigger: return if self.isVisible(): self.hide() else: self.show() def showPrefs(self): d = PrefsDialog(self) d.intervalChanged.connect(self.updateInterval) d.loglevelChanged.connect(self.updateLogLevel) d.logfileChanged.connect(self.updateLogger) d.autoSearchChanged.connect(self.updateAutoSearch) d.exec_() def showError(self, message): self.trayIcon.showMessage('', message, QSystemTrayIcon.Warning) def showStatusMessage(self, message): self.statusBar().showMessage(message, 5000) def showProgress(self, percent): if percent >= 0 and percent <= 99: self.progressBar.setValue(percent) if self.progressBar.isHidden(): self.progressBar.show() else: self.progressBar.hide() def onMailError(self, msg, permalink): self.showError(msg) if permalink in self.permalinks: self.permalinks.remove(permalink) def checkMessages(self, page): url = self.messagesPage.url() logging.info('loaded page ' + url.toString()) soup = BeautifulSoup(page, 'html.parser') if url.host() == 'www.steamtrades.com' or url.host( ) == 'steamtrades.com': if '<span>Messages' not in page: logging.warning( 'log in to SteamTrades to receive message notifications') return if url != messagesUrl: return messageCount = soup.find('span', attrs={'class': 'message_count'}) if not messageCount: self.trayIcon.setIcon(readIcon) self.setWindowIcon(readIcon) return logging.debug('message count:' + messageCount.text) self.trayIcon.setIcon(unreadIcon) self.setWindowIcon(unreadIcon) try: parsed = 0 for comment in soup.find_all('div', attrs={'class': 'comment_inner'}): if parsed >= int(messageCount.text): break if comment.find('div', attrs={'class': 'comment_unread'}) == None: continue parsed += 1 author = comment.find('a', attrs={ 'class': 'author_name' }).text.strip() message = comment.find('div', attrs={ 'class': 'comment_body_default markdown' }).text.strip() permalink = comment.find_all('a')[-1]['href'] if permalink not in self.permalinks: logging.debug('unread comment: \n' + str(comment)) logging.debug('author: ' + author) logging.debug('message: \n' + message) logging.debug('permalink:' + permalink) self.trayIcon.showMessage("New message from " + author, message) s = QSettings(orgName, appName) if s.value('email/notify', False, type=bool): sender = s.value('email/sender') recipient = s.value('email/recipient') smtpServer = s.value('email/host') smtpPort = s.value('email/port') encryption = s.value( 'email/encryption_type') if s.value( 'email/encrypt', False, type=bool) else '' username = s.value('email/username') if s.value( 'email/login', False, type=bool) else '' password = '' try: if s.value('email/login', False, type=bool): password = keyring.get_password( sysName, "email/password") except Exception as e: logging.warning( 'Cannot read password from keyring: ' + str(e)) mailSender = MailSender(sender, recipient, smtpServer, smtpPort, encryption, username, password,\ messageTemplate.format(sender = sender, recipient = recipient, count = messageCount.text, author = author, message = message), permalink) logging.info('sending email...') mailSender.emitter.error.connect(self.onMailError) QThreadPool.globalInstance().start(mailSender) self.permalinks.append(permalink) except Exception as e: logging.error(str(e)) self.error.emit(str(e))
class Worker(QRunnable): def __init__(self, url, haveList=[], wantList=[], id_=-1): super().__init__() self.url = url self.haveList = haveList self.wantList = wantList self.id_ = id_ self.state = WorkerState.PENDING self.mutex = QMutex() self.emitter = Emitter() self.page = QWebEnginePage() self.html = '' self.page.loadFinished.connect(self.loadFinished) self.page.setUrl(QUrl(self.url)) # Set timeout to 3 minutes QTimer.singleShot(3 * 60 * 1000, self.cancel) def changeState(self, new, old=None): mutexLocker = QMutexLocker(self.mutex) if not old or old == self.state: self.state = new return True def run(self): if not self.changeState(WorkerState.RUNNING, WorkerState.PENDING): return try: soup = BeautifulSoup(self.html, 'html.parser') closedTag = soup.find('div', attrs={'class': 'notification yellow'}) if closedTag and closedTag.text.startswith('Closed'): title = 'Closed' else: title = soup.find('div', attrs={ 'class': 'page_heading' }).find('h1').text style = soup.find('div', attrs={ 'class': 'comment_inner' }).find('a', attrs={'class': 'author_avatar'})['style'] res = re.findall('url\((.*)\);', style) if len(res) == 1: iconUrl = res[0] else: iconUrl = '' self.emitter.updateName.emit(self.id_, title) self.emitter.updateIconUrl.emit(self.id_, iconUrl) h = soup.find('div', attrs={'class': 'have markdown'}) if h: hls = h.text.split('\n') for g in self.wantList: for hl in hls: if g in hl.lower(): self.emitter.newNode.emit(self.id_, '[H] ' + hl, NodeType.H_GAME) h = soup.find('div', attrs={'class': 'want markdown'}) if h: hls = h.text.split('\n') for g in self.haveList: for hl in hls: if g in hl.lower(): self.emitter.newNode.emit(self.id_, '[W] ' + hl, NodeType.W_GAME) except Exception as e: logging.error('Error parsing trade page: ' + str(e)) self.changeState(WorkerState.FINISHED) self.emitter.finished.emit(self.id_) def loadFinished(self, ok): if not ok: logging.warning('Failed to load page: ' + self.url) self.changeState(WorkerState.FINISHED) self.emitter.loadError.emit(self.id_) self.emitter.finished.emit(self.id_) return self.page.toHtml(self.processPage) def processPage(self, html): self.html = html QThreadPool.globalInstance().start(self) def cancel(self): if not self.changeState(WorkerState.FINISHED, WorkerState.PENDING): return self.page.triggerAction(QWebEnginePage.Stop) logging.warning('Canceling ' + self.url) self.emitter.loadError.emit(self.id_) self.emitter.finished.emit(self.id_)