-
Notifications
You must be signed in to change notification settings - Fork 1
/
openicgc.py
2654 lines (2429 loc) · 170 KB
/
openicgc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# -*- coding: utf-8 -*-
"""
*******************************************************************************
OpenICGC
A QGIS plugin
Plugin for accessing open data published by the Cartographic and Geological
Institute of Catalonia (Catalan mapping agency).
Includes spatial toponymic searches, streets, roads, coordinates in different
reference systems and load of WMS base layers of Catalonia.
-------------------
begin : 2019-01-18
author : Albert Adell
email : albert.adell@icgc.cat
*******************************************************************************
"""
import os
import sys
import platform
# Import base libraries
import re
import datetime
import zipfile
import io
import logging
import json
from urllib.request import urlopen, Request
from urllib.parse import urljoin, quote
from importlib import reload
# Import QGIS libraries
from qgis.core import QgsRasterLayer, QgsVectorLayer, QgsPointXY, QgsRectangle, QgsGeometry, QgsMultiPolygon
from qgis.core import Qgis, QgsCoordinateTransform, QgsCoordinateReferenceSystem, QgsProject, QgsWkbTypes
from qgis.gui import QgsMapTool, QgsRubberBand
# Import the PyQt and QGIS libraries
from PyQt5.QtCore import QSize, Qt, QPoint, QDateTime
from PyQt5.QtGui import QIcon, QCursor, QColor, QPolygon
from PyQt5.QtWidgets import QApplication, QComboBox, QMessageBox, QStyle, QInputDialog, QLineEdit, QFileDialog, QWidgetAction
# Initialize Qt resources from file resources_rc.py
from . import resources_rc
# Detect import relative mode (for release) or global import mode (for debug)
is_import_relative = os.path.exists(os.path.join(os.path.dirname(__file__), "qlib3"))
if is_import_relative:
# Add a additional library folder to pythonpath (for external libraries)
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
# Import basic plugin functionalities
from .qlib3.base.loginfodialog import LogInfoDialog
from .qlib3.base.pluginbase import PluginBase, WaitCursor
from .qlib3.base.progressdialog import WorkingDialog
# Import geofinder dialog and class
from .geofinder3.geofinder import GeoFinder
from .qlib3.geofinderdialog.geofinderdialog import GeoFinderDialog
# Import photosearch dialog
from .qlib3.photosearchselectiondialog.photosearchselectiondialog import PhotoSearchSelectionDialog
# Import download dialog
from .qlib3.downloaddialog.downloaddialog import DownloadDialog
# Import wms resources access functions
from .resources3.wms import get_historic_ortho, get_lastest_ortoxpres, get_superexpedita_ortho, get_full_ortho
#from .resources3.wfs import get_delimitations as get_wfs_delimitations
from .resources3.fme import get_clip_data_url, get_services, get_data_filters
from .resources3.fme import get_regex_styles as get_fme_regex_styles, FME_DOWNLOAD_EPSG, FME_MAX_POLYGON_POINTS
from .resources3.http import get_historic_ortho_code, get_historic_ortho_ref
from .resources3.http import get_dtms, get_coast_dtms, get_bathimetrics, get_coastlines, get_sheets, get_grids
from .resources3.http import get_delimitations, get_ndvis, get_topographic_5k
from .resources3 import http as http_resources, wms as wms_resources, fme as fme_resources
else:
# Import basic plugin functionalities
import qlib3.base.pluginbase
reload(qlib3.base.pluginbase)
from qlib3.base.pluginbase import PluginBase, WaitCursor
import qlib3.base.loginfodialog
reload(qlib3.base.loginfodialog)
from qlib3.base.loginfodialog import LogInfoDialog
import qlib3.base.progressdialog
reload(qlib3.base.progressdialog)
from qlib3.base.progressdialog import WorkingDialog
# Import geofinder dialog and class
import qlib3.geofinderdialog.geofinderdialog
reload(qlib3.geofinderdialog.geofinderdialog)
from qlib3.geofinderdialog.geofinderdialog import GeoFinderDialog
import geofinder3.geofinder
reload(geofinder3.geofinder)
from geofinder3.geofinder import GeoFinder
# Import photosearch dialog
import qlib3.photosearchselectiondialog.photosearchselectiondialog
reload(qlib3.photosearchselectiondialog.photosearchselectiondialog)
from qlib3.photosearchselectiondialog.photosearchselectiondialog import PhotoSearchSelectionDialog
# Import download dialog
import qlib3.downloaddialog.downloaddialog
reload(qlib3.downloaddialog.downloaddialog)
from qlib3.downloaddialog.downloaddialog import DownloadDialog
# Import wms resources access functions
import resources3.wms
reload(resources3.wms)
from resources3.wms import get_historic_ortho, get_lastest_ortoxpres, get_superexpedita_ortho, get_full_ortho
#import resources3.wfs
#reload(resources3.wfs)
#from resources3.wfs import get_delimitations as get_wfs_delimitations
import resources3.fme
reload(resources3.fme)
from resources3.fme import get_clip_data_url, get_services, get_data_filters
from resources3.fme import get_regex_styles as get_fme_regex_styles, FME_DOWNLOAD_EPSG, FME_MAX_POLYGON_POINTS
import resources3.http
reload(resources3.http)
from resources3.http import get_historic_ortho_code, get_historic_ortho_ref
from resources3.http import get_dtms, get_coast_dtms, get_bathimetrics, get_coastlines, get_sheets, get_grids
from resources3.http import get_delimitations, get_ndvis, get_topographic_5k
from resources3 import http as http_resources, wms as wms_resources, fme as fme_resources
# Global function to set HTML tags to apply fontsize to QInputDialog text
set_html_font_size = lambda text, size=9: ('<html style="font-size:%spt;">%s</html>' % (size, text.replace("\n", "<br/>").replace(" ", " ")))
# Constants
PHOTOLIB_WFS_MAX_FEATURES = 1000
PHOTOLIB_WFS = "https://fototeca-connector.icgc.cat/"
PHOTOLIB_WMS = PHOTOLIB_WFS
class QgsMapToolSubScene(QgsMapTool):
""" Tool class to manage rectangular selections """
def __init__(self, map_canvas, callback=None, \
min_side=None, max_download_area=None, min_px_side=None, max_px_download_area=None, gsd=None, gsd_dict={}, \
mode_area_not_point=None, color=QColor(0,150,0,255), error_color=QColor(255,0,0,255), line_width=3):
# Initialize parent
QgsMapTool.__init__(self, map_canvas)
# Initialize local variables
self.callback = callback
self.pressed = False
self.color = color
self.error_color = error_color
self.line_width = line_width
self.min_side = min_side
self.max_download_area = max_download_area
self.min_px_side = min_px_side
self.max_px_download_area = max_px_download_area
self.gsd = gsd
self.mode_area_not_point = mode_area_not_point
# Initialize paint object
self.rubberBand = QgsRubberBand(map_canvas)
def set_callback(self, callback):
self.callback = callback
def set_min_max(self, min_side, max_download_area, min_px_side, max_px_download_area):
self.min_side = min_side
self.max_download_area = max_download_area
self.min_px_side = min_px_side
self.max_px_download_area = max_px_download_area
def set_gsd(self, gsd):
self.gsd = gsd
def set_mode(self, area_not_point):
self.mode_area_not_point = area_not_point
def canvasPressEvent(self, event):
#click
if event.button() == Qt.LeftButton:
self.pressed = True
self.top_left = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y()))
def canvasMoveEvent(self, event):
# If don't have drag then exit
if not self.pressed:
return
if not self.mode_area_not_point:
return
# Show selection rectangle
cpos = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y()))
width = abs(cpos.x() - self.top_left.x())
height = abs(cpos.y() - self.top_left.y())
area = width * height
area_too_big = self.max_download_area and (area > self.max_download_area) or \
self.max_px_download_area and self.gsd and ((area / self.gsd / self.gsd) > self.max_px_download_area)
area_too_little = self.min_side and (width < self.min_side or height < self.min_side) or \
self.min_px_side and self.gsd and ((width / self.gsd) < self.min_px_side or (height / self.gsd) < self.min_px_side)
color = self.error_color if area_too_big or area_too_little else self.color
self.rubberBand.reset()
self.rubberBand.setLineStyle(Qt.DashLine)
self.rubberBand.setColor(color)
self.rubberBand.setWidth(self.line_width)
self.rubberBand.addPoint(self.top_left, False)
self.rubberBand.addPoint(QgsPointXY(cpos.x(), self.top_left.y()), False)
self.rubberBand.addPoint(cpos, False)
self.rubberBand.addPoint(QgsPointXY(self.top_left.x(), cpos.y()), False)
self.rubberBand.addPoint(self.top_left, True)
def canvasReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.subscene(event.pos().x(), event.pos().y())
def subscene(self, x=None, y=None):
# Gets selection geometry
area = None
if self.mode_area_not_point:
# If area is required takes rubberBans geometry
geo = self.rubberBand.asGeometry()
if geo:
area = geo.boundingBox()
if not area and x is not None and y is not None:
# If not area then we takes a point
point = self.toMapCoordinates(QPoint(x, y))
area = QgsRectangle(point.x(), point.y(), point.x(), point.y())
# Hide selection area
self.rubberBand.reset()
self.pressed = False
# Execute callback with selected area as parameter
if self.callback:
self.callback(area)
class QgsMapToolPhotoSearch(QgsMapTool):
""" Enable to return coordinates from clic in a layer.
"""
def __init__(self, map_canvas, callback=None, action=None):
""" Constructor.
"""
QgsMapTool.__init__(self, map_canvas)
self.map_canvas = map_canvas
self.callback = callback
# Action to check / uncheck tools
self.setAction(action)
# Assign tool cursor
self.setCursor(Qt.CrossCursor)
def canvasReleaseEvent(self, event):
cpos = self.toMapCoordinates(QPoint(event.pos().x(), event.pos().y()))
if self.callback:
self.callback(cpos.x(), cpos.y())
class HelpType:
""" Definition of differents types of show pluggin help """
local = 0
online = 1
online_cached = 2
class UpdateType:
""" Definition of diferents types of plugin updates """
plugin_manager = 0
qgis_web = 1
icgc_web = 2
class OpenICGC(PluginBase):
""" Plugin for accessing open data published by ICGC """
TOOLTIP_HELP = "" # Filled on __init__ (translation required)
SQUARE_CHAR = "\u00B2"
FME_DOWNLOADTYPE_LIST = [] # Filled on __init__ (translation required)
FME_NAMES_DICT = {} # Filled on __init__ (translation required)
FME_ICON_DICT = {
"ct":":/lib/qlib3/base/images/cat_topo5k.png",
"bm":":/lib/qlib3/base/images/cat_topo5k.png",
#"bt":":/lib/qlib3/base/images/cat_topo5k.png",
"di":":/lib/qlib3/base/images/cat_topo5k.png", # divisions-administratives
"to":":/lib/qlib3/base/images/cat_topo5k.png", # topografia-territorial
"of":":/lib/qlib3/base/images/cat_ortho5k.png",
"hc":":/lib/qlib3/base/images/cat_ortho5k.png",
"oi":":/lib/qlib3/base/images/cat_ortho5ki.png",
"hi":":/lib/qlib3/base/images/cat_ortho5ki.png",
"mt":":/lib/qlib3/base/images/cat_topo5k.png",
"co":":/lib/qlib3/base/images/cat_landcover.png",
"me":":/lib/qlib3/base/images/cat_dtm.png",
#"gt":":/lib/qlib3/base/images/cat_geo250k.png",
"mg":":/lib/qlib3/base/images/cat_geo250k.png",
"ma":":/lib/qlib3/base/images/cat_geo250k.png",
"li":":/lib/qlib3/base/images/cat_coast.png",
"ba":":/lib/qlib3/base/images/cat_coast.png",
"el":":/lib/qlib3/base/images/cat_coast.png",
"li":":/lib/qlib3/base/images/cat_lidar.png",
"ph":":/lib/qlib3/photosearchselectiondialog/images/photo_preview.png", # fototeca
}
FME_METADATA_DICT = {
"of": "Current color orthophoto",
"hc": "Color orthophoto (temporal serie)",
"oi": "Current infrared orthophoto",
"hi": "Infrared orthophoto (temporal serie)",
#"bt5m": "Topographic base 1:5,000",
"topografia-territorial": "Territorial topographic referential",
"mtc250m": "Topographic map 1:250,000",
"mtc500m": "Topographic map 1:500,000",
"mtc1000m": "Topographic map 1:1,000,000",
"ct1m": "Topographic cartography 1:1,000",
#"bm5m": "Municipal base 1:5,000",
"divisions-administratives": "Administrative divisions",
"topografia-territorial-gpkg": "Territorial topographic referential",
"topografia-territorial-dgn": "Territorial topographic referential",
"topografia-territorial-dwg": "Territorial topographic referential",
"topografia-territorial-bim-ifc": "Territorial topographic referential",
"topografia-territorial-3d-gpkg": "Territorial topographic referential",
"topografia-territorial-3d-dgn": "Territorial topographic referential",
"topografia-territorial-3d-dwg": "Territorial topographic referential",
"topografia-territorial-volum-dwg": "Territorial topographic referential",
"cobertes-sol-raster": "Land cover map",
"cobertes-sol-vector": "Land cover map",
"met2": "Digital Terrain Model 2m 2008-2011",
"met5": "Digital Terrain Model 5m 2020",
"elevacions-franja-litoral": "Topobathymetric elevation model (-50m) 1m 2022-2024",
"batimetria": "Bathymetric chart (-50m) 2022-2024",
"linia-costa": "Coastline",
"mg50m": "Geological map 1:50,000",
"mg250m": "Geological map 1:250,000",
"mg250m-raster": "Geological map 1:250,000",
"mggt6": "Geological map for the prevention of geological hazards 1:25,000 (GT VI)",
"mggt1": "Geological map 1:25,000 (GT I)",
# Pending revision of symbology
#"gt2": "GT II. Geoanthropic map 1:25,000",
#"gt3": "GT III. Geological map of urban areas 1:5,000",
#"gt4": "GT IV. Soil map 1:25,000",
#"gt5": "GT V. Hydrogeological map 1:25,000",
#"mah250m": "Map of hydrogeological Areas 1:250,000",
"lidar-territorial": "Territorial Lidar",
"of-lidar-territorial": "Territorial Lidar Color Orthophoto",
"oi-lidar-territorial": "Territorial Lidar Infrared Orthophoto",
# No metadata
#"photo": "Photo library",
}
PRODUCT_METADATA_FILE = os.path.join(os.path.dirname(__file__), "data", "product_metadata.json")
CAT_EXTENSION = QgsRectangle(215300, 4478100, 577600, 4758400)
download_action = None
time_series_action = None
photo_search_action = None
photo_search_2_action = None
photo_download_action = None
geopackage_style_action = None
debug_mode = False
test_available = False
###########################################################################
# Plugin initialization
def __init__(self, iface, debug_mode=False):
""" Plugin variables initialization """
# Save reference to the QGIS interface
super().__init__(iface, __file__)
# Detection of developer enviroment
self.debug_mode = debug_mode or __file__.find("pyrepo") >= 0
if self.debug_mode:
self.enable_debug_log()
# Dectection of plugin mode (lite or full)
self.lite = os.environ.get("openicgc_lite", "").lower() in ["true", "1", "enabled"]
self.log.info("Initializing %s%s", self.metadata.get_name(), " Lite" if self.lite else "")
self.extra_countries = self.lite
# Detection of test environment
self.test_available = self.debug.is_test_available()
# Configure library loggers
http_resources.log = self.log
wms_resources.log = self.log
fme_resources.log = self.log
# Load extra fonts (Fira Sans)
t0 = datetime.datetime.now()
fonts_status, self.font_id_list = self.load_fonts(copy_to_temporal_folder=True)
t1 = datetime.datetime.now()
self.log.info("Load fonts folder %s: %s (%s)" % (self.get_fonts_temporal_folder(), fonts_status, t1-t0))
if not fonts_status:
self.log.warning("Error loading extra fonts")
# Translated long tooltip text
self.TOOLTIP_HELP = self.tr("""Find:
Address: municipality, street number or vice versa
Barcelona, Aribau 86
Aribau 86, Barcelona
Barcelona, C/ Aribau 86
Crossing: municipality, street, street
Barcelona, Mallorca, Aribau
Road: road, km
C32 km 10
C32, 10
Toponym: free text
Barcelona
Collserola
Institut Cartografic
Coordinate: x and EPSG: code (by default coordinate system of the project)
429394.751 4580170.875
429394,751 4580170,875
429394.751 4580170.875 EPSG:25831
EPSG:4326 1.9767050 41.3297270
Rectangle: west north east south EPSG: code (by default system coordinates of the project)
427708.277 4582385.829 429808.277 4580285.829
427708,277 4582385,829 429808,277 4580285,829
427708.277 4582385.829 429808.277 4580285.829 EPSG:25831
EPSG:25831 427708.277 4582385.829 429808.277 4580285.829
Cadastral reference: ref (also works with the first 14 digits)
9872023 VH5797S 0001 WX
13 077 A 018 00039 0000 FP
13077A018000390000FP""")
# Set group name for background maps
self.backgroup_map_group_name = self.tr("Background maps")
# Initialize references names (with translation)
self.HTTP_NAMES_DICT = {
"caps-municipi": self.tr("Municipal capitals"), # Available HTTP
"capmunicipi": self.tr("Municipal capitals"), # Available WFS
"capcomarca": self.tr("County capitals"), # # Available WFS
"municipis": self.tr("Municipalities"),
"comarques": self.tr("Counties"),
"vegueries": self.tr("Vegueries"), # Available HTTP
"provincies": self.tr("Provinces"),
"catalunya": self.tr("Catalonia"), #Available HTTP
}
# Initialize download names (with translation)
self.FME_NAMES_DICT = {
"of25c": self.tr("Current color orthophoto 25cm 1:2,500"),
"of5m": self.tr("Current color orthophoto 50cm 1:5,000"),
"of25m": self.tr("Current color orthophoto 2.5m 1:25,000"),
"hc10cm": self.tr("Historic color orthophoto 10cm 1:1,000"),
"hc15cm": self.tr("Historic color orthophoto 15cm 1:1,500"),
"hc25cm": self.tr("Historic color orthophoto 25cm 1:2,500"),
"hc50cm": self.tr("Historic color orthophoto 50cm 1:5,000"),
"hc1m": self.tr("Historic color orthophoto 1m 1:10,000"),
"hc250cm": self.tr("Historic color orthophoto 2.5m 1:25,000"),
"oi25c": self.tr("Current infrared orthophoto 25cm 1:2,500"),
"oi5m": self.tr("Current infrared orthophoto 50cm 1:5,000"),
"oi25m": self.tr("Current infrared orthophoto 2.5m 1:25,000"),
"hi10cm": self.tr("Historic infrared orthophoto 10cm 1:1,000"),
"hi25cm": self.tr("Historic infrared orthophoto 25cm 1:2,500"),
"hi50cm": self.tr("Historic infrared orthophoto 50cm 1:5,000"),
"hi1m": self.tr("Historic infrared orthophoto 1m 1:10,000"),
"hi250cm": self.tr("Historic infrared orthophoto 2.5m 1:25,000"),
#"bt5m": self.tr("Topographic base 1:5,000"),
"topografia-territorial": self.tr("Territorial topographic referential"),
"mtc250m": self.tr("Topographic map 1:250,000"),
"mtc500m": self.tr("Topographic map 1:500,000"),
"mtc1000m": self.tr("Topographic map 1:1,000,000"),
"ct1m": self.tr("Topographic cartography 1:1,000"),
#"bm5m": self.tr("Municipal base 1:5,000"),
"divisions-administratives": self.tr("Administrative divisions"),
"topografia-territorial-gpkg": self.tr("Territorial topographic referential"),
"topografia-territorial-dgn": self.tr("Territorial topographic referential"),
"topografia-territorial-dwg": self.tr("Territorial topographic referential"),
"topografia-territorial-bim-ifc": self.tr("Territorial topographic referential BIM"),
"topografia-territorial-3d-gpkg": self.tr("Territorial topographic referential 3D"),
"topografia-territorial-3d-dgn": self.tr("Territorial topographic referential 3D"),
"topografia-territorial-3d-dwg": self.tr("Territorial topographic referential 3D"),
"topografia-territorial-volum-dwg": self.tr("Territorial topographic referential volume"),
"cobertes-sol-raster": self.tr("Land cover map"),
"cobertes-sol-vector": self.tr("Land cover map"),
"met2": self.tr("Digital terrain model 2m 2008-2011"),
"met5": self.tr("Digital terrain model 5m 2020"),
"elevacions-franja-litoral": self.tr("Topobathymetric elevation model"),
"batimetria": self.tr("Bathymetric chart"),
"linia-costa": self.tr("Coastline"),
"mggt1": self.tr("Geological map 1:25,000 (GT I)"),
"mg50m": self.tr("Geological map 1:50,000"),
"mg250m": self.tr("Geological map 1:250,000"),
"mg250m-raster": self.tr("Geological map 1:250,000"),
"mggt6": self.tr("Geological map for the prevention of geological hazards 1:25,000 (GT VI)"),
# Pending revision of symbology
#"gt2": self.tr("GT II. Geoanthropic map 1:25,000"),
#"gt3": self.tr("GT III. Geological map of urban areas 1:5,000"),
#"gt4": self.tr("GT IV. Soil map 1:25,000"),
#"gt5": self.tr("GT V. Hydrogeological map 1:25,000"),
#"mah250m": self.tr("Map of hydrogeological Areas 1:250,000"),
"lidar-territorial": self.tr("Territorial Lidar"),
"of-lidar-territorial": self.tr("Territorial Lidar Color Orthophoto"),
"oi-lidar-territorial": self.tr("Territorial Lidar Infrared Orthophoto"),
"photo": self.tr("Photograms"),
}
# Initialize download type descriptions (with translation)
self.FME_DOWNLOADTYPE_LIST = [
("dt_area", self.tr("Area"), ""),
("dt_coord", self.tr("Area coordinates"), ""),
("dt_layer_polygon", self.tr("Selected layer polygons"), "pol"),
("dt_layer_polygon_bb", self.tr("Selected layer polygons bounding box"), "pol"),
("dt_sheet", self.tr("Sheet"), "full"),
("dt_municipalities", self.tr("Municipality"), "mu"),
("dt_counties", self.tr("County"), "co"),
("dt_cat", self.tr("Catalonia"), "cat"),
("dt_all", self.tr("Available data"), "tot")]
## Inicitialize default download variables
self.download_type = "dt_area"
self.download_group_name = self.tr("Download")
self.download_ref_pattern = self.tr("Reference %s")
self.cat_limits_dict = { # key: (geometry, epsg)
"cat_rect": self.get_catalonia_limits("cat_rect_limits", buffer=0),
"cat_simple": self.get_catalonia_limits("cat_simple_limits", buffer=0),
"cat_limits": self.get_catalonia_limits("cat_limits", buffer=250),
"lidar1k_limits": self.get_catalonia_limits("cat_lidar1k_limits", buffer=0),
"5k_limits": self.get_catalonia_limits("cat_tall5k_limits", buffer=0),
"25k_limits": self.get_catalonia_limits("cat_tall25k_limits", buffer=0),
}
# Lambda function with last download reference layer used
self.load_last_ref_layer = lambda: None
# Get download services regex styles and filters
self.fme_regex_styles_list = get_fme_regex_styles()
self.fme_data_filters_dict = get_data_filters()
# Initialize reference to DownloadDialog
self.download_dialog = None
# We created a GeoFinder object that will allow us to perform spatial searches
# and we configure it with our plugin logger
self.geofinder = GeoFinder(logger=self.log)
self.geofinder_dialog = GeoFinderDialog(self.geofinder, title=self.tr("Spatial search"),
columns_list=[self.tr("Name"), self.tr("Type"), self.tr("Municipality"), self.tr("Region")],
keep_scale_text=self.tr("Keep scale"))
# Initialize product metatata dictionary with metadata urls
product_dict_list = []
if os.path.exists(self.PRODUCT_METADATA_FILE):
with open(self.PRODUCT_METADATA_FILE, 'r') as json_file:
product_dict_list = json.load(json_file)
self.product_metadata_dict = { product_dict['Carpeta']: product_dict['Metadades'] \
for product_dict in product_dict_list }
# Initialize reference to PhotoSearchSelectionDialog
self.photo_search_dialog = None
# Initialize photo search group names
self.photos_group_name = self.tr("Photograms")
# Initialize photo search label
self.photo_label = self.tr("Photo: %s")
self.photo_layer_id = ""
self.photo_search_label = self.tr("Photo query: %s")
self.photo_search_layer_id = ""
# Configure referrer string to use on url requests
self.request_referrer = "%s_v%s" % (self.metadata.get_name().replace(" ", ""), self.metadata.get_version())
self.request_referrer_param = "referrer=%s" % self.request_referrer
# Check QGIS version problems
self.enable_http_files = self.check_qgis_version(31004)
self.qgis_version_ok = self.check_qgis_version(31004)
self.can_show_point_cloud_files = self.check_qgis_version(31800)
self.can_filter_point_cloud = self.check_qgis_version(32600)
# Map change current layer event
self.iface.layerTreeView().currentLayerChanged.connect(self.on_change_current_layer)
self.iface.layerTreeView().clicked.connect(self.on_click_legend)
def unload(self):
""" Release of resources """
# Unmap signals
self.iface.layerTreeView().currentLayerChanged.disconnect(self.on_change_current_layer)
self.iface.layerTreeView().clicked.disconnect(self.on_click_legend)
self.combobox.activated.disconnect()
photo_search_layer = self.layers.get_by_id(self.photo_search_layer_id)
if photo_search_layer:
photo_search_layer.selectionChanged.disconnect(self.on_change_photo_selection)
if self.photo_search_dialog:
photo_search_layer.willBeDeleted.disconnect(self.photo_search_dialog.reset)
self.log.debug("Disconnected signals")
# Remove photo dialog
if self.photo_search_dialog:
self.photo_search_dialog.visibilityChanged.disconnect()
self.photo_search_dialog.reset()
self.iface.removeDockWidget(self.photo_search_dialog)
self.photo_search_dialog = None
# Remove photo search groups
self.legend.remove_group_by_name(self.photos_group_name)
self.legend.remove_group_by_name(self.download_group_name)
self.log.debug("Removed groups")
# Remove GeoFinder dialog
self.geofinder_dialog = None
# Remove Download dialog
self.download_dialog = None
self.log.debug("Removed dialogs")
# Unload fonts
self.log.debug("Removed fonts: %s" % self.unload_fonts(self.font_id_list))
# Log plugin unloaded
self.log.info("Unload %s%s", self.metadata.get_name(), " Lite" if self.lite else "")
# Parent PluginBase class release all GUI resources created with their functions
super().unload()
def get_catalonia_limits(self, filename, buffer=0, segments=10):
""" Gets Catalonia limits from geojson resource file
Apply 250m of buffer to fix possible errors on CAT envolope scale 1:1,000,000 """
t0 = datetime.datetime.now()
pathname = os.path.join(self.plugin_path, "data", "%s.geojson" % filename)
if not os.path.exists(pathname):
self.log.warning("Geometry limits %s file not found %s", filename, pathname)
return None, None
tmp_layer = QgsVectorLayer(pathname, "cat_limits", "ogr")
if tmp_layer.featureCount() < 1:
self.log.warning("Load geometry limits %s error: %s\nFeatures: %s",
filename, pathname, tmp_layer.featureCount())
geom = list(tmp_layer.getFeatures())[0].geometry().buffer(buffer, segments)
if not geom or geom.isEmpty():
self.log.warning("Load geometry limits %s empty: %s\nFeatures: %s",
filename, pathname, tmp_layer.featureCount())
epsg = tmp_layer.crs().authid()
t1 = datetime.datetime.now()
self.log.info("Load geometry limits: %s (features: %s, empty: %s, buffer: %s, segments: %s, EPSG:%s) (%s)",
pathname, tmp_layer.featureCount(), geom.isEmpty(), buffer, segments, epsg, t1-t0)
return geom, epsg
def format_scale(self, scale):
""" Format scale number with locale separator """
text = format(scale, ",d")
if self.translation.get_qgis_language() in ['ca', 'es']:
text = text.replace(',', '.')
return text
def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
""" GUI initializacion """
# Log plugin started
t0 = datetime.datetime.now()
self.log.info("Initializing GUI")
# Plugin registration in the plugin manager
self.gui.configure_plugin()
# Add combobox to search
self.combobox = QComboBox()
self.combobox.setFixedSize(QSize(250,24))
self.combobox.setEditable(True)
self.combobox.setInsertPolicy(QComboBox.InsertAtTop)
self.combobox.setToolTip(self.TOOLTIP_HELP)
self.combobox.addItems(self.get_setting_value("last_searches", []))
self.combobox.setCurrentText("")
self.combobox.setMaxVisibleItems(20)
self.combobox.activated.connect(self.run) # Press intro and select combo value
# Gets available Topo5k files to simulate WMS-T service
topo5k_time_series_list = [(time_year, "/vsicurl/%s" % url) for time_year, url in get_topographic_5k()]
# Get Available delimitations
delimitations_list = get_delimitations()
# Gets available Sheets and Grids
sheets_list = get_sheets()
grids_list = get_grids()
# Gets available DTMs i costa
dtm_list = [(name, "/vsicurl/%s" % url) for name, url in get_dtms()]
height_highlighting_url = dtm_list[0][1] if dtm_list else None
coast_dtm_list = [(name, "/vsicurl/%s" % url) for name, url in get_coast_dtms()]
bathimetric_list = [(name, "/vsicurl/%s" % url) for name, url in get_bathimetrics()]
coastline_list = [(name, "/vsicurl/%s" % url) for name, url in get_coastlines()]
# Gets available NDVI files to simulate WMS-T service
ndvi_time_series_list = [(time_year, "/vsicurl/%s" % url) for time_year, url in get_ndvis()]
ndvi_current_time = ndvi_time_series_list[-1][0] if ndvi_time_series_list else None
# Gets all ortho data (except satellite)
ortho_wms_url, historic_ortho_list = get_full_ortho()
ortho_color_time_series_list = [(str(year), layer_id) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortofoto" and color != "irc"]
ortho_color_year, ortho_color_current_time = ortho_color_time_series_list[-1] if ortho_color_time_series_list else (None, None)
ortho_infrared_time_series_list = [(str(year), layer_id) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortofoto" and color == "irc"]
ortho_infrared_year, ortho_infrared_current_time = ortho_infrared_time_series_list[-1] if ortho_infrared_time_series_list else (None, None)
ortosuperexp_color_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "superexpedita" and color != "irc"]
ortosuperexp_color_year, ortosuperexp_color_layer_id, ortosuperexp_color_layer_name = ortosuperexp_color_list[-1] if ortosuperexp_color_list else (None, None, None)
ortosuperexp_infrared_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "superexpedita" and color == "irc"]
ortosuperexp_infrared_year, ortosuperexp_infrared_layer_id, ortosuperexp_infrared_layer_name = ortosuperexp_infrared_list[-1] if ortosuperexp_infrared_list else (None, None, None)
ortoxpres_color_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortoxpres" and color != "irc"]
ortoxpres_color_year, ortoxpres_color_layer_id, ortoxpres_color_layer_name = ortoxpres_color_list[-1] if ortoxpres_color_list else (None, None, None)
ortoxpres_infrared_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortoxpres" and color == "irc"]
ortoxpres_infrared_year, ortoxpres_infrared_layer_id, ortoxpres_infrared_layer_name = ortoxpres_infrared_list[-1] if ortoxpres_infrared_list else (None, None, None)
# Gets anaglyph fotograms. Last year can not have full photograms coverage, we select previous year as default
photolib_wms_url = PHOTOLIB_WMS
photolib_time_series_list, photolib_current_time = self.layers.get_wms_t_time_series(photolib_wms_url, "anaglif_central")
photolib_current_time = str(int(photolib_current_time) - 1) if photolib_current_time else photolib_current_time
# Gets available download source data
fme_services_list = get_services()
download_raster_submenu = self.get_download_menu(fme_services_list, raster_not_vector=True)
download_vector_submenu = self.get_download_menu(fme_services_list, raster_not_vector=False)
# Check plugin update
new_icgc_plugin_version = self.check_plugin_update() if check_icgc_updates else None
new_qgis_plugin_version = self.metadata.get_qgis_new_version_available() if check_qgis_updates and not self.lite else None
new_plugin_version = new_qgis_plugin_version or new_icgc_plugin_version
# Add new toolbar with plugin options (using pluginbase functions)
style = self.iface.mainWindow().style()
self.default_map_callback = lambda _checked=False: self.layers.add_wms_layer(\
self.tr("Topographic map (topographical pyramid)"), \
"https://geoserveis.icgc.cat/icc_mapesmultibase/utm/wms/service", \
["topo"], ["default"], "image/png", 25831, self.request_referrer_param, \
self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True)
self.toolbar = self.gui.configure_toolbar(self.tr("Open ICGC Toolbar") + (" lite" if self.lite else ""), [
self.tr("Find"), # Label text
self.combobox, # Editable combobox
(self.tr("Find place names and adresses"), self.run, QIcon(":/lib/qlib3/geofinderdialog/images/geofinder.png")), # Action button
"---",
(self.tr("Background maps"),
self.default_map_callback,
QIcon(":/lib/qlib3/base/images/wms.png"), True, False, "background_maps", [
(self.tr("Topographic map (topographical pyramid)"),
self.default_map_callback,
QIcon(":/lib/qlib3/base/images/cat_topo250k.png"),
self.manage_metadata_button("Topographic map (topographical pyramid)"), True),
(self.tr("Territorial topographic referential"), None, QIcon(":/lib/qlib3/base/images/cat_topo5k.png"), \
self.enable_http_files and len(topo5k_time_series_list) > 0, [
(self.tr("Territorial topographic referential %s (temporal serie)") % topo5k_year,
lambda _checked, topo5k_year=topo5k_year:self.add_wms_t_layer(self.tr("[TS] Territorial topographic referential"), None, topo5k_year, None, "default", "image/png", topo5k_time_series_list[::-1], None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, resampling_bilinear=True, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_topo5k.png"),
self.manage_metadata_button("Territorial topographic referential %s (temporal serie)" % topo5k_year), True)
for topo5k_year, _url in topo5k_time_series_list]),
(self.tr("Topographic map 1:250,000"),
lambda _checked:self.layers.add_wms_layer(self.tr("Topographic map 1:250,000"), "https://geoserveis.icgc.cat/icc_mapesbase/wms/service", ["mtc250m"], ["default"], "image/png", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_topo250k.png"),
self.manage_metadata_button("Topographic map 1:250,000"), True),
"---",
(self.tr("ContextMaps"), None, QIcon(":/lib/qlib3/base/images/cat_cmstandard.png"), [
(self.tr("ContextMaps standard map"),
lambda _checked:self.layers.add_wms_layer(self.tr("ContextMaps standard map"), "https://geoserveis.icgc.cat/servei/catalunya/contextmaps/wms", ["contextmaps-mapa-estandard"], [""], "image/jpeg", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_cmstandard.png"),
self.manage_metadata_button("ContextMaps standard map"), True),
(self.tr("ContextMaps gray map"),
lambda _checked:self.layers.add_wms_layer(self.tr("ContextMaps gray map"), "https://geoserveis.icgc.cat/servei/catalunya/contextmaps/wms", ["contextmaps-mapa-base-gris"], [""], "image/jpeg", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_cmgray.png"),
self.manage_metadata_button("ContextMaps gray map"), True),
(self.tr("ContextMaps simplified gray map"),
lambda _checked:self.layers.add_wms_layer(self.tr("ContextMaps simplified gray map"), "https://geoserveis.icgc.cat/servei/catalunya/contextmaps/wms", ["contextmaps-mapa-base-gris-simplificat"], [""], "image/jpeg", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_cmgray.png"),
self.manage_metadata_button("ContextMaps simplified gray map"), True),
(self.tr("ContextMaps hybrid orthophoto"),
lambda _checked:self.layers.add_wms_layer(self.tr("ContextMaps hybrid orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/contextmaps/wms", ["contextmaps-orto-hibrida"], [""], "image/jpeg", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_cmortho.png"),
self.manage_metadata_button("ContextMaps hybrid orthophoto"), True),
]),
"---",
(self.tr("Administrative divisions"), None, QIcon(":/lib/qlib3/base/images/cat_vector.png"), self.enable_http_files, [
(self.tr("Administrative divisions (raster pyramid)"),
lambda _checked:self.layers.add_wms_layer(self.tr("Administrative divisions (raster pyramid)"), "https://geoserveis.icgc.cat/servei/catalunya/divisions-administratives/wms",
['divisions_administratives_comarques_1000000', 'divisions_administratives_comarques_500000', 'divisions_administratives_comarques_250000', 'divisions_administratives_comarques_100000', 'divisions_administratives_comarques_50000', 'divisions_administratives_comarques_5000', 'divisions_administratives_municipis_250000', 'divisions_administratives_municipis_100000', 'divisions_administratives_municipis_50000', 'divisions_administratives_municipis_5000', 'divisions_administratives_capsdemunicipi_capmunicipi', 'divisions_administratives_capsdemunicipi_capcomarca'],
["default"], "image/png", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_vector.png"),
self.manage_metadata_button("Administrative divisions"), True),
"---",
] + [
(self.HTTP_NAMES_DICT.get(name, name),
(lambda _checked, name=name, scale_list=scale_list, style_file=style_file:self.layers.add_vector_layer(self.HTTP_NAMES_DICT.get(name, name), scale_list[0][1], group_name=self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, style_file=style_file) if len(scale_list) == 1 else None),
QIcon(":/lib/qlib3/base/images/cat_vector.png"), ([
("%s 1:%s" % (self.HTTP_NAMES_DICT.get(name, name), self.format_scale(scale)),
lambda _checked, name=name, scale=scale, url=url, style_file=style_file:self.layers.add_vector_layer("%s 1:%s" % (self.HTTP_NAMES_DICT.get(name, name), self.format_scale(scale)), url, group_name=self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, style_file=style_file),
QIcon(":/lib/qlib3/base/images/cat_vector.png"),
self.manage_metadata_button("Administrative divisions"), True)
for scale, url in scale_list] if len(scale_list) > 1 \
else self.manage_metadata_button("Administrative divisions")),
len(scale_list) == 1)
for name, scale_list, style_file in delimitations_list
]),
(self.tr("Cartographic series"), None, QIcon(":/lib/qlib3/base/images/sheets.png"), self.enable_http_files, [
(self.tr("%s serie") % sheet_name,
lambda _checked, sheet_name=sheet_name, sheet_url=sheet_url:self.layers.add_vector_layer(self.tr("%s serie") % sheet_name, sheet_url, group_name=self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, style_file="talls.qml"),
QIcon(":/lib/qlib3/base/images/sheets.png"), self.enable_http_files,
self.manage_metadata_button("Cartographic series"), True
) for sheet_name, sheet_url in sheets_list
] + [
"---"
] + [
(self.tr("%s grid") % grid_name,
lambda _checked, grid_name=grid_name, grid_url=grid_url:self.layers.add_vector_layer(self.tr("%s grid") % grid_name, grid_url, group_name=self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, style_file="talls.qml"),
QIcon(":/lib/qlib3/base/images/sheets.png"), self.enable_http_files,
self.manage_metadata_button("UTM (MGRS) grids"), True
) for grid_name, grid_url in grids_list
]),
"---",
(self.tr("Geological map 1:250,000"),
lambda _checked:self.layers.add_wms_layer(self.tr("Geological map 1:250,000"), "https://geoserveis.icgc.cat/servei/catalunya/geologia-territorial/wms", ["geologia-territorial-250000-geologic"], ["default"], "image/png", 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, resampling_bilinear=True),
QIcon(":/lib/qlib3/base/images/cat_geo250k.png"),
self.manage_metadata_button("Geological map 1:250,000"), True),
(self.tr("Land cover map (temporal serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[TS] Land cover map"), "https://geoserveis.icgc.cat/servei/catalunya/cobertes-sol/wms", None, None, "default", "image/png", None, r"cobertes_(\d+)", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_landcover.png"),
self.manage_metadata_button("Land cover map (temporal serie)"), True),
"---",
] + [(self.tr("Digital Terrain Model %s") % dtm_name,
# Force EPSG:25831 by problems with QGIS 3.10 version
lambda _checked, dtm_name=dtm_name, dtm_url=dtm_url:self.layers.add_raster_layer(self.tr("Digital Terrain Model %s") % dtm_name, dtm_url, group_name=self.backgroup_map_group_name, group_pos=0, epsg=25831, only_one_map_on_group=False, set_current=True, color_default_expansion=True, resampling_bilinear=True),
QIcon(":/lib/qlib3/base/images/cat_dtm.png"), self.enable_http_files,
self.manage_metadata_button("Digital Terrain Model %s" % dtm_name), True
) for dtm_name, dtm_url in dtm_list] + [
"---",
] + ([
(self.tr("Coast"), None, QIcon(":/lib/qlib3/base/images/cat_coast.png"), [
("%s %s" % (self.tr("Topobathymetric elevation model"), dtm_name),
# Force EPSG:25831 by problems with QGIS 3.10 version
lambda _checked, dtm_name=dtm_name, dtm_url=dtm_url:self.layers.add_raster_layer("%s %s" % (self.tr("Topobathymetric elevation model"), dtm_name), dtm_url, group_name=self.backgroup_map_group_name, group_pos=0, epsg=25831, only_one_map_on_group=False, set_current=True, color_default_expansion=True, resampling_bilinear=True),
QIcon(":/lib/qlib3/base/images/cat_coast.png"), self.enable_http_files,
self.manage_metadata_button("Topobathymetric elevation model %s" % dtm_name), True
) for dtm_name, dtm_url in coast_dtm_list] + [
"---"
] + [
("%s %s" % (self.tr("Bathymetric chart"), bathymetric_name),
# Force EPSG:25831 by problems with QGIS 3.10 version
lambda _checked, bathymetric_name=bathymetric_name, bathymetri_url=bathymetri_url:self.layers.add_vector_layer("%s %s" % (self.tr("Bathymetric chart"), bathymetric_name), bathymetri_url, group_name=self.backgroup_map_group_name, group_pos=0, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_coast.png"), self.enable_http_files,
self.manage_metadata_button("Bathymetric chart %s" % bathymetric_name), True
) for bathymetric_name, bathymetri_url in bathimetric_list] + [
"---"
] + [
("%s %s" % (self.tr("Coastline"), coastline_name),
# Force EPSG:25831 by problems with QGIS 3.10 version
lambda _checked, coastline_name=coastline_name, coastline_url=coastline_url:self.layers.add_vector_layer("%s %s" % (self.tr("Coastline"), coastline_name), coastline_url, group_name=self.backgroup_map_group_name, group_pos=0, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_coast.png"), self.enable_http_files,
self.manage_metadata_button("Coastline %s" % coastline_name), True
) for coastline_name, coastline_url in coastline_list]
),
"---",
] if coast_dtm_list or bathimetric_list or coastline_list else []) + [
(self.tr("NDVI color (temporal serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI color"), "https://geoserveis.icgc.cat/servei/catalunya/ndvi/wms", "ndvi_serie_anual_color", None, "default", "image/png", None, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_landcover.png"),
self.manage_metadata_button("NDVI (temporal serie)"), True),
(self.tr("NDVI (temporal serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI"), None, ndvi_current_time, None, "default", "image/png", ndvi_time_series_list, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_shadows.png"), self.enable_http_files and len(ndvi_time_series_list) > 0,
self.manage_metadata_button("NDVI (temporal serie)"), True),
"---",
(self.tr("Current color orthophoto") + " (%s)" % ortho_color_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Current color orthophoto"), ortho_wms_url, ["ortofoto_color_vigent"], ["default"], "image/png", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Color orthophoto (temporal serie)"), True),
(self.tr("Color orthophoto"), None, QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"), [
] + ([(self.tr("Color orthophoto %s (provisional)") % ortoxpres_color_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Color orthophoto %s (provisional)") % ortoxpres_color_year, ortho_wms_url, [ortoxpres_color_layer_id], [""], "image/png", 25831, self.request_referrer_param + "&bgcolor=0xFFFFFF", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Color orthophoto %s (provisional)" % ortoxpres_color_year), True
)] if ortoxpres_color_list else []) + [
] + ([(self.tr("Color orthophoto %s (rectification without corrections)") % ortosuperexp_color_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Color orthophoto %s (rectification without corrections)") % ortosuperexp_color_year, ortho_wms_url, [ortosuperexp_color_layer_id], [""], "image/png", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Color orthophoto %s (rectification without corrections)" % ortosuperexp_color_year), True
)] if ortosuperexp_color_list else []) + [
"---",
] + [
(self.tr("Color orthophoto %s (temporal serie)") % ortho_year,
lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Color orthophoto"), ortho_wms_url, layer_id, None, "default", "image/png", ortho_color_time_series_list, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Color orthophoto (temporal serie)"), True
) for ortho_year, layer_id in reversed(ortho_color_time_series_list)
] + [
"---",
(self.tr("Color orthophoto (annual serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[AS] Color orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_color_serie_anual", None, "", "image/png", None, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png"),
self.manage_metadata_button("Color orthophoto (temporal serie)"), True),
]),
(self.tr("Satellite color orthophoto (monthly serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite color orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2rgb", None, "", "image/png", None, None, 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png"),
self.manage_metadata_button("Satellite color orthophoto (monthly serie)"), True),
"---",
(self.tr("Current infrared orthophoto") + " (%s)" % ortho_infrared_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Current infrared orthophoto"), ortho_wms_url, ["ortofoto_infraroig_vigent"], ["default"], "image/png", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Infrared orthophoto (temporal serie)"), True),
(self.tr("Infrared orthophoto"), None, QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png"), [
] + ([(self.tr("Infrared orthophoto %s (provisional)") % ortoxpres_infrared_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Infrared orthophoto %s (provisional)") % ortoxpres_infrared_year, ortho_wms_url, [ortoxpres_infrared_layer_id], [""], "image/png", 25831, self.request_referrer_param + "&bgcolor=0xFFFFFF", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png"),
self.manage_metadata_button("Infrared orthophoto %s (provisional)" % ortoxpres_infrared_year), True)
] if ortoxpres_infrared_list else []) + [
] + ([(self.tr("Infrared orthophoto %s (rectification without corrections)") % ortosuperexp_infrared_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Infrared orthophoto %s (rectification without corrections)") % ortosuperexp_infrared_year, ortho_wms_url, [ortosuperexp_infrared_layer_id], [""], "image/png", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png"),
self.manage_metadata_button("Infrared orthophoto %s (rectification without corrections)" % ortosuperexp_infrared_year), True)
] if ortosuperexp_infrared_list else []) + [
"---",
] + [
(self.tr("Infrared orthophoto %s (temporal serie)") % ortho_year,
lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Infrared orthophoto"), ortho_wms_url, layer_id, None, "default", "image/png", ortho_infrared_time_series_list, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"),
self.manage_metadata_button("Infrared orthophoto (temporal serie)"), True
) for ortho_year, layer_id in reversed(ortho_infrared_time_series_list)
] + [
"---",
(self.tr("Infrared orthophoto (annual serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[AS] Infrared orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_infraroig_serie_anual", None, "", "image/png", None, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png"),
self.manage_metadata_button("Infrared orthophoto (temporal serie)"), True),
]),
(self.tr("Satellite infrared orthophoto (monthly serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite infared orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2irc", None, "default", "image/png", None, None, 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png"),
self.manage_metadata_button("Satellite infrared orthophoto (monthly serie)"), True),
"---",
(self.tr("Current gray orthophoto") + " (%s)" % ortho_color_year,
lambda _checked:self.layers.add_wms_layer(self.tr("Current gray orthophoto"), ortho_wms_url, ["ortofoto_gris_vigent"], ["default"], "image/png", 25831, self.request_referrer_param + "&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png"),
self.manage_metadata_button("Gray orthophoto (temporal serie)"), True),
"---",
(self.tr("Centered anaglyph photogram"), None, QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png"), [
(self.tr("Centered anaglyph photogram %s (annual serie)") % anaglyph_year,
lambda _checked,anaglyph_year=anaglyph_year,anaglyph_layer=anaglyph_layer:self.add_wms_t_layer(self.tr("[AS] Centered anaglyph phootogram"), photolib_wms_url, anaglyph_layer, str(anaglyph_year), "central,100,false", "image/png", None, None, 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png")
) for anaglyph_year, anaglyph_layer in reversed(photolib_time_series_list)])
] + ([
(self.tr("Centered rectified photogram (annual serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[AS] Centered rectified photogram"), photolib_wms_url, "ortoxpres_central", photolib_current_time, "central", "image/png", None, None, 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
QIcon(":/lib/qlib3/photosearchselectiondialog/images/rectified_preview.png")),
(self.tr("Centered photogram (annual serie)"),
lambda _checked:self.add_wms_t_layer(self.tr("[AS] Centered photogram"), photolib_wms_url, "foto_central", photolib_current_time, "central", "image/png", None, None, 25831, self.request_referrer_param, self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_preview.png")),
] if self.debug_mode else []) + [
"---"
] + ([
(self.tr("Instamaps pyramid"),
lambda:self.layers.add_wms_layer(self.tr("Instamaps pyramid"), "https://tilemaps.icgc.cat/mapfactory/service", ["osm_suau"], ["default"], "image/png", 25831, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_topo5k.png")),
"---",
(self.tr("Spain"), None, QIcon(":/lib/qlib3/base/images/spain_topo.png"), [
(self.tr("IGN topographic"),
lambda:self.layers.add_wms_layer(self.tr("IGN topographic"), "http://www.ign.es/wms-inspire/mapa-raster", ["mtn_rasterizado"], ["default"], "image/png", 25830, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/spain_topo.png")),
"---",
(self.tr("PNOA orthophoto"),
lambda:self.layers.add_wms_layer(self.tr("PNOA orthophoto"), "http://www.ign.es/wms-inspire/pnoa-ma", ["OI.OrthoimageCoverage"], ["default"], "image/png", 25830, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/spain_orto.png")),
"---",
(self.tr("Cadastral registry"),
lambda:self.layers.add_wms_layer(self.tr("Cadastral registry"), "http://ovc.catastro.meh.es/Cartografia/WMS/ServidorWMS.aspx", ["Catastro"], ["default"], "image/png", 25831, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/spain_cadastral.png")),
]),
(self.tr('Andorra'), None, QIcon(":/lib/qlib3/base/images/andorra_topo50k.png"), [
(self.tr("Andorra topographic 1:50,000 2020"),
lambda:self.layers.add_wms_layer(self.tr("Andorra topographic 1:50,000 2020"), "https://www.ideandorra.ad/Serveis/wmscarto50kraster_2020/wms", ["mta50m2020geotif"], [], "image/png", 27563, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/andorra_topo50k.png")),
"---",
(self.tr("Andorra orthophoto 1:5,000 2012"),
lambda:self.layers.add_wms_layer(self.tr("Andorra orthophoto 1:5,000 2012"), "https://www.ideandorra.ad/Serveis/wmsorto2012/wms", ["orto2012"], [], "image/png", 27563, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/andorra_orto2003.png")),
]),
(self.tr("France"), None, QIcon(":/lib/qlib3/base/images/france_topo.png"), [
(self.tr("France topographic"),
lambda:self.layers.add_wms_layer(self.tr("France topographic"), "http://mapsref.brgm.fr/wxs/refcom-brgm/refign", ["FONDS_SCAN"], [], "image/png", 23031, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/france_topo.png")),
"---",
(self.tr("France orthophoto 20cm"),
lambda:self.layers.add_wms_layer(self.tr("France orthophoto 20cm"), "https://data.geopf.fr/annexes/ressources/wms-r/ortho.xml", ["HR.ORTHOIMAGERY.ORTHOPHOTOS"], ["normal"], "image/png", 23031, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True, ignore_get_map_url=False),
QIcon(":/lib/qlib3/base/images/france_ortho.png")),
]),
(self.tr("World"), None, QIcon(":/lib/qlib3/base/images/world.png"), [
(self.tr("OpenStreetMap"),
lambda:self.layers.add_wms_layer(self.tr("OpenStreetMap"), "http://ows.terrestris.de/osm/service", ["OSM-WMS"], [], "image/png", 4326, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/world.png")),
(self.tr("NASA blue marble"),
lambda:self.layers.add_wms_layer(self.tr("NASA blue marble"), "http://geoserver.webservice-energy.org/geoserver/ows", ["gn:bluemarble-2048"], [], "image/png", 4326, '', self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/world.png")),
]),
"---",
] if self.extra_countries or self.debug_mode else []) + [
(self.tr("Delete background maps"), lambda _checked:self.legend.empty_group_by_name(self.backgroup_map_group_name),
QIcon(":/lib/qlib3/base/images/wms_remove.png"), True, False, "delete_background")
]),
(self.tr("Time series"),
lambda _checked:self.tools.toggle_time_series_dialog(self.iface.mapCanvas().currentLayer(), self.tr("Time series"), self.tr("Selected: ")) if type(self.iface.mapCanvas().currentLayer()) in [QgsRasterLayer, QgsVectorLayer] else None,
QIcon(":/lib/qlib3/base/images/time.png"),
False, True, "time_series"),
] + ([
(self.tr("Search photograms"), (self.enable_search_photos, self.pair_photo_search_checks), QIcon(":/plugins/openicgc/images/search.png"), True, True, "photo_search", [
(self.tr("Search photograms interactively"), (self.enable_search_photos, self.pair_photo_search_checks), QIcon(":/plugins/openicgc/images/search.png"), True, True, "photo_search_2"),
(self.tr("Search photograms by coordinates"), lambda _checked:self.search_photos_by_point(), QIcon(":/plugins/openicgc/images/search_coord.png"), True, False),
(self.tr("Search photograms by name"), lambda _checked:self.search_photos_by_name(), QIcon(":/plugins/openicgc/images/search_name.png"), True, False),
]),
(self.tr("Download tool"), self.enable_last_download, QIcon(":/plugins/openicgc/images/download_area.png"), True, True, "download", [
(self.tr("Select download folder"), self.set_download_folder, QIcon(":/lib/qlib3/base/images/download_folder.png"), True, False, "select_download_folder"),
(self.tr("Open download folder"), self.open_download_folder, style.standardIcon(QStyle.SP_DirIcon), True, False, "open_download_folder"),
"---",
] + download_vector_submenu + [
"---"
] + download_raster_submenu + [
"---",
(self.tr("Save map as PDF"), lambda:self.save_map("A4H", "", self.tr("Save map as PDF")), QIcon(":/plugins/openicgc/images/pdf.png"), True, False, "save_pdf"),
(self.tr("Save location map as PDF"), lambda:self.save_map("A4V", self.tr(" (location)"), self.tr("Save location map as PDF")), QIcon(":/plugins/openicgc/images/pdf.png"), True, False, "save_location_pdf"),
])
] if not self.lite else []) + [
(self.tr("Paint styles for selected layers"), None, QIcon(":/lib/qlib3/base/images/style.png"), [
(self.tr("Transparence"),
lambda _checked:self.tools.show_transparency_dialog(self.tr("Transparence"), self.iface.mapCanvas().currentLayer()) if type(self.iface.mapCanvas().currentLayer()) in [QgsRasterLayer, QgsVectorLayer] else None,
QIcon(":/lib/qlib3/base/images/transparency.png")),
(self.tr("Desaturate raster layer"),
lambda _checked:self.layers.set_saturation(self.iface.mapCanvas().currentLayer(), -100, True) if type(self.iface.mapCanvas().currentLayer()) is QgsRasterLayer else None,
QIcon(":/lib/qlib3/base/images/desaturate.png")),
(self.tr("Height highlighting"),
lambda _checked, dtm_url=height_highlighting_url:self.add_height_highlighting_layer(self.tr("Height highlighting"), dtm_url, style_file="ressaltat_alçades.qml", group_name=self.backgroup_map_group_name),
QIcon(":/lib/qlib3/base/images/cat_shadows.png"), self.enable_http_files and height_highlighting_url),