Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: add location option to create menus in QGIS browser from project #129

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 53 additions & 71 deletions menu_from_project/logic/layer_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
)
from qgis.PyQt import QtXml
from qgis.PyQt.QtCore import QCoreApplication, QFileInfo, Qt, QUuid
from qgis.PyQt.QtWidgets import QMenu, QWidget
from qgis.utils import iface, plugins

# project
from menu_from_project.__about__ import __title__
from menu_from_project.datamodel.project_config import MenuLayerConfig
from menu_from_project.logic.qgs_manager import (
QgsDomManager,
is_absolute,
Expand Down Expand Up @@ -435,29 +435,26 @@ def buildRelations(

return targetRelations + relationsToBuild

def loadLayer(
self,
uri: Optional[str],
fileName: Optional[str],
layerId: Optional[str],
menu: Optional[QMenu] = None,
visible: Optional[bool] = None,
expanded: Optional[bool] = None,
):
def load_layer_list(
self, layer_config_list: List[MenuLayerConfig], group_name: str
) -> None:
"""Load a list of layer to current QgsProject

:param layer_config_list: menu layer configuration list
:type layer_config_list: List[MenuLayerConfig]
:param group_name: group name in case of create group option
:type group_name: str
"""
for layer_config in layer_config_list:
self.load_layer(layer_config=layer_config, group_name=group_name)

def load_layer(self, layer_config: MenuLayerConfig, group_name: str) -> None:
"""Load layer to current QgsProject

:param uri: The layer URI (file path or PG URI)
:type uri: Optional[str]
:param fileName: path to QgsProject file, None for Load all option
:type fileName: Optional[str]
:param layerId: id of layer to load (from QgsProject file), None for Load all option
:type layerId: Optional[str]
:param menu: QMenu where the action is located, defaults to None
:type menu: Optional[QMenu], optional
:param visible: define layer visibility in layer tree, defaults to None
:type visible: Optional[bool], optional
:param expanded: define if layer is expanded in layer tree, defaults to None
:type expanded: Optional[bool], optional
:param layer_config: configuration of layer to load
:type layer_config: MenuLayerConfig
:param group_name: group name in case of create group option
:type group_name: str
"""
self.canvas.freeze(True)
self.canvas.setRenderFlag(False)
Expand All @@ -468,60 +465,45 @@ def loadLayer(
settings = self.plg_settings.get_plg_settings()

try:
if (
menu
and isinstance(menu.parentWidget(), (QMenu, QWidget))
and settings.optionCreateGroup
):
groupName = menu.title().replace("&", "")
group = QgsProject.instance().layerTreeRoot().findGroup(groupName)
if settings.optionCreateGroup:
group = QgsProject.instance().layerTreeRoot().findGroup(group_name)
if group is None:
group = (
QgsProject.instance().layerTreeRoot().insertGroup(0, groupName)
QgsProject.instance().layerTreeRoot().insertGroup(0, group_name)
)
doc, _ = self.qgs_dom_manager.getQgsDoc(layer_config.filename)

# Loading layer
layer, relationsToBuild = self.addLayer(
layer_config.filename,
doc,
layer_config.layer_id,
group,
layer_config.visible,
layer_config.expanded,
{},
0,
)
for relDict in relationsToBuild:
self.buildProjectRelation(doc, relDict)

# load all layers
if fileName is None and layerId is None and settings.optionLoadAll:
for action in menu.actions()[::-1]:
if (
action.text() != self.tr("Load all")
and action.text() != "Load all"
):
action.trigger()
else:
doc, _ = self.qgs_dom_manager.getQgsDoc(fileName)

# Loading layer
layer, relationsToBuild = self.addLayer(
uri, doc, layerId, group, visible, expanded, {}, 0
)
for relDict in relationsToBuild:
self.buildProjectRelation(doc, relDict)

# is joined layers exists ?
if (
settings.optionOpenLinks
and layer
and isinstance(layer, QgsVectorLayer)
):
for j in layer.vectorJoins():
try:
joinLayer, joinRelations = self.addLayer(
uri, doc, j.joinLayerId(), group
)
for relDict in joinRelations:
self.buildProjectRelation(doc, relDict)

if joinLayer:
j.setJoinLayerId(joinLayer.id())
j.setJoinLayer(joinLayer)
layer.addJoin(j)
except Exception:
self.log(
"Joined layer {} not added.".format(j.joinLayerId())
)
pass
# is joined layers exists ?
if settings.optionOpenLinks and layer and isinstance(layer, QgsVectorLayer):
for j in layer.vectorJoins():
try:
joinLayer, joinRelations = self.addLayer(
layer_config.filename, doc, j.joinLayerId(), group
)
for relDict in joinRelations:
self.buildProjectRelation(doc, relDict)

if joinLayer:
j.setJoinLayerId(joinLayer.id())
j.setJoinLayer(joinLayer)
layer.addJoin(j)
except Exception:
self.log("Joined layer {} not added.".format(j.joinLayerId()))
pass
except Exception as e:
# fixme fileName is not defined
# self.log(
Expand Down
97 changes: 42 additions & 55 deletions menu_from_project/menu_from_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,9 @@
read_from_http,
)
from menu_from_project.logic.tools import icon_per_layer_type
from menu_from_project.toolbelt.preferences import (
SOURCE_MD_LAYER,
SOURCE_MD_NOTE,
SOURCE_MD_OGC,
PlgOptionsManager,
)
from menu_from_project.toolbelt.preferences import PlgOptionsManager
from menu_from_project.ui.menu_conf_dlg import MenuConfDialog # noqa: F4 I001
from menu_from_project.ui.menu_layer_data_item_provider import MenuLayerProvider

# ############################################################################
# ########## Classes ###############
Expand Down Expand Up @@ -98,6 +94,9 @@ def __init__(self, iface):
self.action_project_configuration = None
self.action_menu_help = None

self.registry = QgsApplication.instance().dataItemProviderRegistry()
self.provider = None

@staticmethod
def tr(message):
return QCoreApplication.translate("MenuFromProject", message)
Expand Down Expand Up @@ -167,7 +166,7 @@ def load_all_project_config(
return result

def project_config_loaded(
self, exception: Any, project_configs: List[Tuple[Any, MenuProjectConfig]]
self, exception: Any, project_configs: List[Tuple[Project, MenuProjectConfig]]
) -> None:
"""Add menu after project configuration load

Expand All @@ -177,19 +176,25 @@ def project_config_loaded(
:type project_configs: List[Tuple[Any, MenuProjectConfig]]
"""
QgsApplication.setOverrideCursor(Qt.CursorShape.WaitCursor)

if self.provider:
self.registry.removeProvider(self.provider)
self.provider = MenuLayerProvider(project_configs)

previous = None
for project, project_config in project_configs:
# Add to QGIS instance
previous = self.add_project_config(project, project_config, previous)

self.registry.addProvider(self.provider)
QgsApplication.restoreOverrideCursor()

def add_project_config(
self,
project: Project,
project_config: MenuProjectConfig,
previous: Optional[QMenu],
) -> QMenu:
) -> Optional[QMenu]:
"""Add a project menu configuration to current QGIS instance

:param menu_name: Name of the menu to create
Expand All @@ -206,13 +211,14 @@ def add_project_config(
project_menu = self.create_project_menu(
menu_name=project_config.project_name, project=project, previous=previous
)
self.add_group_childs(project_config.root_group, project_menu)
if project_menu:
self.add_group_childs(project_config.root_group, project_menu)

return project_menu

def create_project_menu(
self, menu_name: str, project: Project, previous: Optional[QMenu]
) -> QMenu:
) -> Optional[QMenu]:
"""Create project menu and add it to QGIS instance

:param menu_name: Name of the menu to create
Expand All @@ -222,13 +228,14 @@ def create_project_menu(
:param previous: previous created menu
:type previous: Optional[QMenu]
:return: created menu
:rtype: QMenu
:rtype: Optional[QMenu]
"""
project_menu = None
location = project.location
if location == "merge" and previous:
project_menu = previous
project_menu.addSeparator()
else:
elif location in ["layer", "new"]:
if location == "layer":
menu_bar = self.iface.addLayerMenu()
if location == "new":
Expand All @@ -244,9 +251,13 @@ def create_project_menu(
self.layerMenubarActions.append(project_action)
if location == "new":
self.menubarActions.append(project_action)
else:
project_menu = None
return project_menu

def add_group_childs(self, group: MenuGroupConfig, grp_menu: QMenu) -> bool:
def add_group_childs(
self, group: MenuGroupConfig, grp_menu: QMenu
) -> List[MenuLayerConfig]:
"""Add all childs of a group config

:param uri: initial uri of project (can be from local file / http / postgres)
Expand All @@ -255,16 +266,16 @@ def add_group_childs(self, group: MenuGroupConfig, grp_menu: QMenu) -> bool:
:type group: MenuGroupConfig
:param grp_menu: menu for group
:type grp_menu: QMenu
:return: True if a layer was inserted, False otherwise
:rtype: bool
:return: list of inserted layer configuration
:rtype: List[MenuLayerConfig]
"""
layer_inserted = False
layer_inserted = []
for child in group.childs:
if isinstance(child, MenuGroupConfig):
self.add_group(child, grp_menu)
elif isinstance(child, MenuLayerConfig):
layer_inserted = True
self.add_layer(child, grp_menu)
layer_inserted.append(child)
self.add_layer(child, grp_menu, group.name, child.name)
return layer_inserted

def add_group(self, group: MenuGroupConfig, menu: QMenu) -> None:
Expand Down Expand Up @@ -300,69 +311,42 @@ def add_group(self, group: MenuGroupConfig, menu: QMenu) -> None:

layer_inserted = self.add_group_childs(group=group, grp_menu=grp_menu)

if layer_inserted and settings.optionLoadAll:
if len(layer_inserted) and settings.optionLoadAll:
action = QAction(self.tr("Load all"), self.iface.mainWindow())
font = QFont()
font.setBold(True)
action.setFont(font)
grp_menu.addAction(action)
action.triggered.connect(
lambda checked, f=None, w=None, m=grp_menu: LayerLoad().loadLayer(
None, f, w, m
)
lambda checked: LayerLoad().load_layer_list(layer_inserted, name)
)

def add_layer(self, layer: MenuLayerConfig, menu: QMenu) -> None:
def add_layer(
self, layer: MenuLayerConfig, menu: QMenu, group_name: str, action_text: str
) -> None:
"""Add layer menu configuration to a menu

:param uri: initial uri of project (can be from local file / http / postgres)
:type uri: str
:param layer: layer menu configuration
:type layer: MenuLayerConfig
:param group_name: group name in case of create group option
:type group_name: str
:param menu: input menu
:type menu: QMenu
"""
settings = self.plg_settings.get_plg_settings()
action = QAction(layer.name, self.iface.mainWindow())
action = QAction(action_text, self.iface.mainWindow())

# add menu item
action.triggered.connect(
lambda checked, uri=layer.filename, f=layer.filename, lid=layer.layer_id, m=menu, v=layer.visible, x=layer.expanded: LayerLoad().loadLayer(
uri, f, lid, m, v, x
)
lambda checked: LayerLoad().load_layer(layer, group_name)
)
action.setIcon(
icon_per_layer_type(layer.is_spatial, layer.layer_type, layer.geometry_type)
)
if settings.optionTooltip:
if settings.optionSourceMD == SOURCE_MD_OGC:
abstract = layer.abstract or layer.metadata_abstract
title = layer.title or layer.metadata_title
else:
abstract = layer.metadata_abstract or layer.abstract
title = layer.metadata_title or layer.title

abstract = ""
title = ""
for oSource in settings.optionSourceMD:
if oSource == SOURCE_MD_OGC:
abstract = layer.metadata_abstract if abstract == "" else abstract
title = title or layer.metadata_title

if oSource == SOURCE_MD_LAYER:
abstract = layer.abstract if abstract == "" else abstract
title = title or layer.title

if oSource == SOURCE_MD_NOTE:
abstract = layer.layer_notes if abstract == "" else abstract

if (abstract != "") and (title == ""):
action.setToolTip("<p>{}</p>".format(abstract))
else:
if abstract != "" or title != "":
action.setToolTip("<b>{}</b><br/>{}".format(title, abstract))
else:
action.setToolTip("")
action.setToolTip(settings.tooltip_for_layer(layer))

menu.addAction(action)

Expand Down Expand Up @@ -425,6 +409,9 @@ def unload(self):

self.iface.initializationCompleted.disconnect(self.on_initializationCompleted)

if self.provider:
self.registry.removeProvider(self.provider)

def open_projects_config(self):
dlg = MenuConfDialog(self.iface.mainWindow())
dlg.setModal(True)
Expand Down
Loading
Loading