diff --git a/lizmap/dialogs/main.py b/lizmap/dialogs/main.py
index 964ba64b..babcf54c 100755
--- a/lizmap/dialogs/main.py
+++ b/lizmap/dialogs/main.py
@@ -133,7 +133,7 @@ def __init__(self, parent=None, is_dev_version=True):
"To know how to fix these checks, either use the tooltip (by hovering your mouse pointer on the table "
"row) in the last column '{column_name}', or check the documentation in the next tab "
"'{tab_name}' for all errors which can be reported."
- ).format(column_name=Headers.Error.label, tab_name=self.tab_log.tabText(1))
+ ).format(column_name=Headers().error.label, tab_name=self.tab_log.tabText(1))
)
auto_fix_panel = self.mOptionsListWidget.item(Panels.AutoFix).text()
self.label_autofix.setText(tr(
@@ -309,30 +309,32 @@ def __init__(self, parent=None, is_dev_version=True):
self.safe_number_parent.setValue(QgsSettings().value(Settings.key(Settings.NumberParentFolder), type=int))
self.safe_number_parent.valueChanged.connect(self.save_settings)
+ self.checks = Checks()
+
# Other drive
self.safe_other_drive.setChecked(QgsSettings().value(Settings.key(Settings.PreventDrive), type=bool))
self.safe_other_drive.toggled.connect(self.save_settings)
- self.safe_other_drive.setToolTip(Checks.PreventDrive.description)
+ self.safe_other_drive.setToolTip(self.checks.PreventDrive.description)
# PG Service
self.safe_pg_service.setChecked(QgsSettings().value(Settings.key(Settings.PreventPgService), type=bool))
self.safe_pg_service.toggled.connect(self.save_settings)
- self.safe_pg_service.setToolTip(Checks.PgService.description)
+ self.safe_pg_service.setToolTip(self.checks.PgService.description)
# PG Auth DB
self.safe_pg_auth_db.setChecked(QgsSettings().value(Settings.key(Settings.PreventPgAuthDb), type=bool))
self.safe_pg_auth_db.toggled.connect(self.save_settings)
- self.safe_pg_auth_db.setToolTip(Checks.AuthenticationDb.description)
+ self.safe_pg_auth_db.setToolTip(self.checks.AuthenticationDb.description)
# User password
self.safe_pg_user_password.setChecked(QgsSettings().value(Settings.key(Settings.ForcePgUserPass), type=bool))
self.safe_pg_user_password.toggled.connect(self.save_settings)
- self.safe_pg_user_password.setToolTip(Checks.PgForceUserPass.description)
+ self.safe_pg_user_password.setToolTip(self.checks.PgForceUserPass.description)
# ECW
self.safe_ecw.setChecked(QgsSettings().value(Settings.key(Settings.PreventEcw), type=bool))
self.safe_ecw.toggled.connect(self.save_settings)
- self.safe_ecw.setToolTip(Checks.PreventEcw.description)
+ self.safe_ecw.setToolTip(self.checks.PreventEcw.description)
msg = tr(
"Some safeguards are overridden by {host}. Even in 'normal' mode, some safeguards are becoming 'blocking' "
@@ -438,17 +440,21 @@ def visit_settings_panel(self):
def auto_fix_tooltip(self, lizmap_cloud):
""" Set some tooltips on these auto-fix buttons, according to Lizmap Cloud status. """
- self.label_pg_ssl.setToolTip(Checks.SSLConnection.html_tooltip(lizmap_cloud))
- self.button_convert_ssl.setToolTip(Checks.SSLConnection.html_tooltip(lizmap_cloud))
+ tooltip = self.checks.SSLConnection.html_tooltip(lizmap_cloud)
+ self.label_pg_ssl.setToolTip(tooltip)
+ self.button_convert_ssl.setToolTip(tooltip)
- self.label_pg_estimated.setToolTip(Checks.EstimatedMetadata.html_tooltip(lizmap_cloud))
- self.button_use_estimated_md.setToolTip(Checks.EstimatedMetadata.html_tooltip(lizmap_cloud))
+ tooltip = self.checks.EstimatedMetadata.html_tooltip(lizmap_cloud)
+ self.label_pg_estimated.setToolTip(tooltip)
+ self.button_use_estimated_md.setToolTip(tooltip)
- self.label_trust_project.setToolTip(Checks.TrustProject.html_tooltip(lizmap_cloud))
- self.button_trust_project.setToolTip(Checks.TrustProject.html_tooltip(lizmap_cloud))
+ tooltip = self.checks.TrustProject.html_tooltip(lizmap_cloud)
+ self.label_trust_project.setToolTip(tooltip)
+ self.button_trust_project.setToolTip(tooltip)
- self.label_simplify.setToolTip(Checks.SimplifyGeometry.html_tooltip(lizmap_cloud))
- self.button_simplify_geom.setToolTip(Checks.SimplifyGeometry.html_tooltip(lizmap_cloud))
+ tooltip = self.checks.SimplifyGeometry.html_tooltip(lizmap_cloud)
+ self.label_simplify.setToolTip(tooltip)
+ self.button_simplify_geom.setToolTip(tooltip)
def has_auto_fix(self) -> bool:
""" Return if an auto-fix is enabled. """
diff --git a/lizmap/plugin.py b/lizmap/plugin.py
index 5fb748b0..6f57f7dd 100755
--- a/lizmap/plugin.py
+++ b/lizmap/plugin.py
@@ -272,13 +272,15 @@ def __init__(self, iface, lwc_version: LwcVersions = None):
temp_dir = Path(tempfile.gettempdir()).joinpath('QGIS_Lizmap')
if not temp_dir.exists():
temp_dir.mkdir()
- file_handler = logging.FileHandler(temp_dir.joinpath("lizmap.log"))
- file_handler.setLevel(logging.DEBUG)
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
- file_handler.setFormatter(formatter)
- add_logging_handler_once(LOGGER, file_handler)
- LOGGER.debug(
- "The directory {0} is currently used for file logging.".format(temp_dir))
+
+ if not to_bool(os.getenv("CI"), default_value=False):
+ file_handler = logging.FileHandler(temp_dir.joinpath("lizmap.log"))
+ file_handler.setLevel(logging.DEBUG)
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ file_handler.setFormatter(formatter)
+ add_logging_handler_once(LOGGER, file_handler)
+ LOGGER.debug(
+ "The directory {0} is currently used for file logging.".format(temp_dir))
# All logs
def write_log_message(message, tag, level):
@@ -2916,7 +2918,7 @@ def project_config_file(
Severities,
SourceLayer,
)
-
+ checks = Checks()
valid, _ = self.check_project_validity()
if with_gui:
@@ -2933,13 +2935,13 @@ def project_config_file(
for name, count in duplicated_in_cfg.items():
if count >= 2:
source = '"{}" → "'.format(name) + tr("count {} layers").format(count)
- self.dlg.check_results.add_error(Error(source, Checks.DuplicatedLayerNameOrGroup))
+ self.dlg.check_results.add_error(Error(source, checks.DuplicatedLayerNameOrGroup))
# Layer ID as short name
if lwc_version >= LwcVersions.Lizmap_3_6:
use_layer_id, _ = self.project.readEntry('WMSUseLayerIDs', '/')
if to_bool(use_layer_id, False):
- self.dlg.check_results.add_error(Error(Path(self.project.fileName()).name, Checks.WmsUseLayerIds))
+ self.dlg.check_results.add_error(Error(Path(self.project.fileName()).name, checks.WmsUseLayerIds))
target_status = self.dlg.server_combo.currentData(ServerComboData.LwcBranchStatus.value)
if not target_status:
@@ -3017,16 +3019,18 @@ def project_config_file(
self.dlg.log_panel.append("
")
+ severities = Severities()
+
for layer, error in results.items():
# Severity depends on beginner mode
- severity = Severities.Blocking if beginner_mode else Severities.Important
+ severity = severities.blocking if beginner_mode else severities.important
# But override severities for Lizmap Cloud
# Because even with a 'normal' user, it won't work
override = (
- Checks.PreventEcw, Checks.PgForceUserPass, Checks.AuthenticationDb, Checks.PreventDrive)
+ checks.PreventEcw, checks.PgForceUserPass, checks.AuthenticationDb, checks.PreventDrive)
if error in override:
- severity = Severities.Blocking
+ severity = severities.bocking
self.dlg.check_results.add_error(
Error(
@@ -3059,7 +3063,7 @@ def project_config_file(
self.dlg.check_results.add_error(
Error(
layer.name,
- Checks.SSLConnection,
+ checks.SSLConnection,
source_type=SourceLayer(layer.name, layer.layer_id),
)
)
@@ -3070,7 +3074,7 @@ def project_config_file(
self.dlg.check_results.add_error(
Error(
layer.name,
- Checks.MissingPk,
+ checks.MissingPk,
source_type=SourceLayer(layer.name, layer.layer_id),
)
)
@@ -3078,7 +3082,7 @@ def project_config_file(
self.dlg.check_results.add_error(
Error(
layer.name,
- Checks.PkInt8,
+ checks.PkInt8,
source_type=SourceLayer(layer.name, layer.layer_id),
)
)
@@ -3100,7 +3104,7 @@ def project_config_file(
self.dlg.check_results.add_error(
Error(
layer.name,
- Checks.SimplifyGeometry,
+ checks.SimplifyGeometry,
source_type=SourceLayer(layer.name, layer.layer_id),
)
)
@@ -3111,14 +3115,14 @@ def project_config_file(
self.dlg.check_results.add_error(
Error(
layer.name,
- Checks.EstimatedMetadata,
+ checks.EstimatedMetadata,
source_type=SourceLayer(layer.name, layer.layer_id),
)
)
self.dlg.enabled_estimated_md_button(True)
if not project_trust_layer_metadata(self.project):
- self.dlg.check_results.add_error(Error(Path(self.project.fileName()).name, Checks.TrustProject))
+ self.dlg.check_results.add_error(Error(Path(self.project.fileName()).name, checks.TrustProject))
self.dlg.enabled_trust_project(True)
# Not blocking, we change it in the background
@@ -3576,7 +3580,7 @@ def check_project_validity(self):
self.dlg.check_results.add_error(
Error(
Path(self.project.fileName()).name,
- Checks.OgcValid,
+ Checks().OgcValid,
)
)
@@ -3697,9 +3701,10 @@ def save_cfg_file(
server_metadata = self.dlg.server_combo.currentData(ServerComboData.JsonMetadata.value)
self.dlg.check_results.truncate()
beginner_mode = QgsSettings().value(Settings.key(Settings.BeginnerMode), True, bool)
+ severities = Severities()
self.dlg.html_help.setHtml(
- Checks.html(
- severity=Severities.Blocking if beginner_mode else Severities.Important,
+ Checks().html(
+ severity=severities.blocking if beginner_mode else severities.important,
lizmap_cloud=is_lizmap_cloud(server_metadata)
)
)
diff --git a/lizmap/project_checker_tools.py b/lizmap/project_checker_tools.py
index 1ca4195a..499957f1 100644
--- a/lizmap/project_checker_tools.py
+++ b/lizmap/project_checker_tools.py
@@ -57,24 +57,25 @@ def project_safeguards_checks(
# Do not use homePath, it's not designed for this if the user has set a custom home path
project_home = Path(project.absolutePath())
results = {}
+ checks = Checks()
for layer in project.mapLayers().values():
if isinstance(layer, QgsRasterLayer):
if layer.source().lower().endswith('ecw') and prevent_ecw:
- results[SourceLayer(layer.name(), layer.id())] = Checks.PreventEcw
+ results[SourceLayer(layer.name(), layer.id())] = checks.PreventEcw
if is_vector_pg(layer):
# Make a copy by using a string, so we are sure to have user or password
datasource = QgsDataSourceUri(layer.source())
if datasource.authConfigId() != '' and prevent_auth_id:
- results[SourceLayer(layer.name(), layer.id())] = Checks.AuthenticationDb
+ results[SourceLayer(layer.name(), layer.id())] = checks.AuthenticationDb
# We can continue
continue
if datasource.service() != '' and prevent_service:
- results[SourceLayer(layer.name(), layer.id())] = Checks.PgService
+ results[SourceLayer(layer.name(), layer.id())] = checks.PgService
# We can continue
continue
@@ -82,7 +83,7 @@ def project_safeguards_checks(
if not datasource.service():
if datasource.host().endswith(CLOUD_DOMAIN) or force_pg_user_pass:
if not datasource.username() or not datasource.password():
- results[SourceLayer(layer.name(), layer.id())] = Checks.PgForceUserPass
+ results[SourceLayer(layer.name(), layer.id())] = checks.PgForceUserPass
# We can continue
continue
@@ -107,7 +108,7 @@ def project_safeguards_checks(
# For instance, H: and C:
if lizmap_cloud or prevent_other_drive:
- results[SourceLayer(layer.name(), layer.id())] = Checks.PreventDrive
+ results[SourceLayer(layer.name(), layer.id())] = checks.PreventDrive
continue
# Not sure what to do for now...
@@ -117,11 +118,11 @@ def project_safeguards_checks(
if allow_parent_folder:
# The user allow parent folder, so we check against the string provided in the function call
if parent_folder in relative_path:
- results[SourceLayer(layer.name(), layer.id())] = Checks.PreventParentFolder
+ results[SourceLayer(layer.name(), layer.id())] = checks.PreventParentFolder
else:
# The user wants only local files, we only check for ".."
if '..' in relative_path:
- results[SourceLayer(layer.name(), layer.id())] = Checks.PreventParentFolder
+ results[SourceLayer(layer.name(), layer.id())] = checks.PreventParentFolder
return results
@@ -348,12 +349,12 @@ def trailing_layer_group_name(layer_tree: QgsLayerTreeNode, project, results: Li
layer = project.mapLayer(child.layerId())
if layer.name().strip() != layer.name():
results.append(
- Error(layer.name(), Checks.LeadingTrailingSpaceLayerGroupName, SourceLayer(layer.name(), layer.id())))
+ Error(layer.name(), Checks().LeadingTrailingSpaceLayerGroupName, SourceLayer(layer.name(), layer.id())))
else:
child = cast_to_group(child)
if child.name().strip() != child.name():
results.append(
- Error(child.name(), Checks.LeadingTrailingSpaceLayerGroupName, SourceGroup))
+ Error(child.name(), Checks().LeadingTrailingSpaceLayerGroupName, SourceGroup))
# Recursive call
results = trailing_layer_group_name(child, project, results)
diff --git a/lizmap/test/test_table_checks.py b/lizmap/test/test_table_checks.py
index 01786fc5..c65206cf 100644
--- a/lizmap/test/test_table_checks.py
+++ b/lizmap/test/test_table_checks.py
@@ -17,10 +17,11 @@ def test(self):
self.assertEqual(table.verticalHeader().count(), 0)
self.assertEqual(table.rowCount(), 0)
+ checks = Checks()
- table.add_error(Error('my-tailor-is-rich', Checks.DuplicatedLayerNameOrGroup))
- table.add_error(Error('home-sweet-home', Checks.DuplicatedLayerNameOrGroup))
- table.add_error(Error('home-sweet-home', Checks.MissingPk))
+ table.add_error(Error('my-tailor-is-rich', checks.DuplicatedLayerNameOrGroup))
+ table.add_error(Error('home-sweet-home', checks.DuplicatedLayerNameOrGroup))
+ table.add_error(Error('home-sweet-home', checks.MissingPk))
self.assertEqual(table.rowCount(), 3)
expected = [
diff --git a/lizmap/widgets/check_project.py b/lizmap/widgets/check_project.py
index d2bfac2e..a257ff4c 100644
--- a/lizmap/widgets/check_project.py
+++ b/lizmap/widgets/check_project.py
@@ -2,7 +2,6 @@
__license__ = 'GPL version 3'
__email__ = 'info@3liz.org'
-from enum import Enum
from qgis.core import (
QgsMapLayerModel,
@@ -34,12 +33,19 @@ def __init__(self, data: str, label: str, tooltip: str):
self.tooltip = tooltip
-class Headers(Header, Enum):
+class Headers:
""" List of headers in the table. """
- Severity = 'severity', tr('Severity'), tr("Severity of the error")
- Level = 'level', tr('Level'), tr("Level of the error")
- Object = 'source', tr('Source'), tr("Source of the error")
- Error = 'error', tr('Error'), tr('Description of the error')
+
+ def __init__(self):
+ self.members = []
+ self.severity = Header('severity', tr('Severity'), tr("Severity of the error"))
+ self.level = Header('level', tr('Level'), tr("Level of the error"))
+ self.source = Header('source', tr('Source'), tr("Source of the error"))
+ self.error = Header('error', tr('Error'), tr('Description of the error'))
+ self.members.append(self.severity)
+ self.members.append(self.level)
+ self.members.append(self.source)
+ self.members.append(self.error)
class Severity:
@@ -70,14 +76,26 @@ def __str__(self):
return f''
-class Severities(Severity, Enum):
+class Severities:
""" List of severities. """
- Blocking = 0, tr('Blocking'), tr('This is blocking the Lizmap configuration file'), 'red', 3
- Important = 1, tr('Important'), tr('This is important to fix, to improve performance'), 'orange', 2.5
- # Normal = 2, tr('Normal'), tr('This would be nice to have look'), 'blue', 2
- Low = 3, tr('Low'), tr('Nice to do'), 'yellow', 2
- # Some severities can only done on runtime, QGIS version and/or Lizmap Cloud
- Unknown = 99, 'Unknown', 'Severity will be determined on runtime', 'green', 1
+ def __init__(self):
+ self.members = []
+ self.blocking = Severity(
+ 0, tr('Blocking'), tr('This is blocking the Lizmap configuration file'), 'red', 3)
+ self.important = Severity(
+ 1, tr('Important'), tr('This is important to fix, to improve performance'), 'orange', 2.5)
+ self.normal = Severity(
+ 2, tr('Normal'), tr('This would be nice to have look'), 'blue', 2)
+ self.low = Severity(
+ 3, tr('Low'), tr('Nice to do'), 'yellow', 2)
+ # Some severities can only done on runtime, QGIS version and/or Lizmap Cloud
+ self.unknown = Severity(
+ 99, 'Unknown', 'Severity will be determined on runtime', 'green', 1)
+ self.members.append(self.blocking)
+ self.members.append(self.important)
+ self.members.append(self.normal)
+ self.members.append(self.low)
+ self.members.append(self.unknown)
class Level:
@@ -162,6 +180,7 @@ def html_help(self, index: int, severity: Severity, lizmap_cloud: False) -> str:
if index % 2:
row_class = "class=\"odd-row\""
+ severities = Severities()
html_str = (
""
"{title} | "
@@ -176,7 +195,7 @@ def html_help(self, index: int, severity: Severity, lizmap_cloud: False) -> str:
description=self.description_text(lizmap_cloud),
how_to_fix=self.help_text(lizmap_cloud),
level=self.level.label,
- severity=severity.label if self.severity == Severities.Unknown else self.severity.label,
+ severity=severity.label if self.severity == severities.unknown else self.severity.label,
)
return html_str
@@ -196,394 +215,393 @@ def __str__(self):
return f'<{self.title} : {self.description_text(False)} :{self.level} → {self.severity}>'
-# Check QGIS_VERSION_INT
-qgis_32200 = tr(
- 'With QGIS ≥ 3.22, you can use the auto-fix button in the "Settings" panel of the plugin to fix currently loaded '
- 'layers'
-)
-other_auth = tr('Either switch to another authentication mechanism')
-safeguard = tr('Or disable this safeguard in your Lizmap plugin settings')
-global_connection = tr(
- 'To fix layers loaded later, edit your global PostgreSQL connection to enable this option, then change the '
- 'datasource by right clicking on each layer above, then click "Change datasource" in the menu. Finally reselect '
- 'your layer in the new dialog with the updated connection. When opening a QGIS project in your computer, with a '
- 'fresh launched QGIS software, you mustn\'t have any prompt for a user or password. '
- 'The edited connection will take effect only on newly added layer into a project that\'s why the right-click step '
- 'is required.'
-)
-either_move_file = tr('Either move the file used for the layer')
-move_file = tr('Move the file used for the layer')
-
-
-class Checks(Check, Enum):
+class Checks:
""" List of checks defined. """
- OgcValid = (
- 'ogc_validity',
- tr('OGC validity (QGIS server)'),
- tr(
- "According to OGC standard, the project is not valid."
- ),
- (
- ''
- '- {project_properties}
'
- '- {project_shortname}
'
- '- {layer_shortname}
'
- '
'
- ).format(
- project_properties=tr(
- "Open the 'Project properties', then 'QGIS Server' tab, at the bottom, you can check your project "
- "according to OGC standard"
+ def __init__(self):
+ # Check QGIS_VERSION_INT
+ qgis_32200 = tr(
+ 'With QGIS ≥ 3.22, you can use the auto-fix button in the "Settings" panel of the plugin to fix currently '
+ 'loaded layers'
+ )
+ other_auth = tr('Either switch to another authentication mechanism')
+ safeguard = tr('Or disable this safeguard in your Lizmap plugin settings')
+ global_connection = tr(
+ 'To fix layers loaded later, edit your global PostgreSQL connection to enable this option, then '
+ 'change the datasource by right clicking on each layer above, then click "Change datasource" in the menu. '
+ 'Finally reselect your layer in the new dialog with the updated connection. When opening a QGIS project in '
+ 'your computer, with a fresh launched QGIS software, you mustn\'t have any prompt for a user or password. '
+ 'The edited connection will take effect only on newly added layer into a project that\'s why the '
+ 'right-click step is required.'
+ )
+ either_move_file = tr('Either move the file used for the layer')
+ move_file = tr('Move the file used for the layer')
+
+ self.OgcValid = Check(
+ 'ogc_validity',
+ tr('OGC validity (QGIS server)'),
+ tr(
+ "According to OGC standard, the project is not valid."
),
- layer_shortname=tr(
- "If you need to fix a layer shortname, go to the 'Layer properties' "
- "for the given layer, then 'QGIS Server' tab, edit the shortname."
+ (
+ ''
+ '- {project_properties}
'
+ '- {project_shortname}
'
+ '- {layer_shortname}
'
+ '
'
+ ).format(
+ project_properties=tr(
+ "Open the 'Project properties', then 'QGIS Server' tab, at the bottom, you can check your project "
+ "according to OGC standard"
+ ),
+ layer_shortname=tr(
+ "If you need to fix a layer shortname, go to the 'Layer properties' "
+ "for the given layer, then 'QGIS Server' tab, edit the shortname."
+ ),
+ project_shortname=tr(
+ "If you need to fix the project shortname, go to the 'Project properties', "
+ "then 'QGIS Server' tab, first tab, and change the shortname."
+ ),
),
- project_shortname=tr(
- "If you need to fix the project shortname, go to the 'Project properties', "
- "then 'QGIS Server' tab, first tab, and change the shortname."
+ Levels.Project,
+ Severities().low,
+ QIcon(':/images/themes/default/mIconWms.svg'),
+ )
+ self.PkInt8 = Check(
+ 'primary_key_bigint',
+ tr('Invalid bigint (integer8) field for QGIS Server as primary key'),
+ tr(
+ "Primary key should be an integer. If not fixed, expect layer to have some issues with some tools in "
+ "Lizmap Web Client: zoom to feature, filtering…"
),
- ),
- Levels.Project,
- Severities.Low,
- QIcon(':/images/themes/default/mIconWms.svg'),
- )
- PkInt8 = (
- 'primary_key_bigint',
- tr('Invalid bigint (integer8) field for QGIS Server as primary key'),
- tr(
- "Primary key should be an integer. If not fixed, expect layer to have some issues with some tools in "
- "Lizmap Web Client: zoom to feature, filtering…"
- ),
- (
- ''
- ).format(
- help=tr(
- "We highly recommend you to set a proper integer field as a primary key, but neither a bigint nor "
- "an integer8."
+ (
+ ''
+ ).format(
+ help=tr(
+ "We highly recommend you to set a proper integer field as a primary key, but neither a bigint nor "
+ "an integer8."
+ ),
),
- ),
- Levels.Layer,
- Severities.Important,
- QIcon(':/images/themes/default/mIconFieldInteger.svg'),
- )
- MissingPk = (
- 'missing_primary_key',
- tr('Missing a proper primary key in the database.'),
- tr(
- "The layer must have a proper primary key defined. When it's missing, QGIS Desktop tried to set a "
- "temporary field called 'tid/ctid/…' to be a unique identifier. On QGIS Server, this will bring issues."
- ),
- (
- ''
- ).format(
- help=tr(
- "We highly recommend you to set a proper integer field as a primary key, but neither a bigint nor "
- "an integer8."
+ Levels.Layer,
+ Severities().important,
+ QIcon(':/images/themes/default/mIconFieldInteger.svg'),
+ )
+ self.MissingPk = Check(
+ 'missing_primary_key',
+ tr('Missing a proper primary key in the database.'),
+ tr(
+ "The layer must have a proper primary key defined. When it's missing, QGIS Desktop tried to set a "
+ "temporary field called 'tid/ctid/…' to be a unique identifier. On QGIS Server, this will bring issues."
),
- ),
- Levels.Layer,
- Severities.Important,
- QIcon(':/images/themes/default/mSourceFields.svg'),
- )
- SSLConnection = (
- 'ssl_connection',
- tr('SSL connections to a PostgreSQL database'),
- tr("Connections to a PostgreSQL database hosted on {} must use a SSL secured connection.").format(CLOUD_NAME),
- (
- ''
- '- {auto_fix}
'
- '- {help}
'
- '
'
- ).format(
- auto_fix=qgis_32200,
- help=global_connection,
- ),
- Levels.Layer,
- Severities.Blocking if qgis_version() >= 32200 else Severities.Important,
- QIcon(':/images/themes/default/mIconPostgis.svg'),
- )
- EstimatedMetadata = (
- 'estimated_metadata',
- tr('Estimated metadata'),
- tr("PostgreSQL layer can have the use estimated metadata option enabled"),
- (
- ''
- '- {auto_fix}
'
- '- {help}
'
- '
'
- ).format(
- auto_fix=qgis_32200,
- help=global_connection,
- ),
- Levels.Layer,
- Severities.Blocking if qgis_version() >= 32200 else Severities.Important,
- QIcon(':/images/themes/default/mIconPostgis.svg'),
- )
- SimplifyGeometry = (
- 'simplify_geometry',
- tr('Simplify geometry on the provider side'),
- tr("PostgreSQL layer can have the geometry simplification on the server side enabled"),
- (
- ''
- '- {auto_fix}
'
- '- {help}
'
- '
'
- ).format(
- auto_fix=qgis_32200,
- help=tr(
- 'Visit the layer properties, then in the "Rendering" tab to enable it simplification on the provider '
- 'side on the given layer.'
+ (
+ ''
+ ).format(
+ help=tr(
+ "We highly recommend you to set a proper integer field as a primary key, but neither a bigint nor "
+ "an integer8."
+ ),
),
- ),
- Levels.Layer,
- Severities.Blocking if qgis_version() >= 32200 else Severities.Important,
- QIcon(':/images/themes/default/mIconGeometryCollectionLayer.svg'),
- )
- DuplicatedLayerNameOrGroup = (
- 'duplicated_layer_name_or_group',
- tr('Duplicated layer name or group'),
- tr("It's not possible to store all the Lizmap configuration for these layer(s) or group(s)."),
- (
- ''
- ).format(
- tr('You must change them to make them unique'),
- tr('Reconfigure their settings in the "Layers" tab of the plugin')
- ),
- Levels.Project,
- Severities.Important,
- QIcon(':/images/themes/default/propertyicons/editmetadata.svg'),
- )
- WmsUseLayerIds = (
- 'wms_use_layer_id',
- tr('Do not use layer IDs as name'),
- tr(
- "It's not possible anymore to use the option 'Use layer IDs as name' in the project properties dialog, "
- "QGIS server tab, then WMS capabilities."
- ),
- ''.format(
- help=tr("Uncheck this checkbox and re-save the Lizmap configuration file")
- ),
- Levels.Project,
- Severities.Blocking,
- QIcon(':/images/themes/default/mIconWms.svg'),
- )
- TrustProject = (
- 'trust_project_metadata',
- tr('Trust project metadata'),
- tr('The project does not have the "Trust project metadata" enabled at the project level'),
- (
- ''
- '- {auto_fix}
'
- '- {help}
'
- '
'.format(
+ Levels.Layer,
+ Severities().important,
+ QIcon(':/images/themes/default/mSourceFields.svg'),
+ )
+ self.SSLConnection = Check(
+ 'ssl_connection',
+ tr('SSL connections to a PostgreSQL database'),
+ tr("Connections to a PostgreSQL database hosted on {} must use a SSL secured connection.").format(CLOUD_NAME),
+ (
+ ''
+ '- {auto_fix}
'
+ '- {help}
'
+ '
'
+ ).format(
+ auto_fix=qgis_32200,
+ help=global_connection,
+ ),
+ Levels.Layer,
+ Severities().blocking if qgis_version() >= 32200 else Severities().important,
+ QIcon(':/images/themes/default/mIconPostgis.svg'),
+ )
+ self.EstimatedMetadata = Check(
+ 'estimated_metadata',
+ tr('Estimated metadata'),
+ tr("PostgreSQL layer can have the use estimated metadata option enabled"),
+ (
+ ''
+ '- {auto_fix}
'
+ '- {help}
'
+ '
'
+ ).format(
+ auto_fix=qgis_32200,
+ help=global_connection,
+ ),
+ Levels.Layer,
+ Severities().blocking if qgis_version() >= 32200 else Severities().important,
+ QIcon(':/images/themes/default/mIconPostgis.svg'),
+ )
+ self.SimplifyGeometry = Check(
+ 'simplify_geometry',
+ tr('Simplify geometry on the provider side'),
+ tr("PostgreSQL layer can have the geometry simplification on the server side enabled"),
+ (
+ ''
+ '- {auto_fix}
'
+ '- {help}
'
+ '
'
+ ).format(
+ auto_fix=qgis_32200,
help=tr(
- 'In the project properties → Data sources → at the bottom, there is a checkbox to trust the '
- 'project when the layer has no metadata.'
+ 'Visit the layer properties, then in the "Rendering" tab to enable it simplification on the provider '
+ 'side on the given layer.'
),
- auto_fix=tr('With QGIS ≥ 3.22, you can use the auto-fix button in the "Settings" panel of the plugin'),
- )
- ),
- Levels.Project,
- Severities.Blocking if qgis_version() >= 32200 else Severities.Important,
- QIcon(':/images/themes/default/mIconQgsProjectFile.svg'),
- )
- LeadingTrailingSpaceLayerGroupName = (
- 'leading_trailing_space',
- tr('Leading/trailing space in layer/group name'),
- tr(
- 'The layer/group name has some leading/trailing spaces. It must be removed and the configuration in the '
- 'plugin might be needed.'
- ), (
- ''.format(
- edit_layer=tr('Rename your layer/group to remove leading/trailing spaces (left and right)'),
- )
- ),
- Levels.Layer,
- Severities.Blocking,
- QIcon(':/images/themes/default/algorithms/mAlgorithmMergeLayers.svg'),
- )
- PreventEcw = (
- Settings.PreventEcw,
- tr('ECW raster'),
- tr(
- 'The layer is using the ECW raster format. Because of the ECW\'s licence, this format is not compatible '
- 'with most of QGIS server installations. You have activated a safeguard about preventing you using an '
- 'ECW layer.'),
- (
- ''
- '- {help}
'
- '- {other}
'
- '
'.format(
- help=tr('Either switch to a COG format'),
- other=safeguard,
- )
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/images/themes/default/mIconRasterLayer.svg'),
- tr(
- 'The layer is using an ECW raster format. Because of the ECW\'s licence, this format is not compatible '
- 'with QGIS server.'
- ),
- (
- ''
- ).format(help=tr('Switch to a COG format'))
- )
- AuthenticationDb = (
- Settings.PreventPgAuthDb,
- tr('QGIS Authentication database'),
- tr(
- 'The layer is using the QGIS authentication database. You have activated a safeguard preventing you using '
- 'the QGIS authentication database.'
- ),
- (
- ''
- '- {help}
'
- '- {other}
'
- '- {global_connection}
'
- '
'.format(
- help=other_auth,
- other=safeguard,
- global_connection=global_connection,
- )
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/images/themes/default/mIconPostgis.svg'),
- tr('The layer is using the QGIS authentication database. This is not compatible with {}').format(CLOUD_NAME),
- (
- ''
- '- {service}
'
- '- {login_pass}
'
- '
'
- ).format(
- service=tr('Either use a PostgreSQL service'),
- login_pass=tr('Or store the login and password in the layer.')
+ ),
+ Levels.Layer,
+ Severities().blocking if qgis_version() >= 32200 else Severities().important,
+ QIcon(':/images/themes/default/mIconGeometryCollectionLayer.svg'),
)
- )
- PgService = (
- Settings.PreventPgService,
- tr('PostgreSQL service'),
- tr(
- 'Using a PostgreSQL service file is recommended in many cases, but it requires a configuration step. '
- 'If you have done the configuration (on the server side mainly), you can disable this safeguard.'
- ),
- (
- ''
- '- {help}
'
- '- {other}
'
- '- {doc}
'
- '- {global_connection}
'
- '
'.format(
- help=other_auth,
- other=safeguard,
- doc=pg_service_help().toString(), # Sorry, the link is not easily clickable in a QTextEdit
- global_connection=global_connection,
- )
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/images/themes/default/mIconPostgis.svg'),
- )
- PgForceUserPass = (
- Settings.ForcePgUserPass,
- tr('PostgreSQL user and/or password'),
- tr(
- 'The layer is missing some credentials, either user and/or password.'
- ),
- (
- ''
- '- {edit_layer}
'
- '- {help}
'
- '- {other}
'
- '- {global_connection}
'
- '
'.format(
- edit_layer=tr('Edit your layer configuration by force saving user&password'),
- help=other_auth,
- other=safeguard,
- global_connection=global_connection,
+ self.DuplicatedLayerNameOrGroup = Check(
+ 'duplicated_layer_name_or_group',
+ tr('Duplicated layer name or group'),
+ tr("It's not possible to store all the Lizmap configuration for these layer(s) or group(s)."),
+ (
+ ''
+ ).format(
+ tr('You must change them to make them unique'),
+ tr('Reconfigure their settings in the "Layers" tab of the plugin')
+ ),
+ Levels.Project,
+ Severities().important,
+ QIcon(':/images/themes/default/propertyicons/editmetadata.svg'),
+ )
+ self.WmsUseLayerIds = Check(
+ 'wms_use_layer_id',
+ tr('Do not use layer IDs as name'),
+ tr(
+ "It's not possible anymore to use the option 'Use layer IDs as name' in the project properties dialog, "
+ "QGIS server tab, then WMS capabilities."
+ ),
+ ''.format(
+ help=tr("Uncheck this checkbox and re-save the Lizmap configuration file")
+ ),
+ Levels.Project,
+ Severities().blocking,
+ QIcon(':/images/themes/default/mIconWms.svg'),
+ )
+ self.TrustProject = Check(
+ 'trust_project_metadata',
+ tr('Trust project metadata'),
+ tr('The project does not have the "Trust project metadata" enabled at the project level'),
+ (
+ ''
+ '- {auto_fix}
'
+ '- {help}
'
+ '
'.format(
+ help=tr(
+ 'In the project properties → Data sources → at the bottom, there is a checkbox to trust the '
+ 'project when the layer has no metadata.'
+ ),
+ auto_fix=tr('With QGIS ≥ 3.22, you can use the auto-fix button in the "Settings" panel of the plugin'),
+ )
+ ),
+ Levels.Project,
+ Severities().blocking if qgis_version() >= 32200 else Severities().important,
+ QIcon(':/images/themes/default/mIconQgsProjectFile.svg'),
+ )
+ self.LeadingTrailingSpaceLayerGroupName = Check(
+ 'leading_trailing_space',
+ tr('Leading/trailing space in layer/group name'),
+ tr(
+ 'The layer/group name has some leading/trailing spaces. It must be removed and the configuration in the '
+ 'plugin might be needed.'
+ ), (
+ ''.format(
+ edit_layer=tr('Rename your layer/group to remove leading/trailing spaces (left and right)'),
+ )
+ ),
+ Levels.Layer,
+ Severities().blocking,
+ QIcon(':/images/themes/default/algorithms/mAlgorithmMergeLayers.svg'),
+ )
+ self.PreventEcw = Check(
+ Settings.PreventEcw,
+ tr('ECW raster'),
+ tr(
+ 'The layer is using the ECW raster format. Because of the ECW\'s licence, this format is not compatible '
+ 'with most of QGIS server installations. You have activated a safeguard about preventing you using an '
+ 'ECW layer.'),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '
'.format(
+ help=tr('Either switch to a COG format'),
+ other=safeguard,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/images/themes/default/mIconRasterLayer.svg'),
+ tr(
+ 'The layer is using an ECW raster format. Because of the ECW\'s licence, this format is not compatible '
+ 'with QGIS server.'
+ ),
+ (
+ ''
+ ).format(help=tr('Switch to a COG format'))
+ )
+ self.AuthenticationDb = Check(
+ Settings.PreventPgAuthDb,
+ tr('QGIS Authentication database'),
+ tr(
+ 'The layer is using the QGIS authentication database. You have activated a safeguard preventing you using '
+ 'the QGIS authentication database.'
+ ),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '- {global_connection}
'
+ '
'.format(
+ help=other_auth,
+ other=safeguard,
+ global_connection=global_connection,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/images/themes/default/mIconPostgis.svg'),
+ tr('The layer is using the QGIS authentication database. This is not compatible with {}').format(CLOUD_NAME),
+ (
+ ''
+ '- {service}
'
+ '- {login_pass}
'
+ '
'
+ ).format(
+ service=tr('Either use a PostgreSQL service'),
+ login_pass=tr('Or store the login and password in the layer.')
)
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/images/themes/default/mIconPostgis.svg'),
- )
- PreventDrive = (
- Settings.PreventDrive,
- tr('Other drive (network or local)'),
- tr('The layer is stored on another drive.'),
- (
- ''
- '- {help}
'
- '- {other}
'
- '
'.format(
- help=either_move_file,
- other=safeguard,
+ )
+ self.PgService = Check(
+ Settings.PreventPgService,
+ tr('PostgreSQL service'),
+ tr(
+ 'Using a PostgreSQL service file is recommended in many cases, but it requires a configuration step. '
+ 'If you have done the configuration (on the server side mainly), you can disable this safeguard.'
+ ),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '- {doc}
'
+ '- {global_connection}
'
+ '
'.format(
+ help=other_auth,
+ other=safeguard,
+ doc=pg_service_help().toString(), # Sorry, the link is not easily clickable in a QTextEdit
+ global_connection=global_connection,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/images/themes/default/mIconPostgis.svg'),
+ )
+ self.PgForceUserPass = Check(
+ Settings.ForcePgUserPass,
+ tr('PostgreSQL user and/or password'),
+ tr(
+ 'The layer is missing some credentials, either user and/or password.'
+ ),
+ (
+ ''
+ '- {edit_layer}
'
+ '- {help}
'
+ '- {other}
'
+ '- {global_connection}
'
+ '
'.format(
+ edit_layer=tr('Edit your layer configuration by force saving user&password'),
+ help=other_auth,
+ other=safeguard,
+ global_connection=global_connection,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/images/themes/default/mIconPostgis.svg'),
+ )
+ self.PreventDrive = Check(
+ Settings.PreventDrive,
+ tr('Other drive (network or local)'),
+ tr('The layer is stored on another drive.'),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '
'.format(
+ help=either_move_file,
+ other=safeguard,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/qt-project.org/styles/commonstyle/images/networkdrive-16.png'),
+ tr('The layer is stored on another drive, which is not possible using {}.').format(CLOUD_NAME),
+ (
+ ''
+ ).format(
+ help=move_file,
)
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/qt-project.org/styles/commonstyle/images/networkdrive-16.png'),
- tr('The layer is stored on another drive, which is not possible using {}.').format(CLOUD_NAME),
- (
- ''
- ).format(
- help=move_file,
)
- )
- PreventParentFolder = (
- Settings.AllowParentFolder,
- tr('Parent folder'),
- tr('The layer is stored in too many parent\'s folder, compare to the QGS file.'),
- (
- ''
- '- {help}
'
- '- {other}
'
- '
'.format(
+ self.PreventParentFolder = Check(
+ Settings.AllowParentFolder,
+ tr('Parent folder'),
+ tr('The layer is stored in too many parent\'s folder, compare to the QGS file.'),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '
'.format(
+ help=either_move_file,
+ other=safeguard,
+ )
+ ),
+ Levels.Layer,
+ Severities().unknown,
+ QIcon(':/images/themes/default/mIconFolderOpen.svg'),
+ tr('The layer is stored in too many parent\'s folder, compare to the QGS file.'),
+ (
+ ''
+ '- {help}
'
+ '- {other}
'
+ '- {fyi}
'
+ '
'
+ ).format(
help=either_move_file,
other=safeguard,
+ fyi=tr(
+ 'For your information, the maximum of parents is {count} on {hosting_name}. This will be overriden '
+ 'on runtime if you use a higher value according to the server selected in the first panel.'
+ ).format(
+ count=CLOUD_MAX_PARENT_FOLDER,
+ hosting_name=CLOUD_NAME
+ ),
)
- ),
- Levels.Layer,
- Severities.Unknown,
- QIcon(':/images/themes/default/mIconFolderOpen.svg'),
- tr('The layer is stored in too many parent\'s folder, compare to the QGS file.'),
- (
- ''
- '- {help}
'
- '- {other}
'
- '- {fyi}
'
- '
'
- ).format(
- help=either_move_file,
- other=safeguard,
- fyi=tr(
- 'For your information, the maximum of parents is {count} on {hosting_name}. This will be overriden '
- 'on runtime if you use a higher value according to the server selected in the first panel.'
- ).format(
- count=CLOUD_MAX_PARENT_FOLDER,
- hosting_name=CLOUD_NAME
- ),
)
- )
- @classmethod
- def html(cls, severity: Severity, lizmap_cloud: bool) -> str:
+ def html(self, severity: Severity, lizmap_cloud: bool) -> str:
""" Generate an HTML table, according to the instance. """
html_str = ''
html_str += (
@@ -595,8 +613,9 @@ def html(cls, severity: Severity, lizmap_cloud: bool) -> str:
level=tr('Level'),
severity=tr('Severity'),
)
- copy_sort = list(cls.__members__.values())
- copy_sort.sort(key=lambda x: severity.data if x.severity == Severities.Unknown else x.severity.data)
+ copy_sort = list(self.__dict__.values())
+ copy_sort = [c for c in copy_sort if isinstance(c, Check)]
+ copy_sort.sort(key=lambda x: severity.data if x.severity == Severities().unknown else x.severity.data)
for i, check in enumerate(copy_sort):
html_str += check.html_help(i, severity, lizmap_cloud)
html_str += '
'
@@ -665,8 +684,9 @@ def setup(self):
# Bug, same as self.sort()
# self.setSortingEnabled(True)
- self.setColumnCount(len(Headers))
- for i, header in enumerate(Headers):
+ headers = Headers()
+ self.setColumnCount(len(headers.members))
+ for i, header in enumerate(headers.members):
column = QTableWidgetItem(header.label)
column.setToolTip(header.tooltip)
self.setHorizontalHeaderItem(i, column)
@@ -697,9 +717,10 @@ def to_json(self) -> list:
""" Export data to JSON. """
result = []
+ headers = Headers()
for row in range(self.rowCount()):
data = dict()
- for i, header in enumerate(Headers):
+ for i, header in enumerate(headers.members):
data[header.data] = self.item(row, i).data(self.JSON)
result.append(data)
@@ -736,7 +757,7 @@ def add_error(self, error: Error, lizmap_cloud: bool = False, severity=None):
""" Add an error in the table. """
# By default, let's take the one in the error
used_severity = error.check.severity
- if used_severity == Severities.Unknown:
+ if used_severity == Severities().unknown:
if severity:
# The given severity is overriden the one in the error
used_severity = severity