Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
LETG
Rename bands
Commits
caa9813e
Commit
caa9813e
authored
Sep 14, 2021
by
PIERSON Julie
Browse files
first poc for using custom widget based on ReliefColorsWidget
parent
71cac81d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
484 additions
and
1 deletion
+484
-1
BandTableWidget.py
BandTableWidget.py
+269
-0
bandtablewidgetbase.ui
bandtablewidgetbase.ui
+127
-0
merge_rename_bands_algorithm.py
merge_rename_bands_algorithm.py
+88
-1
No files found.
BandTableWidget.py
0 → 100644
View file @
caa9813e
# -*- coding: utf-8 -*-
"""
***************************************************************************
BandTableWidget.py
---------------------
Date : 2021-09-14
Copyright : (C) 2021 by J. Pierson, UMR 6554 LETG, CNRS
Email : julie.pierson@univ-brest.fr
Based upon : ReliefColorsWidget.py (C) 2016 by Alexander Bruy
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__
=
'J. Pierson, UMR 6554 LETG, CNRS'
__date__
=
'2021-09-14'
__copyright__
=
'(C) 2021 by J. Pierson, UMR 6554 LETG, CNRS'
import
os
import
codecs
from
qgis.PyQt
import
uic
from
qgis.PyQt.QtCore
import
pyqtSlot
,
QDir
from
qgis.PyQt.QtGui
import
QColor
,
QBrush
from
qgis.PyQt.QtWidgets
import
(
QTreeWidgetItem
,
QFileDialog
,
QMessageBox
,
QInputDialog
,
QColorDialog
)
from
qgis.PyQt.QtXml
import
QDomDocument
from
qgis.core
import
QgsApplication
,
QgsMapLayer
from
qgis.analysis
import
QgsRelief
from
processing.gui.wrappers
import
WidgetWrapper
from
processing.tools
import
system
pluginPath
=
os
.
path
.
dirname
(
__file__
)
WIDGET
,
BASE
=
uic
.
loadUiType
(
os
.
path
.
join
(
pluginPath
,
'bandtablewidgetbase.ui'
))
class
BandTableWidget
(
BASE
,
WIDGET
):
def
__init__
(
self
):
super
(
BandTableWidget
,
self
).
__init__
(
None
)
self
.
setupUi
(
self
)
self
.
btnAdd
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/symbologyAdd.svg'
))
self
.
btnRemove
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/symbologyRemove.svg'
))
self
.
btnUp
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/mActionArrowUp.svg'
))
self
.
btnDown
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/mActionArrowDown.svg'
))
self
.
btnLoad
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/mActionFileOpen.svg'
))
self
.
btnSave
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/mActionFileSave.svg'
))
self
.
btnAuto
.
setIcon
(
QgsApplication
.
getThemeIcon
(
'/mActionReload.svg'
))
self
.
layer
=
None
@
pyqtSlot
()
def
on_btnAdd_clicked
(
self
):
item
=
QTreeWidgetItem
()
item
.
setText
(
0
,
'0.00'
)
item
.
setText
(
1
,
'0.00'
)
item
.
setBackground
(
2
,
QBrush
(
QColor
(
127
,
127
,
127
)))
self
.
bandClassTree
.
addTopLevelItem
(
item
)
@
pyqtSlot
()
def
on_btnRemove_clicked
(
self
):
selectedItems
=
self
.
bandClassTree
.
selectedItems
()
for
item
in
selectedItems
:
self
.
bandClassTree
.
invisibleRootItem
().
removeChild
(
item
)
item
=
None
@
pyqtSlot
()
def
on_btnDown_clicked
(
self
):
selectedItems
=
self
.
bandClassTree
.
selectedItems
()
for
item
in
selectedItems
:
currentIndex
=
self
.
bandClassTree
.
indexOfTopLevelItem
(
item
)
if
currentIndex
<
self
.
bandClassTree
.
topLevelItemCount
()
-
1
:
self
.
bandClassTree
.
takeTopLevelItem
(
currentIndex
)
self
.
bandClassTree
.
insertTopLevelItem
(
currentIndex
+
1
,
item
)
self
.
bandClassTree
.
setCurrentItem
(
item
)
@
pyqtSlot
()
def
on_btnUp_clicked
(
self
):
selectedItems
=
self
.
bandClassTree
.
selectedItems
()
for
item
in
selectedItems
:
currentIndex
=
self
.
bandClassTree
.
indexOfTopLevelItem
(
item
)
if
currentIndex
>
0
:
self
.
bandClassTree
.
takeTopLevelItem
(
currentIndex
)
self
.
bandClassTree
.
insertTopLevelItem
(
currentIndex
-
1
,
item
)
self
.
bandClassTree
.
setCurrentItem
(
item
)
@
pyqtSlot
()
def
on_btnLoad_clicked
(
self
):
fileName
,
_
=
QFileDialog
.
getOpenFileName
(
None
,
self
.
tr
(
'Import Colors and elevations from XML'
),
QDir
.
homePath
(),
self
.
tr
(
'XML files (*.xml *.XML)'
))
if
fileName
==
''
:
return
doc
=
QDomDocument
()
with
codecs
.
open
(
fileName
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
content
=
f
.
read
()
if
not
doc
.
setContent
(
content
):
QMessageBox
.
critical
(
None
,
self
.
tr
(
'Error parsing XML'
),
self
.
tr
(
'The XML file could not be loaded'
))
return
self
.
bandClassTree
.
clear
()
reliefColorList
=
doc
.
elementsByTagName
(
'ReliefColor'
)
for
i
in
range
(
reliefColorList
.
length
()):
elem
=
reliefColorList
.
at
(
i
).
toElement
()
item
=
QTreeWidgetItem
()
item
.
setText
(
0
,
elem
.
attribute
(
'MinElevation'
))
item
.
setText
(
1
,
elem
.
attribute
(
'MaxElevation'
))
item
.
setBackground
(
2
,
QBrush
(
QColor
(
int
(
elem
.
attribute
(
'red'
)),
int
(
elem
.
attribute
(
'green'
)),
int
(
elem
.
attribute
(
'blue'
)))))
self
.
bandClassTree
.
addTopLevelItem
(
item
)
@
pyqtSlot
()
def
on_btnSave_clicked
(
self
):
fileName
,
_
=
QFileDialog
.
getSaveFileName
(
None
,
self
.
tr
(
'Export Colors and elevations as XML'
),
QDir
.
homePath
(),
self
.
tr
(
'XML files (*.xml *.XML)'
))
if
fileName
==
''
:
return
if
not
fileName
.
lower
().
endswith
(
'.xml'
):
fileName
+=
'.xml'
doc
=
QDomDocument
()
colorsElem
=
doc
.
createElement
(
'ReliefColors'
)
doc
.
appendChild
(
colorsElem
)
colors
=
self
.
reliefColors
()
for
c
in
colors
:
elem
=
doc
.
createElement
(
'ReliefColor'
)
elem
.
setAttribute
(
'MinElevation'
,
str
(
c
.
minElevation
))
elem
.
setAttribute
(
'MaxElevation'
,
str
(
c
.
maxElevation
))
elem
.
setAttribute
(
'red'
,
str
(
c
.
color
.
red
()))
elem
.
setAttribute
(
'green'
,
str
(
c
.
color
.
green
()))
elem
.
setAttribute
(
'blue'
,
str
(
c
.
color
.
blue
()))
colorsElem
.
appendChild
(
elem
)
with
codecs
.
open
(
fileName
,
'w'
,
encoding
=
'utf-8'
)
as
f
:
f
.
write
(
doc
.
toString
(
2
))
@
pyqtSlot
()
def
on_btnAuto_clicked
(
self
):
if
self
.
layer
is
None
:
return
relief
=
QgsRelief
(
self
.
layer
,
system
.
getTempFilename
(),
'GTiff'
)
colors
=
relief
.
calculateOptimizedReliefClasses
()
self
.
populateColors
(
colors
)
@
pyqtSlot
(
QTreeWidgetItem
,
int
)
def
on_bandClassTree_itemDoubleClicked
(
self
,
item
,
column
):
if
not
item
:
return
if
column
==
0
:
d
,
ok
=
QInputDialog
.
getDouble
(
None
,
self
.
tr
(
'Enter lower elevation class bound'
),
self
.
tr
(
'Elevation'
),
float
(
item
.
text
(
0
)),
decimals
=
2
)
if
ok
:
item
.
setText
(
0
,
str
(
d
))
elif
column
==
1
:
d
,
ok
=
QInputDialog
.
getDouble
(
None
,
self
.
tr
(
'Enter upper elevation class bound'
),
self
.
tr
(
'Elevation'
),
float
(
item
.
text
(
1
)),
decimals
=
2
)
if
ok
:
item
.
setText
(
1
,
str
(
d
))
elif
column
==
2
:
c
=
QColorDialog
.
getColor
(
item
.
background
(
2
).
color
(),
None
,
self
.
tr
(
'Select color for relief class'
))
if
c
.
isValid
():
item
.
setBackground
(
2
,
QBrush
(
c
))
def
reliefColors
(
self
):
colors
=
[]
for
i
in
range
(
self
.
bandClassTree
.
topLevelItemCount
()):
item
=
self
.
bandClassTree
.
topLevelItem
(
i
)
if
item
:
c
=
QgsRelief
.
ReliefColor
(
item
.
background
(
2
).
color
(),
float
(
item
.
text
(
0
)),
float
(
item
.
text
(
1
)))
colors
.
append
(
c
)
return
colors
def
populateColors
(
self
,
colors
):
self
.
bandClassTree
.
clear
()
for
c
in
colors
:
item
=
QTreeWidgetItem
()
item
.
setText
(
0
,
str
(
c
.
minElevation
))
item
.
setText
(
1
,
str
(
c
.
maxElevation
))
item
.
setBackground
(
2
,
QBrush
(
c
.
color
))
self
.
bandClassTree
.
addTopLevelItem
(
item
)
def
setLayer
(
self
,
layer
):
self
.
layer
=
layer
def
setValue
(
self
,
value
):
self
.
bandClassTree
.
clear
()
rows
=
value
.
split
(
';'
)
for
r
in
rows
:
v
=
r
.
split
(
','
)
item
=
QTreeWidgetItem
()
item
.
setText
(
0
,
v
[
0
])
item
.
setText
(
1
,
v
[
1
])
color
=
QColor
(
int
(
v
[
2
]),
int
(
v
[
3
]),
int
(
v
[
4
]))
item
.
setBackground
(
2
,
QBrush
(
color
))
self
.
bandClassTree
.
addTopLevelItem
(
item
)
def
value
(
self
):
rColors
=
self
.
reliefColors
()
colors
=
''
for
c
in
rColors
:
colors
+=
'{:f}, {:f}, {:d}, {:d}, {:d};'
.
format
(
c
.
minElevation
,
c
.
maxElevation
,
c
.
color
.
red
(),
c
.
color
.
green
(),
c
.
color
.
blue
())
return
colors
[:
-
1
]
class
BandTableWidgetWrapper
(
WidgetWrapper
):
def
createWidget
(
self
):
return
BandTableWidget
()
def
postInitialize
(
self
,
wrappers
):
for
wrapper
in
wrappers
:
if
wrapper
.
param
.
name
==
self
.
param
.
parent
:
self
.
setLayer
(
wrapper
.
value
())
wrapper
.
widgetValueHasChanged
.
connect
(
self
.
parentValueChanged
)
break
def
parentValueChanged
(
self
,
wrapper
):
self
.
setLayer
(
wrapper
.
parameterValue
())
def
setLayer
(
self
,
layer
):
if
isinstance
(
layer
,
QgsMapLayer
):
layer
=
layer
.
source
()
self
.
widget
.
setLayer
(
layer
)
def
setValue
(
self
,
value
):
self
.
widget
.
setValue
(
value
)
def
value
(
self
):
return
self
.
widget
.
value
()
bandtablewidgetbase.ui
0 → 100644
View file @
caa9813e
<?xml version="1.0" encoding="UTF-8"?>
<ui
version=
"4.0"
>
<class>
Form
</class>
<widget
class=
"QWidget"
name=
"Form"
>
<property
name=
"geometry"
>
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
505
</width>
<height>
209
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
<string
notr=
"true"
>
Form
</string>
</property>
<layout
class=
"QGridLayout"
name=
"gridLayout"
>
<item
row=
"0"
column=
"0"
>
<widget
class=
"QTreeWidget"
name=
"bandClassTree"
>
<column>
<property
name=
"text"
>
<string>
Lower bound
</string>
</property>
</column>
<column>
<property
name=
"text"
>
<string>
Upper bound
</string>
</property>
</column>
<column>
<property
name=
"text"
>
<string>
Color
</string>
</property>
</column>
</widget>
</item>
<item
row=
"0"
column=
"1"
>
<layout
class=
"QVBoxLayout"
name=
"verticalLayout"
>
<item>
<widget
class=
"QToolButton"
name=
"btnAdd"
>
<property
name=
"toolTip"
>
<string>
Add row
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnRemove"
>
<property
name=
"toolTip"
>
<string>
Remove row
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnUp"
>
<property
name=
"toolTip"
>
<string>
Move up
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnDown"
>
<property
name=
"toolTip"
>
<string>
Move down
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<spacer
name=
"verticalSpacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Vertical
</enum>
</property>
<property
name=
"sizeHint"
stdset=
"0"
>
<size>
<width>
20
</width>
<height>
40
</height>
</size>
</property>
</spacer>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnLoad"
>
<property
name=
"toolTip"
>
<string>
Load colors from file
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnSave"
>
<property
name=
"toolTip"
>
<string>
Save colors to file
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QToolButton"
name=
"btnAuto"
>
<property
name=
"toolTip"
>
<string>
Generate color table automatically
</string>
</property>
<property
name=
"text"
>
<string>
…
</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
merge_rename_bands_algorithm.py
View file @
caa9813e
...
...
@@ -31,13 +31,85 @@ __copyright__ = '(C) 2021 by J. Pierson, UMR 6554 LETG, CNRS'
__revision__
=
'$Format:%H$'
from
qgis.PyQt.QtCore
import
QCoreApplication
from
qgis.PyQt.QtGui
import
QIcon
,
QColor
from
qgis.core
import
(
QgsProcessing
,
QgsProcessingAlgorithm
,
QgsProcessingParameterRasterLayer
,
QgsProcessingParameterMatrix
,
QgsProcessingParameterDefinition
,
QgsProcessingParameterString
,
QgsProcessingParameterRasterDestination
)
from
processing.algs.qgis.QgisAlgorithm
import
QgisAlgorithm
from
processing.gui.wrappers
import
WidgetWrapper
#import BandTableWidget
from
qgis.PyQt.QtWidgets
import
QTableWidget
from
osgeo
import
gdal
# custom table widget
class
ParameterBandTable
(
QgsProcessingParameterDefinition
):
def
__init__
(
self
,
name
=
''
,
description
=
''
,
parent
=
None
,
optional
=
True
):
super
().
__init__
(
name
,
description
,
None
,
optional
)
self
.
parent
=
parent
self
.
setMetadata
({
'widget_wrapper'
:
'BandTableWidget.BandTableWidgetWrapper'
})
def
type
(
self
):
return
'band table'
def
clone
(
self
):
return
ParameterBandTable
(
self
.
name
(),
self
.
description
(),
self
.
parent
,
self
.
flags
()
&
QgsProcessingParameterDefinition
.
FlagOptional
)
@
staticmethod
def
valueToColors
(
value
):
if
value
is
None
:
return
None
if
value
==
''
:
return
None
if
isinstance
(
value
,
str
):
return
value
.
split
(
';'
)
else
:
return
ParameterBandTable
.
colorsToString
(
value
)
@
staticmethod
def
colorsToString
(
colors
):
s
=
''
for
c
in
colors
:
s
+=
'{:f}, {:f}, {:d}, {:d}, {:d};'
.
format
(
c
[
0
],
c
[
1
],
c
[
2
],
c
[
3
],
c
[
4
])
return
s
[:
-
1
]
class
TableWidget
(
WidgetWrapper
):
"""
QTable widget
"""
def
createWidget
(
self
):
self
.
_combo
=
QTableWidget
()
# row count
self
.
_combo
.
setRowCount
(
1
)
# column count
self
.
_combo
.
setColumnCount
(
2
)
# column headers
self
.
_combo
.
setHorizontalHeaderLabels
([
"Name"
,
"Future name"
])
return
self
.
_combo
def
value
(
self
):
# retrieve table values [["name 1", "future name 1"], ["name 2", "future name 2"], ...]
table
=
[]
nrow
=
self
.
_combo
.
rowCount
()
#ncol = self._combo.columnCount()
for
i
in
range
(
nrow
):
table
.
append
([
self
.
_combo
.
cellWidget
(
i
,
0
),
self
.
_combo
.
cellWidget
(
i
,
1
)])
return
table
class
MergeAndRenameAlgorithm
(
QgsProcessingAlgorithm
):
"""
...
...
@@ -51,6 +123,8 @@ class MergeAndRenameAlgorithm(QgsProcessingAlgorithm):
INPUT
=
'INPUT'
TABLE
=
'TABLE'
TABLEWIDGET
=
'TABLEWIDGET'
BANDTABLEWIDGET
=
'BANDTABLEWIDGET'
OUTPUT
=
'OUTPUT'
def
initAlgorithm
(
self
,
config
):
...
...
@@ -79,6 +153,19 @@ class MergeAndRenameAlgorithm(QgsProcessingAlgorithm):
defaultValue
=
[
None
,
None
]
)
)
# custom parameter
param
=
QgsProcessingParameterString
(
self
.
TABLEWIDGET
,
'Band table'
)
param
.
setMetadata
({
'widget_wrapper'
:
{
'class'
:
TableWidget
}})
self
.
addParameter
(
param
)
# custom parameter : band table widget
self
.
addParameter
(
ParameterBandTable
(
self
.
BANDTABLEWIDGET
,
self
.
tr
(
'Band table'
),
self
.
INPUT
,
True
))
# output raster layer
self
.
addParameter
(
...
...
@@ -89,7 +176,6 @@ class MergeAndRenameAlgorithm(QgsProcessingAlgorithm):
)
def
processAlgorithm
(
self
,
parameters
,
context
,
feedback
):
"""
Here is where the processing itself takes place.
...
...
@@ -98,6 +184,7 @@ class MergeAndRenameAlgorithm(QgsProcessingAlgorithm):
# RETRIEVE INPUTS AND OUTPUT
input_raster
=
self
.
parameterAsRasterLayer
(
parameters
,
self
.
INPUT
,
context
)
band_table
=
self
.
parameterAsMatrix
(
parameters
,
self
.
TABLE
,
context
)
mytable
=
self
.
parameterAsString
(
parameters
,
self
.
TABLEWIDGET
,
context
)
output_raster_path
=
self
.
parameterAsOutputLayer
(
parameters
,
self
.
OUTPUT
,
context
)
# GETTING USEFUL PAREMETERS
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment