Exemple #1
0
 def __create_window_request(self, fake_page: QWebEnginePage, url: QUrl):
     if not self.__check_in_scope(url):
         if url.scheme != 'about' and url.scheme != "":
             print("Going outside because of " + url.toString())
             webbrowser.open(url.toString())
             return False
     else:
         self.setUrl(url)
         return False
Exemple #2
0
    def acceptNavigationRequest(self, url: QUrl, request_type,
                                is_main_frame: bool):
        if request_type != QWebEnginePage.NavigationTypeLinkClicked:
            return True

        if not is_main_frame:
            return True

        if not self.__check_in_scope(url):
            print("Going outside because of " + url.toString())
            webbrowser.open(url.toString())
            return False
        else:
            return True
Exemple #3
0
def _generate_pdfjs_script(filename):
    """Generate the script that shows the pdf with pdf.js.

    Args:
        filename: The name of the file to open.
    """
    url = QUrl('qute://pdfjs/file')
    url_query = QUrlQuery()
    url_query.addQueryItem('filename', filename)
    url.setQuery(url_query)

    return jinja.js_environment.from_string("""
        document.addEventListener("DOMContentLoaded", function() {
          {% if disable_create_object_url %}
          PDFJS.disableCreateObjectURL = true;
          {% endif %}
          PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;

          const viewer = window.PDFView || window.PDFViewerApplication;
          viewer.open("{{ url }}");
        });
    """).render(
        url=javascript.string_escape(url.toString(QUrl.FullyEncoded)),
        # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70420
        disable_create_object_url=(
            not qtutils.version_check('5.12')
            and not qtutils.version_check('5.7.1', exact=True, compiled=False)
            and objects.backend == usertypes.Backend.QtWebEngine))
Exemple #4
0
def itemFromUrl(url: QtCore.QUrl) -> Union[Tuple[str, str, str], None]:
    """
		Parses a URL constructed by urlForItem.
		Returns a tuple (module, id, name ) if parsing is successfull, None otherwise.
		@param url: Url which should be parsed.
		@type url: QUrl or String
		@returns: Tuple (module, id, name ) or None
	"""
    if isinstance(url, QtCore.QUrl):
        url = url.toString()
    # Strip host and query-string
    url = url[url.find("/", 7):]
    if "?" in url:
        url = url[:url.find("?")]
    parts = [x for x in url.split("/") if x]
    if len(parts) < 3:
        return None
    if parts[1].lower() != "view":
        return None
    modul = parts[0]
    if modul not in conf.serverConfig["modules"]:  # Unknown module
        return None
    if len(parts) > 3:
        return modul, parts[2], parts[3]
    else:
        return modul, parts[2], ""
Exemple #5
0
 def handleVideoButton(self, url):
     if validYoutubeUrl(url):
         self.videoDownloadButton.show()
         return
     self.video_URL = False
     frames = [self.tabWidget.currentWidget().page().mainFrame()]
     frames += self.tabWidget.currentWidget().page().mainFrame(
     ).childFrames()
     for frame in frames:
         videos = frame.findAllElements('video').toList()
         for video in videos:
             dl_link = video.attribute('src')
             child = video.findFirst('source[src]')
             if dl_link == '' and not child.isNull():
                 dl_link = child.attribute('src')
             dl_url = QUrl(dl_link)
             if not dl_url.isValid(): continue
             if dl_url.isRelative():
                 dl_url = frame.url().resolved(dl_url)
             self.video_URL = QUrl.fromUserInput(dl_url.toString())
             self.video_page_url = frame.url().toString()
             break
             break
     if self.video_URL:
         self.videoDownloadButton.show()
     else:
         self.videoDownloadButton.hide()
Exemple #6
0
    def handleAuthenticationRequired(self, requestUrl: QUrl,
                                     auth: QAuthenticator):
        mainWindow = self.view().window()
        dialog = QDialog(mainWindow,
                         Qt.WindowFlags() & ~Qt.WindowContextHelpButtonHint)
        dialog.setModal(True)
        # dialog.setWindowFlags(dialog.windowFlags() & ~Qt.WindowContextHelpButtonHint)

        passwordDialog = Ui_PasswordDialog()
        passwordDialog.setupUi(dialog)

        passwordDialog.m_iconLabel.setText('')
        icon = QIcon(mainWindow.style().standardIcon(
            QStyle.SP_MessageBoxQuestion, widget=mainWindow))
        passwordDialog.m_iconLabel.setPixmap(icon.pixmap(32, 32))

        introMessage = self.tr(
            "Enter username and password for \"{}\" at {}").format(
                # auth.realm(), requestUrl.toString().toHtmlEscaped())
                auth.realm(),
                requestUrl.toString())  # TODO: toHtmlEscaped()?
        passwordDialog.m_infoLabel.setText(introMessage)
        passwordDialog.m_infoLabel.setWordWrap(True)

        if dialog.exec() == QDialog.Accepted:
            auth.setUser(passwordDialog.m_userNameLineEdit.text())
            auth.setPassword(passwordDialog.m_passwordLineEdit.text())
        else:
            # Set authenticator null if dialog is cancelled
            # auth = QAuthenticator()
            self.setHtml('auth canceled')  # TODO: proper workaround?
Exemple #7
0
class AdBlockedPageEntry(object):
    """
    Class implementing a data structure for web page rules.
    """
    def __init__(self, rule, url):
        """
        Constructor
        
        @param rule AdBlock rule to add (AdBlockRule)
        @param url URL that matched the rule (QUrl)
        """
        self.rule = rule
        self.url = QUrl(url)

    def __eq__(self, other):
        """
        Special method to test equality.
        
        @param other reference to the other entry (AdBlockedPageEntry)
        @return flag indicating equality (boolean)
        """
        return self.rule == other.rule and self.url == other.url

    def urlString(self):
        """
        Public method to get the URL as a string.
        
        @return URL as a string (string)
        """
        return self.url.toString()
Exemple #8
0
    def keyPressEvent(self, evt):
        """
        Protected method to handle key presses.
        
        @param evt reference to the key press event (QKeyEvent)
        """
        if evt.key() == Qt.Key_Escape and self.__browser is not None:
            self.setText(
                str(self.__browser.url().toEncoded(), encoding="utf-8"))
            self.selectAll()
            return

        currentText = self.text().strip()
        if evt.key() in [Qt.Key_Enter, Qt.Key_Return] and \
           not currentText.lower().startswith("http://"):
            append = ""
            if evt.modifiers() == Qt.KeyboardModifiers(Qt.ControlModifier):
                append = ".com"
            elif evt.modifiers() == Qt.KeyboardModifiers(Qt.ControlModifier
                                                         | Qt.ShiftModifier):
                append = ".org"
            elif evt.modifiers() == Qt.KeyboardModifiers(Qt.ShiftModifier):
                append = ".net"

            if append != "":
                url = QUrl("http://www." + currentText)
                host = url.host()
                if not host.lower().endswith(append):
                    host += append
                    url.setHost(host)
                    self.setText(url.toString())

        E5LineEdit.keyPressEvent(self, evt)
Exemple #9
0
 def keyPressEvent(self, evt):
     """
     Protected method to handle key presses.
     
     @param evt reference to the key press event (QKeyEvent)
     """
     if evt.key() == Qt.Key_Escape and self.__browser is not None:
         self.setText(
             str(self.__browser.url().toEncoded(), encoding="utf-8"))
         self.selectAll()
         return
     
     currentText = self.text().strip()
     if evt.key() in [Qt.Key_Enter, Qt.Key_Return] and \
        not currentText.lower().startswith("http://"):
         append = ""
         if evt.modifiers() == Qt.KeyboardModifiers(Qt.ControlModifier):
             append = ".com"
         elif evt.modifiers() == Qt.KeyboardModifiers(
                 Qt.ControlModifier | Qt.ShiftModifier):
             append = ".org"
         elif evt.modifiers() == Qt.KeyboardModifiers(Qt.ShiftModifier):
             append = ".net"
         
         if append != "":
             url = QUrl("http://www." + currentText)
             host = url.host()
             if not host.lower().endswith(append):
                 host += append
                 url.setHost(host)
                 self.setText(url.toString())
     
     E5LineEdit.keyPressEvent(self, evt)
Exemple #10
0
    def test02_check_scene1_webpage(self):
        """render exported web page and check page capture"""

        html_path = outputPath("scene1.html")

        url = QUrl.fromLocalFile(html_path)
        url = QUrl(url.toString() + "#cx=-20&cy=16&cz=-34&tx=-2&ty=0&tz=8")

        loop = QEventLoop()
        page = QWebPage()
        page.setViewportSize(QSize(OUT_WIDTH, OUT_HEIGHT))
        page.loadFinished.connect(loop.quit)
        page.mainFrame().setUrl(url)
        loop.exec_()

        page.mainFrame().evaluateJavaScript('document.getElementById("progress").style.display = "none";')

        timer = QTimer()
        timer.timeout.connect(loop.quit)
        timer.start(100)
        while page.mainFrame().evaluateJavaScript("app.loadingManager.isLoading"):
            loop.exec_()

        timer.stop()

        image = QImage(OUT_WIDTH, OUT_HEIGHT, QImage.Format_ARGB32_Premultiplied)
        painter = QPainter(image)
        page.mainFrame().render(painter)
        painter.end()

        filename = "scene1_qwebpage.png"
        image.save(outputPath(filename))
        assert QImage(outputPath(filename)) == QImage(expectedDataPath(filename)), "captured image is different from expected."
Exemple #11
0
def filename_from_url(url: QUrl, fallback: str = None) -> Optional[str]:
    """Get a suitable filename from a URL.

    Args:
        url: The URL to parse, as a QUrl.
        fallback: Value to use if no name can be determined.

    Return:
        The suggested filename as a string, or None.
    """
    if not url.isValid():
        return fallback

    if url.scheme().lower() == 'data':
        mimetype, _encoding = mimetypes.guess_type(url.toString())
        if not mimetype:
            return fallback

        ext = utils.mimetype_extension(mimetype) or ''
        return 'download' + ext

    pathname = posixpath.basename(url.path())
    if pathname:
        return pathname
    elif url.host():
        return url.host() + '.html'
    else:
        return fallback
Exemple #12
0
class AdBlockedPageEntry(object):
    """
    Class implementing a data structure for web page rules.
    """
    def __init__(self, rule, url):
        """
        Constructor
        
        @param rule AdBlock rule to add (AdBlockRule)
        @param url URL that matched the rule (QUrl)
        """
        self.rule = rule
        self.url = QUrl(url)
    
    def __eq__(self, other):
        """
        Special method to test equality.
        
        @param other reference to the other entry (AdBlockedPageEntry)
        @return flag indicating equality (boolean)
        """
        return self.rule == other.rule and self.url == other.url
    
    def urlString(self):
        """
        Public method to get the URL as a string.
        
        @return URL as a string (string)
        """
        return self.url.toString()
 def __init__(self, remoteName, remoteUrl, parent=None):
     """
     Constructor
     
     @param remoteName name of the remote repository
     @type str
     @param remoteUrl URL of the remote repository
     @type str
     @param parent reference to the parent widget
     @type QWidget
     """
     super(GitRemoteCredentialsDialog, self).__init__(parent)
     self.setupUi(self)
     
     url = QUrl(remoteUrl)
     
     self.nameEdit.setText(remoteName)
     self.urlEdit.setText(url.toString(QUrl.RemoveUserInfo))
     self.userEdit.setText(url.userName())
     self.passwordEdit.setText(url.password())
     
     self.userEdit.setFocus(Qt.OtherFocusReason)
     
     msh = self.minimumSizeHint()
     self.resize(max(self.width(), msh.width()), msh.height())
Exemple #14
0
    def handle_starttag(self, tag, alist):
        if tag not in ['a', 'link']:
            return

        attrs = dict(alist)
        href = attrs.get('href')

        if not isinstance(href, str):
            return

        if len(href) > 1024:
            return

        href = unquote(href)

        url = QUrl(href)
        if not url.isValid():
            return

        if not url.scheme() or url.isRelative():
            # Relative URL
            p = self.base.child(href)
            if p and self.pathValid(p):
                self.links.append(p)

        elif isIpfsUrl(url):
            # Absolute URL
            p = IPFSPath(url.toString())
            if self.pathValid(p):
                self.links.append(p)
Exemple #15
0
def test_client():
    q=QUrl("entry: abc")
    print(q.toString().split(":")[1].strip("/ "))
    print(q.scheme())
    print(q.host())
    print(q.path())
    print(q.fragment())
Exemple #16
0
    def _format_body(self, body: str, origin_url: QUrl) -> str:
        """Format the body according to the server capabilities.

        If the server doesn't support x-kde-origin-name, we include the origin URL as a
        prefix. If possible, we hyperlink it.

        For both prefix and body, we'll need to HTML escape it if the server supports
        body markup.
        """
        urlstr = origin_url.toDisplayString()
        is_useful_origin = self._should_include_origin(origin_url)

        if self._capabilities.kde_origin_name or not is_useful_origin:
            prefix = None
        elif self._capabilities.body_markup and self._capabilities.body_hyperlinks:
            href = html.escape(
                origin_url.toString(
                    QUrl.FullyEncoded)  # type: ignore[arg-type]
            )
            text = html.escape(urlstr, quote=False)
            prefix = f'<a href="{href}">{text}</a>'
        elif self._capabilities.body_markup:
            prefix = html.escape(urlstr, quote=False)
        else:
            prefix = urlstr

        if self._capabilities.body_markup:
            body = html.escape(body, quote=False)

        if prefix is None:
            return body

        return prefix + '\n\n' + body
Exemple #17
0
def _render_header(title, mode, phrase, filters):
    r = []
    r.append(ADV_HEADER)
    r.append("<h1>{0}</h1>".format(title))
    r.append('<ul class="nav">\n')

    modes = [(name, spec) for (name, spec) in MODE_DICT.items()]
    modes.sort(key=itemgetter(0))

    for (name, spec) in modes:
        q = QUrlQuery()
        if phrase:
            q.addQueryItem("phrase", phrase)
        if filters:
            q.addQueryItem("filters", filters)
        q.addQueryItem("mode", name)
        href = QUrl("search:///?" + q.toString())
        if name != mode:
            r.append(
                '<li><a href="{href}">{title}</a></li>\n'.format(
                    href=href.toString(), title=spec["title"]
                )
            )
        else:
            r.append(
                '<li><span class="sel">{title}<span></li>\n'.format(title=spec["title"])
            )

    r.append("</ul>\n")
    return "".join(r)
Exemple #18
0
def _generate_pdfjs_script(filename):
    """Generate the script that shows the pdf with pdf.js.

    Args:
        filename: The name of the file to open.
    """
    url = QUrl('qute://pdfjs/file')
    url_query = QUrlQuery()
    url_query.addQueryItem('filename', filename)
    url.setQuery(url_query)

    js_url = javascript.to_js(
        url.toString(QUrl.FullyEncoded))  # type: ignore[arg-type]

    return jinja.js_environment.from_string("""
        document.addEventListener("DOMContentLoaded", function() {
          if (typeof window.PDFJS !== 'undefined') {
              // v1.x
              window.PDFJS.verbosity = window.PDFJS.VERBOSITY_LEVELS.info;
          } else {
              // v2.x
              const options = window.PDFViewerApplicationOptions;
              options.set('verbosity', pdfjsLib.VerbosityLevel.INFOS);
          }

          const viewer = window.PDFView || window.PDFViewerApplication;
          viewer.open({{ url }});
        });
    """).render(url=js_url)
Exemple #19
0
    def yank(self, url: QUrl, context: HintContext) -> None:
        """Yank an element to the clipboard or primary selection."""
        sel = (context.target == Target.yank_primary
               and utils.supports_selection())

        flags = QUrl.FullyEncoded | QUrl.RemovePassword
        if url.scheme() == 'mailto':
            flags |= QUrl.RemoveScheme
        urlstr = url.toString(flags)  # type: ignore[arg-type]

        new_content = urlstr

        # only second and consecutive yanks are to append to the clipboard
        if context.rapid and not context.first_run:
            try:
                old_content = utils.get_clipboard(selection=sel)
            except utils.ClipboardEmptyError:
                pass
            else:
                new_content = os.linesep.join([old_content, new_content])
        utils.set_clipboard(new_content, selection=sel)

        msg = "Yanked URL to {}: {}".format(
            "primary selection" if sel else "clipboard", urlstr)
        message.info(msg)
Exemple #20
0
    def __init__(self, url: QUrl) -> None:
        super().__init__()
        self.setupUi(self)

        self.m_cookies = []

        self.m_urlLineEdit.setText(url.toString())

        self.m_layout = QVBoxLayout()
        self.m_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum, QSizePolicy.Expanding))
        self.m_layout.setContentsMargins(0, 0, 0, 0)
        self.m_layout.setSpacing(0)

        w = QWidget()
        p = w.palette()
        p.setColor(self.widget.backgroundRole(), Qt.white)
        w.setPalette(p)
        w.setLayout(self.m_layout)

        self.m_scrollArea.setWidget(w)
        self.m_scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.m_scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        self.m_urlButton.clicked.connect(self.handleUrlClicked)
        self.m_deleteAllButton.clicked.connect(self.handleDeleteAllClicked)
        self.m_newButton.clicked.connect(self.handleNewClicked)

        self.m_store: QWebEngineCookieStore = self.m_webview.page().profile(
        ).cookieStore()
        self.m_store.cookieAdded.connect(self.handleCookieAdded)
        self.m_store.loadAllCookies()
        self.m_webview.load(url)
Exemple #21
0
 def _hoverLink(self, url:QUrl) -> None:
     """ In general, if the mouse has moved over a new hyperlink, we save it and send the mouseover signal.
         An empty URL is given when the mouse moves off a hyperlink, which counts as a deselection.
         However, mouseovers are error-prone; there are unavoidable breaks between characters in a column.
         To avoid twitchy selection/deselection, we only send mouseover signals when the reference isn't empty. """
     self._url = url
     if url.toString():
         self.linkOver.emit(url)
 def getPrinterList(self, base_url):        
     self._instance_responded = False
     url = QUrl("http://" + base_url + "/printer/info")
     Logger.log("d", "getPrinterList:" + url.toString())
     settings_request = QNetworkRequest(url)        
     settings_request.setRawHeader("User-Agent".encode(), self._user_agent)
     self._printerlist_reply=self._network_manager.get(settings_request)
     return self._printers
Exemple #23
0
    def _is_blocked(
        self,
        request_url: QUrl,
        first_party_url: Optional[QUrl] = None,
        resource_type: Optional[interceptor.ResourceType] = None,
    ) -> bool:
        """Check whether the given request is blocked."""
        if not self.enabled:
            # Do nothing if `content.blocking.method` is not set to enable the
            # use of this adblocking module.
            return False

        if (
            first_party_url is None
            or not first_party_url.isValid()
            or first_party_url.scheme() == "file"
        ):
            # FIXME: It seems that when `first_party_url` is None, every URL
            # I try is blocked. This may have been a result of me incorrectly
            # using the upstream library, or an upstream bug. For now we don't
            # block any request with `first_party_url=None`.
            return False

        qtutils.ensure_valid(request_url)

        if not config.get("content.blocking.enabled", url=first_party_url):
            # Do nothing if adblocking is disabled for this site.
            return False

        result = self._engine.check_network_urls(
            request_url.toString(),
            first_party_url.toString(),
            _resource_type_to_string(resource_type),
        )

        if not result.matched:
            return False
        elif result.exception is not None and not result.important:
            # Exception is not `None` when the blocker matched on an exception
            # rule. Effectively this means that there was a match, but the
            # request should not be blocked.
            #
            # An `important` match means that exceptions should not apply and
            # no further checking is necessary--the request should be blocked.
            logger.debug(
                "Excepting %s from being blocked by %s because of %s",
                request_url.toDisplayString(),
                result.filter,
                result.exception,
            )
            return False
        elif blockutils.is_whitelisted_url(request_url):
            logger.debug(
                "Request to %s is whitelisted, thus not blocked",
                request_url.toDisplayString(),
            )
            return False
        return True
    def is_url_whitelisted(self, url: QUrl):
        url_string = url.toString()
        if url_string.startswith("https://accounts.google.com/signin") or \
                url_string.startswith("https://accounts.google.com/AddSession") or \
                url_string.startswith("https://accounts.google.com/ServiceLogin") or \
                url_string.startswith("https://accounts.google.com/o/oauth2"):
            return True

        return False
Exemple #25
0
    def checkWhitelist(self, url: QUrl):
        global dirname
        currentUrl = url.toString()

        for x in args.whiteList:
            if (currentUrl.startswith(x)):
                return True
            elif (args.enablepdfsupport):
                global dirname
                # Because of Crossplatform compatibility all the slashs and backslashes of local paths are removes
                pdfjsviewer_checkstring = (
                    "file:///" +
                    dirname + "/plugins/pdf.js/web/viewer.html?").replace(
                        "\\", "/").replace("/", "")
                checkurl_checkstring = currentUrl.replace("\\", "/").replace(
                    "/", "")
                if (checkurl_checkstring.startswith(pdfjsviewer_checkstring)
                        or (currentUrl.startswith("file:///")
                            and currentUrl.endswith("?downloadPdfFromPykib"))):
                    return True
                else:
                    self.closePDFPage()

        logging.info("Site " + currentUrl + " is not whitelisted")

        #If Remote Browser is used we will show no warning an won't open the page
        if (args.remoteBrowserDaemon):
            return False

        msg = QtWidgets.QMessageBox()
        msg.setIcon(QtWidgets.QMessageBox.Warning)
        msg.setText("Site " + currentUrl + " is not white-listed")
        msg.setWindowTitle("Whitelist Error")

        backButton = QtWidgets.QPushButton("Go Back")
        backButton.setIcon(QIcon(os.path.join(dirname, 'icons/back.png')))
        backButton.setIconSize(QSize(24, 24))
        backButton.setObjectName("backButton")

        msg.addButton(backButton, QtWidgets.QMessageBox.NoRole)

        homeButton = QtWidgets.QPushButton("Go Home")
        homeButton.setIcon(QIcon(os.path.join(dirname, 'icons/home.png')))
        homeButton.setIconSize(QSize(24, 24))
        homeButton.setObjectName("homeButton")

        msg.addButton(homeButton, QtWidgets.QMessageBox.NoRole)

        msg.show()
        retval = msg.exec_()

        if (retval == 0):
            self.view().stop()
        else:
            self.view().load(args.url)

        return False
Exemple #26
0
def get_main_url(filename: str, original_url: QUrl) -> QUrl:
    """Get the URL to be opened to view a local PDF."""
    url = QUrl('qute://pdfjs/web/viewer.html')
    query = QUrlQuery()
    query.addQueryItem('filename', filename)  # read from our JS
    query.addQueryItem('file', '')  # to avoid pdfjs opening the default PDF
    urlstr = original_url.toString(QUrl.FullyEncoded)  # type: ignore[arg-type]
    query.addQueryItem('source', urlstr)
    url.setQuery(query)
    return url
Exemple #27
0
    def acceptNavigationRequest(self, url: QUrl,
                                type: QWebEnginePage.NavigationType,
                                isMainFrame: bool, **kwargs):
        if type == QWebEnginePage.NavigationTypeLinkClicked:
            if url.scheme() == 'entry':
                try:
                    _, item = url.toString().split(":")
                except:
                    return False
                ProgressDialog.show_progress(self.parent(), "Loading...")
                item = item.strip("/ ")
                dict_name = CurrentState.get_cur_dict()
                self.lookupThread.word = item
                self.lookupThread.dicts = [dict_name]
                self.lookupThread.start()
                #dict_name=CurrentState.get_cur_dict()
                #try:
                #result_obj: dict = SocketClient.lookup(item,[dict_name])
                #raw_html = pretty_dict_result(dict_name,result_obj.get(dict_name,"No entry found"))
                #except Exception as e:
                #    print(f"Lookup {item} error = {e}")
                #    return False
                #print(self.url())
                #self.setHtml(raw_html,self.url())
                #CurrentState.add_history(item)

            elif url.scheme() == 'sound':
                item = url.toString().split("://")[1]
                name = CurrentState.get_cur_dict()
                try:
                    httpPlaySound(item, name)
                except Exception as e:
                    self.play_sound_error_sig.emit(str(e))
                    print(f"play sound error = {e}")

                #command=[SOUND_PLAYER, str(Path(data_folder).joinpath(item))]
                #os.system(SOUND_PLAYER+" "+str(Path(data_folder).joinpath(item)))
                #subprocess.Popen(command)

            return False

        return True
Exemple #28
0
 def on_post_auth_redirect(self, url: Core.QUrl):
     url = urllib.parse.urlsplit(url.toString())
     if Authorizer._is_auth_page(url):
         self._view.urlChanged.disconnect(self.on_post_auth_redirect)
         auth_result = url.fragment.split('&')
         auth_result = dict(map(lambda p: tuple(p.split('=')), auth_result))
         if 'auth_token' in auth_result:
             signal = self.auth_success
         else:
             signal = self.auth_fail
         signal.emit(auth_result)
Exemple #29
0
    def spawn(self, url: QUrl, context: HintContext) -> None:
        """Spawn a simple command from a hint.

        Args:
            url: The URL to open as a QUrl.
            context: The HintContext to use.
        """
        urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
        args = context.get_args(urlstr)
        commandrunner = runners.CommandRunner(self._win_id)
        commandrunner.run_safely('spawn ' + ' '.join(args))
Exemple #30
0
    def _resource_url(self, path: str) -> str:
        """Load qutebrowser resource files.

        Arguments:
            path: The relative path to the resource.
        """
        assert not posixpath.isabs(path), path
        url = QUrl('qute://resource')
        url.setPath('/' + path)
        urlutils.ensure_valid(url)
        urlstr = url.toString(QUrl.FullyEncoded)  # type: ignore[arg-type]
        return urlstr
Exemple #31
0
        def emit_message_info(title=False):
            """
            If requesting for the document's title, emit it. Otherwise,
            if a link is focused, emit its target to the message label

            """

            if title:
                self.show_message.emit(self.title())
            elif self.__in_focus is not None:
                qurl = QUrl(self.__in_focus.attribute('href'))
                qurl = do_redirect(qurl)
                self.show_message.emit(qurl.toString())
Exemple #32
0
    def acceptNavigationRequest(self, url: QUrl,
                                type: QWebEnginePage.NavigationType,
                                isMainFrame: bool, **kwargs):
        if type == QWebEnginePage.NavigationTypeLinkClicked:
            if url.scheme() == 'entry':
                _, item = url.toString().split(":")
                item = item.strip("/ ")
                dict_name, data_folder = CurrentState.get_cur_dict_info()
                result_obj: dict = SocketClient.lookup(item, [dict_name])
                raw_html = pretty_dict_result(dict_name, result_obj[dict_name])
                #print(self.url())
                self.setHtml(raw_html, self.url())
                CurrentState.add_history(item)
            elif url.scheme() == 'sound':
                item = url.toString().split("://")[1].lower()
                _, data_folder = CurrentState.get_cur_dict_info()
                command = [SOUND_PLAYER, str(Path(data_folder).joinpath(item))]
                #os.system(SOUND_PLAYER+" "+str(Path(data_folder).joinpath(item)))
                subprocess.Popen(command)

            return False

        return True
Exemple #33
0
 def addHistoryEntry(self, url):
     """
     Public method to add a history entry.
     
     @param url URL to be added (string)
     """
     cleanurl = QUrl(url)
     if cleanurl.scheme() not in ["eric", "about"]:
         if cleanurl.password():
             # don't save the password in the history
             cleanurl.setPassword("")
         if cleanurl.host():
             cleanurl.setHost(cleanurl.host().lower())
         itm = HistoryEntry(cleanurl.toString(), QDateTime.currentDateTime())
         self._addHistoryEntry(itm)
Exemple #34
0
def resource_url(path, qutescheme=False):
    """Load images from a relative path (to qutebrowser).

    Arguments:
        path: The relative path to the image
        qutescheme: If the logo needs to be served via a qute:// scheme.
                    This is the case when we want to show an error page from
                    there.
    """
    if qutescheme:
        url = QUrl()
        url.setScheme('qute')
        url.setHost('resource')
        url.setPath('/' + path)
        qtutils.ensure_valid(url)
        return url.toString(QUrl.FullyEncoded)
    else:
        full_path = utils.resource_filename(path)
        return QUrl.fromLocalFile(full_path).toString(QUrl.FullyEncoded)
Exemple #35
0
def _generate_pdfjs_script(filename):
    """Generate the script that shows the pdf with pdf.js.

    Args:
        filename: The name of the file to open.
    """
    url = QUrl('qute://pdfjs/file')
    url_query = QUrlQuery()
    url_query.addQueryItem('filename', filename)
    url.setQuery(url_query)

    return jinja.js_environment.from_string("""
        document.addEventListener("DOMContentLoaded", function() {
          if (typeof window.PDFJS !== 'undefined') {
              // v1.x
              {% if disable_create_object_url %}
              window.PDFJS.disableCreateObjectURL = true;
              {% endif %}
              window.PDFJS.verbosity = window.PDFJS.VERBOSITY_LEVELS.info;
          } else {
              // v2.x
              const options = window.PDFViewerApplicationOptions;
              {% if disable_create_object_url %}
              options.set('disableCreateObjectURL', true);
              {% endif %}
              options.set('verbosity', pdfjsLib.VerbosityLevel.INFOS);
          }

          const viewer = window.PDFView || window.PDFViewerApplication;
          viewer.open({{ url }});
        });
    """).render(
        url=javascript.to_js(url.toString(QUrl.FullyEncoded)),
        # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70420
        disable_create_object_url=(
            not qtutils.version_check('5.12') and
            not qtutils.version_check('5.7.1', exact=True, compiled=False) and
            objects.backend == usertypes.Backend.QtWebEngine))
Exemple #36
0
 def __convertFromOldBookmarks(self):
     """
     Private method to convert the old bookmarks into the new ones.
     """
     bmNames = Preferences.Prefs.settings.value('Bookmarks/Names')
     bmFiles = Preferences.Prefs.settings.value('Bookmarks/Files')
     
     if bmNames is not None and bmFiles is not None:
         if len(bmNames) == len(bmFiles):
             convertedRootNode = BookmarkNode(BookmarkNode.Folder)
             convertedRootNode.title = self.tr("Converted {0}")\
                 .format(QDate.currentDate().toString(
                     Qt.SystemLocaleShortDate))
             for i in range(len(bmNames)):
                 node = BookmarkNode(BookmarkNode.Bookmark,
                                     convertedRootNode)
                 node.title = bmNames[i]
                 url = QUrl(bmFiles[i])
                 if not url.scheme():
                     url.setScheme("file")
                 node.url = url.toString()
             self.addBookmark(self.menu(), convertedRootNode)
             
             Preferences.Prefs.settings.remove('Bookmarks')
Exemple #37
0
    def start(self, fn, noEntries=0):
        """
        Public slot to start the svn log command.
        
        @param fn filename to show the log for (string)
        @param noEntries number of entries to show (integer)
        """
        self.errorGroup.hide()

        fetchLimit = 10

        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        QApplication.processEvents()

        self.filename = fn
        dname, fname = self.vcs.splitPath(fn)

        opts = self.vcs.options["global"] + self.vcs.options["log"]
        verbose = "--verbose" in opts

        self.activateWindow()
        self.raise_()

        locker = QMutexLocker(self.vcs.vcsExecutionMutex)
        cwd = os.getcwd()
        os.chdir(dname)
        try:
            nextRev = 0
            fetched = 0
            logs = []
            limit = noEntries or 9999999
            while fetched < limit:
                flimit = min(fetchLimit, limit - fetched)
                if fetched == 0:
                    revstart = pysvn.Revision(pysvn.opt_revision_kind.head)
                else:
                    revstart = pysvn.Revision(pysvn.opt_revision_kind.number, nextRev)
                allLogs = self.client.log(
                    fname,
                    revision_start=revstart,
                    discover_changed_paths=verbose,
                    limit=flimit + 1,
                    strict_node_history=False,
                )
                if len(allLogs) <= flimit or self._clientCancelCallback():
                    logs.extend(allLogs)
                    break
                else:
                    logs.extend(allLogs[:-1])
                    nextRev = allLogs[-1]["revision"].number
                    fetched += fetchLimit
            locker.unlock()

            self.contents.clear()
            self.__pegRev = None
            for log in logs:
                ver = "{0:d}".format(log["revision"].number)
                dstr = "<b>{0} {1}</b>".format(self.revString, ver)
                if self.__pegRev is None:
                    self.__pegRev = int(ver)
                try:
                    lv = "{0:d}".format(logs[logs.index(log) + 1]["revision"].number)
                    url = QUrl()
                    url.setScheme("file")
                    url.setPath(self.filename)
                    query = lv + "_" + ver
                    url.setQuery(query)
                    dstr += ' [<a href="{0}" name="{1}">{2}</a>]'.format(
                        url.toString(), query, self.tr("diff to {0}").format(lv)
                    )
                except IndexError:
                    pass
                dstr += "<br />\n"
                self.contents.insertHtml(dstr)

                author = log["author"]
                message = log["message"]
                if sys.version_info[0] == 2:
                    author = author.decode("utf-8")
                    message = message.decode("utf-8")
                dstr = self.tr("<i>author: {0}</i><br />\n").format(author)
                self.contents.insertHtml(dstr)

                dstr = self.tr("<i>date: {0}</i><br />\n").format(formatTime(log["date"]))
                self.contents.insertHtml(dstr)

                self.contents.insertHtml("<br />\n")

                for line in message.splitlines():
                    self.contents.insertHtml(Utilities.html_encode(line))
                    self.contents.insertHtml("<br />\n")

                if len(log["changed_paths"]) > 0:
                    self.contents.insertHtml("<br />\n")
                    for changeInfo in log["changed_paths"]:
                        action = changeInfo["action"]
                        path = changeInfo["path"]
                        if sys.version_info[0] == 2:
                            action = action.decode("utf-8")
                            path = path.decode("utf-8")
                        dstr = "{0} {1}".format(self.flags[action], path)
                        if changeInfo["copyfrom_path"] is not None:
                            copyfrom_path = changeInfo["copyfrom_path"]
                            if sys.version_info[0] == 2:
                                copyfrom_path = copyfrom_path.decode("utf-8")
                            dstr += self.tr(" (copied from {0}, revision {1})").format(
                                copyfrom_path, changeInfo["copyfrom_revision"].number
                            )
                        dstr += "<br />\n"
                        self.contents.insertHtml(dstr)

                self.contents.insertHtml("<hr /><br />\n")
        except pysvn.ClientError as e:
            locker.unlock()
            self.__showError(e.args[0])
        os.chdir(cwd)
        self.__finish()
Exemple #38
0
 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
Exemple #39
0
class ClickToFlash(QWidget, Ui_ClickToFlash):
    """
    Class implementing the Flash blocker.
    """
    _acceptedUrl = QUrl()
    _acceptedArgNames = []
    _acceptedArgValues = []

    def __init__(self, plugin, mimeType, url, argumentNames, argumentValues,
                 parent=None):
        """
        Constructor
        
        @param plugin reference to the plug-in (ClickToFlashPlugin)
        @param mimeType MIME type for the plug-in (string)
        @param url requested URL (QUrl)
        @param argumentNames list of argument names (list of strings)
        @param argumentValues list of argument values (list of strings)
        @param parent reference to the parent widget (QWidget)
        """
        super(ClickToFlash, self).__init__(parent)
        
        # Check AdBlock first
        import Helpviewer.HelpWindow
        manager = Helpviewer.HelpWindow.HelpWindow.adBlockManager()
        if manager.isEnabled():
            urlString = bytes(url.toEncoded()).decode()
            urlDomain = url.host()
            for subscription in manager.subscriptions():
                blockedRule = subscription.match(
                    QNetworkRequest(url), urlDomain, urlString)
                if blockedRule:
                    QTimer.singleShot(200, self.__hideAdBlocked)
                    return
        
        self.setupUi(self)
        
        self.__swapping = False
        self.__element = QWebElement()
        
        self.__plugin = plugin
        self.__url = QUrl(url)
        self.__argumentNames = argumentNames[:]
        self.__argumentValues = argumentValues[:]
        self.__mimeType = mimeType
        
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.__showContextMenu)
        self.setToolTip(self.__url.toString())
        
        iconName = plugin.getIconName(mimeType)
        if iconName:
            self.loadFlashButton.setIcon(UI.PixmapCache.getIcon(iconName))
        else:
            self.loadFlashButton.setText(self.tr("Load"))
    
    @pyqtSlot()
    def on_loadFlashButton_clicked(self):
        """
        Private slot handling the flash activation.
        """
        self.__load()
    
    def __showContextMenu(self):
        """
        Private slot to show the context menu.
        """
        menu = QMenu()
        act = menu.addAction(self.tr("Object blocked by ClickToFlash"))
        font = act.font()
        font.setBold(True)
        act.setFont(font)
        menu.addAction(
            self.tr("Show information about object"), self.__showInfo)
        menu.addSeparator()
        menu.addAction(self.tr("Load"), self.__load)
        menu.addAction(self.tr("Delete object"), self.__hideAdBlocked)
        menu.addSeparator()
        host = self.__url.host()
        add = menu.addAction(
            self.tr("Add '{0}' to Whitelist").format(host),
            self.__addToWhitelist)
        remove = menu.addAction(
            self.tr("Remove '{0}' from Whitelist").format(host),
            self.__removeFromWhitelist)
        onWhitelist = self.__plugin.onWhitelist(host)
        add.setEnabled(not onWhitelist)
        remove.setEnabled(onWhitelist)
        menu.addSeparator()
        menu.addAction(self.tr("Configure Whitelist"), self.__configure)
        menu.actions()[0].setEnabled(False)
        
        menu.exec_(QCursor.pos())
    
    def swapping(self):
        """
        Public method to check, if the plug-in is swapping.
        
        @return flag indicating the swapping status (boolean)
        """
        return self.__swapping
    
    def __configure(self):
        """
        Private slot to configure the whitelist.
        """
        self.__plugin.configure()
    
    def __addToWhitelist(self):
        """
        Private slot to add the host to the whitelist.
        """
        self.__plugin.addToWhitelist(self.__url.host())
    
    def __removeFromWhitelist(self):
        """
        Private slot to remove the host from the whitelist.
        """
        self.__plugin.removeFromWhitelist(self.__url.host())
    
    def __load(self, all=False):
        """
        Private slot to load the flash content.
        
        @param all flag indicating to load all flash players. (boolean)
        """
        self.__findElement()
        if not self.__element.isNull():
            substitute = self.__element.clone()
            substitute.setAttribute("type", self.__mimeType)
            self.__element.replace(substitute)

            ClickToFlash._acceptedUrl = self.__url
            ClickToFlash._acceptedArgNames = self.__argumentNames
            ClickToFlash._acceptedArgValues = self.__argumentValues
    
    def __findElement(self):
        """
        Private method to find the element belonging to this ClickToFlash
        instance.
        """
        parent = self.parentWidget()
        view = None
        while parent is not None:
            if isinstance(parent, QWebView):
                view = parent
                break
            parent = parent.parentWidget()
        if view is None:
            return
        
        objectPos = view.mapFromGlobal(self.loadFlashButton.mapToGlobal(
            self.loadFlashButton.pos()))
        objectFrame = view.page().frameAt(objectPos)
        hitResult = QWebHitTestResult()
        hitElement = QWebElement()
        
        if objectFrame is not None:
            hitResult = objectFrame.hitTestContent(objectPos)
            hitElement = hitResult.element()
        
        if not hitElement.isNull() and \
           hitElement.tagName().lower() in ["embed", "object"]:
            self.__element = hitElement
            return
        
        # hit test failed, trying to find element by src
        # attribute in elements of all frames on page (although less accurate
        frames = []
        frames.append(view.page().mainFrame())
        while frames:
            frame = frames.pop(0)
            if not frame:
                continue
            docElement = frame.documentElement()
            elements = QWebElementCollection()
            elements.append(docElement.findAll("embed"))
            elements.append(docElement.findAll("object"))
            
            for element in elements:
                if not self.__checkElement(element) and \
                   not self.__checkUrlOnElement(element, view):
                    continue
                self.__element = element
                return
            frames.extend(frame.childFrames())
    
    def __checkUrlOnElement(self, element, view):
        """
        Private slot to check the URL of an element.
        
        @param element reference to the element to check (QWebElement)
        @param view reference to the view object (QWebView)
        @return flag indicating a positive result (boolean)
        """
        checkString = element.attribute("src")
        if checkString == "":
            checkString = element.attribute("data")
        if checkString == "":
            checkString = element.attribute("value")
        
        checkString = view.url().resolved(QUrl(checkString)).toString(
            QUrl.RemoveQuery)
        return self.__url.toEncoded().contains(
            QByteArray(checkString.encode("utf-8")))
    
    def __checkElement(self, element):
        """
        Private slot to check an element against the saved arguments.
        
        @param element reference to the element to check (QWebElement)
        @return flag indicating a positive result (boolean)
        """
        if self.__argumentNames == element.attributeNames():
            for name in self.__argumentNames:
                if element.attribute(name) not in self.__argumentValues:
                    return False
            
            return True
        
        return False
    
    def __hideAdBlocked(self):
        """
        Private slot to hide the object.
        """
        self.__findElement()
        if not self.__element.isNull():
            self.__element.setStyleProperty("display", "none")
        else:
            self.hide()
    
    def __showInfo(self):
        """
        Private slot to show information about the blocked object.
        """
        dlg = QDialog()
        dlg.setWindowTitle(self.tr("Flash Object"))
        dlg.setSizeGripEnabled(True)
        layout = QFormLayout(dlg)
        layout.addRow(QLabel(self.tr("<b>Attribute Name</b>")),
                      QLabel(self.tr("<b>Value</b>")))
        
        index = 0
        for name in self.__argumentNames:
            nameLabel = QLabel(self.__elide(name, length=30))
            value = self.__argumentValues[index]
            valueLabel = QLabel(self.__elide(value, length=60))
            valueLabel.setTextInteractionFlags(
                Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse)
            layout.addRow(nameLabel, valueLabel)
            
            index += 1
        
        if index == 0:
            layout.addRow(QLabel(self.tr("No information available.")))
        
        dlg.setMaximumHeight(500)
        dlg.setMaximumWidth(500)
        dlg.exec_()
    
    def __elide(self, txt, mode=Qt.ElideMiddle, length=40):
        """
        Private method to elide some text.
        
        @param txt text to be elided (string)
        @keyparam mode elide mode (Qt.TextElideMode)
        @keyparam length amount of characters to be used (integer)
        @return the elided text (string)
        """
        if mode == Qt.ElideNone or len(txt) < length:
            return txt
        elif mode == Qt.ElideLeft:
            return "...{0}".format(txt[-length:])
        elif mode == Qt.ElideMiddle:
            return "{0}...{1}".format(txt[:length // 2], txt[-(length // 2):])
        elif mode == Qt.ElideRight:
            return "{0}...".format(txt[:length])
        else:
            # just in case
            return txt
    
    @classmethod
    def isAlreadyAccepted(cls, url, argumentNames, argumentValues):
        """
        Class method to check, if the given parameter combination is being
        accepted.
        
        @param url URL to be checked for (QUrl)
        @param argumentNames argument names to be checked for (list of strings)
        @param argumentValues argument values to be checked for (list of
            strings)
        @return flag indicating that this was already accepted (boolean)
        """
        return url == cls._acceptedUrl and \
            argumentNames == cls._acceptedArgNames and \
            argumentValues == cls._acceptedArgValues
Exemple #40
0
class WebView(QWebView):

    """One browser tab in TabbedBrowser.

    Our own subclass of a QWebView with some added bells and whistles.

    Attributes:
        hintmanager: The HintManager instance for this view.
        progress: loading progress of this page.
        scroll_pos: The current scroll position as (x%, y%) tuple.
        statusbar_message: The current javascript statusbar message.
        inspector: The QWebInspector used for this webview.
        load_status: loading status of this page (index into LoadStatus)
        viewing_source: Whether the webview is currently displaying source
                        code.
        keep_icon: Whether the (e.g. cloned) icon should not be cleared on page
                   load.
        registry: The ObjectRegistry associated with this tab.
        tab_id: The tab ID of the view.
        win_id: The window ID of the view.
        search_text: The text of the last search.
        search_flags: The search flags of the last search.
        _has_ssl_errors: Whether SSL errors occurred during loading.
        _zoom: A NeighborList with the zoom levels.
        _old_scroll_pos: The old scroll position.
        _check_insertmode: If True, in mouseReleaseEvent we should check if we
                           need to enter/leave insert mode.
        _default_zoom_changed: Whether the zoom was changed from the default.
        _ignore_wheel_event: Ignore the next wheel event.
                             See https://github.com/The-Compiler/qutebrowser/issues/395

    Signals:
        scroll_pos_changed: Scroll percentage of current tab changed.
                            arg 1: x-position in %.
                            arg 2: y-position in %.
        linkHovered: QWebPages linkHovered signal exposed.
        load_status_changed: The loading status changed
        url_text_changed: Current URL string changed.
        shutting_down: Emitted when the view is shutting down.
    """

    scroll_pos_changed = pyqtSignal(int, int)
    linkHovered = pyqtSignal(str, str, str)
    load_status_changed = pyqtSignal(str)
    url_text_changed = pyqtSignal(str)
    shutting_down = pyqtSignal()

    def __init__(self, win_id, parent=None):
        super().__init__(parent)
        if sys.platform == 'darwin' and qtutils.version_check('5.4'):
            # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-42948
            # See https://github.com/The-Compiler/qutebrowser/issues/462
            self.setStyle(QStyleFactory.create('Fusion'))
        self.win_id = win_id
        self.load_status = LoadStatus.none
        self._check_insertmode = False
        self.inspector = None
        self.scroll_pos = (-1, -1)
        self.statusbar_message = ''
        self._old_scroll_pos = (-1, -1)
        self._zoom = None
        self._has_ssl_errors = False
        self._ignore_wheel_event = False
        self.keep_icon = False
        self.search_text = None
        self.search_flags = 0
        self.selection_enabled = False
        self.init_neighborlist()
        self._set_bg_color()
        cfg = objreg.get('config')
        cfg.changed.connect(self.init_neighborlist)
        # For some reason, this signal doesn't get disconnected automatically
        # when the WebView is destroyed on older PyQt versions.
        # See https://github.com/The-Compiler/qutebrowser/issues/390
        self.destroyed.connect(functools.partial(
            cfg.changed.disconnect, self.init_neighborlist))
        self.cur_url = QUrl()
        self._orig_url = QUrl()
        self.progress = 0
        self.registry = objreg.ObjectRegistry()
        self.tab_id = next(tab_id_gen)
        tab_registry = objreg.get('tab-registry', scope='window',
                                  window=win_id)
        tab_registry[self.tab_id] = self
        objreg.register('webview', self, registry=self.registry)
        page = self._init_page()
        hintmanager = hints.HintManager(win_id, self.tab_id, self)
        hintmanager.mouse_event.connect(self.on_mouse_event)
        hintmanager.start_hinting.connect(page.on_start_hinting)
        hintmanager.stop_hinting.connect(page.on_stop_hinting)
        objreg.register('hintmanager', hintmanager, registry=self.registry)
        mode_manager = objreg.get('mode-manager', scope='window',
                                  window=win_id)
        mode_manager.entered.connect(self.on_mode_entered)
        mode_manager.left.connect(self.on_mode_left)
        self.viewing_source = False
        self.setZoomFactor(float(config.get('ui', 'default-zoom')) / 100)
        self._default_zoom_changed = False
        if config.get('input', 'rocker-gestures'):
            self.setContextMenuPolicy(Qt.PreventContextMenu)
        self.urlChanged.connect(self.on_url_changed)
        self.loadProgress.connect(lambda p: setattr(self, 'progress', p))
        objreg.get('config').changed.connect(self.on_config_changed)

    @pyqtSlot()
    def on_initial_layout_completed(self):
        """Add url to history now that we have displayed something."""
        history = objreg.get('web-history')
        if not self._orig_url.matches(self.cur_url,
                                      QUrl.UrlFormattingOption(0)):
            # If the url of the page is different than the url of the link
            # originally clicked, save them both.
            url = self._orig_url.toString(QUrl.FullyEncoded |
                                          QUrl.RemovePassword)
            history.add_url(url, self.title(), hidden=True)
        url = self.cur_url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)

        history.add_url(url, self.title())

    def _init_page(self):
        """Initialize the QWebPage used by this view."""
        page = webpage.BrowserPage(self.win_id, self.tab_id, self)
        self.setPage(page)
        page.linkHovered.connect(self.linkHovered)
        page.mainFrame().loadStarted.connect(self.on_load_started)
        page.mainFrame().loadFinished.connect(self.on_load_finished)
        page.mainFrame().initialLayoutCompleted.connect(
            self.on_initial_layout_completed)
        page.statusBarMessage.connect(
            lambda msg: setattr(self, 'statusbar_message', msg))
        page.networkAccessManager().sslErrors.connect(
            lambda *args: setattr(self, '_has_ssl_errors', True))
        return page

    def __repr__(self):
        url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode), 100)
        return utils.get_repr(self, tab_id=self.tab_id, url=url)

    def __del__(self):
        # Explicitly releasing the page here seems to prevent some segfaults
        # when quitting.
        # Copied from:
        # https://code.google.com/p/webscraping/source/browse/webkit.py#325
        try:
            self.setPage(None)
        except RuntimeError:
            # It seems sometimes Qt has already deleted the QWebView and we
            # get: RuntimeError: wrapped C/C++ object of type WebView has been
            # deleted
            pass

    def _set_load_status(self, val):
        """Setter for load_status."""
        if not isinstance(val, LoadStatus):
            raise TypeError("Type {} is no LoadStatus member!".format(val))
        log.webview.debug("load status for {}: {}".format(repr(self), val))
        self.load_status = val
        self.load_status_changed.emit(val.name)
        if val == LoadStatus.loading:
            self._orig_url = self.cur_url

    def _set_bg_color(self):
        """Set the webpage background color as configured."""
        col = config.get('colors', 'webpage.bg')
        palette = self.palette()
        if col is None:
            col = self.style().standardPalette().color(QPalette.Base)
        palette.setColor(QPalette.Base, col)
        self.setPalette(palette)

    @pyqtSlot(str, str)
    def on_config_changed(self, section, option):
        """Reinitialize the zoom neighborlist if related config changed."""
        if section == 'ui' and option in ('zoom-levels', 'default-zoom'):
            if not self._default_zoom_changed:
                self.setZoomFactor(float(config.get('ui', 'default-zoom')) /
                                   100)
            self._default_zoom_changed = False
            self.init_neighborlist()
        elif section == 'input' and option == 'rocker-gestures':
            if config.get('input', 'rocker-gestures'):
                self.setContextMenuPolicy(Qt.PreventContextMenu)
            else:
                self.setContextMenuPolicy(Qt.DefaultContextMenu)
        elif section == 'colors' and option == 'webpage.bg':
            self._set_bg_color()

    def init_neighborlist(self):
        """Initialize the _zoom neighborlist."""
        levels = config.get('ui', 'zoom-levels')
        self._zoom = usertypes.NeighborList(
            levels, mode=usertypes.NeighborList.Modes.edge)
        self._zoom.fuzzyval = config.get('ui', 'default-zoom')

    def _mousepress_backforward(self, e):
        """Handle back/forward mouse button presses.

        Args:
            e: The QMouseEvent.
        """
        if e.button() in (Qt.XButton1, Qt.LeftButton):
            # Back button on mice which have it, or rocker gesture
            if self.page().history().canGoBack():
                self.back()
            else:
                message.error(self.win_id, "At beginning of history.",
                              immediately=True)
        elif e.button() in (Qt.XButton2, Qt.RightButton):
            # Forward button on mice which have it, or rocker gesture
            if self.page().history().canGoForward():
                self.forward()
            else:
                message.error(self.win_id, "At end of history.",
                              immediately=True)

    def _mousepress_insertmode(self, e):
        """Switch to insert mode when an editable element was clicked.

        Args:
            e: The QMouseEvent.
        """
        pos = e.pos()
        frame = self.page().frameAt(pos)
        if frame is None:
            # This happens when we click inside the webview, but not actually
            # on the QWebPage - for example when clicking the scrollbar
            # sometimes.
            log.mouse.debug("Clicked at {} but frame is None!".format(pos))
            return
        # You'd think we have to subtract frame.geometry().topLeft() from the
        # position, but it seems QWebFrame::hitTestContent wants a position
        # relative to the QWebView, not to the frame. This makes no sense to
        # me, but it works this way.
        hitresult = frame.hitTestContent(pos)
        if hitresult.isNull():
            # For some reason, the whole hit result can be null sometimes (e.g.
            # on doodle menu links). If this is the case, we schedule a check
            # later (in mouseReleaseEvent) which uses webelem.focus_elem.
            log.mouse.debug("Hitresult is null!")
            self._check_insertmode = True
            return
        try:
            elem = webelem.WebElementWrapper(hitresult.element())
        except webelem.IsNullError:
            # For some reason, the hit result element can be a null element
            # sometimes (e.g. when clicking the timetable fields on
            # http://www.sbb.ch/ ). If this is the case, we schedule a check
            # later (in mouseReleaseEvent) which uses webelem.focus_elem.
            log.mouse.debug("Hitresult element is null!")
            self._check_insertmode = True
            return
        if ((hitresult.isContentEditable() and elem.is_writable()) or
                elem.is_editable()):
            log.mouse.debug("Clicked editable element!")
            modeman.enter(self.win_id, usertypes.KeyMode.insert, 'click',
                          only_if_normal=True)
        else:
            log.mouse.debug("Clicked non-editable element!")
            if config.get('input', 'auto-leave-insert-mode'):
                modeman.maybe_leave(self.win_id, usertypes.KeyMode.insert,
                                    'click')

    def mouserelease_insertmode(self):
        """If we have an insertmode check scheduled, handle it."""
        if not self._check_insertmode:
            return
        self._check_insertmode = False
        try:
            elem = webelem.focus_elem(self.page().currentFrame())
        except (webelem.IsNullError, RuntimeError):
            log.mouse.debug("Element/page vanished!")
            return
        if elem.is_editable():
            log.mouse.debug("Clicked editable element (delayed)!")
            modeman.enter(self.win_id, usertypes.KeyMode.insert,
                          'click-delayed', only_if_normal=True)
        else:
            log.mouse.debug("Clicked non-editable element (delayed)!")
            if config.get('input', 'auto-leave-insert-mode'):
                modeman.maybe_leave(self.win_id, usertypes.KeyMode.insert,
                                    'click-delayed')

    def _mousepress_opentarget(self, e):
        """Set the open target when something was clicked.

        Args:
            e: The QMouseEvent.
        """
        if e.button() == Qt.MidButton or e.modifiers() & Qt.ControlModifier:
            background_tabs = config.get('tabs', 'background-tabs')
            if e.modifiers() & Qt.ShiftModifier:
                background_tabs = not background_tabs
            if background_tabs:
                target = usertypes.ClickTarget.tab_bg
            else:
                target = usertypes.ClickTarget.tab
            self.page().open_target = target
            log.mouse.debug("Middle click, setting target: {}".format(target))
        else:
            self.page().open_target = usertypes.ClickTarget.normal
            log.mouse.debug("Normal click, setting normal target")

    def shutdown(self):
        """Shut down the webview."""
        self.shutting_down.emit()
        # We disable javascript because that prevents some segfaults when
        # quitting it seems.
        log.destroy.debug("Shutting down {!r}.".format(self))
        settings = self.settings()
        settings.setAttribute(QWebSettings.JavascriptEnabled, False)
        self.stop()
        self.page().shutdown()

    def openurl(self, url):
        """Open a URL in the browser.

        Args:
            url: The URL to load as QUrl
        """
        qtutils.ensure_valid(url)
        urlstr = url.toDisplayString()
        log.webview.debug("New title: {}".format(urlstr))
        self.titleChanged.emit(urlstr)
        self.cur_url = url
        self.url_text_changed.emit(url.toDisplayString())
        self.load(url)
        if url.scheme() == 'qute':
            frame = self.page().mainFrame()
            frame.javaScriptWindowObjectCleared.connect(self.add_js_bridge)

    @pyqtSlot()
    def add_js_bridge(self):
        """Add the javascript bridge for qute:... pages."""
        frame = self.sender()
        if not isinstance(frame, QWebFrame):
            log.webview.error("Got non-QWebFrame {!r} in "
                              "add_js_bridge!".format(frame))
            return

        if frame.url().scheme() == 'qute':
            bridge = objreg.get('js-bridge')
            frame.addToJavaScriptWindowObject('qute', bridge)

    def zoom_perc(self, perc, fuzzyval=True):
        """Zoom to a given zoom percentage.

        Args:
            perc: The zoom percentage as int.
            fuzzyval: Whether to set the NeighborLists fuzzyval.
        """
        if fuzzyval:
            self._zoom.fuzzyval = int(perc)
        if perc < 0:
            raise ValueError("Can't zoom {}%!".format(perc))
        self.setZoomFactor(float(perc) / 100)
        self._default_zoom_changed = True

    def zoom(self, offset):
        """Increase/Decrease the zoom level.

        Args:
            offset: The offset in the zoom level list.

        Return:
            The new zoom percentage.
        """
        level = self._zoom.getitem(offset)
        self.zoom_perc(level, fuzzyval=False)
        return level

    @pyqtSlot('QUrl')
    def on_url_changed(self, url):
        """Update cur_url when URL has changed.

        If the URL is invalid, we just ignore it here.
        """
        if url.isValid():
            self.cur_url = url
            self.url_text_changed.emit(url.toDisplayString())
            if not self.title():
                self.titleChanged.emit(self.url().toDisplayString())

    @pyqtSlot('QMouseEvent')
    def on_mouse_event(self, evt):
        """Post a new mouse event from a hintmanager."""
        log.modes.debug("Hint triggered, focusing {!r}".format(self))
        self.setFocus()
        QApplication.postEvent(self, evt)

    @pyqtSlot()
    def on_load_started(self):
        """Leave insert/hint mode and set vars when a new page is loading."""
        self.progress = 0
        self.viewing_source = False
        self._has_ssl_errors = False
        self._set_load_status(LoadStatus.loading)

    @pyqtSlot()
    def on_load_finished(self):
        """Handle a finished page load.

        We don't take loadFinished's ok argument here as it always seems to be
        true when the QWebPage has an ErrorPageExtension implemented.
        See https://github.com/The-Compiler/qutebrowser/issues/84
        """
        ok = not self.page().error_occurred
        if ok and not self._has_ssl_errors:
            if self.cur_url.scheme() == 'https':
                self._set_load_status(LoadStatus.success_https)
            else:
                self._set_load_status(LoadStatus.success)

        elif ok:
            self._set_load_status(LoadStatus.warn)
        else:
            self._set_load_status(LoadStatus.error)
        if not self.title():
            self.titleChanged.emit(self.url().toDisplayString())
        self._handle_auto_insert_mode(ok)

    def _handle_auto_insert_mode(self, ok):
        """Handle auto-insert-mode after loading finished."""
        if not config.get('input', 'auto-insert-mode'):
            return
        mode_manager = objreg.get('mode-manager', scope='window',
                                  window=self.win_id)
        cur_mode = mode_manager.mode
        if cur_mode == usertypes.KeyMode.insert or not ok:
            return
        frame = self.page().currentFrame()
        try:
            elem = webelem.WebElementWrapper(frame.findFirstElement(':focus'))
        except webelem.IsNullError:
            log.webview.debug("Focused element is null!")
            return
        log.modes.debug("focus element: {}".format(repr(elem)))
        if elem.is_editable():
            modeman.enter(self.win_id, usertypes.KeyMode.insert,
                          'load finished', only_if_normal=True)

    @pyqtSlot(usertypes.KeyMode)
    def on_mode_entered(self, mode):
        """Ignore attempts to focus the widget if in any status-input mode."""
        if mode in (usertypes.KeyMode.command, usertypes.KeyMode.prompt,
                    usertypes.KeyMode.yesno):
            log.webview.debug("Ignoring focus because mode {} was "
                              "entered.".format(mode))
            self.setFocusPolicy(Qt.NoFocus)
        elif mode == usertypes.KeyMode.caret:
            settings = self.settings()
            settings.setAttribute(QWebSettings.CaretBrowsingEnabled, True)
            self.selection_enabled = bool(self.page().selectedText())

            if self.isVisible():
                # Sometimes the caret isn't immediately visible, but unfocusing
                # and refocusing it fixes that.
                self.clearFocus()
                self.setFocus(Qt.OtherFocusReason)

                # Move the caret to the first element in the viewport if there
                # isn't any text which is already selected.
                #
                # Note: We can't use hasSelection() here, as that's always
                # true in caret mode.
                if not self.page().selectedText():
                    self.page().currentFrame().evaluateJavaScript(
                        utils.read_file('javascript/position_caret.js'))

    @pyqtSlot(usertypes.KeyMode)
    def on_mode_left(self, mode):
        """Restore focus policy if status-input modes were left."""
        if mode in (usertypes.KeyMode.command, usertypes.KeyMode.prompt,
                    usertypes.KeyMode.yesno):
            log.webview.debug("Restoring focus policy because mode {} was "
                              "left.".format(mode))
        elif mode == usertypes.KeyMode.caret:
            settings = self.settings()
            if settings.testAttribute(QWebSettings.CaretBrowsingEnabled):
                if self.selection_enabled and self.hasSelection():
                    # Remove selection if it exists
                    self.triggerPageAction(QWebPage.MoveToNextChar)
                settings.setAttribute(QWebSettings.CaretBrowsingEnabled, False)
                self.selection_enabled = False

        self.setFocusPolicy(Qt.WheelFocus)

    def search(self, text, flags):
        """Search for text in the current page.

        Args:
            text: The text to search for.
            flags: The QWebPage::FindFlags.
        """
        log.webview.debug("Searching with text '{}' and flags "
                          "0x{:04x}.".format(text, int(flags)))
        old_scroll_pos = self.scroll_pos
        flags = QWebPage.FindFlags(flags)
        found = self.findText(text, flags)
        backward = flags & QWebPage.FindBackward

        if not found and not flags & QWebPage.HighlightAllOccurrences and text:
            # User disabled wrapping; but findText() just returns False. If we
            # have a selection, we know there's a match *somewhere* on the page
            if (not flags & QWebPage.FindWrapsAroundDocument and
                    self.hasSelection()):
                if not backward:
                    message.warning(self.win_id, "Search hit BOTTOM without "
                                    "match for: {}".format(text),
                                    immediately=True)
                else:
                    message.warning(self.win_id, "Search hit TOP without "
                                    "match for: {}".format(text),
                                    immediately=True)
            else:
                message.warning(self.win_id, "Text '{}' not found on "
                                "page!".format(text), immediately=True)
        else:
            def check_scroll_pos():
                """Check if the scroll position got smaller and show info."""
                if not backward and self.scroll_pos < old_scroll_pos:
                    message.info(self.win_id, "Search hit BOTTOM, continuing "
                                 "at TOP", immediately=True)
                elif backward and self.scroll_pos > old_scroll_pos:
                    message.info(self.win_id, "Search hit TOP, continuing at "
                                 "BOTTOM", immediately=True)
            # We first want QWebPage to refresh.
            QTimer.singleShot(0, check_scroll_pos)

    def createWindow(self, wintype):
        """Called by Qt when a page wants to create a new window.

        This function is called from the createWindow() method of the
        associated QWebPage, each time the page wants to create a new window of
        the given type. This might be the result, for example, of a JavaScript
        request to open a document in a new window.

        Args:
            wintype: This enum describes the types of window that can be
                     created by the createWindow() function.

                     QWebPage::WebBrowserWindow: The window is a regular web
                                                 browser window.
                     QWebPage::WebModalDialog: The window acts as modal dialog.

        Return:
            The new QWebView object.
        """
        if wintype == QWebPage.WebModalDialog:
            log.webview.warning("WebModalDialog requested, but we don't "
                                "support that!")
        tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                    window=self.win_id)
        return tabbed_browser.tabopen(background=False)

    def paintEvent(self, e):
        """Extend paintEvent to emit a signal if the scroll position changed.

        This is a bit of a hack: We listen to repaint requests here, in the
        hope a repaint will always be requested when scrolling, and if the
        scroll position actually changed, we emit a signal.

        Args:
            e: The QPaintEvent.

        Return:
            The superclass event return value.
        """
        frame = self.page().mainFrame()
        new_pos = (frame.scrollBarValue(Qt.Horizontal),
                   frame.scrollBarValue(Qt.Vertical))
        if self._old_scroll_pos != new_pos:
            self._old_scroll_pos = new_pos
            m = (frame.scrollBarMaximum(Qt.Horizontal),
                 frame.scrollBarMaximum(Qt.Vertical))
            perc = (round(100 * new_pos[0] / m[0]) if m[0] != 0 else 0,
                    round(100 * new_pos[1] / m[1]) if m[1] != 0 else 0)
            self.scroll_pos = perc
            self.scroll_pos_changed.emit(*perc)
        # Let superclass handle the event
        super().paintEvent(e)

    def mousePressEvent(self, e):
        """Extend QWidget::mousePressEvent().

        This does the following things:
            - Check if a link was clicked with the middle button or Ctrl and
              set the page's open_target attribute accordingly.
            - Emit the editable_elem_selected signal if an editable element was
              clicked.

        Args:
            e: The arrived event.

        Return:
            The superclass return value.
        """
        is_rocker_gesture = (config.get('input', 'rocker-gestures') and
                             e.buttons() == Qt.LeftButton | Qt.RightButton)

        if e.button() in (Qt.XButton1, Qt.XButton2) or is_rocker_gesture:
            self._mousepress_backforward(e)
            super().mousePressEvent(e)
            return
        self._mousepress_insertmode(e)
        self._mousepress_opentarget(e)
        self._ignore_wheel_event = True
        super().mousePressEvent(e)

    def mouseReleaseEvent(self, e):
        """Extend mouseReleaseEvent to enter insert mode if needed."""
        super().mouseReleaseEvent(e)
        # We want to make sure we check the focus element after the WebView is
        # updated completely.
        QTimer.singleShot(0, self.mouserelease_insertmode)

    def contextMenuEvent(self, e):
        """Save a reference to the context menu so we can close it."""
        menu = self.page().createStandardContextMenu()
        self.shutting_down.connect(menu.close)
        modeman.instance(self.win_id).entered.connect(menu.close)
        menu.exec_(e.globalPos())

    def wheelEvent(self, e):
        """Zoom on Ctrl-Mousewheel.

        Args:
            e: The QWheelEvent.
        """
        if self._ignore_wheel_event:
            self._ignore_wheel_event = False
            # See https://github.com/The-Compiler/qutebrowser/issues/395
            return
        if e.modifiers() & Qt.ControlModifier:
            e.accept()
            divider = config.get('input', 'mouse-zoom-divider')
            factor = self.zoomFactor() + e.angleDelta().y() / divider
            if factor < 0:
                return
            perc = int(100 * factor)
            message.info(self.win_id, "Zoom level: {}%".format(perc))
            self._zoom.fuzzyval = perc
            self.setZoomFactor(factor)
            self._default_zoom_changed = True
        else:
            super().wheelEvent(e)
Exemple #41
0
 def savePlaylist(self, path):
     """Save playlist to path."""
     if path.toString()[len(path.toString()) - 4:] != '.m3u':
         path = QUrl('{}.m3u'.format(path.toString()))
     self.playlist.save(path, 'm3u')
Exemple #42
0
 def load_account_page(self, account, tab=None, task=None, reset_history=False, set_home=False):
     self.tab = tab
     self.task = task
     self.account = account
     url = QUrl(account.server.settings_url)
     url_query = QUrlQuery()
     for name, value in self.query_items:
         url_query.addQueryItem(name, value)
     url.setQuery(url_query)
     if set_home:
         self.homepage = url
     if reset_history:
         self.history().clear()
         self.page().mainFrame().evaluateJavaScript('window.location.replace("{}");'.format(url.toString()))  # this will replace the current url in the history
     else:
         self.load(url)
	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|&params[^&]*','',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)
Exemple #44
0
class CoverArtImage:

    # Indicate if types are provided by the source, ie. CAA or certain file
    # formats may have types associated with cover art, but some other sources
    # don't provide such information
    support_types = False
    # `is_front` has to be explicitly set, it is used to handle CAA is_front
    # indicator
    is_front = None
    sourceprefix = "URL"

    def __init__(self, url=None, types=None, comment='', data=None):
        if types is None:
            self.types = []
        else:
            self.types = types
        if url is not None:
            self.parse_url(url)
        else:
            self.url = None
        self.comment = comment
        self.datahash = None
        # thumbnail is used to link to another CoverArtImage, ie. for PDFs
        self.thumbnail = None
        self.can_be_saved_to_tags = True
        self.can_be_saved_to_disk = True
        self.can_be_saved_to_metadata = True
        if data is not None:
            self.set_data(data)

    def parse_url(self, url):
        self.url = QUrl(url)
        self.host = string_(self.url.host())
        self.port = self.url.port(80)
        self.path = string_(self.url.path(QUrl.FullyEncoded))
        if self.url.hasQuery():
            self.path += '?' + string_(self.url.query(QUrl.FullyEncoded))

    @property
    def source(self):
        if self.url is not None:
            return "%s: %s" % (self.sourceprefix, self.url.toString())
        else:
            return "%s" % self.sourceprefix

    def is_front_image(self):
        """Indicates if image is considered as a 'front' image.
        It depends on few things:
            - if `is_front` was set, it is used over anything else
            - if `types` was set, search for 'front' in it
            - if `support_types` is False, default to True for any image
            - if `support_types` is True, default to False for any image
        """
        if not self.can_be_saved_to_metadata:
            # ignore thumbnails
            return False
        if self.is_front is not None:
            return self.is_front
        if 'front' in self.types:
            return True
        return (self.support_types is False)

    def imageinfo_as_string(self):
        if self.datahash is None:
            return ""
        return "w=%d h=%d mime=%s ext=%s datalen=%d file=%s" % (self.width,
                                                                self.height,
                                                                self.mimetype,
                                                                self.extension,
                                                                self.datalength,
                                                                self.tempfile_filename)

    def __repr__(self):
        p = []
        if self.url is not None:
            p.append("url=%r" % self.url.toString())
        if self.types:
            p.append("types=%r" % self.types)
        if self.is_front is not None:
            p.append("is_front=%r" % self.is_front)
        if self.comment:
            p.append("comment=%r" % self.comment)
        return "%s(%s)" % (self.__class__.__name__, ", ".join(p))

    def __str__(self):
        p = ['Image']
        if self.url is not None:
            p.append("from %s" % self.url.toString())
        if self.types:
            p.append("of type %s" % ','.join(self.types))
        if self.comment:
            p.append("and comment '%s'" % self.comment)
        return ' '.join(p)

    def __eq__(self, other):
        if self and other:
            if self.types and other.types:
                return (self.datahash, self.types) == (other.datahash, other.types)
            else:
                return self.datahash == other.datahash
        elif not self and not other:
            return True
        else:
            return False

    def __hash__(self):
        if self.datahash is None:
            return 0
        return hash(self.datahash.hash())

    def set_data(self, data):
        """Store image data in a file, if data already exists in such file
           it will be re-used and no file write occurs
        """
        if self.datahash:
            self.datahash.delete_file()
            self.datahash = None

        try:
            (self.width, self.height, self.mimetype, self.extension,
             self.datalength) = imageinfo.identify(data)
        except imageinfo.IdentificationError as e:
            raise CoverArtImageIdentificationError(e)

        try:
            self.datahash = DataHash(data, suffix=self.extension)
        except (OSError, IOError) as e:
            raise CoverArtImageIOError(e)

    @property
    def maintype(self):
        """Returns one type only, even for images having more than one type set.
        This is mostly used when saving cover art to tags because most formats
        don't support multiple types for one image.
        Images coming from CAA can have multiple types (ie. 'front, booklet').
        """
        if self.is_front_image() or not self.types or 'front' in self.types:
            return 'front'
        # TODO: do something better than randomly using the first in the list
        return self.types[0]

    def _make_image_filename(self, filename, dirname, metadata):
        filename = ScriptParser().eval(filename, metadata)
        if config.setting["ascii_filenames"]:
            if isinstance(filename, str):
                filename = unaccent(filename)
            filename = replace_non_ascii(filename)
        if not filename:
            filename = "cover"
        if not os.path.isabs(filename):
            filename = os.path.join(dirname, filename)
        # replace incompatible characters
        if config.setting["windows_compatibility"] or sys.platform == "win32":
            filename = replace_win32_incompat(filename)
        # remove null characters
        if isinstance(filename, bytes):
            filename = filename.replace(b"\x00", "")
        return encode_filename(filename)

    def save(self, dirname, metadata, counters):
        """Saves this image.

        :dirname: The name of the directory that contains the audio file
        :metadata: A metadata object
        :counters: A dictionary mapping filenames to the amount of how many
                    images with that filename were already saved in `dirname`.
        """
        if not self.can_be_saved_to_disk:
            return
        if (config.setting["caa_image_type_as_filename"] and
            not self.is_front_image()):
            filename = self.maintype
            log.debug("Make cover filename from types: %r -> %r",
                      self.types, filename)
        else:
            filename = config.setting["cover_image_filename"]
            log.debug("Using default cover image filename %r", filename)
        filename = self._make_image_filename(filename, dirname, metadata)

        overwrite = config.setting["save_images_overwrite"]
        ext = encode_filename(self.extension)
        image_filename = self._next_filename(filename, counters)
        while os.path.exists(image_filename + ext) and not overwrite:
            if not self._is_write_needed(image_filename + ext):
                break
            image_filename = self._next_filename(filename, counters)
        else:
            new_filename = image_filename + ext
            # Even if overwrite is enabled we don't need to write the same
            # image multiple times
            if not self._is_write_needed(new_filename):
                return
            log.debug("Saving cover image to %r", new_filename)
            try:
                new_dirname = os.path.dirname(new_filename)
                if not os.path.isdir(new_dirname):
                    os.makedirs(new_dirname)
                shutil.copyfile(self.tempfile_filename, new_filename)
            except (OSError, IOError) as e:
                raise CoverArtImageIOError(e)

    def _next_filename(self, filename, counters):
        if counters[filename]:
            new_filename = b"%b (%d)" % (filename, counters[filename])
        else:
            new_filename = filename
        counters[filename] += 1
        return new_filename

    def _is_write_needed(self, filename):
        if (os.path.exists(filename)
                and os.path.getsize(filename) == self.datalength):
            log.debug("Identical file size, not saving %r", filename)
            return False
        return True

    @property
    def data(self):
        """Reads the data from the temporary file created for this image.
        May raise CoverArtImageIOError
        """
        try:
            return self.datahash.data
        except (OSError, IOError) as e:
            raise CoverArtImageIOError(e)

    @property
    def tempfile_filename(self):
        return self.datahash.filename

    def types_as_string(self, translate=True, separator=', '):
        if self.types:
            types = self.types
        elif self.is_front_image():
            types = ['front']
        else:
            types = ['-']
        if translate:
            types = [translate_caa_type(type) for type in types]
        return separator.join(types)
Exemple #45
0
 def __procFinished(self, exitCode, exitStatus):
     """
     Private slot connected to the finished signal.
     
     @param exitCode exit code of the process (integer)
     @param exitStatus exit status of the process (QProcess.ExitStatus)
     """
     self.inputGroup.setEnabled(False)
     self.inputGroup.hide()
     
     self.contents.clear()
     
     lvers = 1
     for s in self.buf:
         rev_match = False
         if self.rx_rev.exactMatch(s):
             ver = self.rx_rev.cap(1)
             author = self.rx_rev.cap(2)
             date = self.rx_rev.cap(3)
             # number of lines is ignored
             rev_match = True
         elif self.rx_rev2.exactMatch(s):
             ver = self.rx_rev2.cap(1)
             author = self.rx_rev2.cap(2)
             date = self.rx_rev2.cap(3)
             # number of lines is ignored
             rev_match = True
         
         if rev_match:
             dstr = '<b>{0} {1}</b>'.format(self.revString, ver)
             try:
                 lv = self.revisions[lvers]
                 lvers += 1
                 url = QUrl()
                 url.setScheme("file")
                 url.setPath(self.filename)
                 if qVersion() >= "5.0.0":
                     query = lv + '_' + ver
                     url.setQuery(query)
                 else:
                     query = QByteArray()
                     query.append(lv).append('_').append(ver)
                     url.setEncodedQuery(query)
                 dstr += ' [<a href="{0}" name="{1}">{2}</a>]'.format(
                     url.toString(), query,
                     self.tr('diff to {0}').format(lv),
                 )
             except IndexError:
                 pass
             dstr += '<br />\n'
             self.contents.insertHtml(dstr)
             
             dstr = self.tr('<i>author: {0}</i><br />\n').format(author)
             self.contents.insertHtml(dstr)
             
             dstr = self.tr('<i>date: {0}</i><br />\n').format(date)
             self.contents.insertHtml(dstr)
         
         elif self.rx_sep.exactMatch(s) or self.rx_sep2.exactMatch(s):
             self.contents.insertHtml('<hr />\n')
         
         elif self.rx_flags.exactMatch(s):
             dstr = self.flags[self.rx_flags.cap(1)]
             dstr += self.rx_flags.cap(2)
             dstr += '<br />\n'
             self.contents.insertHtml(dstr)
         
         elif self.rx_changed.exactMatch(s):
             dstr = '<br />{0}<br />\n'.format(s)
             self.contents.insertHtml(dstr)
         
         else:
             if s == "":
                 s = self.contents.insertHtml('<br />\n')
             else:
                 self.contents.insertHtml(Utilities.html_encode(s))
                 self.contents.insertHtml('<br />\n')
     
     tc = self.contents.textCursor()
     tc.movePosition(QTextCursor.Start)
     self.contents.setTextCursor(tc)
     self.contents.ensureCursorVisible()
