Ejemplo n.º 1
0
def test_addGetDisplayComponent():
    stage = Stage()
    stage.addDisplayComponent("BLORP", "location")
    assert stage.getDisplayComponent("BLORP") == QUrl.fromLocalFile("location")

    stage.addDisplayComponent("MEEP!", QUrl.fromLocalFile("MEEP"))
    assert stage.getDisplayComponent("MEEP!") == QUrl.fromLocalFile("MEEP")
Ejemplo n.º 2
0
def search_engine(q):
    ans = QUrl('https://google.com/search')
    # ans = QUrl('https://duckduckgo.com/lite')
    # ans = QUrl('https://duckduckgo.com')
    qq = QUrlQuery()
    qq.addQueryItem('q', q)
    ans.setQuery(qq)
    return ans
Ejemplo n.º 3
0
def get_proxy_auth_credentials(qurl, authenticator, proxy_host, parent=None):
    qurl = QUrl(qurl)
    qurl.setFragment(None)
    d = Credentials(
        _('Please specify a password for {0} at the proxy: {1}').format(
            qurl.toString(), proxy_host), parent)
    if d.exec() == d.Accepted:
        username, password = d.credentials
        authenticator.setUser(username)
        authenticator.setPassword(password)
Ejemplo n.º 4
0
class ColorImage(QQuickPaintedItem):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._source = QUrl()
        self._color = QColor()
        self._svg_data = b""
        self._renderer = None

    sourceChanged = pyqtSignal()
    colorChanged = pyqtSignal()

    def _updateSVG(self) -> None:
        if not self._source or self._source.toLocalFile() == "":
            return
        try:
            with open(self._source.toLocalFile(), "rb") as f:
                self._svg_data = f.read()
        except FileNotFoundError:
            Logger.log(
                "w",
                f"Unable to find image located at {self._source.toLocalFile()}"
            )
            return
        self._svg_data = self._svg_data.replace(
            b"<svg ",
            b"<svg fill=\"%s\" " % self._color.name().encode("utf-8"))
        self._renderer = QSvgRenderer(self._svg_data)
        self.update()

    def setSource(self, source: QUrl) -> None:
        if self._source != source:
            self._source = source
            self.sourceChanged.emit()
            self._updateSVG()

    @pyqtProperty(QUrl, fset=setSource, notify=sourceChanged)
    def source(self) -> QUrl:
        return self._source

    def setColor(self, color: QColor) -> None:
        if self._color != color:
            self._color = color
            self.colorChanged.emit()
            self._updateSVG()

    @pyqtProperty(QColor, fset=setColor, notify=colorChanged)
    def color(self) -> QColor:
        return self._color

    def paint(self, painter: QPainter) -> None:
        pixel_ratio = Application.getInstance().getMainWindow(
        ).effectiveDevicePixelRatio()
        painter.scale(1 / pixel_ratio, 1 / pixel_ratio)
        if self._renderer:
            self._renderer.render(painter)
Ejemplo n.º 5
0
    def _onActionTriggered(self, message: Message, action: str) -> None:
        """Callback function for the "download" button on the update notification.

        This function is here is because the custom Signal in Uranium keeps a list of weak references to its
        connections, so the callback functions need to be long-lived.
        """
        if action == "download":
            if self._download_url is not None:
                QDesktopServices.openUrl(QUrl(message.download_url))
        elif action == "new_features":
            QDesktopServices.openUrl(QUrl(message.change_log_url))
Ejemplo n.º 6
0
    def __init__(self, url: str, home_url: str, icon: QIcon, ua: str):
        super().__init__()
        self.home_url = QUrl(home_url)
        self.web_view = QWebEngineView()
        self.page = MyWebPage(QApplication.instance().applicationName(), ua)

        self._setup_ui(icon)
        self._setup_events()
        self._setup_webview()
        self.page.setUrl(QUrl(url))
        self.web_view.show()
Ejemplo n.º 7
0
    def activeToolPanel(self):
        if not self._active_tool:
            return QUrl()
        try:
            panel_file = self._active_tool.getMetaData()["tool_panel"]
        except KeyError:
            return QUrl()

        return QUrl.fromLocalFile(
            os.path.join(
                PluginRegistry.getInstance().getPluginPath(
                    self._active_tool.getPluginId()), panel_file))
