diff --git a/menu_from_project/i18n/fr.qm b/menu_from_project/i18n/fr.qm index e369f04..742a03e 100644 Binary files a/menu_from_project/i18n/fr.qm and b/menu_from_project/i18n/fr.qm differ diff --git a/menu_from_project/i18n/fr.ts b/menu_from_project/i18n/fr.ts index b1f9bb9..b537970 100644 --- a/menu_from_project/i18n/fr.ts +++ b/menu_from_project/i18n/fr.ts @@ -89,35 +89,30 @@ Options - + New menu Nouveau menu - + Add layer menu Ajouter une couche - + Merge with previous Intégrer dans le précédent - + OGC QGis Server metadata métadonnées OGC QGis server - + Layer metadata métadonnées de la couche - - - Show title && abstract in tooltip. Priority to : - Afficher titre et résumé en info bulle. En priorité : - Opens with layer, layers linked by 'relations' or joins. @@ -128,36 +123,66 @@ Also load linked layers. Ouvrir aussi les couches liées. + + + Show title && abstract in tooltip - click to move the item to the first position + Afficher titre et résumé en info bulle. Cliquer sur un item... + + + + Tooltip. Priority to : + Info bulle. En priorité : + + + + 1 : + 1 : + + + + 2 : + 2 : + + + + 3 : + 3 : + + + + Layer notes + Notes de couche + MenuConfDialog - + Add from file Fichier QGS/QGZ - + Add from PostgreSQL database Base de données PostgreSQL - + Add from URL Serveur HTTP - + Use project title Utiliser le titre du projet - + Edit this project Modifier la source - + No HTTP Browser, simply paste your URL into the 'project' column. Copiez simplement l'url du projet dans la cellule 'projet QGis'. @@ -165,30 +190,45 @@ MenuFromProject - + Load all Tout ajouter - + Projects configuration Configurer les projets - + Help Aide + + + QGis Server metadata + QGis server + + + + Layer Metadata + Méta-données de la couche + + + + Layer Notes + Notes de couche + menu_from_project - + Projects configuration Configurer les projets - + QGIS projects (*.qgs *.qgz) Projets QGIS (*.qgs *.qgz) diff --git a/menu_from_project/i18n/ja.qm b/menu_from_project/i18n/ja.qm index acc83d5..2c71eed 100644 Binary files a/menu_from_project/i18n/ja.qm and b/menu_from_project/i18n/ja.qm differ diff --git a/menu_from_project/i18n/ja.ts b/menu_from_project/i18n/ja.ts index 4d3efdb..1d8d66f 100644 --- a/menu_from_project/i18n/ja.ts +++ b/menu_from_project/i18n/ja.ts @@ -1,5 +1,6 @@ - + + ConfDialog @@ -88,75 +89,100 @@ グループを作成 - - Show title && abstract in tooltip. Priority to : - タイトルと抄録をツールチップに表示する。優先順位: - - - + OGC QGis Server metadata - OGC QGisサーバーメタデータ + サーバーメタデータ - + Layer metadata レイヤメタデータ - + New menu 新規メニュー - + Add layer menu レイヤメニューを追加 - + Merge with previous 従来のものと統合 Opens with layer, layers linked by 'relations' or joins. - + レイヤー、関係または結合によってリンクされたレイヤーとともに開きます。 + + + + Show title && abstract in tooltip - click to move the item to the first position + ツールチップにタイトルと概要を表示 - クリックすると項目が最初の位置に移動します + + + + Tooltip. Priority to : + ツールチップ。優先度: + + + + Layer notes + レイヤーノート Also load linked layers. - + リンクされたレイヤーも読み込みます。 + + + + 1 : + + + + + 2 : + + + + + 3 : + MenuConfDialog - + Add from file ファイルから追加 - + Add from PostgreSQL database PostgreSQLデータベースから追加 - + Add from URL URLから追加 - + Use project title プロジェクトのタイトルを使用 - + No HTTP Browser, simply paste your URL into the 'project' column. HTTPブラウザを使わず、「プロジェクト」欄にURLを貼り付ける。 - + Edit this project このプロジェクトを編集 @@ -164,30 +190,45 @@ MenuFromProject - + Load all すべてを読み込む - + Projects configuration プロジェクトのコンフィグ - + Help ヘルプ + + + QGis Server metadata + サーバーメタデータ + + + + Layer Metadata + レイヤメタデータ + + + + Layer Notes + レイヤーノート + menu_from_project - + Projects configuration プロジェクトのコンフィグ - + QGIS projects (*.qgs *.qgz) QGISプロジェクト(*.qgs *.qgz) diff --git a/menu_from_project/menu_from_project.py b/menu_from_project/menu_from_project.py index f0a27da..03583b6 100644 --- a/menu_from_project/menu_from_project.py +++ b/menu_from_project/menu_from_project.py @@ -168,6 +168,7 @@ def project_trusted(doc): class MenuFromProject: SOURCE_MD_OGC = "ogc" SOURCE_MD_LAYER = "layer" + SOURCE_MD_NOTE = "note" def on_initializationCompleted(self): # build menu @@ -175,6 +176,19 @@ def on_initializationCompleted(self): def __init__(self, iface): self.path = QFileInfo(os.path.realpath(__file__)).path() + + # default lang + settings = QgsSettings() + locale = settings.value("locale/userLocale") + self.myLocale = locale[0:2] + # dictionary + localePath = self.path + "/i18n/" + self.myLocale + ".qm" + # translator + if QFileInfo(localePath).exists(): + self.translator = QTranslator() + self.translator.load(localePath) + QCoreApplication.installTranslator(self.translator) + self.iface = iface self.toolBar = None self.project_registry = QgsApplication.projectStorageRegistry() @@ -189,10 +203,14 @@ def __init__(self, iface): self.optionCreateGroup = False self.optionLoadAll = False self.optionOpenLinks = False - self.optionSourceMD = MenuFromProject.SOURCE_MD_OGC + self.sourcesMdText = { + MenuFromProject.SOURCE_MD_OGC: self.tr("QGis Server metadata"), + MenuFromProject.SOURCE_MD_LAYER: self.tr("Layer Metadata"), + MenuFromProject.SOURCE_MD_NOTE: self.tr("Layer Notes"), + } + self.optionSourceMD = list(self.sourcesMdText.keys()) self.mapLayerIds = {} self.read() - settings = QgsSettings() if settings.value("menu_from_project/is_setup_visible") is None: # This setting does not exist. We add it by default. @@ -206,17 +224,6 @@ def __init__(self, iface): self.action_project_configuration = None self.action_menu_help = None - # default lang - locale = settings.value("locale/userLocale") - self.myLocale = locale[0:2] - # dictionary - localePath = self.path + "/i18n/" + self.myLocale + ".qm" - # translator - if QFileInfo(localePath).exists(): - self.translator = QTranslator() - self.translator.load(localePath) - QCoreApplication.installTranslator(self.translator) - @staticmethod def tr(message): return QCoreApplication.translate("MenuFromProject", message) @@ -224,9 +231,7 @@ def tr(message): @staticmethod def log(message, application=__title__, indent=0): indent_chars = " .. " * indent - QgsMessageLog.logMessage( - f"{indent_chars}{message}", application, notifyUser=True - ) + QgsMessageLog.logMessage(f"{indent_chars}{message}", application, notifyUser=True) def store(self): """Store the configuration in the QSettings.""" @@ -238,7 +243,7 @@ def store(self): s.setValue("optionCreateGroup", self.optionCreateGroup) s.setValue("optionLoadAll", self.optionLoadAll) s.setValue("optionOpenLinks", self.optionOpenLinks) - s.setValue("optionSourceMD", self.optionSourceMD) + s.setValue("optionSourceMD", ",".join(self.optionSourceMD)) s.beginWriteArray("projects", len(self.projects)) try: @@ -250,7 +255,8 @@ def store(self): s.setValue( "type_storage", project.get( - "type_storage", guess_type_from_uri(project.get("file")) + "type_storage", + guess_type_from_uri(project.get("file")), ), ) finally: @@ -268,9 +274,45 @@ def read(self): self.optionCreateGroup = s.value("optionCreateGroup", False, type=bool) self.optionLoadAll = s.value("optionLoadAll", False, type=bool) self.optionOpenLinks = s.value("optionOpenLinks", True, type=bool) + defaultOptionSourceMD = "{},{},{}".format( + MenuFromProject.SOURCE_MD_OGC, + MenuFromProject.SOURCE_MD_LAYER, + MenuFromProject.SOURCE_MD_NOTE, + ) self.optionSourceMD = s.value( - "optionSourceMD", MenuFromProject.SOURCE_MD_OGC, type=str + "optionSourceMD", + defaultOptionSourceMD, + type=str, ) + self.optionSourceMD = self.optionSourceMD.split(",") + # Retro comp + if ( + len(self.optionSourceMD) == 1 + and self.optionSourceMD[0] == MenuFromProject.SOURCE_MD_OGC + ): + self.optionSourceMD = [ + MenuFromProject.SOURCE_MD_OGC, + MenuFromProject.SOURCE_MD_LAYER, + MenuFromProject.SOURCE_MD_NOTE, + ] + if ( + len(self.optionSourceMD) == 1 + and self.optionSourceMD[0] == MenuFromProject.SOURCE_MD_LAYER + ): + self.optionSourceMD = [ + MenuFromProject.SOURCE_MD_LAYER, + MenuFromProject.SOURCE_MD_OGC, + MenuFromProject.SOURCE_MD_NOTE, + ] + if ( + len(self.optionSourceMD) == 1 + and self.optionSourceMD[0] == MenuFromProject.SOURCE_MD_NOTE + ): + self.optionSourceMD = [ + MenuFromProject.SOURCE_MD_NOTE, + MenuFromProject.SOURCE_MD_LAYER, + MenuFromProject.SOURCE_MD_OGC, + ] size = s.beginReadArray("projects") try: @@ -279,9 +321,7 @@ def read(self): file = s.value("file", "") name = s.value("name", "") location = s.value("location", "new") - type_storage = s.value( - "type_storage", guess_type_from_uri(file) - ) + type_storage = s.value("type_storage", guess_type_from_uri(file)) if file != "": self.projects.append( { @@ -315,27 +355,36 @@ def addToolTip(self, ml, action): md = ml.namedItem("resourceMetadata") mdLayerTitle = md.namedItem("title").firstChild().toText().data() mdLayerAbstract = md.namedItem("abstract").firstChild().toText().data() + mdLayerAbstract = "
".join(mdLayerAbstract.split("\n")) + ogcTitle = ml.namedItem("title").firstChild().toText().data() ogcAbstract = ml.namedItem("abstract").firstChild().toText().data() + ogcAbstract = "
".join(ogcAbstract.split("\n")) - if self.optionSourceMD == MenuFromProject.SOURCE_MD_OGC: - abstract = ogcAbstract or mdLayerAbstract - title = ogcTitle or mdLayerTitle - else: - abstract = mdLayerAbstract or ogcAbstract - title = mdLayerTitle or ogcTitle + userNotes = "" + eltNote = ml.namedItem("userNotes") + if eltNote.toElement().hasAttribute("value"): + userNotes = eltNote.toElement().attribute("value") + + abstract = "" + title = "" + for oSource in self.optionSourceMD: + if oSource == MenuFromProject.SOURCE_MD_OGC: + abstract = abstract or ogcAbstract + title = title or ogcTitle + + if oSource == MenuFromProject.SOURCE_MD_LAYER: + abstract = abstract or mdLayerAbstract + title = title or mdLayerTitle + + if oSource == MenuFromProject.SOURCE_MD_NOTE: + abstract = abstract or userNotes if (abstract != "") and (title == ""): - action.setToolTip( - "

{}

".format("
".join(abstract.split("\n"))) - ) + action.setToolTip("

{}

".format(abstract)) else: if abstract != "" or title != "": - action.setToolTip( - "{}
{}".format( - title, "
".join(abstract.split("\n")) - ) - ) + action.setToolTip("{}
{}".format(title, abstract)) else: action.setToolTip("") @@ -395,9 +444,7 @@ def addMenuItem(self, uri, filename, node, menu, absolute, mapLayersDict): if self.optionTooltip: # search embeded maplayer (for title, abstract) - mapLayer = self.getMapLayerDomFromQgs( - efilename, layerId - ) + mapLayer = self.getMapLayerDomFromQgs(efilename, layerId) if mapLayer is not None: self.addToolTip(mapLayer, action) else: @@ -425,9 +472,7 @@ def addMenuItem(self, uri, filename, node, menu, absolute, mapLayersDict): # Add geometry type icon try: - map_layer = self.getMapLayerDomFromQgs( - efilename, layerId - ).toElement() + map_layer = self.getMapLayerDomFromQgs(efilename, layerId).toElement() geometry_type = map_layer.attribute("geometry") if geometry_type == "": # A TMS has not a geometry attribute. @@ -476,7 +521,10 @@ def addMenuItem(self, uri, filename, node, menu, absolute, mapLayersDict): doc, _ = self.getQgsDoc(efilename) groupNode = getFirstChildByAttrValue( - doc.documentElement(), "layer-tree-group", "name", name + doc.documentElement(), + "layer-tree-group", + "name", + name, ) # and do recursion @@ -520,7 +568,12 @@ def addMenuItem(self, uri, filename, node, menu, absolute, mapLayersDict): # ! recursion r = self.addMenuItem( - uri, filename, childNode, sousmenu, absolute, mapLayersDict + uri, + filename, + childNode, + sousmenu, + absolute, + mapLayersDict, ) if r and self.optionLoadAll and (len(sousmenu.actions()) > 1): @@ -601,7 +654,12 @@ def addMenu(self, name, uri, filepath, domdoc, location, previous=None): if node: node = node.firstChild() self.addMenuItem( - uri, filepath, node, projectMenu, is_absolute(domdoc), mapLayersDict + uri, + filepath, + node, + projectMenu, + is_absolute(domdoc), + mapLayersDict, ) return projectMenu @@ -678,7 +736,12 @@ def initMenus(self): uri = project["file"] doc, path = self.getQgsDoc(uri) previous = self.addMenu( - project["name"], uri, path, doc, project["location"], previous + project["name"], + uri, + path, + doc, + project["location"], + previous, ) except Exception as e: project["valid"] = False @@ -697,13 +760,9 @@ def initGui(self): self.iface.mainWindow(), ) - self.iface.addPluginToMenu( - "&" + __title__, self.action_project_configuration - ) + self.iface.addPluginToMenu("&" + __title__, self.action_project_configuration) # Add actions to the toolbar - self.action_project_configuration.triggered.connect( - self.open_projects_config - ) + self.action_project_configuration.triggered.connect(self.open_projects_config) # menu item - Documentation self.action_menu_help = QAction( @@ -840,7 +899,8 @@ def addLayer( plugins["db-style-manager"].load_style_from_database(theLayer) except Exception: self.log( - "DB-Style-Manager failed to load the style.", indent=loop + "DB-Style-Manager failed to load the style.", + indent=loop, ) # needed @@ -986,7 +1046,10 @@ def buildProjectRelation(self, doc, relDict): # Adapter le formulaire de la couche referencedLayer try: self.fixForm( - doc, relDict["referencedLayer"], oldRelationId, newRelationId + doc, + relDict["referencedLayer"], + oldRelationId, + newRelationId, ) except Exception: self.log( @@ -1001,9 +1064,7 @@ def buildProjectRelation(self, doc, relDict): for m in e.args: self.log(m) - def buildRelations( - self, uri, doc, oldLayerId, newLayerId, group, parentsLoop, loop - ): + def buildRelations(self, uri, doc, oldLayerId, newLayerId, group, parentsLoop, loop): """identify the relations to be created (later, after source layer creation) Based on those of the source project, adapted to the new identifiers of the layers @@ -1020,9 +1081,7 @@ def buildRelations( # La couche cible a déjà été ajoutée (boucle infinie) # on se contente de référencer celle-ci relDict["referencedLayer"] = newLayerId - relDict["referencingLayer"] = parentsLoop[ - relDict["referencingLayer"] - ] + relDict["referencingLayer"] = parentsLoop[relDict["referencingLayer"]] relationsToBuild.append(relDict) else: # la couche cible n'a pas été ajoutée @@ -1106,9 +1165,7 @@ def loadLayer(self, uri, fileName, layerId, menu=None, visible=None, expanded=No j.setJoinLayer(joinLayer) layer.addJoin(j) except Exception as e: - self.log( - "Joined layer {} not added.".format(j.joinLayerId()) - ) + self.log("Joined layer {} not added.".format(j.joinLayerId())) pass except Exception as e: diff --git a/menu_from_project/metadata.txt b/menu_from_project/metadata.txt index c583660..7af92bc 100644 --- a/menu_from_project/metadata.txt +++ b/menu_from_project/metadata.txt @@ -1,13 +1,14 @@ [general] name=Layers menu from project -qgisMinimumVersion=3.14 +qgisMinimumVersion=3.20 qgisMaximumVersion=3.98 description=Build layers shortcuts menus based on QGIS projects about=Allow easy opening of layers maintaining their style. -version=2.1.0 +version=2.2.0-beta1 changelog= + 2.2.0-beta1 : Layer notes as tooltip. Minimum Version is 3.20 2.1.0 : Support relations, fix #20 2.1.0-beta1 : #51 Support relations 2.0.8 : Minimum Version is 3.14 diff --git a/menu_from_project/ui/conf_dialog.ui b/menu_from_project/ui/conf_dialog.ui index b58ec2a..5dd7a72 100644 --- a/menu_from_project/ui/conf_dialog.ui +++ b/menu_from_project/ui/conf_dialog.ui @@ -9,7 +9,7 @@ 0 0 - 638 + 660 310 @@ -21,7 +21,7 @@ - 550 + 660 310 @@ -116,7 +116,7 @@ true - 21 + 23 false @@ -358,8 +358,11 @@ + + Show title && abstract in tooltip - click to move the item to the first position + - Show title && abstract in tooltip. Priority to : + Tooltip. Priority to : true @@ -370,32 +373,91 @@ - - - - 0 - 0 - + + + + 75 + true + + + + 1 : + + + + OGC QGis Server metadata - + + false + + + true + + + false + + true - - - - 0 - 0 - + + + + 75 + true + + + + 2 : + + + + + + + + true + Layer metadata + + true + + + + + + + + 75 + true + + + + 3 : + + + + + + + + true + + + + Layer notes + + + true + @@ -435,8 +497,6 @@ cbxCreateGroup cbxOpenLinks cbxShowTooltip - mdSourceOGC - mdSourceLayer diff --git a/menu_from_project/ui/menu_conf_dlg.py b/menu_from_project/ui/menu_conf_dlg.py index 26f03ba..f7f1935 100644 --- a/menu_from_project/ui/menu_conf_dlg.py +++ b/menu_from_project/ui/menu_conf_dlg.py @@ -30,7 +30,10 @@ # project from menu_from_project.__about__ import DIR_PLUGIN_ROOT, __title__, __version__ from menu_from_project.logic.custom_datatypes import TABLE_COLUMNS_ORDER -from menu_from_project.logic.tools import guess_type_from_uri, icon_per_storage_type +from menu_from_project.logic.tools import ( + guess_type_from_uri, + icon_per_storage_type, +) # ############################################################################ # ########## Globals ############### @@ -194,15 +197,16 @@ def __init__(self, parent, plugin): self.cbxOpenLinks.setCheckState(self.plugin.optionOpenLinks) self.cbxOpenLinks.setTristate(False) - self.mdSourceOGC.setChecked( - self.plugin.optionSourceMD == self.plugin.SOURCE_MD_OGC - ) - self.mdSourceLayer.setChecked( - self.plugin.optionSourceMD == self.plugin.SOURCE_MD_LAYER - ) + self.optionSourceMD = self.plugin.optionSourceMD + self.setSourceMdText() self.tableTunning() + def setSourceMdText(self): + self.mdSource1.setText(self.plugin.sourcesMdText[self.optionSourceMD[0]]) + self.mdSource2.setText(self.plugin.sourcesMdText[self.optionSourceMD[1]]) + self.mdSource3.setText(self.plugin.sourcesMdText[self.optionSourceMD[2]]) + def addEditButton(self, row, guess_type): """Add edit button, adapted to the type of resource @@ -239,13 +243,10 @@ def onFileSearchPressed(self, row: int): :type row: int """ file_widget = self.tableWidget.cellWidget(row, self.cols.uri) - item = self.tableWidget.item(row, 1) filePath = QFileDialog.getOpenFileName( self, - QgsApplication.translate( - "menu_from_project", "Projects configuration", None - ), + QgsApplication.translate("menu_from_project", "Projects configuration", None), file_widget.text(), QgsApplication.translate( "menu_from_project", "QGIS projects (*.qgs *.qgz)", None @@ -278,9 +279,7 @@ def onHttpSearchPressed(self, row: int): """ self.plugin.iface.messageBar().pushMessage( "Message", - self.tr( - "No HTTP Browser, simply paste your URL into the 'project' column." - ), + self.tr("No HTTP Browser, simply paste your URL into the 'project' column."), level=Qgis.Info, ) @@ -344,11 +343,8 @@ def onAccepted(self): self.plugin.optionLoadAll = self.cbxLoadAll.isChecked() self.plugin.optionCreateGroup = self.cbxCreateGroup.isChecked() self.plugin.optionOpenLinks = self.cbxOpenLinks.isChecked() - self.plugin.optionSourceMD = ( - self.plugin.SOURCE_MD_OGC - if self.mdSourceOGC.isChecked() - else self.plugin.SOURCE_MD_LAYER - ) + + self.plugin.optionSourceMD = self.optionSourceMD self.plugin.store() @@ -374,7 +370,9 @@ def onAdd(self, qgs_type_storage: str = "file"): # project storage type self.tableWidget.setCellWidget( - row, self.cols.type_storage, self.mk_prj_storage_icon(qgs_type_storage) + row, + self.cols.type_storage, + self.mk_prj_storage_icon(qgs_type_storage), ) # menu location @@ -384,9 +382,7 @@ def onAdd(self, qgs_type_storage: str = "file"): location_combo.addItem(self.LOCATIONS[pk]["label"], pk) location_combo.setCurrentIndex(0) - self.tableWidget.setCellWidget( - row, self.cols.type_menu_location, location_combo - ) + self.tableWidget.setCellWidget(row, self.cols.type_menu_location, location_combo) # project file path itemFile = QTableWidgetItem() @@ -544,6 +540,16 @@ def onTextChanged(self, text: str): self.plugin.log("Error during project reading: {}".format(err)) file_widget.setStyleSheet("color: {};".format("red")) + def on_mdSource2_released(self): + myorder = [1, 0, 2] + self.optionSourceMD = [self.optionSourceMD[i] for i in myorder] + self.setSourceMdText() + + def on_mdSource3_released(self): + myorder = [2, 0, 1] + self.optionSourceMD = [self.optionSourceMD[i] for i in myorder] + self.setSourceMdText() + def tableTunning(self): """Prettify table aspect""" # edit button