Exemple #46
0
 def __finish(self):
     """
     Private slot called when the process finished or the user pressed
     the button.
     """
     self.inputGroup.setEnabled(False)
     self.inputGroup.hide()
     
     self.contents.clear()
     
     if not self.logEntries:
         self.errors.append(self.tr("No log available for '{0}'")
                            .format(self.filename))
         self.errorGroup.show()
         return
     
     html = ""
     
     if self.initialText:
         for line in self.initialText:
             html += Utilities.html_encode(line.strip())
             html += '<br />\n'
         html += '{0}<br/>\n'.format(80 * "=")
         
     for entry in self.logEntries:
         fileCopies = {}
         if entry["file_copies"]:
             for fentry in entry["file_copies"].split(", "):
                 newName, oldName = fentry[:-1].split(" (")
                 fileCopies[newName] = oldName
         
         rev, hexRev = entry["change"].split(":")
         dstr = '<p><b>{0} {1}</b>'.format(self.revString, entry["change"])
         if entry["parents"]:
             parents = entry["parents"].split()
         else:
             parents = self.__getParents(rev)
         for parent in parents:
             url = QUrl()
             url.setScheme("file")
             url.setPath(self.filename)
             if qVersion() >= "5.0.0":
                 query = parent.split(":")[0] + '_' + rev
                 url.setQuery(query)
             else:
                 query = QByteArray()
                 query.append(parent.split(":")[0]).append('_').append(rev)
                 url.setEncodedQuery(query)
             dstr += ' [<a href="{0}" name="{1}" id="{1}">{2}</a>]'.format(
                 url.toString(), query,
                 self.tr('diff to {0}').format(parent),
             )
         dstr += '<br />\n'
         html += dstr
         
         if "phase" in entry:
             html += self.tr("Phase: {0}<br />\n")\
                 .format(entry["phase"])
         
         html += self.tr("Branch: {0}<br />\n")\
             .format(entry["branches"])
         
         html += self.tr("Tags: {0}<br />\n").format(entry["tags"])
         
         if "bookmarks" in entry:
             html += self.tr("Bookmarks: {0}<br />\n")\
                 .format(entry["bookmarks"])
         
         html += self.tr("Parents: {0}<br />\n")\
             .format(entry["parents"])
         
         html += self.tr('<i>Author: {0}</i><br />\n')\
             .format(Utilities.html_encode(entry["user"]))
         
         date, time = entry["date"].split()[:2]
         html += self.tr('<i>Date: {0}, {1}</i><br />\n')\
             .format(date, time)
         
         for line in entry["description"]:
             html += Utilities.html_encode(line.strip())
             html += '<br />\n'
         
         if entry["file_adds"]:
             html += '<br />\n'
             for f in entry["file_adds"].strip().split(", "):
                 if f in fileCopies:
                     html += self.tr(
                         'Added {0} (copied from {1})<br />\n')\
                         .format(Utilities.html_encode(f),
                                 Utilities.html_encode(fileCopies[f]))
                 else:
                     html += self.tr('Added {0}<br />\n')\
                         .format(Utilities.html_encode(f))
         
         if entry["files_mods"]:
             html += '<br />\n'
             for f in entry["files_mods"].strip().split(", "):
                 html += self.tr('Modified {0}<br />\n')\
                     .format(Utilities.html_encode(f))
         
         if entry["file_dels"]:
             html += '<br />\n'
             for f in entry["file_dels"].strip().split(", "):
                 html += self.tr('Deleted {0}<br />\n')\
                     .format(Utilities.html_encode(f))
         
         html += '</p>{0}<br/>\n'.format(60 * "=")
     
     self.contents.setHtml(html)
     tc = self.contents.textCursor()
     tc.movePosition(QTextCursor.Start)
     self.contents.setTextCursor(tc)
     self.contents.ensureCursorVisible()