Skip to content

Commit

Permalink
Merge pull request #129 from aeag/feat/project_in_qgis_browser
Browse files Browse the repository at this point in the history
Feature: add location option to create menus in QGIS browser from project
  • Loading branch information
jmkerloch authored Dec 20, 2024
2 parents fc31d50 + 836eedb commit 3118929
Show file tree
Hide file tree
Showing 5 changed files with 508 additions and 127 deletions.
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

0 comments on commit 3118929

Please sign in to comment.