Ejemplo n.º 8
0
def get_http_auth_credentials(qurl, authenticator, parent=None):
    qurl = QUrl(qurl)
    qurl.setFragment(None)
    realm = authenticator.realm()
    trealm = (' (%s)' % realm) if realm else ''
    ac = parent and parent.get_login_credentials(qurl.toString())
    d = Credentials(
        _('Please specify a password for {0}{1}').format(
            qurl.toString(), trealm), parent)
    if ac is not None:
        if ac['autologin']:
            authenticator.setUser(ac['username'])
            authenticator.setPassword(ac['password'])
            return
        d.credentials = ac['username'], ac['password']

    if d.exec() == QDialog.DialogCode.Accepted:
        username, password = d.credentials
        authenticator.setUser(username)
        authenticator.setPassword(password)
        if parent is not None:
            parent.on_login_form_submit(qurl.toString(), username, password)
    else:
        if parent is not None:
            parent.setHtml(
                '<p style="font-family:sans-serif">{} {}</p>'.format(
                    _('Authentication required to access: '),
                    '<a href="{0}">{0}</a>'.format(qurl.toDisplayString())))
Ejemplo n.º 9
0
    def getIcon(self, icon_name: str, detail_level: str = "default") -> QUrl:
        """
        Finds and returns the url of the requested icon. The icons are organized in folders according to their detail
        level and the same icon may exist with more details. If a detail level is not specified, the icon will be
        retrieved from the "default" folder. Icons with a higher detail level are recommended to be used with a bigger
        width/height.

        :param icon_name: The name of the icon to be retrieved. The same icon may exist in multiple detail levels.
        :param detail_level: The level of detail of the icon. Choice between "low, "default", "medium", "high".
        :return: The file url of the requested icon, in the requested detail level.
        """
        if detail_level in self._icons:
            if icon_name in self._icons[detail_level]:
                return self._icons[detail_level][icon_name]
        elif icon_name in self._icons[
                "icons"]:  # Retrieve the "old" icon from the base icon folder
            return self._icons["icons"][icon_name]

        if icon_name in self._deprecated_icons:
            new_icon = self._deprecated_icons[icon_name]["new_icon"]
            warning = f"The icon '{icon_name}' is deprecated. Please use icon '{new_icon}' instead."

            Logger.log("w_once", warning)
            warnings.warn(warning, DeprecationWarning, stacklevel=2)
            return self.getIcon(self._deprecated_icons[icon_name]["new_icon"],
                                self._deprecated_icons[icon_name]["size"])

        # We don't log this anymore since we have new fallback behavior to load the icon from a plugin folder
        # Logger.log("w", "No icon %s defined in Theme", icon_name)
        return QUrl()
Ejemplo n.º 10
0
    def createQmlComponent(self, qml_file_path: str, context_properties: Dict[str, "QObject"] = None) -> Optional["QObject"]:
        """Create a QML component from a qml file.
        :param qml_file_path:: The absolute file path to the root qml file.
        :param context_properties:: Optional dictionary containing the properties that will be set on the context of the
        qml instance before creation.
        :return: None in case the creation failed (qml error), else it returns the qml instance.
        :note If the creation fails, this function will ensure any errors are logged to the logging service.
        """

        if self._qml_engine is None: # Protect in case the engine was not initialized yet
            return None
        path = QUrl.fromLocalFile(qml_file_path)
        component = QQmlComponent(self._qml_engine, path)
        result_context = QQmlContext(self._qml_engine.rootContext()) #type: ignore #MyPy doens't realise that self._qml_engine can't be None here.
        if context_properties is not None:
            for name, value in context_properties.items():
                result_context.setContextProperty(name, value)
        result = component.create(result_context)
        for err in component.errors():
            Logger.log("e", str(err.toString()))
        if result is None:
            return None

        # We need to store the context with the qml object, else the context gets garbage collected and the qml objects
        # no longer function correctly/application crashes.
        result.attached_context = result_context
        return result
Ejemplo n.º 11
0
 def readLocalFile(self,
                   file: QUrl,
                   add_to_recent_files_hint: bool = True) -> None:
     if not file.isValid():
         return
     if add_to_recent_files_hint:
         self._add_to_recent_files_hints.append(file)
     self._readLocalFile(file, add_to_recent_files_hint)
Ejemplo n.º 12
0
 def interceptRequest(self, req):
     qurl = req.requestUrl()
     url = qurl.toString()
     changed, nurl = substitute(url)
     if changed:
         print(
             _('Redirecting {0} to {1} because of a URL substitution rule').
             format(url, nurl))
         req.redirect(QUrl(nurl))
Ejemplo n.º 13
0
    def test_activeToolPanel(self):
        # There is no active tool, so it should be empty
        assert self.proxy.activeToolPanel == QUrl()

        with patch.object(self.tool, "getMetaData",
                          MagicMock(return_value={"tool_panel": "derp"})):
            with patch("UM.PluginRegistry.PluginRegistry.getPluginPath",
                       MagicMock(return_value="OMG")):
                Application.getInstance().getController().setActiveTool(
                    self.tool)
                assert self.proxy.activeToolPanel == QUrl.fromLocalFile(
                    "OMG/derp")
        # Try again with empty metadata
        with patch("UM.PluginRegistry.PluginRegistry.getMetaData",
                   MagicMock(return_value={"tool": {}})):
            Application.getInstance().getController().setActiveTool("")
            Application.getInstance().getController().setActiveTool(self.tool)
            assert self.proxy.activeToolPanel == QUrl.fromLocalFile("")
Ejemplo n.º 14
0
    def _createRequest(
            self,
            http_method: str,
            url: str,
            headers_dict: Optional[Dict[str, str]] = None,
            data: Optional[Union[bytes, bytearray]] = None,
            callback: Optional[Callable[["QNetworkReply"], None]] = None,
            error_callback: Optional[Callable[
                ["QNetworkReply", "QNetworkReply.NetworkError"], None]] = None,
            download_progress_callback: Optional[Callable[[int, int],
                                                          None]] = None,
            upload_progress_callback: Optional[Callable[[int, int],
                                                        None]] = None,
            timeout: Optional[float] = None,
            scope: Optional[HttpRequestScope] = None) -> "HttpRequestData":
        # Sanity checks
        if timeout is not None and timeout <= 0:
            raise ValueError(
                "Timeout must be a positive number if provided, but [%s] was given"
                % timeout)

        request = QNetworkRequest(QUrl(url))

        # Set headers
        if headers_dict is not None:
            for key, value in headers_dict.items():
                request.setRawHeader(key.encode("utf-8"),
                                     value.encode("utf-8"))

        if scope is not None:
            scope.requestHook(request)

        # Generate a unique request ID
        request_id = uuid.uuid4().hex

        # Create the request data
        request_data = HttpRequestData(
            request_id,
            http_method=http_method,
            request=request,
            data=data,
            manager_timeout_callback=self._onRequestTimeout,
            callback=callback,
            error_callback=error_callback,
            download_progress_callback=download_progress_callback,
            upload_progress_callback=upload_progress_callback,
            timeout=timeout)

        with self._request_lock:
            self._request_queue.append(request_data)

            # Schedule a call to process pending requests in the queue
            if not self._process_requests_scheduled:
                self.callLater(0, self._processNextRequestsInQueue)
                self._process_requests_scheduled = True

        return request_data
Ejemplo n.º 15
0
 def _readLocalFile(self,
                    file: QUrl,
                    add_to_recent_files_hint: bool = True) -> None:
     from UM.FileHandler.ReadFileJob import ReadFileJob
     filename = file.toLocalFile()
     job = ReadFileJob(filename,
                       handler=self,
                       add_to_recent_files=add_to_recent_files_hint)
     job.finished.connect(self._readWorkspaceFinished)
     job.start()
Ejemplo n.º 16
0
 def _readLocalFile(self,
                    file: QUrl,
                    add_to_recent_files_hint: bool = True):
     # We need to prevent circular dependency, so do some just in time importing.
     from UM.Mesh.ReadMeshJob import ReadMeshJob
     filename = file.toLocalFile()
     job = ReadMeshJob(filename,
                       add_to_recent_files=add_to_recent_files_hint)
     job.finished.connect(self._readMeshFinished)
     job.start()
Ejemplo n.º 17
0
    def _create_empty_request(self, path: str) -> QNetworkRequest:
        """"Creates an empty HTTP request (GET or POST).

    Args:
      path: HTTP relative path.
    """
        url = QUrl(f'http://{self._ip_address}{path}')
        Logger.log('d', url.toString())
        request = QNetworkRequest(url)
        if USE_QT5:
            request.setAttribute(QNetworkRequest.FollowRedirectsAttribute,
                                 True)
        else:
            # FollowRedirectsAttribute was deprecated in PyQt6.
            # https://doc.qt.io/qt-6/network-changes-qt6.html#redirect-policies.
            request.setAttribute(
                QNetworkRequest.Attribute.RedirectPolicyAttribute,
                QNetworkRequest.RedirectPolicy.ManualRedirectPolicy)
        return request
Ejemplo n.º 18
0
    def openUrl(self, target_url: str, allowed_schemes: List[str]) -> bool:
        """
        Opens the target_url if it has an allowed and valid scheme. This function can be called inside QML files.

        :param target_url: The URL string to be opened e.g. 'https://example.org'
        :param allowed_schemes: A list of the schemes that are allowed to be opened e.g. ['http', 'https']
        :return: True if the URL opens successfully, False if an invalid scheme is used
        """
        if self._urlHasValidScheme(target_url, allowed_schemes):
            QDesktopServices.openUrl(QUrl(target_url))
            return True
        return False
Ejemplo n.º 19
0
 def set_message(self, text, color_, bold=False, is_permanent=False):
     from vise.view import certificate_error_domains
     key = (text, color_.name(), bold, is_permanent)
     if key == self.current_key:
         return
     self.current_key = key
     self.is_permanent = is_permanent
     prefix = text.partition(':')[0]
     self.is_address = self.is_permanent and prefix.lower() in {
         'http', 'https', 'vise', 'file'
     }
     self.is_secure = prefix.lower() in {'https', 'vise', 'file'}
     color_ = color_ or self.palette().color(self.palette().WindowText)
     if self.is_address:
         qurl = QUrl(text)
         if self.is_secure and qurl.host() in certificate_error_domains:
             self.is_secure = False
         if qurl.scheme() in {'vise', 'file'}:
             host = qurl.path()
             rest = ''
             sep = ':'
         else:
             host = qurl.host()
             rest = qurl.toDisplayString(
                 QUrl.UrlFormattingOption.RemoveScheme
                 | QUrl.UrlFormattingOption.RemoveAuthority)
             sep = '://'
         self.static_text = QStaticText(
             '<span style="white-space:nowrap; color: {fg}">'
             '<span style="color:{emph}; font-weight:bold">{scheme}</span><span style="color:{dull}">{sep}</span>'
             '<span style="color:{fg}">{host}</span>'
             '<span style="color:{dull}">{rest}</span>'.format(
                 fg=color_.name(),
                 emph='green' if self.is_secure else 'red',
                 scheme=escape(qurl.scheme()),
                 host=escape(host),
                 dull=color('status bar dull foreground', 'gray'),
                 sep=sep,
                 rest=escape(rest)))
     else:
         self.static_text = QStaticText(
             '<span style="color:{}; font-weight: {}; white-space:nowrap">{}</span>'
             .format(color_.name(), ('bold' if bold else 'normal'),
                     escape(text)))
     to = QTextOption(Qt.AlignmentFlag.AlignLeft
                      | Qt.AlignmentFlag.AlignTop)
     to.setWrapMode(QTextOption.WrapMode.NoWrap)
     self.static_text.setTextOption(to)
     self.static_text.prepare(font=self.font())
     self.update()
Ejemplo n.º 20
0
def _paste_and_go(window, in_current_tab=True):
    c = QApplication.clipboard()
    for mode in QClipboard.Mode.Clipboard, QClipboard.Mode.Selection:
        text = c.text(mode).strip()
        if text:
            if text.partition(':')[0].lower() in {
                    'file', 'http', 'https', 'about', 'chrome'
            }:
                qurl = QUrl.fromUserInput(text)
                if qurl.isValid() and not qurl.isEmpty():
                    window.open_url(qurl, in_current_tab=in_current_tab)
                    return
    window.show_status_message(_('No URL in clipboard'), 2, 'success')
Ejemplo n.º 21
0
 def icon(self):
     if self._icon is None:
         self._icon = QIcon()
         url = places.favicon_url(self.place_id)
         if url is not None:
             f = QApplication.instance().disk_cache.data(QUrl(url))
             if f is not None:
                 with closing(f):
                     raw = f.readAll()
                 p = QPixmap()
                 p.loadFromData(raw)
                 if not p.isNull():
                     self._icon.addPixmap(p)
     return self._icon
Ejemplo n.º 22
0
def _construct_Qurl(path):
    """
     A helper function to make sure scheme
     and etc is set for correct QUrl
    """
    url = QUrl()
    url.setScheme("file")
    raw_path = "/" + os.path.dirname(path) + "/"
    url.setPath(raw_path)
    return url
Ejemplo n.º 23
0
    def addFileToRecentFiles(self, file_name: str) -> None:
        file_path = QUrl.fromLocalFile(file_name)

        if file_path in self._recent_files:
            self._recent_files.remove(file_path)

        self._recent_files.insert(0, file_path)
        if len(self._recent_files) > 10:
            del self._recent_files[10]

        pref = ""
        for path in self._recent_files:
            pref += path.toLocalFile() + ";"

        self.getPreferences().setValue("%s/recent_files" % self.getApplicationName(), pref)
        self.recentFilesChanged.emit()
    def _onEngineCreated(self) -> None:
        qmlRegisterType(
            MaterialSettingsPluginVisibilityHandler.
            MaterialSettingsPluginVisibilityHandler, "Cura", 1, 0,
            "MaterialSettingsVisibilityHandler")

        # Adding/removing pages from the preferences dialog is handles in QML
        # There is no way to access the preferences dialog directly, so we have to search for it
        preferencesDialog = None
        main_window = CuraApplication.getInstance().getMainWindow()
        if not main_window:
            Logger.log(
                "e",
                "Could not replace Materials preferencepane with patched version because there is no main window"
            )
            return
        for child in main_window.contentItem().children():
            try:
                test = child.setPage  # only PreferencesDialog has a setPage function
                preferencesDialog = child
                break
            except:
                pass

        if preferencesDialog:
            Logger.log(
                "d", "Replacing Materials preferencepane with patched version")

            qml_folder = "qml" if not USE_QT5 else "qml_qt5"
            materialPreferencesPage = QUrl.fromLocalFile(
                os.path.join(os.path.dirname(os.path.abspath(__file__)),
                             qml_folder, "MaterialsPage.qml"))
            if USE_QT5:
                materialPreferencesPage = materialPreferencesPage.toString()

            preferencesDialog.removePage(3)
            preferencesDialog.insertPage(
                3, catalog.i18nc("@title:tab", "Materials"),
                materialPreferencesPage)
        else:
            Logger.log(
                "e",
                "Could not replace Materials preferencepane with patched version"
            )
Ejemplo n.º 25
0
 def download_files(self):
     if len(self.file_list):
         if not self.file_number: self.file_number=len(self.file_list)
         tmp=self.file_list[-1]
         if exists(tmp[-1]):
             try: remove(tmp[-1])
             except: pass
         self.webEngineView.page().profile().downloadRequested.connect(lambda event:\
             self.on_downloadRequested(event))
         self.label.setText('Статус: скачивание файла "%s" ( %i из %i )'%\
                            (tmp[2],self.file_number-len(self.file_list)+1,self.file_number))
         self.webEngineView.page().download(QUrl(tmp[3]),tmp[-1])
     else:
         self.webEngineView.page().profile().downloadRequested.disconnect()
         self.label.setText('Статус:...')
         self.reload()
         try:
             for b in self.buttons: b.setEnabled(True)
         except: pass
Ejemplo n.º 26
0
    def installPlugin(self, plugin_path: str) -> Optional[Dict[str, str]]:
        plugin_path = QUrl(plugin_path).toLocalFile()

        plugin_id = self._getPluginIdFromFile(plugin_path)
        if plugin_id is None:  #Failed to load.
            return None

        # Remove it from the to-be-removed list if it's there
        if plugin_id in self._plugins_to_remove:
            self._plugins_to_remove.remove(plugin_id)
            self._savePluginData()

        # Copy the plugin file to the cache directory so it can later be used for installation
        cache_dir = os.path.join(Resources.getCacheStoragePath(), "plugins")
        if not os.path.exists(cache_dir):
            os.makedirs(cache_dir, exist_ok=True)
        cache_plugin_filename = os.path.join(cache_dir, plugin_id + ".plugin")
        if os.path.exists(cache_plugin_filename):
            os.remove(cache_plugin_filename)
        shutil.copy2(plugin_path, cache_plugin_filename)

        # Add new install data
        install_info = {
            "plugin_id": plugin_id,
            "filename": cache_plugin_filename
        }
        self._plugins_to_install[plugin_id] = install_info
        self._savePluginData()
        Logger.log("i", "Plugin '%s' has been scheduled for installation.",
                   plugin_id)

        result = {
            "status":
            "ok",
            "id":
            "",
            "message":
            i18n_catalog.i18nc(
                "@info:status",
                "The plugin has been installed.\nPlease re-start the application to activate the plugin."
            ),
        }
        return result
Ejemplo n.º 27
0
    def openVideoFile(self):
        # self.mediaPlayer.setMedia(QMediaContent())
        if self.sender() == self.openVideoAction:
            self.videoFile, _ = QFileDialog.getOpenFileName(
                self, "Open video", QDir.homePath())
            # if self.videoFile != '':
            #     self.setWindowTitle('{} - {}'.format(os.path.basename(self.videoFile),
            #                                          os.path.basename(self.projectFile)))

        if self.videoFile != '':
            self.setWindowTitle('{} - {}'.format(
                os.path.basename(self.videoFile),
                os.path.basename(self.projectFile)))
            self.saveProjectAction.setEnabled(True)
            self.maskGenAction.setEnabled(True)
            # self.loadGraphAction.setEnabled(True)
            # self.saveGraphAction.setEnabled(True)
            # self.drawPointAction.setEnabled(True)
            # self.drawLineAction.setEnabled(True)
            # self.drawZoneAction.setEnabled(True)

            creation_datetime, width, height = getVideoMetadata(self.videoFile)
            self.videoStartDatetime = self.videoCurrentDatetime = creation_datetime
            self.dateLabel.setText(creation_datetime.strftime('%a, %b %d, %Y'))

            self.gView.setSceneRect(0, 0, width, height)

            self.videoItem = QGraphicsVideoItem()
            self.videoItem.setAspectRatioMode(
                Qt.AspectRatioMode.KeepAspectRatio)
            self.gScene.addItem(self.videoItem)
            self.videoItem.mouseMoveEvent = self.gView.mouseMoveEvent
            self.videoItem.setSize(QSizeF(width, height))

            self.mediaPlayer.setVideoOutput(self.videoItem)
            self.mediaPlayer.setSource(QUrl.fromLocalFile(self.videoFile))

            self.gView.labelSize = width / 50

            self.playButton.setEnabled(True)
            # self.gView.setViewport(QOpenGLWidget())
            self.mediaPlayer.pause()
Ejemplo n.º 28
0
 def _onMessageActionTriggered(self, message, action):
     if action == "open_folder" and hasattr(message, "_folder"):
         QDesktopServices.openUrl(QUrl.fromLocalFile(message._folder))
