# This file contains metadata for your plugin.

# This file should be included when you package your plugin.
# Mandatory items:

[general]
name=FilterMate
qgisMinimumVersion=3.22
qgisMaximumVersion=4.99
supportsQt6=yes
description=🚀 The ultimate spatial filtering plugin! Explore, filter & export vector data with lightning-fast performance on ANY data source. Full QGIS 4 / Qt6 support.
version=4.8.3
author=imagodata
email=simon.ducournau+filter_mate@gmail.com

about=🎯 FilterMate 4.8.3 - Your Swiss Army Knife for Spatial Data!

    Stop struggling with complex filters. FilterMate makes spatial queries intuitive, fast, and powerful.

    🌟 WHY FILTERMATE?
    ━━━━━━━━━━━━━━━━━
    ✓ Works with EVERYTHING: PostgreSQL, Spatialite, GeoPackage, Shapefiles, WFS...
    ✓ Lightning fast: 2-8× faster with 4 performance optimizers + smart caching
    ✓ Intuitive: Filter by clicking, drawing, or selecting - no SQL needed!
    ✓ Professional: Undo/Redo, Favorites, Dark Mode, 34 languages
    ✓ Shareable: Git-backed favorites sharing + REST API for automation

    🔥 KILLER FEATURES:
    ━━━━━━━━━━━━━━━━━━
    📍 Geometric filtering with buffer, intersection, containment...
    🔍 Smart entity search across any layer type
    ⭐ Save & share your favorite filter configurations with spatial context
    🤝 Publish favorites to git repos (private/team) with authcfg credentials
    🌐 REST API to drive FilterMate from external tools (X-API-Key auth)
    📦 One-click export to GeoPackage with embedded QGIS project (preserves group structure, styles & CRS)
    🎨 Beautiful UI that adapts to your QGIS theme
    ⚡ Filter chaining with dynamic buffer expressions

    💡 v4.8.3: Config log cleanup — the "Schema file not found" message logged on every config reload (config_schema.json was intentionally removed in a prior release) is now Info instead of Warning. Also closed out 2 live-testing reports as confirmed non-bugs (QGIS3-named settings path is QGIS 4.2's own behavior; "Adding layers" progress is QGIS-core, not FilterMate).
    💡 v4.8.2: 🚑 Second QGIS 4.x hotfix — v4.8.1's fix still crashed ("DockWidgetFeature has no attribute AllDockWidgetFeatures"): that convenience constant was deprecated in Qt 5.13 and fully removed in Qt6, not just rescoped. Now ORs the 3 individual flags it used to expand to.
    💡 v4.8.1: 🚑 Critical fix for QGIS 4.x — the dockwidget failed to load entirely ("QDockWidget has no attribute AllDockWidgetFeatures") because PyQt6's UI loader can't resolve the .ui file's features flag; now set programmatically instead. Also fixed BatchFilterAlgorithm.tr() crashing the Processing Toolbox entry. Found via real-world QGIS 4.2/Windows testing right after v4.8.0 shipped.
    💡 v4.8.0: 🎉 Full QGIS 4.2 / Qt6 support! Three sweeps across the whole codebase — QMetaType field-type migration, QtWidgets→QtGui relocations (QShortcut & co.), remaining flat-enum fixes — plus 2 AST regression guards to keep it that way. New: FilterMate algorithms now in the Processing Toolbox (batch-filter multiple layers with one expression).
    💡 v4.7.3: Stability + Qt6-readiness release. Fix crash on QGIS 4.0.1/Windows when the standalone sip package wasn't importable (unguarded top-level import in the dockwidget). Security — resolved all Bandit findings (asserts replaced with explicit raises, corrected nosec code for ElementTree import, documented exception-suppression guards). Qt6 readiness — qualified ~165 flat PyQt/PyQGIS enum accesses to their scoped form and dropped exec_() across 50 files, no Qt5 behavior change.
    💡 v4.7.2: Spatial filtering fixes (SpatiaLite source_srid staleness causing silent 0-feature filters, Custom Selection "all-features" mode no longer shadowed by a stale layer selection), export hardening (blocked export with no Exploring selection, SHP/batch warnings surfaced, GPKG styles embedded on reprojection + streaming, empty-layer streaming crash fixed, partial-file cleanup on failure/cancel, format registry consolidation, ~900 LOC dead export code removed), HIDPI display fix (combobox/input stuck at 20px on 4K/Retina/150%%+ scaling)
    💡 v4.7.1: Hardening release — export pipeline (12 fixes across SHP/CSV/GPKG/SpatiaLite/ZIP), spatialite cascade (drop GeomFromGPB wrap, preserve ST_* + EXISTS/NOT predicates), Qt main-thread marshalling for QGISFilterMateAccessor, REST API hardening (503 favorites, no input echo, 1 MiB body cap, api_key hash-at-rest), portable Git SHA-256 digest enforcement, favorites deep audit follow-through (37 findings, FavoritesSpatialHandler extraction, FavoritesError exception family), auto-zoom on filtered union, +200 tests (1493 ✅)

    📖 Full docs: https://imagodata.github.io/filter_mate

tracker=https://github.com/imagodata/filter_mate/issues
repository=https://github.com/imagodata/filter_mate
# End of mandatory metadata

# Recommended items: regexp

hasProcessingProvider=yes

changelog=v4.8.3 (2026-07-31): Config log cleanup, from continued real-world QGIS 4.2/PostgreSQL testing. The "Schema file not found: config_schema.json" message logged on every single config load/reload (the schema file was intentionally deleted as unused in a prior release, but the validator still logged a Warning for this permanent, expected condition) is now Info instead. Two other reports investigated and closed as confirmed non-bugs, no code change: the "Configuration reloaded from: .../QGIS3/profiles/..." log while running QGIS 4.2 is QGIS 4.2's own QgsApplication.qgisSettingsDirPath() still returning a QGIS3-named directory (not a FilterMate hardcoded path); an "Adding layers" progress dialog stuck at 33%% on a large PostgreSQL project turned out (confirmed via screenshot) to be QGIS's own native project-loading dialog, not a FilterMate task -- out of this plugin's scope, and FilterMate's own SQLite connections already use a bounded timeout so can't be an unbounded-hang source. Tests -- 1493 passed, 1 skipped. v4.8.2 (2026-07-31): Second QGIS 4.x hotfix. The v4.8.1 fix for the dockwidget-load crash (moving the `features` property from the .ui file to a programmatic setFeatures() call) still crashed on real QGIS 4.2/Windows testing: "type object 'DockWidgetFeature' has no attribute 'AllDockWidgetFeatures'". Root cause was more specific than a scoping issue — AllDockWidgetFeatures was deprecated in Qt 5.13 and is gone entirely in Qt6, not just moved into a nested enum. Fixed by ORing the 3 individual flags it used to expand to (DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable), valid under both PyQt5 and PyQt6. Tests — 1493 passed, 1 skipped. v4.8.1 (2026-07-31): Critical QGIS 4.x fix, found via real-world testing right after v4.8.0 shipped. filter_mate_dockwidget_base.ui — the `features` <set> property (QDockWidget::AllDockWidgetFeatures) can't be resolved by PyQt6's dynamic uic loader, crashing dockwidget creation outright and making the plugin unusable on QGIS 4.x ("type object 'QDockWidget' has no attribute 'AllDockWidgetFeatures'"); removed from the .ui file and set programmatically instead (QDockWidget.DockWidgetFeature.AllDockWidgetFeatures), valid under both PyQt5 and PyQt6. Neither the prior enum-scoping sweeps nor the unit tests ever touched .ui XML, so this class of bug was invisible to every static check. processing/algorithms/batch_filter_algorithm.py — BatchFilterAlgorithm.tr() didn't exist (QgsProcessingAlgorithm isn't a QObject subclass and never provides tr() on any QGIS/Qt version; every algorithm must define its own), crashing as soon as Processing tried to load it. Tests — 1493 passed, 1 skipped. v4.8.0 (2026-07-31): Full QGIS 4.2 / Qt6 support release. Qt6 — closed out the remaining gaps from the v4.7.3 sweep: migrated QgsField.type() checks from QVariant.Xxx to QMetaType.Type.Xxx across PK-detection and field-mapping code (6 files); fixed QShortcut imported from QtWidgets instead of QtGui (Qt6 relocated QAction/QActionGroup/QFileSystemModel/QShortcut/QUndoCommand/QUndoGroup/QUndoStack to QtGui — this broke dockwidget keyboard shortcuts and the JSON config search widget at load time under PyQt6); qualified the remaining flat PyQt5-style enum accesses (Qt.ForegroundRole, Qt.CaseInsensitive, Qt.RightToLeft, QPalette.Window, QStyle.CC_SpinBox, QStyle.PE_IndicatorViewItemCheck, QAbstractSpinBox.NoButtons) mostly in ui/widgets/json_view/, missed because that directory wasn't covered by the original 50-file audit. Added two AST-based static regression guards (test_no_unguarded_sip_import.py, test_no_qtwidgets_relocated_symbols.py) that scan the whole plugin tree so these bug classes can't resurface silently. Processing Toolbox — FilterMate algorithms are now registered via a QgsProcessingProvider; first algorithm "Filtrer plusieurs couches (batch)" (filtermate:batch_filter) applies one filter expression to multiple vector layers in a single run, usable from Processing models/batch processing. Tests — 1486 ✅ (7 pre-existing, unrelated export-pipeline failures tracked separately). v4.7.3 (2026-07-30): Stability + Qt6-readiness release. Fix — remove unguarded top-level `import sip` in filter_mate_dockwidget.py that crashed dockable panel creation on QGIS 4.0.1/Windows when the standalone sip package wasn't reliably importable; route the four sip.isdeleted() call sites through the already-hardened is_sip_deleted() helper instead, which degrades gracefully rather than crashing. Security — resolved all Bandit findings: replaced 4 assert statements (silently stripped under python -O) with explicit ValueError/TypeError raises; corrected the nosec code on the ElementTree import from B314 to B405 (the wrong code meant the suppression was silently a no-op — Bandit still flagged both lines); reviewed and confirmed the 3 subprocess.run calls in the favorites-sharing git integration as safe (list-form argv, no shell=True, timeouts); documented ~166 except-Exception suppressions (B110/B112) with inline justifications. Qt6 readiness — qualified ~165 flat PyQt/PyQGIS enum accesses to their scoped form (e.g. Qt.LeftButton -> Qt.MouseButton.LeftButton) across 50 files, renamed .exec_() calls/overrides to .exec(), switched 3 direct PyQt5 imports to qgis.PyQt; all forms are valid under both PyQt5 (current QGIS) and PyQt6, so this is purely additive with no behavior change on the current Qt5 install. Tests — new tests/test_no_unguarded_sip_import.py AST-scans the whole plugin tree as a static regression guard; full suite 1491+ new tests ✅. v4.7.2 (2026-07-30): Spatial filtering + export hardening release. SpatiaLite — fix source_srid staleness in build_expression() (kwarg now preferred over stale task_params CRS), fixing filters that silently returned 0 features when source and target layers shared their original CRS. Custom Selection — "all-features" mode (always-true expression, e.g. "1") could be silently overridden by an unrelated leftover QGIS selection on the source layer, causing spatial filters to run against a stray selection instead of the full layer and match nothing with no visible error; fixed in both the SpatiaLite/GeoPackage and OGR backends' source-mode resolution. Export — fix export blocked with a silent log-only error when no layer was picked in the Exploring tab (export is independent from Exploring), surface SHP pre-flight warnings and batch per-layer failures to the user instead of dropping them, embed GPKG styles in layer_styles on the reprojection and streaming paths (previously silently dropped), fix FileNotFoundError when streaming an empty layer, remove a misleading post-write cancel check, clean up partial output files on writer failure/cancellation, consolidate three drifting format/driver maps into a single _FORMAT_REGISTRY, remove ~900 LOC of dead/unwired export code found during a full pipeline audit. UI — fix HIDPI display profile: combobox/input fields stuck at 20px on 4K/Retina/150%%+ Windows scaling due to a QSS placeholder-substitution pipeline broken since v4.0.x, profile recalibrated to avoid double-scaling on top of Qt's own DPR auto-scaling. Tests — 1491 ✅. v4.7.1 (2026-04-29): Hardening + audit follow-through release. Export — V3 API migration, streaming CRS plumbing, SHP pre-flight checks, normcase UI paths, GPKG bypass of qgis:package on path-detect, CSV WKT injection guard, SpatiaLite extension fixes, ZIP path-traversal leak (CRITICAL), batch collision detection, validator drivers list, GPKG path detection — 12 fixes total + 24 tests. SpatiaLite cascade — drop GeomFromGPB wrap (use ST_* prefix), preserve ST_* spatial predicates in sanitizer (was wiping standalone calls), fix SQLite lock + OGR queue routing, route apply_filter through subset queue for Qt thread safety, restore SpatialitePersistentCache f-string interpolation (silent cache no-op for 100+ days). Sanitizer — preserve EXISTS(...)/NOT(...)/ST_* predicates (3 cascade no-op regressions fixed), collapse whitespace runs before top-level marker scan. REST API — refuse insecure default api_key (S1), warn on plaintext JSON load (S4 hardening), hash-at-rest for api_key, 503 when favorites service unavailable, no input echo, 1 MiB body cap, marshall qgis_accessor mutations to Qt main thread (P0-B). Security — defense-in-depth PostgreSQL SQL guards (S2), reject non-http(s) URLs in PortableGit downloader (B310), refuse PortableGit install without SHA-256 digest (S6), favorites-sharing legacy auth header tripwire (EXT6). Favorites deep audit (2026-04-29, 37 findings) — FavoritesSpatialHandler extraction (5 stages, ~927 LOC), FavoritesError exception family (FavoritesNotInitialized + FavoritePersistenceError), FavoritesExtensionBridge + FavoritesMenuBuilder + FavoriteImportHandler + LayerSignature, drop dead second FavoritesService instance (XCUT-1), drop bridge fallback paths in dialog (XCUT-2), pin DockwidgetSurface Protocol (XCUT-3), drop dead-defensive hasattr guards (CORE-1a), rename _favorites_manager → _favorites_service (CORE-1b), route global INSERTs through add_favorite (CORE-2), drop orphan Service methods + dead signals (CORE-3), drop orphan load/reload + count/get_by_id aliases (CORE-4/6), drop unused TABLE_FAVORITES/TABLE_PROJECTS constants (CORE-8), drop orphan ensure_global_project_exists (CORE-11), drop spatial-handler delegations from controller (UI-5), plug favoriteApplied signal leak (UI-6), pin BuilderContext Protocol for menu builder (UI-8), factor migration_service bootstrap (UI-9), drop _show_global_favorites_dialog placeholder (UI-13), extract SharedFavoritesQuery + FavoritesForkService + BundlePublisher + publish_model helpers (EXT-1/EXT-2 stages 1-4), factor worker close lifecycle (EXT-7), validator version-tolerance contract test (EXT-9). Domain — wire IFeedback adapter to remove iface from core (A1), drop QgsProject.instance() fallback in LayerSignatureIndex (A2), merge filter_parameter_builder + layer_filter_builder (A3 paire 4). Auto-zoom — zoom on filtered layers union after filter or favorite, subset-change token blocks stale post-task zoom. QFieldCloud — park orphan PushWorker on terminate timeout (C1). UI — favorites manager dialog leak fix, refresh() preserves active search and scope filters, F11 feedback policy alignment (4 rules, 5 callsites), shared QSS + icon registry. Config — refresh schema-owned metadata on existing keys, mutate-in-place CONFIG_DATA, preserve EXTENSIONS panel label across migrations. Tests — 1493 ✅ (+200 since v4.7.0): T1 FavoritesSpatialHandler.restore_spatial_config, T2 auto-zoom helpers + e2e flows, T3 HistoryService + LayerHistory wrapper, FCB-TESTS 10 edge cases for filter_config_builder. v4.7.0 (2026-04-27): Favorites sharing — git-backed publish to remote repos with authcfg credentials (QgsAuthManager), repo manager dialog, quick 1-click publish, picker disambiguation when (name, author) collide, optional Resource Sharing extension, JSON Schema v3, per-user scope + profile-dir local_clone. REST API (filtermate_api) — GET /layers, POST /filters/apply, /filters/status, /undo, /redo, /favorites with X-API-Key auth middleware. QFieldCloud — harden PushWorker teardown (disconnect before terminate), fix signal leaks + broken menu removal on unload, gate favorites-sharing activation on resource_sharing plugin. Performance — stream feature IDs instead of materializing full list, cache parsed QgsExpression in evaluation task, collapse double getFeatures() in buffer simplification, limit QgsProperty buffer-distance fetch to first feature. Audit hardening — path traversal + argv injection guards, M2 sanitizer + M7 git stderr scrubbing, single HistoryService consolidation, deprecation registry adoption, PostgreSQL QgsDataSourceUri table parsing. Favorites deep audit (2026-04-23) — CRIT/HIGH/MED/LOW regressions, v3 round-trip, capture geometric predicates from live widgets, propagate predicates to combobox + canonical PROJECT_LAYERS keys, sanitize at setSubsetString chokepoint, strip stale COALESCE display expressions from subset chain, exact filtered feature_count + refresh on apply. UI fixes — exploring sidebar visibility + HIDPI profile + QSS cascade cleanup, custom selection layout, harmonize SINGLE/MULTIPLE groupbox display with CUSTOM, restore groupbox mode on apply. Filter — use pointOnSurface instead of centroid for spatial filtering. Export — sidecar style naming, LIBKML groups, case-preserved OGR drivers. i18n — full 34-locale coverage for favorites-sharing + datasource manager. v4.6.6 (2026-04-08): Security fixes — use defusedxml for XML parsing in GPKG/KML exporters, replace insecure tempfile.mktemp with mkstemp in F5-TTS narrator. v4.6.5 (2026-04-08): Config tree restructure with live save and auto-migration from flat to tree format. Fix live language switching: resolve NameError, stale reentrant guard, spurious currentIndexChanged on editor open, use item's own model for setModelData. Defer language retranslate to next event loop tick. Add 79 missing translations + QFieldCloud i18n + cleanup obsolete entries. v4.6.3 (2026-04-07): i18n expanded from 22 to 34 languages (+Korean, Japanese, Arabic, Thai, Ukrainian, Czech, Romanian, Greek, Hungarian, Bulgarian, Malay, Catalan). Fix live language switching: full UI retranslation (retranslateUi + dynamic tooltips + indicators). Handle QEvent.LanguageChange for QGIS locale changes. v4.6.2 (2026-03-17): Feature picker fixes: debounce with FID storage, refresh on display field change, next/prev browser buttons initialization, always-enabled identify/zoom buttons. v4.6.1 (2026-03-09): QGIS 4 / Qt6 compatibility. Edit mode popup before filter/unfilter operations. i18n 22 languages at 100%%. Config harmonization with single source of truth. v4.6.0 (2026-02-18): GPKG export now embeds a full QGIS project preserving layer group hierarchy, styles and CRS. Fix action buttons not disabled when switching to exporting tab. v4.5.3 (2026-02-18): Fix GPKG export crash caused by GUI calls from background thread. v4.5.2 (2026-02-12): Fix square key buttons sizing, exploring sidebar layout alignment. v4.5.1 (2026-02-11): Website launch, org migration, 600 tests, quality score 9.0/10.

# Tags are comma separated with spaces allowed
tags=python,filter,vector,layers,geofilter,search,postgis,ogr,spatialite,data,exploration,subset,export

homepage=https://imagodata.github.io/filter_mate/
category=Plugins
icon=icon.png
# experimental flag
experimental=False

# deprecated flag (applies to the whole plugin, not just a single version)
deprecated=False

# Since QGIS 3.8, a comma separated list of plugins to be installed
# (or upgraded) can be specified.
# Check the documentation for more information.
# plugin_dependencies=

Category of the plugin: Raster, Vector, Database or Web
#category=Database

# If the plugin can run on QGIS Server.
server=False
