def load_directories(self):
     """Update the repository directory."""
     self._directories = {}
     settings = QgsSettings()
     settings.beginGroup(repo_settings_group())
     # Loop through the repositories from the official directory
     for online_dir_name in self._online_directories:
         # Check if the repository is already present
         repo_present = False
         for repo_name in settings.childGroups():
             url = settings.value(repo_name + "/url", "", type=str)
             if url == self._online_directories[online_dir_name]:
                 repo_present = True
                 break
             if online_dir_name == repo_name:
                 repo_present = True
                 nameWarn = (
                     "The repository " + repo_name + " is masking "
                     "an official repository with the same name"
                 )
                 LOGGER.warning(nameWarn)
                 break
         if not repo_present:
             self.add_directory(
                 online_dir_name, self._online_directories[online_dir_name]
             )
     for repo_name in settings.childGroups():
         self._directories[repo_name] = {}
         url = settings.value(repo_name + "/url", "", type=str)
         self._directories[repo_name]["url"] = url
         auth_cfg = settings.value(repo_name + "/auth_cfg", "", type=str).strip()
         self._directories[repo_name]["auth_cfg"] = auth_cfg
     settings.endGroup()
 def fetch_online_directories(self):
     """Fetch online directory of repositories."""
     downloader = NetworkManager(self.DIRECTORY_URL)
     status, _ = downloader.fetch()
     if status:
         directory_file = QTemporaryFile()
         if directory_file.open():
             directory_file.write(downloader.content)
             directory_file.close()
         with open(directory_file.fileName()) as csv_file:
             reader = csv.DictReader(csv_file, fieldnames=("name", "url"))
             for row in reader:
                 repName = row["name"]
                 repUrl = row["url"]
                 # Check name and URL for None before stripping and adding
                 if repName is not None and repUrl is not None:
                     self._online_directories[row["name"]] = repUrl.strip()
                 else:
                     if repName is None:
                         # No name
                         LOGGER.warning("Missing name for repository" " - not added")
                     else:
                         # No URL
                         LOGGER.warning(
                             "Missing URL for repository"
                             + str(row["name"])
                             + " - not added"
                         )
         # Save to settings
         settings = QgsSettings()
         settings.beginGroup(repo_settings_group())
         settings.setValue("online_directories", self._online_directories)
         settings.endGroup()
     else:
         # Use settings
         settings = QgsSettings()
         settings.beginGroup(repo_settings_group())
         self._online_directories = settings.value("online_directories", {})
         settings.endGroup()
    def remove_directory(self, repo_name):
        """Remove a directory and all its collections.

        :param repo_name: The old name of the repository
        :type repo_name: str
        """
        self._repositories.pop(repo_name, None)
        self.rebuild_collections()
        # Remove repository from QgsSettings
        settings = QgsSettings()
        settings.beginGroup(repo_settings_group())
        settings.remove(repo_name)
        settings.endGroup()
        # Serialize repositories
        self.serialize_repositories()
    def add_directory(self, repo_name, url, auth_cfg=None):
        """Add a directory to settings and add the collections from that repo.

        :param repo_name: The name of the repository
        :type repo_name: str

        :param url: The URL of the repository
        :type url: str
        """
        repo_handler = BaseRepositoryHandler.get_handler(url)
        if repo_handler is None:
            LOGGER.warning("There is no handler available for URL '" + str(url) + "'!")
        if auth_cfg:
            repo_handler.auth_cfg = auth_cfg
        # Fetch metadata
        status, fetcherror = repo_handler.fetch_metadata()
        if status:
            # Parse metadata
            try:
                collections = repo_handler.parse_metadata()
            except MetadataError as me:
                metadata_warning = (
                    "Error parsing metadata for " + str(repo_name) + ":\n" + str(me)
                )
                LOGGER.warning(metadata_warning)
                return False, metadata_warning
            # Add the repository and its collections
            self._repositories[repo_name] = collections
            self.rebuild_collections()
            # Add to QgsSettings
            settings = QgsSettings()
            settings.beginGroup(repo_settings_group())
            settings.setValue(repo_name + "/url", url)
            if auth_cfg:
                settings.setValue(repo_name + "/auth_cfg", auth_cfg)
            settings.endGroup()
            # Serialize repositories every time we successfully added a repo
            self.serialize_repositories()
        return status, fetcherror
    def edit_directory(
        self, old_repo_name, new_repo_name, old_url, new_url, new_auth_cfg
    ):
        """Edit the directory of repositories and update the
        collections.
        Also used to reload repositories (old == new for url and repo_name)

        :param old_repo_name: The old name of the repository
        :type old_repo_name: str
        :param new_repo_name: The new name of the repository
        :type new_repo_name: str
        :param old_url: The old URL of the repository
        :type old_url: str
        :param new_url: The new URL of the repository
        :type new_url: str
        :param new_auth_cfg: The auth config id.
        :type new_auth_cfg: str
        :return: (status, error)
        :rtype: (boolean, string)
        """
        old_collections = self._repositories.get(old_repo_name, [])
        if (old_repo_name != new_repo_name) and (old_url == new_url):
            # Renaming a repository (same URL)
            for old_collection in old_collections:
                coll_id = self._collections_manager.get_collection_id(
                    old_collection["register_name"], old_collection["repository_url"]
                )
                old_path = local_collection_path(coll_id)
                # Update the repository name for this collection
                config.COLLECTIONS[coll_id]["repository_name"] = new_repo_name
                new_path = local_collection_path(coll_id)
                # If the repository is renamed (same URL), the directories
                # of its collections should be renamed accordingly (so that
                # they remain accessible)
                if old_path.exists():
                    old_path.rename(new_path)
            new_collections = old_collections
            status = True
            fetcherror = ""
        else:
            # old_repo_name == new_repo_name and old_url == new_url
            # or new_url != old_url
            # Fetch the metadata (metadata.ini) from the new url
            repo_handler = BaseRepositoryHandler.get_handler(new_url)
            if repo_handler is None:
                repo_warning = "No handler for URL '" + str(new_url) + "'!"
                LOGGER.warning(repo_warning)
                return (False, repo_warning)
            if new_auth_cfg:
                repo_handler.auth_cfg = new_auth_cfg
            status, fetcherror = repo_handler.fetch_metadata()
            if status:
                # Parse metadata
                try:
                    new_collections = repo_handler.parse_metadata()
                except MetadataError as me:
                    metadata_warning = (
                        "Error parsing metadata for "
                        + str(new_repo_name)
                        + ":\n"
                        + str(me)
                    )
                    LOGGER.warning(metadata_warning)
                    return (False, metadata_warning)
                    # raise MetadataError(metadata_warning)
                # Get all the installed collections from the old repository
                installed_old_collections = []
                for old_collection in old_collections:
                    if old_collection["status"] == COLLECTION_INSTALLED_STATUS:
                        installed_old_collections.append(old_collection)
                # Handling installed collections
                # An old collection that is present in the new location
                # (URL) is identified by its register name.
                # Cases for installed collections:
                # 1. Old collection exists in the new, same URL: use the new
                # one, else: update the status to INSTALLED
                # 2. Old collection exists in the new, different URL: keep them
                # both (add the old one). Because they should be treated as
                # different collections
                # 3. Old collection doesn't exist in the new, same URL: keep
                # the old collection
                # 4. Old collection doesn't exist in the new, different URL:
                # same as 3
                for installed_collection in installed_old_collections:
                    reg_name = installed_collection["register_name"]
                    is_present = False
                    for n_coll in new_collections:
                        # Look for collections that are already present
                        if n_coll["register_name"] == reg_name:
                            # Already present
                            is_present = True
                            if old_url == new_url:
                                # Set the status to installed
                                n_coll["status"] = COLLECTION_INSTALLED_STATUS
                                # Keep the collection statistics
                                for key in installed_collection.keys():
                                    if key in [
                                        "models",
                                        "processing",
                                        "rscripts",
                                        "style",
                                        "svg",
                                        "symbol",
                                        "expressions",
                                    ]:
                                        n_coll[key] = installed_collection[key]
                            else:
                                # Different repository URLs, so append
                                new_collections.append(installed_collection)
                            break
                    if not is_present:
                        new_collections.append(installed_collection)
        # Remove the old repository and add the new one
        self._repositories.pop(old_repo_name, None)
        self._repositories[new_repo_name] = new_collections
        self.rebuild_collections()
        # Update QgsSettings
        settings = QgsSettings()
        settings.beginGroup(repo_settings_group())
        settings.remove(old_repo_name)
        settings.setValue(new_repo_name + "/url", new_url)
        settings.setValue(new_repo_name + "/auth_cfg", new_auth_cfg)
        settings.endGroup()
        # Serialize repositories every time we successfully edited repo
        self.serialize_repositories()
        return status, fetcherror
Пример #6
0
 def edit_repository(self):
     """Open edit repository dialog."""
     selected_item = self.tree_repositories.currentItem()
     if selected_item:
         repo_name = selected_item.text(0)
     if not repo_name:
         return
     # Check if it is among the officially approved QGIS repositories
     settings = QgsSettings()
     settings.beginGroup(repo_settings_group())
     if (settings.value(repo_name + "/url")
             in self.repository_manager._online_directories.values()):
         self.message_bar.pushMessage(
             self.tr("You can not edit the official repositories!"),
             Qgis.Warning, 5)
         return
     dlg = ManageRepositoryDialog(self)
     dlg.line_edit_name.setText(repo_name)
     dlg.line_edit_url.setText(
         self.repository_manager.directories[repo_name]["url"])
     dlg.line_edit_auth_id.setText(
         self.repository_manager.directories[repo_name]["auth_cfg"])
     if not dlg.exec_():
         return
     # Check if the changed URL is already present and that
     # the new repository name is unique
     new_url = dlg.line_edit_url.text().strip()
     old_url = self.repository_manager.directories[repo_name]["url"]
     new_name = dlg.line_edit_name.text().strip()
     for repoName, repo in self.repository_manager.directories.items():
         if new_url == repo["url"] and (old_url != new_url):
             self.message_bar.pushMessage(
                 self.tr("Unable to add another repository with the same "
                         "URL!"),
                 Qgis.Warning,
                 5,
             )
             return
         if new_name == repoName and (repo_name != new_name):
             self.message_bar.pushMessage(
                 self.tr("Repositories must have unique names!"),
                 Qgis.Warning, 5)
             return
     # Redundant
     if (new_name in self.repository_manager.directories) and (new_name !=
                                                               repo_name):
         new_name += "(2)"
     new_auth_cfg = dlg.line_edit_auth_id.text()
     # Show progress dialog
     self.show_progress_dialog("Fetching repository's metadata")
     # Edit repository
     try:
         status, editerror = self.repository_manager.edit_directory(
             repo_name, new_name, old_url, new_url, new_auth_cfg)
         if status:
             self.message_bar.pushMessage(
                 self.tr("Repository is successfully updated"),
                 Qgis.Success, 5)
         else:
             self.message_bar.pushMessage(
                 self.tr("Unable to edit repository: %s") % editerror,
                 Qgis.Warning,
                 5,
             )
     except Exception as e:
         self.message_bar.pushMessage(self.tr("%s") % e, Qgis.Warning, 5)
     finally:
         self.progress_dialog.hide()
     # Reload data and widget
     self.reload_data_and_widget()
     # Deactivate the edit and delete buttons
     self.button_edit.setEnabled(False)
     self.button_delete.setEnabled(False)