Commit cc51d5d2 authored by PIERSON Julie's avatar PIERSON Julie
Browse files

using checkablecombobox for selecting single band rasters

parent ae70241a
# -*- 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
from qgis.PyQt import uic
from qgis.PyQt.QtCore import pyqtSlot
from qgis.PyQt.QtWidgets import (QTreeWidgetItem,
QMessageBox,
QInputDialog,
)
from qgis.core import (QgsApplication,
QgsProject,
QgsMapLayer,
QgsProcessing,
QgsMapLayerProxyModel)
from processing.gui.wrappers import WidgetWrapper
from osgeo import gdal
pluginPath = os.path.dirname(__file__)
WIDGET, BASE = uic.loadUiType(os.path.join(pluginPath, 'mergebandtablewidgetbase.ui'))
class MergeBandTableWidget(BASE, WIDGET):
def __init__(self):
super(MergeBandTableWidget, self).__init__(None)
self.setupUi(self)
#self.multiLayers.setLayerType(QgsProcessing.TypeRaster) # 3 for TypeRaster
self.multiLayers.checkedItemsChanged.connect(self.layersChanged)
self.btnUp.setIcon(QgsApplication.getThemeIcon('/mActionArrowUp.svg'))
self.btnDown.setIcon(QgsApplication.getThemeIcon('/mActionArrowDown.svg'))
self.layer = None
# when alg is launched by user, populate combobox with loaded raster layers
self.populateMultiLayers()
# this is how to display a message for debugging
#QMessageBox.information(None, self.tr('window name'), self.tr('message'))
# populate checkable combobox with every loaded single band raster layer
def populateMultiLayers(self):
# get a list of loaded raster layers
layerList = QgsProject.instance().mapLayers().values()
rasterList = [i for i in list(layerList) if i.type() == QgsMapLayer.RasterLayer]
# keep only single band rasters in list
rasterNames = [i.name() for i in list(rasterList) if i.bandCount() == 1]
# populate combobox
for r in rasterNames:
self.multiLayers.addItem(r)
# when user changes selected layer in combobox
def layersChanged(self):
# remove table content
self._removeBandData()
# get raster layers
rasterNames = self.multiLayers.checkedItems()
# if there is at least one selected raster
if len(rasterNames) != 0:
for r in rasterNames:
self._addBandData(r)
# # if there is one
# if layer != None:
# input_raster = gdal.Open(layer.source())
# # get number of bands in raster
# nbands = input_raster.RasterCount
# # for each band
# for band_number in range(nbands):
# band = input_raster.GetRasterBand(band_number + 1)
# # add band number to table
# bandnumber = str(band_number+1)
# bandname = band.GetDescription()
# self._addBandData(bandnumber, bandname)
# add selected raster names to table
def _addBandData(self, rastername):
item = QTreeWidgetItem()
item.setText(0, rastername)
self.bandClassTree.addTopLevelItem(item)
# remove all rows from table
def _removeBandData(self,):
self.bandClassTree.clear()
# move down selected line in table when down button is clicked
@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)
# move up selected line in table when up button is clicked
@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)
# when a cell in 2nd column is clicked, open dialog box for entering value
@pyqtSlot(QTreeWidgetItem, int)
def on_bandClassTree_itemDoubleClicked(self, item, column):
if not item:
return
if column == 1:
d, ok = QInputDialog.getText(None,
self.tr('Band name'),
self.tr('Enter new band name')
)
if ok:
item.setText(1, str(d))
# return table values in a list, one element for each row
# [['band 1', 'old name 1', 'new name 1'], ['band 2', 'old name 2', 'new name 2']]
def bandNames(self):
band_names = []
for i in range(self.bandClassTree.topLevelItemCount()):
item = self.bandClassTree.topLevelItem(i)
if item:
row = [item.text(0), item.text(1), item.text(2)]
band_names.append(row)
return band_names
def setLayers(self, layers):
self.layers = layers
self.updateTable(layers)
def updateTable(self, layers):
item = QTreeWidgetItem()
item.setText(0, '0.00')
item.setText(1, '0.00')
self.bandClassTree.addTopLevelItem(item)
def setValue(self, value):
self.bandClassTree.clear()
param = value.split(';')
# setting input layer
layer_name = param[0]
# # if layer is loaded in project
# if QgsProject.instance().mapLayersByName(layer_name):
# layer = QgsProject.instance().mapLayersByName(layer_name)[0]
# self.multiLayers.setLayer(layer)
# # setting table values
# self.bandClassTree.clear()
# rows = param[2:]
# for r in rows:
# v = r.split(',')
# item = QTreeWidgetItem()
# item.setText(0, v[0])
# item.setText(1, v[1])
# item.setText(2, v[2])
# self.bandClassTree.addTopLevelItem(item)
# return a list where 1st element is input raster path
# and then each element for a table row
def value(self):
# adding input layer names to values (useful to select again this layer when using toolbox history)
allValues = self.multiLayers.currentLayer().name()
allValues += ';'
# adding input layer path to values
allValues += self.multiLayers.currentLayer().source()
allValues += ';'
# adding table content to values
for b in self.bandNames():
allValues += '{0},{1},{2};'.format(b[0], b[1], b[2])
return allValues[:-1]
class MergeBandTableWidgetWrapper(WidgetWrapper):
def createWidget(self):
return MergeBandTableWidget()
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)
self.widget.updateTable(layer)
def setValue(self, value):
self.widget.setValue(value)
def value(self):
return self.widget.value()
<?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="QLabel" name="label_2">
<property name="text">
<string>Raster layers</string>
</property>
<property name="buddy">
<cstring>multiLayers</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsCheckableComboBox" name="multiLayers">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QTreeWidget" name="bandClassTree">
<column>
<property name="text">
<string>Band name</string>
</property>
</column>
<column>
<property name="text">
<string>Band future name</string>
</property>
</column>
</widget>
</item>
<item row="1" column="3">
<layout class="QVBoxLayout" name="verticalLayout">
<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>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment