def load(self, url=None, encoding=None, keepUndo=False): """Load the specified or current url (if None was specified). Currently only local files are supported. An IOError is raised when trying to load a nonlocal URL. If loading succeeds and an url was specified, the url is made the current url (by calling setUrl() internally). If keepUndo is True, the loading can be undone (with Ctrl-Z). """ if url is None: url = QUrl() u = url if not url.isEmpty() else self.url() text = self.load_data(u, encoding or self._encoding) if keepUndo: c = QTextCursor(self) c.select(QTextCursor.Document) c.insertText(text) else: self.setPlainText(text) self.setModified(False) if not url.isEmpty(): self.setUrl(url)
def save(self, url=None, encoding=None): """Saves the document to the specified or current url. Currently only local files are supported. An IOError is raised when trying to save a nonlocal URL. If saving succeeds and an url was specified, the url is made the current url (by calling setUrl() internally). """ if url is None: url = QUrl() u = url if not url.isEmpty() else self.url() filename = u.toLocalFile() # currently, we do not support non-local files if not filename: raise IOError("not a local file") # keep the url if specified when we didn't have one, even if saving # would fail if self.url().isEmpty() and not url.isEmpty(): self.setUrl(url) with self.saving(), app.documentSaving(self): with open(filename, "wb") as f: f.write(self.encodedText()) f.flush() os.fsync(f.fileno()) self.setModified(False) if not url.isEmpty(): self.setUrl(url) self.saved() app.documentSaved(self)
def save(self, url=None, encoding=None): """Saves the document to the specified or current url. Currently only local files are supported. An IOError is raised when trying to save a nonlocal URL. If saving succeeds and an url was specified, the url is made the current url (by calling setUrl() internally). This method is never called directly but only from the overriding subclass methods that make further specific use of the modified results. """ if url is None: url = QUrl() u = url if not url.isEmpty() else self.url() filename = u.toLocalFile() # currently, we do not support non-local files if not filename: raise IOError("not a local file") # keep the url if specified when we didn't have one, even if saving # would fail if self.url().isEmpty() and not url.isEmpty(): self.setUrl(url) return url, filename
def contextMenuEvent(self, evt): """ Protected method handling context menu events. @param evt reference to the context menu event (QContextMenuEvent) """ point = evt.globalPos() if self.__browser: point = self.__browser.mapFromGlobal(point) if not self.__browser.rect().contains(point, True): return link = QUrl(self.__browser.anchorAt(point)) else: point = self.__result.mapFromGlobal(point) link = self.__result.linkAt(point) if link.isEmpty() or not link.isValid(): return menu = QMenu() curTab = menu.addAction(self.tr("Open Link")) newTab = menu.addAction(self.tr("Open Link in New Tab")) menu.move(evt.globalPos()) act = menu.exec_() if act == curTab: self.linkActivated.emit(link) elif act == newTab: self.__mw.newTab(link)
def __testWebBrowserView(self, view, url): """ Private method to test a web browser view against an URL. @param view reference to the web browser view to be tested @type WebBrowserView @param url URL to test against @type QUrl @return flag indicating, that the view is the one for the URL @rtype bool """ if view.tabWidget().count() < 2: return False page = view.page() if page.history().count() != 0: return False if (not page.url().isEmpty() and page.url().host() == url.host()): return True requestedUrl = page.requestedUrl() if requestedUrl.isEmpty(): requestedUrl = QUrl(view.tabWidget().urlBarForView(view).text()) return requestedUrl.isEmpty() or requestedUrl.host() == url.host()
def __showContextMenu(self, pos): """ Private slot showing the context menu. @param pos position to show the menu at (QPoint) """ idx = self.__index.indexAt(pos) if idx.isValid(): menu = QMenu() curTab = menu.addAction(self.tr("Open Link")) newTab = menu.addAction(self.tr("Open Link in New Tab")) newBackgroundTab = menu.addAction( self.tr("Open Link in Background Tab")) newWindow = menu.addAction(self.tr("Open Link in New Window")) menu.move(self.__index.mapToGlobal(pos)) act = menu.exec_() model = self.__index.model() if model is not None: keyword = model.data(idx, Qt.DisplayRole) links = model.linksForKeyword(keyword) if len(links) == 1: link = QUrl(links[list(links.keys())[0]]) else: link = self.__selectLink(links, keyword) if not link.isEmpty() and link.isValid(): if act == curTab: self.openUrl.emit(link) elif act == newTab: self.newTab.emit(link) elif act == newBackgroundTab: self.newBackgroundTab.emit(link) elif act == newWindow: self.newWindow.emit(link)
def __showEnginesMenu(self): """ Private slot to handle the display of the engines menu. """ self.__enginesMenu.clear() from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction engineNames = self.__openSearchManager.allEnginesNames() for engineName in engineNames: engine = self.__openSearchManager.engine(engineName) action = OpenSearchEngineAction(engine, self.__enginesMenu) action.setData(engineName) action.triggered.connect(self.__changeCurrentEngine) self.__enginesMenu.addAction(action) if self.__openSearchManager.currentEngineName() == engineName: action.setCheckable(True) action.setChecked(True) ct = self.__mw.currentBrowser() linkedResources = ct.linkedResources("search") if len(linkedResources) > 0: self.__enginesMenu.addSeparator() for linkedResource in linkedResources: url = QUrl(linkedResource.href) title = linkedResource.title mimetype = linkedResource.type_ if mimetype != "application/opensearchdescription+xml": continue if url.isEmpty(): continue if url.isRelative(): url = ct.url().resolved(url) if not title: if not ct.title(): title = url.host() else: title = ct.title() action = self.__enginesMenu.addAction( self.tr("Add '{0}'").format(title), self.__addEngineFromUrl) action.setData(url) action.setIcon(ct.icon()) self.__enginesMenu.addSeparator() self.__enginesMenu.addAction(self.__mw.searchEnginesAction()) if self.__recentSearches: self.__enginesMenu.addAction(self.tr("Clear Recent Searches"), self.clear)
class NetArchitecture(QObject): def __init__(self, parent=None): # TODO should know its name super(NetArchitecture, self).__init__() self.renderer = QSvgRenderer() self.source_url = QUrl("") self.settings = QSettings('dt', 'DeepThought') self.graph = None self.update_source() def source_setting_changed(self): return not self.settings.value('protofile') == self.source_url def update_source(self): if self.settings.contains('protofile'): source_url = QUrl(self.settings.value('protofile')) source = source_url.toDisplayString(QUrl.RemoveScheme) if os.path.isfile(source): self.source_url = source_url self.set_source(source) return not self.source_url.isEmpty() def set_source(self, caffeproto_file): net = caffe_pb2.NetParameter() text_format.Merge(open(caffeproto_file).read(), net) self.graph = caffe.draw.draw_net(net, 'LR', 'svg') # self.sourceChanged.emit('network_architecture') def get_image(self, size): if self.source_setting_changed(): self.update_source() image = QImage(size.width(), size.height(), QImage.Format_ARGB32) painter = QPainter(image) if self.graph is None: if self.settings.contains('protofile'): url = QUrl(self.settings.value('protofile')) self.set_source(url.toDisplayString(QUrl.RemoveScheme)) else: image.fill(QColor(200, 200, 200)) return image self.renderer.load(QByteArray(self.graph)) self.renderer.render(painter) return image
class LoginForm(object): """ Class implementing a data structure for login forms. """ def __init__(self): """ Constructor """ self.url = QUrl() self.name = "" self.postData = "" def isValid(self): """ Public method to test for validity. @return flag indicating a valid form (boolean) """ return (not self.url.isEmpty() and bool(self.postData))
def dropEvent(self, evt): """ Protected method to handle drop events. @param evt reference to the drop event (QDropEvent) """ mimeData = evt.mimeData() url = QUrl() if mimeData.hasUrls(): url = mimeData.urls()[0] elif mimeData.hasText(): url = QUrl.fromEncoded(mimeData.text().encode(), QUrl.TolerantMode) if url.isEmpty() or not url.isValid(): E5LineEdit.dropEvent(self, evt) return self.setText(str(url.toEncoded(), encoding="utf-8")) self.selectAll() evt.acceptProposedAction()
def dropEvent(self, evt): """ Protected method to handle drop events. @param evt reference to the drop event (QDropEvent) """ mimeData = evt.mimeData() url = QUrl() if mimeData.hasUrls(): url = mimeData.urls()[0] elif mimeData.hasText(): url = QUrl.fromEncoded(mimeData.text().encode("utf-8"), QUrl.TolerantMode) if url.isEmpty() or not url.isValid(): E5LineEdit.dropEvent(self, evt) return self.setText(str(url.toEncoded(), encoding="utf-8")) self.selectAll() evt.acceptProposedAction()
def lookupUrl(self, url): """ Public method to lookup an URL. @param url URL to be checked @type str or QUrl @return tuple containing the list of threat lists the URL was found in and an error message @rtype tuple of (list of ThreatList, str) @exception ValueError raised for an invalid URL """ if self.isEnabled(): if self.__useLookupApi: if isinstance(url, str): url = QUrl(url.strip()) if url.isEmpty(): raise ValueError("Empty URL given.") listNames, error = self.__apiClient.lookupUrl( url, self.__platforms) return listNames, error else: if isinstance(url, QUrl): urlStr = url.toString().strip() else: urlStr = url.strip() if not urlStr: raise ValueError("Empty URL given.") urlHashes = SafeBrowsingUrl(urlStr).hashes() listNames = self.__lookupHashes(urlHashes) return listNames, "" return None, ""
def contextMenuEvent(self, event): self.img_url = '' menu = self.page().createStandardContextMenu() hit = self.page().currentFrame().hitTestContent(event.pos()) hit_m = self.page().mainFrame() hit_n = hit_m.hitTestContent(event.pos()) url = hit.linkUrl() arr = ['Download As Fanart', 'Download As Cover'] arr_extra_tvdb = ['Series Link', 'Season Episode Link'] arr_extra_tmdb = ['Series/Movie Link'] arr_last = ['Artist Link'] action = [] self.img_url = hit.imageUrl() self.title_page = hit.linkText() yt = False title_found = False self.ui.logger.info('elm: {}; text:{};'.format( hit.element(), hit.element().toPlainText())) try: if self.title_page: if 'youtube.com' in self.url().toString(): self.title_page = hit_n.linkElement().toPlainText() self.ui.logger.info(self.title_page) if not self.title_page: self.title_page = hit.linkText() self.title_page = self.title_page.strip() self.title_page = self.title_page.replace('\n', ' - ') self.ui.logger.info(self.title_page) elif hit.element(): self.title_page = hit.element().toPlainText() self.ui.logger.info(self.title_page) title_found = True else: self.title_page = hit.title() except Exception as err: self.ui.logger.error(err) self.title_page = hit.title() if (url.isEmpty() or not url.toString().startswith('http')) and self.img_url: url = self.img_url if url.isEmpty(): url = self.url() if not title_found: self.title_page = hit_m.title() if 'reload' in self.url().toString(): url = self.url().toString() n_url = re.sub('\?reload[^\/]*\/|&mode=NORMAL|¶ms[^&]*', '', url) url = QUrl(n_url) if not url.isEmpty() or self.img_url: if 'tvdb' in url.toString(): arr = arr + arr_extra_tvdb elif 'themoviedb' in url.toString(): arr = arr_extra_tmdb elif 'last.fm' in url.toString(): arr = arr + arr_last elif 'youtube.com' in url.toString( ) or 'ytimg.com' in url.toString() or url.toString().startswith( 'http'): yt = True arr.append('Play with Kawaii-Player') arr.append('Queue Item') arr.append('Download') if self.ui.pc_to_pc_casting == "master": arr.append("Cast This Item") arr.append("Cast Queue") if 'ytimg.com' in url.toString(): yt_id = url.toString().split('/')[-2] url = QUrl('https://m.youtube.com/watch?v=' + yt_id) try: self.title_page = self.playlist_dict[yt_id] except Exception as err: self.ui.logger.error(err) self.title_page = '' arr.append('Add as Local Playlist') self.playlist_name = self.epn_name_in_list menu.addSeparator() submenuR = QtWidgets.QMenu(menu) submenuR.setTitle("Add To Playlist") menu.addMenu(submenuR) pls = os.listdir(os.path.join(self.home, 'Playlists')) home1 = os.path.join(self.home, 'Playlists') pls = sorted( pls, key=lambda x: os.path.getmtime(os.path.join(home1, x)), reverse=True) item_m = [] for i in pls: item_m.append(submenuR.addAction(i)) submenuR.addSeparator() new_pls = submenuR.addAction("Create New Playlist") for nmenu in arr: action.append(menu.addAction(nmenu)) act = menu.exec_(event.globalPos()) for i, acts in enumerate(action): if act == acts: self.download(url, arr[i]) if yt: for i, acts in enumerate(item_m): if act == acts: if 'views' in self.title_page: self.title_page = re.sub('[0-9][^ ]* ', '', self.title_page, 1) self.title_page = re.sub('[0-9][^ ]* views', '', self.title_page, 1) self.title_page = self.title_page.replace('/', '-') if not self.title_page: content = ccurl(url.toString()) soup = BeautifulSoup(content, 'lxml') self.title_page = soup.title.text.strip().replace( '/', '-') self.triggerPlaylist(pls[i], url.toString(), self.title_page) if act == new_pls: MainWindow = QtWidgets.QWidget() item, ok = QtWidgets.QInputDialog.getText( MainWindow, 'Input Dialog', 'Enter Playlist Name') if ok and item: file_path = os.path.join(self.home, 'Playlists', item) if not os.path.exists(file_path): f = open(file_path, 'w') f.close() super(Browser, self).contextMenuEvent(event)
def importedBookmarks(self): """ Public method to get the imported bookmarks. @return imported bookmarks (BookmarkNode) """ from ..BookmarkNode import BookmarkNode importRootNode = BookmarkNode(BookmarkNode.Root) # step 1: build the hierarchy of bookmark folders folders = {} try: cursor = self.__db.cursor() cursor.execute( "SELECT id, parent, title FROM moz_bookmarks " "WHERE type = 2 and title !=''") for row in cursor: id_ = row[0] parent = row[1] title = row[2] if parent in folders: folder = BookmarkNode(BookmarkNode.Folder, folders[parent]) else: folder = BookmarkNode(BookmarkNode.Folder, importRootNode) folder.title = title.replace("&", "&&") folders[id_] = folder except sqlite3.DatabaseError as err: self._error = True self._errorString = self.tr( "Unable to open database.\nReason: {0}").format(str(err)) return None try: cursor = self.__db.cursor() cursor.execute( "SELECT parent, title, fk, position FROM moz_bookmarks" " WHERE type = 1 and title != '' ORDER BY position") for row in cursor: parent = row[0] title = row[1] placesId = row[2] cursor2 = self.__db.cursor() cursor2.execute( "SELECT url FROM moz_places WHERE id = {0}" .format(placesId)) row2 = cursor2.fetchone() if row2: url = QUrl(row2[0]) if not title or url.isEmpty() or \ url.scheme() in ["place", "about"]: continue if parent in folders: bookmark = BookmarkNode(BookmarkNode.Bookmark, folders[parent]) else: bookmark = BookmarkNode(BookmarkNode.Bookmark, importRootNode) bookmark.url = url.toString() bookmark.title = title.replace("&", "&&") except sqlite3.DatabaseError as err: self._error = True self._errorString = self.tr( "Unable to open database.\nReason: {0}").format(str(err)) return None importRootNode.setType(BookmarkNode.Folder) if self._id == "firefox": importRootNode.title = self.tr("Mozilla Firefox Import") else: importRootNode.title = self.tr("Imported {0}")\ .format(QDate.currentDate().toString(Qt.SystemLocaleShortDate)) return importRootNode
class SlippyMap(QObject): updated = pyqtSignal(QRect) def __init__(self, parent=None): super(SlippyMap, self).__init__(parent) self._offset = QPoint() self._tilesRect = QRect() self._tilePixmaps = {} # Point(x, y) to QPixmap mapping self._manager = QNetworkAccessManager() self._url = QUrl() # public vars self.width = 400 self.height = 300 self.zoom = 15 self.latitude = 59.9138204 self.longitude = 10.7387413 self._emptyTile = QPixmap(TDIM, TDIM) self._emptyTile.fill(Qt.lightGray) cache = QNetworkDiskCache() cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation)) self._manager.setCache(cache) self._manager.finished.connect(self.handleNetworkData) def invalidate(self): if self.width <= 0 or self.height <= 0: return ct = tileForCoordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM) yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM) # first tile vertical and horizontal xa = (xp + TDIM - 1) / TDIM ya = (yp + TDIM - 1) / TDIM xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self._offset = QPoint(xp - xa * TDIM, yp - ya * TDIM) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / TDIM ye = int(ty) + (self.height - yp - 1) / TDIM # build a rect self._tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1) if self._url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, p, rect): for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(x + self._tilesRect.left(), y + self._tilesRect.top()) box = self.tileRect(tp) if rect.intersects(box): p.drawPixmap(box, self._tilePixmaps.get(tp, self._emptyTile)) def pan(self, delta): dx = QPointF(delta) / float(TDIM) center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitudeFromTile(center.y(), self.zoom) self.longitude = longitudeFromTile(center.x(), self.zoom) self.invalidate() # slots def handleNetworkData(self, reply): img = QImage() tp = Point(reply.request().attribute(QNetworkRequest.User)) url = reply.url() if not reply.error(): if img.load(reply, None): self._tilePixmaps[tp] = QPixmap.fromImage(img) reply.deleteLater() self.updated.emit(self.tileRect(tp)) # purge unused tiles bound = self._tilesRect.adjusted(-2, -2, 2, 2) for tp in list(self._tilePixmaps.keys()): if not bound.contains(tp): del self._tilePixmaps[tp] self.download() def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % ( self.zoom, grab.x(), grab.y()) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request) def tileRect(self, tp): t = tp - self._tilesRect.topLeft() x = t.x() * TDIM + self._offset.x() y = t.y() * TDIM + self._offset.y() return QRect(x, y, TDIM, TDIM)
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)
def contextMenuEvent(self, event): self.img_url = '' menu = self.page().createStandardContextMenu() hit = self.page().currentFrame().hitTestContent(event.pos()) hit_m = self.page().mainFrame() hit_n = hit_m.hitTestContent(event.pos()) url = hit.linkUrl() arr = ['Download As Fanart','Download As Cover'] arr_extra_tvdb = ['Series Link','Season Episode Link'] arr_last = ['Artist Link'] action = [] self.img_url = hit.imageUrl() self.title_page = hit.linkText() yt = False try: if self.title_page: print('self.title_page=',self.title_page) #self.title_page = self.title_page.strip() if 'youtube.com' in self.url().toString(): self.title_page = hit_n.linkElement().toPlainText() if not self.title_page: self.title_page = hit.linkText() self.title_page = self.title_page.strip() tmp = self.title_page.replace('\n','#') print(tmp) tmp1 = re.search('#[^#]*',tmp) print(tmp1) self.title_page = tmp1.group() self.title_page = self.title_page.replace('#','') else: self.title_page = hit.title() except: self.title_page = hit.title() print('url--info\n',self.img_url.toString(),'=img_url\n',url,'=url', hit.title(),'=title\n',hit.linkText(),'=linktext\n',hit_m.title(), '--p_title--',hit_n.linkElement().toPlainText(),'--link-element') if (url.isEmpty() or not url.toString().startswith('http')) and self.img_url: url = self.img_url if url.isEmpty(): url = self.url() print('--next--url=',self.url().toString()) self.title_page = hit_m.title() if 'reload' in self.url().toString(): print('reload # in url') url = self.url().toString() n_url = re.sub('\?reload[^\/]*\/|&mode=NORMAL|¶ms[^&]*','',url) url = QUrl(n_url) print('--next--url=',url.toString()) if not url.isEmpty() or self.img_url: if 'tvdb' in url.toString(): arr = arr + arr_extra_tvdb if 'last.fm' in url.toString(): arr = arr + arr_last if 'youtube.com' in url.toString() or 'ytimg.com' in url.toString(): yt = True arr[:]=[] arr.append('Play with AnimeWatch') arr.append('Queue Item') arr.append('Download') arr.append('Get Subtitle (If Available)') if 'ytimg.com' in url.toString(): print(self.playlist_dict) yt_id = url.toString().split('/')[-2] url = QUrl('https://m.youtube.com/watch?v='+yt_id) print('url=',url) try: self.title_page = self.playlist_dict[yt_id] except: self.title_page = '' arr.append('Add as Local Playlist') self.playlist_name = self.epn_name_in_list menu.addSeparator() submenuR = QtWidgets.QMenu(menu) submenuR.setTitle("Add To Playlist") menu.addMenu(submenuR) pls = os.listdir(os.path.join(self.home,'Playlists')) home1 = os.path.join(self.home,'Playlists') pls = sorted(pls, key = lambda x:os.path.getmtime(os.path.join(home1,x)), reverse=True) item_m = [] for i in pls: item_m.append(submenuR.addAction(i)) submenuR.addSeparator() new_pls = submenuR.addAction("Create New Playlist") for i in range(len(arr)): action.append(menu.addAction(arr[i])) act = menu.exec_(event.globalPos()) for i in range(len(action)): if act == action[i]: self.download(url,arr[i]) if yt: for i in range(len(item_m)): #print(hit.title(),self.title_page) if act == item_m[i]: if 'views' in self.title_page: #content = ccurl(url.toString()) #soup = BeautifulSoup(content,'lxml') self.title_page = re.sub('[0-9][^ ]* ','',self.title_page,1) self.title_page = re.sub('[0-9][^ ]* views','',self.title_page,1) self.title_page = self.title_page.replace('/','-') print('self.title_page=',self.title_page) if not self.title_page: content = ccurl(url.toString()) soup = BeautifulSoup(content,'lxml') self.title_page = soup.title.text.strip().replace('/','-') ##self.title_page = hit_m.title().strip().replace('/','-') ##print(hit.title(),self.title_page) #thr = downloadThread(url.toString(),self,pls[i]) #thr.start() self.triggerPlaylist(pls[i],url.toString(),self.title_page) if act == new_pls: print ("creating") MainWindow = QtWidgets.QWidget() item, ok = QtWidgets.QInputDialog.getText( MainWindow, 'Input Dialog', 'Enter Playlist Name') if ok and item: file_path = os.path.join(self.home,'Playlists',item) if not os.path.exists(file_path): f = open(file_path,'w') f.close() super(Browser, self).contextMenuEvent(event)
def contextMenuEvent(self, event): self.img_url = '' menu = self.page().createStandardContextMenu() hit = self.page().currentFrame().hitTestContent(event.pos()) hit_m = self.page().mainFrame() hit_n = hit_m.hitTestContent(event.pos()) url = hit.linkUrl() arr = ['Download As Fanart','Download As Cover'] arr_extra_tvdb = ['Series Link','Season Episode Link'] arr_last = ['Artist Link'] action = [] self.img_url = hit.imageUrl() self.title_page = hit.linkText() yt = False try: if self.title_page: print('self.title_page=',self.title_page) #self.title_page = self.title_page.strip() if 'youtube.com' in self.url().toString(): self.title_page = hit_n.linkElement().toPlainText() if not self.title_page: self.title_page = hit.linkText() self.title_page = self.title_page.strip() tmp = self.title_page.replace('\n','#') print(tmp) tmp1 = re.search('#[^#]*',tmp) print(tmp1) self.title_page = tmp1.group() self.title_page = self.title_page.replace('#','') else: self.title_page = hit.title() except: self.title_page = hit.title() print('url--info\n',self.img_url.toString(),'=img_url\n',url,'=url', hit.title(),'=title\n',hit.linkText(),'=linktext\n',hit_m.title(), '--p_title--',hit_n.linkElement().toPlainText(),'--link-element') if (url.isEmpty() or not url.toString().startswith('http')) and self.img_url: url = self.img_url if url.isEmpty(): url = self.url() print('--next--url=',self.url().toString()) self.title_page = hit_m.title() if 'reload' in self.url().toString(): print('reload # in url') url = self.url().toString() n_url = re.sub('\?reload[^\/]*\/|&mode=NORMAL|¶ms[^&]*','',url) url = QUrl(n_url) print('--next--url=',url.toString()) if not url.isEmpty() or self.img_url: if 'tvdb' in url.toString(): arr = arr + arr_extra_tvdb if 'last.fm' in url.toString(): arr = arr + arr_last if 'youtube.com' in url.toString() or 'ytimg.com' in url.toString(): yt = True arr[:]=[] arr.append('Play with Kawaii-Player') arr.append('Queue Item') arr.append('Download') arr.append('Get Subtitle (If Available)') if 'ytimg.com' in url.toString(): print(self.playlist_dict) yt_id = url.toString().split('/')[-2] url = QUrl('https://m.youtube.com/watch?v='+yt_id) print('url=',url) try: self.title_page = self.playlist_dict[yt_id] except: self.title_page = '' arr.append('Add as Local Playlist') self.playlist_name = self.epn_name_in_list menu.addSeparator() submenuR = QtWidgets.QMenu(menu) submenuR.setTitle("Add To Playlist") menu.addMenu(submenuR) pls = os.listdir(os.path.join(self.home,'Playlists')) home1 = os.path.join(self.home,'Playlists') pls = sorted(pls, key = lambda x:os.path.getmtime(os.path.join(home1,x)), reverse=True) item_m = [] for i in pls: item_m.append(submenuR.addAction(i)) submenuR.addSeparator() new_pls = submenuR.addAction("Create New Playlist") for i in range(len(arr)): action.append(menu.addAction(arr[i])) act = menu.exec_(event.globalPos()) for i in range(len(action)): if act == action[i]: self.download(url,arr[i]) if yt: for i in range(len(item_m)): #print(hit.title(),self.title_page) if act == item_m[i]: if 'views' in self.title_page: #content = ccurl(url.toString()) #soup = BeautifulSoup(content,'lxml') self.title_page = re.sub('[0-9][^ ]* ','',self.title_page,1) self.title_page = re.sub('[0-9][^ ]* views','',self.title_page,1) self.title_page = self.title_page.replace('/','-') print('self.title_page=',self.title_page) if not self.title_page: content = ccurl(url.toString()) soup = BeautifulSoup(content,'lxml') self.title_page = soup.title.text.strip().replace('/','-') ##self.title_page = hit_m.title().strip().replace('/','-') ##print(hit.title(),self.title_page) #thr = downloadThread(url.toString(),self,pls[i]) #thr.start() self.triggerPlaylist(pls[i],url.toString(),self.title_page) if act == new_pls: print ("creating") MainWindow = QtWidgets.QWidget() item, ok = QtWidgets.QInputDialog.getText( MainWindow, 'Input Dialog', 'Enter Playlist Name') if ok and item: file_path = os.path.join(self.home,'Playlists',item) if not os.path.exists(file_path): f = open(file_path,'w') f.close() super(Browser, self).contextMenuEvent(event)
class SlippyMap(QObject): updated = pyqtSignal(QRect) def __init__(self, parent=None): super(SlippyMap, self).__init__(parent) self._offset = QPoint() self._tilesRect = QRect() self._tilePixmaps = {} # Point(x, y) to QPixmap mapping self._manager = QNetworkAccessManager() self._url = QUrl() # public vars self.width = 400 self.height = 300 self.zoom = 15 self.latitude = 59.9138204 self.longitude = 10.7387413 self._emptyTile = QPixmap(TDIM, TDIM) self._emptyTile.fill(Qt.lightGray) cache = QNetworkDiskCache() cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation)) self._manager.setCache(cache) self._manager.finished.connect(self.handleNetworkData) def invalidate(self): if self.width <= 0 or self.height <= 0: return ct = tileForCoordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = int(self.width / 2 - (tx - math.floor(tx)) * TDIM) yp = int(self.height / 2 - (ty - math.floor(ty)) * TDIM) # first tile vertical and horizontal xa = (xp + TDIM - 1) / TDIM ya = (yp + TDIM - 1) / TDIM xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self._offset = QPoint(xp - xa * TDIM, yp - ya * TDIM) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / TDIM ye = int(ty) + (self.height - yp - 1) / TDIM # build a rect self._tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1) if self._url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, p, rect): for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(x + self._tilesRect.left(), y + self._tilesRect.top()) box = self.tileRect(tp) if rect.intersects(box): p.drawPixmap(box, self._tilePixmaps.get(tp, self._emptyTile)) def pan(self, delta): dx = QPointF(delta) / float(TDIM) center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitudeFromTile(center.y(), self.zoom) self.longitude = longitudeFromTile(center.x(), self.zoom) self.invalidate() # slots def handleNetworkData(self, reply): img = QImage() tp = Point(reply.request().attribute(QNetworkRequest.User)) url = reply.url() if not reply.error(): if img.load(reply, None): self._tilePixmaps[tp] = QPixmap.fromImage(img) reply.deleteLater() self.updated.emit(self.tileRect(tp)) # purge unused tiles bound = self._tilesRect.adjusted(-2, -2, 2, 2) for tp in list(self._tilePixmaps.keys()): if not bound.contains(tp): del self._tilePixmaps[tp] self.download() def download(self): grab = None for x in range(self._tilesRect.width()): for y in range(self._tilesRect.height()): tp = Point(self._tilesRect.topLeft() + QPoint(x, y)) if tp not in self._tilePixmaps: grab = QPoint(tp) break if grab is None: self._url = QUrl() return path = 'http://tile.openstreetmap.org/%d/%d/%d.png' % (self.zoom, grab.x(), grab.y()) self._url = QUrl(path) request = QNetworkRequest() request.setUrl(self._url) request.setRawHeader(b'User-Agent', b'Nokia (PyQt) Graphics Dojo 1.0') request.setAttribute(QNetworkRequest.User, grab) self._manager.get(request) def tileRect(self, tp): t = tp - self._tilesRect.topLeft() x = t.x() * TDIM + self._offset.x() y = t.y() * TDIM + self._offset.y() return QRect(x, y, TDIM, TDIM)
def _on_link_click(self, url: QUrl) -> None: """ If the graph is enabled, send the fragment string of the clicked URL and set focus on it. When we click something that isn't a link, this will be sent with an empty string. """ if self._mouse_enabled: self._has_focus = not url.isEmpty() self._send_action(url)
class SlippyMap(QObject): def __init__(self, parent: QObject = None) -> None: super().__init__(parent) self.width: int = 400 self.height: int = 300 self.zoom: int = 15 self.latitude: float = 59.9138204 self.longitude: float = 10.7387413 self.m_offset = QPoint() self.m_tilesRect = QRect() self.m_emptyTile = QPixmap(tdim, tdim) self.m_emptyTile.fill(Qt.lightGray) self.m_tilePixmaps: typing.Dict[QPointH, QPixmap] = dict() self.m_manager = QNetworkAccessManager() self.m_url = QUrl() cache = QNetworkDiskCache() cache.setCacheDirectory( QStandardPaths.writableLocation(QStandardPaths.CacheLocation) ) self.m_manager.setCache(cache) self.m_manager.finished.connect(self.handleNetworkData) def invalidate(self) -> None: if self.width <= 0 or self.height <= 0: return ct = tileForCoordinate(self.latitude, self.longitude, self.zoom) tx = ct.x() ty = ct.y() # top-left corner of the center tile xp = self.width / 2 - (tx - math.floor(tx)) * tdim yp = self.height / 2 - (ty - math.floor(ty)) * tdim xa = (xp + tdim - 1) / tdim ya = (yp + tdim - 1) / tdim xs = int(tx) - xa ys = int(ty) - ya # offset for top-left tile self.m_offset = QPoint(xp - xa * tdim, yp - ya * tdim) # last tile vertical and horizontal xe = int(tx) + (self.width - xp - 1) / tdim ye = int(ty) + (self.height - yp - 1) / tdim # build a rect self.m_tilesRect = QRect(xs, ys, xe - xs + 1, ye - ys + 1) if self.m_url.isEmpty(): self.download() self.updated.emit(QRect(0, 0, self.width, self.height)) def render(self, painter: QPainter, rect: QRect) -> None: for x in range(self.m_tilesRect.width() + 1): for y in range(self.m_tilesRect.height() + 1): tp = QPoint(x + self.m_tilesRect.left(), y + self.m_tilesRect.top()) box = self.tileRect(tp) if rect.intersects(box): painter.drawPixmap( box, self.m_tilePixmaps.get(QPointH(tp), self.m_emptyTile) ) def pan(self, delta: QPoint) -> None: dx = QPointF(delta) / float(tdim) center = tileForCoordinate(self.latitude, self.longitude, self.zoom) - dx self.latitude = latitudeFromTile(center.y(), self.zoom) self.longitude = longitudeFromTile(center.x(), self.zoom) self.invalidate() updated = pyqtSignal(QRect) @pyqtSlot(QNetworkReply) def handleNetworkData(self, reply: QNetworkReply) -> None: img = QImage() tp = reply.request().attribute(QNetworkRequest.User) if not reply.error(): if not img.load(reply, ""): img = QImage() reply.deleteLater() self.m_tilePixmaps[QPointH(tp)] = ( self.m_emptyTile if img.isNull() else QPixmap.fromImage(img) ) self.updated.emit(self.tileRect(tp)) # purge unused spaces bound = self.m_tilesRect.adjusted(-2, -2, 2, 2) self.m_tilePixmaps = { tp: pixmap for tp, pixmap in self.m_tilePixmaps.items() if bound.contains(tp) } self.download() @pyqtSlot() def download(self): grab = QPoint(0, 0) for x in range(self.m_tilesRect.width() + 1): for y in range(self.m_tilesRect.height() + 1): tp = self.m_tilesRect.topLeft() + QPoint(x, y) if QPointH(tp) not in self.m_tilePixmaps: grab = tp break if grab == QPoint(0, 0): self.m_url = QUrl() return path = "http://tile.openstreetmap.org/%d/%d/%d.png" self.m_url = QUrl(path % (self.zoom, grab.x(), grab.y())) request = QNetworkRequest() request.setUrl(self.m_url) request.setRawHeader(b"User-Agent", b"The Qt Company (Qt) Graphics Dojo 1.0") request.setAttribute(QNetworkRequest.User, grab) self.m_manager.get(request) def tileRect(self, tp: QPoint): t = tp - self.m_tilesRect.topLeft() x = t.x() * tdim + self.m_offset.x() y = t.y() * tdim + self.m_offset.y() return QRect(x, y, tdim, tdim)
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()))
class GreaseMonkeyScript(object): """ Class implementing the GreaseMonkey script. """ DocumentStart = 0 DocumentEnd = 1 def __init__(self, manager, path): """ Constructor @param manager reference to the manager object (GreaseMonkeyManager) @param path path of the Javascript file (string) """ self.__manager = manager self.__name = "" self.__namespace = "GreaseMonkeyNS" self.__description = "" self.__version = "" self.__include = [] self.__exclude = [] self.__downloadUrl = QUrl() self.__startAt = GreaseMonkeyScript.DocumentEnd self.__script = "" self.__fileName = path self.__enabled = True self.__valid = False self.__parseScript(path) 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 downloadUrl(self): """ Public method to get the download URL of the script. @return download URL of the script (QUrl) """ return QUrl(self.__downloadUrl) 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 isEnabled(self): """ Public method to check, if the script is enabled. @return flag indicating an enabled state (boolean) """ return self.__enabled 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) """ list = [] for matcher in self.__include: list.append(matcher.pattern()) return list def exclude(self): """ Public method to get the list of excluded URLs. @return list of excluded URLs (list of strings) """ list = [] for matcher in self.__exclude: list.append(matcher.pattern()) return list def script(self): """ Public method to get the Javascript source. @return Javascript source (string) """ return self.__script def fileName(self): """ Public method to get the path of the Javascript file. @return path path of the Javascript file (string) """ return self.__fileName def match(self, urlString): """ Public method to check, if the script matches the given URL. @param urlString URL (string) @return flag indicating a match (boolean) """ if not self.__enabled: return False for matcher in self.__exclude: if matcher.match(urlString): return False for matcher in self.__include: if matcher.match(urlString): return True return False def __parseScript(self, path): """ Private method to parse the given script and populate the data structure. @param path path of the Javascript file (string) """ try: f = open(path, "r", encoding="utf-8") fileData = f.read() f.close() except (IOError, OSError): # silently ignore because it shouldn't happen return rx = QRegExp("// ==UserScript==(.*)// ==/UserScript==") rx.indexIn(fileData) metaDataBlock = rx.cap(1).strip() if metaDataBlock == "": # invalid script file return requireList = [] for line in metaDataBlock.splitlines(): if not line.startswith("// @"): continue line = line[3:].replace("\t", " ") index = line.find(" ") if index < 0: continue key = line[:index].strip() value = line[index + 1:].strip() # Ignored values: @resource, @unwrap if not key or not value: 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 == "@updateURL": self.__downloadUrl = QUrl(value) elif key in ["@include", "@match"]: self.__include.append(GreaseMonkeyUrlMatcher(value)) elif key in ["@exclude", "@exclude_match"]: self.__exclude.append(GreaseMonkeyUrlMatcher(value)) elif key == "@require": requireList.append(value) elif key == "@run-at": if value == "document-end": self.__startAt = GreaseMonkeyScript.DocumentEnd elif value == "document-start": self.__startAt = GreaseMonkeyScript.DocumentStart elif key == "@downloadURL" and self.__downloadUrl.isEmpty(): self.__downloadUrl = QUrl(value) if not self.__include: self.__include.append(GreaseMonkeyUrlMatcher("*")) marker = "// ==/UserScript==" index = fileData.find(marker) + len(marker) script = fileData[index:].strip() script = "{0}{1}".format( self.__manager.requireScripts(requireList), script) self.__script = "(function(){{{0}}})();".format(script) self.__valid = len(script) > 0
def handleWebViewUrlChanged(self, url: QUrl): self.m_urlLineEdit.setUrl(url) if url.isEmpty(): self.m_urlLineEdit.setFocus()