Ejemplo n.º 29
0
	def _getArticle(self, article_id, language="en_US") -> List[List[str]]:
		"""
		Gets the rich text of a specified article.

		This function lazily loads an article from a file. If it's never been
		loaded before the article gets parsed and stored. Otherwise it'll get
		taken from the cache.
		:param article_id: The ID of the article to get.
		:param language: The language to get the article in.
		:return: A list of article "parts". Each article part is a list, where
		the first element indicates the type of part and the rest contains the
		content. Possible types of parts are "rich_text", "images" or
		"checkbox".
		"""
		if article_id in self.articles and language in self.articles[article_id]:
			return self.articles[article_id][language]

		images_path = os.path.join(os.path.dirname(__file__), "resources", "articles", "images")
		try:
			if language not in self.article_locations[article_id]:
				language = "en_US"  # Fall back to English if the preferred language is not available.
			markdown_file = self.article_locations[article_id][language]
			with open(markdown_file, encoding="utf-8") as f:
				markdown_str = f.read()
			images_path = os.path.dirname(markdown_file)
		except (OSError, KeyError):  # File doesn't exist or is otherwise not readable.
			if self.definition_container and article_id in self.definition_container.getAllKeys():
				markdown_str = self.definition_container.getProperty(article_id, "label") + "\n====\n"
				markdown_str += "*" + self.definition_container.getProperty(article_id, "description") + "*"  # Use the setting description as fallback.
			else:
				markdown_str = "There is no article on this topic."

		# Store this unparsed for later.
		if language not in self.articles_source:
			self.articles_source[language] = {}
		self.articles_source[language][article_id] = markdown_str

		if images_path not in self._markdown_per_folder:
			renderer = QtMarkdownRenderer.QtMarkdownRenderer(images_path)
			self._markdown_per_folder[images_path] = mistune.Markdown(renderer=renderer)  # Renders the Markdown articles into the subset of HTML supported by Qt.

		# Pre-process so that comments and conditionals don't influence the business.
		markdown_str = QtMarkdownRenderer.QtMarkdownRenderer.preprocess_conditionals(markdown_str)
		markdown_str = QtMarkdownRenderer.QtMarkdownRenderer.preprocess_comments(markdown_str)

		find_images = re.compile(r"!\[(.*)\]\(([^\)]+)\)")
		find_checkboxes = re.compile(r"\[ \]\s*([^\n]+)")
		image_description = None
		parts = []  # type: List[List[str]]  # List of items in the article. Each item starts with a type ID, and then a variable number of data items.
		for index, part_between_images in enumerate(find_images.split(markdown_str)):
			# The parts of the regex split alternate between text, image description and image URL.
			if index % 3 == 0:
				part_between_images = part_between_images.strip()
				if part_between_images or index == 0:
					parts_between_checkboxes = find_checkboxes.split(part_between_images)
					for index2, part_between_checkboxes in enumerate(parts_between_checkboxes):
						part_between_checkboxes = part_between_checkboxes.strip()
						# The parts of the regex split alternate between text and checkbox description.
						if index2 % 2 == 0:
							if part_between_checkboxes:
								rich_text = self._markdown_per_folder[images_path](part_between_checkboxes)
								parts.append(["rich_text", rich_text])
						else:  # if index2 == 1:
							preference_key = "settings_guide/" + urllib.parse.quote_plus(part_between_checkboxes).lower()
							parts.append(["checkbox", preference_key, part_between_checkboxes])
			elif index % 3 == 1:
				image_description = mistune.markdown(part_between_images)
			else:  # if index % 3 == 2:
				if image_description is not None:
					if parts[-1][0] != "images":  # List of images.
						parts.append(["images"])
					image_url = os.path.join(images_path, part_between_images)
					parts[-1].append(QUrl.fromLocalFile(image_url).toString() + "|" + image_description)
					image_description = None

		if article_id not in self.articles:
			self.articles[article_id] = {}
		self.articles[article_id][language] = parts
		if article_id not in self.articles_rich_text:
			self.articles_rich_text[article_id] = {}
		self.articles_rich_text[article_id][language] = self._markdown_per_folder[images_path](markdown_str)

		return self.articles[article_id][language]
Ejemplo n.º 30
0
    loaded = pyqtSignal()
    error = pyqtSignal(str, arguments=["errorText"])

    metaDataChanged = pyqtSignal()
    @pyqtProperty("QVariantMap", notify=metaDataChanged)
    def metaData(self):
        return self._metadata

    @pyqtProperty(str, notify=loaded)
    def definitionId(self):
        return self._definition_id

signal.signal(signal.SIGINT, signal.SIG_DFL)

file_name = None
if len(sys.argv) > 1:
    file_name = sys.argv[1]
    del sys.argv[1]

app = QApplication(sys.argv)
engine = QQmlApplicationEngine()

qmlRegisterType(DefinitionLoader, "Example", 1, 0, "DefinitionLoader")
qmlRegisterType(DefinitionTreeModel.DefinitionTreeModel, "Example", 1, 0, "DefinitionTreeModel")

if file_name:
    engine.rootContext().setContextProperty("open_file", QUrl.fromLocalFile(file_name))

engine.load(os.path.join(os.path.dirname(os.path.abspath(__file__)), "main.qml"))
app.exec()