"""
Module that contains the StretchLayout, RuleLayout
and StretchDefaultsDialog classes
"""
# This file is part of 'TuiView' - a simple Raster viewer
# Copyright (C) 2012 Sam Gillingham
#
# 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.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from PyQt5.QtWidgets import QDialog, QFormLayout, QGridLayout, QVBoxLayout
from PyQt5.QtWidgets import QHBoxLayout, QComboBox, QToolBar, QAction, QLabel
from PyQt5.QtWidgets import QPushButton, QGroupBox, QDockWidget, QFileDialog
from PyQt5.QtWidgets import QTabWidget, QWidget, QSpinBox, QDoubleSpinBox, QCheckBox
from PyQt5.QtWidgets import QToolButton, QColorDialog, QMessageBox
from PyQt5.QtGui import QIcon, QPixmap, QColor
from PyQt5.QtCore import QSettings, Qt
import json
import os
from . import viewerstretch
from . import pseudocolor
from .viewerstrings import MESSAGE_TITLE
# strings for the combo boxes and their values
MODE_DATA = (("Color Table", viewerstretch.VIEWER_MODE_COLORTABLE),
("Greyscale", viewerstretch.VIEWER_MODE_GREYSCALE),
("PseudoColor", viewerstretch.VIEWER_MODE_PSEUDOCOLOR),
("RGB", viewerstretch.VIEWER_MODE_RGB))
STRETCH_DATA = (("None", viewerstretch.VIEWER_STRETCHMODE_NONE),
("Linear", viewerstretch.VIEWER_STRETCHMODE_LINEAR),
("Standard Deviation", viewerstretch.VIEWER_STRETCHMODE_STDDEV),
("Histogram", viewerstretch.VIEWER_STRETCHMODE_HIST))
DEFAULT_STRETCH_KEY = 'DefaultStretch'
MAX_BAND_NUMBER = 100 # for spin boxes
STRETCH_FILTER = ".stretch Files (*.stretch)"
[docs]class StretchLayout(QFormLayout):
"""
Layout that contains the actual stretch information
"""
def __init__(self, parent, stretch, gdaldataset=None):
QFormLayout.__init__(self)
# the mode
self.modeCombo = QComboBox(parent)
for text, code in MODE_DATA:
self.modeCombo.addItem(text, code)
# callback so we can set the state of other items when changed
self.modeCombo.currentIndexChanged.connect(self.modeChanged)
self.rampCombo = QComboBox(parent)
# make sure the pseudocolor has the extra ramps loaded
try:
pseudocolor.loadExtraRamps()
except Exception as e:
QMessageBox.critical(parent, MESSAGE_TITLE, str(e))
# populate combo - sort by type
for (name, display) in pseudocolor.getRampsForDisplay():
self.rampCombo.addItem(display, name)
self.modeLayout = QHBoxLayout()
self.modeLayout.addWidget(self.modeCombo)
self.modeLayout.addWidget(self.rampCombo)
self.addRow("Mode", self.modeLayout)
if gdaldataset is None:
# we don't have a dateset - is a rule
# create spin boxes for the bands
self.createSpinBands(parent)
else:
# we have a dataset. create combo
# boxes with the band names
self.createComboBands(gdaldataset, parent)
self.addRow("Bands", self.bandLayout)
# create the combo for the type of stretch
self.stretchLayout = QHBoxLayout()
self.stretchCombo = QComboBox(parent)
for text, code in STRETCH_DATA:
self.stretchCombo.addItem(text, code)
# callback so we can set the state of other items when changed
self.stretchCombo.currentIndexChanged.connect(self.stretchChanged)
self.stretchLayout.addWidget(self.stretchCombo)
# create the spin boxes for the std devs or hist min and max
self.stretchParam1 = QDoubleSpinBox(parent)
self.stretchParam1.setDecimals(3)
self.stretchParam1Stats = QCheckBox(parent)
self.stretchParam1Stats.setText("Statistics Min")
self.stretchParam1Stats.stateChanged.connect(self.param1StatsChanged)
self.stretchParam2 = QDoubleSpinBox(parent)
self.stretchParam2.setDecimals(3)
self.stretchParam2Stats = QCheckBox(parent)
self.stretchParam2Stats.setText("Statistics Max")
self.stretchParam2Stats.stateChanged.connect(self.param2StatsChanged)
self.stretchLayout.addWidget(self.stretchParam1)
self.stretchLayout.addWidget(self.stretchParam1Stats)
self.stretchLayout.addWidget(self.stretchParam2)
self.stretchLayout.addWidget(self.stretchParam2Stats)
self.addRow("Stretch", self.stretchLayout)
# now for no data, background and NaN
self.fixedColorLayout = QHBoxLayout()
self.nodataLabel = QLabel(parent)
self.nodataLabel.setText("No Data")
self.fixedColorLayout.addWidget(self.nodataLabel)
self.fixedColorLayout.setAlignment(self.nodataLabel, Qt.AlignRight)
self.nodataButton = ColorButton(parent)
self.fixedColorLayout.addWidget(self.nodataButton)
self.backgroundLabel = QLabel(parent)
self.backgroundLabel.setText("Background")
self.fixedColorLayout.addWidget(self.backgroundLabel)
self.fixedColorLayout.setAlignment(self.backgroundLabel, Qt.AlignRight)
self.backgroundButton = ColorButton(parent)
self.fixedColorLayout.addWidget(self.backgroundButton)
self.NaNLabel = QLabel(parent)
self.NaNLabel.setText("NaN")
self.fixedColorLayout.addWidget(self.NaNLabel)
self.fixedColorLayout.setAlignment(self.NaNLabel, Qt.AlignRight)
self.NaNButton = ColorButton(parent)
self.fixedColorLayout.addWidget(self.NaNButton)
self.addRow("Fixed Colors", self.fixedColorLayout)
# set state of GUI for this stretch
self.updateStretch(stretch)
[docs] def param1StatsChanged(self, state):
"""
Called when the 'Statistics Min' box is checked
"""
self.stretchParam1.setEnabled(state != Qt.Checked)
[docs] def param2StatsChanged(self, state):
"""
Called when the 'Statistics Max' box is checked
"""
self.stretchParam2.setEnabled(state != Qt.Checked)
[docs] def updateStretch(self, stretch):
"""
Change the state of the GUI to match the given stretch
"""
# the mode
idx = self.modeCombo.findData(stretch.mode)
if idx != -1:
self.modeCombo.setCurrentIndex(idx)
# ramp
if stretch.rampName is not None:
idx = self.rampCombo.findData(stretch.rampName)
if idx != -1:
self.rampCombo.setCurrentIndex(idx)
# set ramp state depending on if we are pseudo color or not
state = stretch.mode == viewerstretch.VIEWER_MODE_PSEUDOCOLOR
self.rampCombo.setEnabled(state)
# set the bands depending on if we are RGB or not
if stretch.mode == viewerstretch.VIEWER_MODE_RGB:
self.redWidget.setToolTip("Red")
self.greenWidget.setToolTip("Green")
self.blueWidget.setToolTip("Blue")
(r, g, b) = stretch.bands
if isinstance(self.redWidget, QSpinBox):
self.redWidget.setValue(r)
self.greenWidget.setValue(g)
self.blueWidget.setValue(b)
else:
self.redWidget.setCurrentIndex(r - 1)
self.greenWidget.setCurrentIndex(g - 1)
self.blueWidget.setCurrentIndex(b - 1)
else:
self.redWidget.setToolTip("Displayed Band")
self.greenWidget.setEnabled(False)
self.blueWidget.setEnabled(False)
if isinstance(self.redWidget, QSpinBox):
self.redWidget.setValue(stretch.bands[0])
else:
self.redWidget.setCurrentIndex(stretch.bands[0] - 1)
# stretch mode
idx = self.stretchCombo.findData(stretch.stretchmode)
if idx != -1:
self.stretchCombo.setCurrentIndex(idx)
state = stretch.mode != viewerstretch.VIEWER_MODE_COLORTABLE
self.stretchCombo.setEnabled(state)
if stretch.stretchmode == viewerstretch.VIEWER_STRETCHMODE_STDDEV:
self.stretchParam2.setEnabled(False)
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1.setRange(0, 10)
self.stretchParam1.setSingleStep(0.1)
self.stretchParam1.setValue(stretch.stretchparam[0])
self.stretchParam1.setToolTip("Number of Standard Deviations")
elif stretch.stretchmode == viewerstretch.VIEWER_STRETCHMODE_HIST:
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1.setRange(0, 1)
self.stretchParam1.setSingleStep(0.005)
self.stretchParam1.setValue(stretch.stretchparam[0])
self.stretchParam1.setToolTip("Minimum Proportion of Histogram")
self.stretchParam2.setRange(0, 1)
self.stretchParam2.setSingleStep(0.005)
self.stretchParam2.setValue(stretch.stretchparam[1])
self.stretchParam2.setToolTip("Maximum Proportion of Histogram")
elif stretch.stretchmode == viewerstretch.VIEWER_STRETCHMODE_LINEAR:
self.stretchParam1Stats.setEnabled(True)
self.stretchParam2Stats.setEnabled(True)
self.stretchParam1.setRange(-2**32, 2**32)
self.stretchParam1.setSingleStep(1)
if stretch.stretchparam[0] is None:
self.stretchParam1Stats.setCheckState(Qt.Checked)
else:
self.stretchParam1.setValue(stretch.stretchparam[0])
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam1.setToolTip("Minimum Value")
self.stretchParam2.setRange(-2**32, 2**32)
self.stretchParam2.setSingleStep(1)
if stretch.stretchparam[1] is None:
self.stretchParam2Stats.setCheckState(Qt.Checked)
else:
self.stretchParam2.setValue(stretch.stretchparam[1])
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam2.setToolTip("Maximum Value")
else:
# no stretch
self.stretchParam1.setEnabled(False)
self.stretchParam2.setEnabled(False)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1.setToolTip("")
self.stretchParam2.setToolTip("")
# nodata etc
self.nodataButton.setColorAsRGBATuple(stretch.nodata_rgba)
self.backgroundButton.setColorAsRGBATuple(stretch.background_rgba)
self.NaNButton.setColorAsRGBATuple(stretch.nan_rgba)
[docs] def createSpinBands(self, parent):
"""
For the case where we are creating a rule
we have no band names so create spin boxes
"""
# create the 3 band spin boxes
self.bandLayout = QHBoxLayout()
self.redWidget = QSpinBox(parent)
self.redWidget.setRange(1, MAX_BAND_NUMBER)
self.bandLayout.addWidget(self.redWidget)
self.greenWidget = QSpinBox(parent)
self.greenWidget.setRange(1, MAX_BAND_NUMBER)
self.bandLayout.addWidget(self.greenWidget)
self.blueWidget = QSpinBox(parent)
self.blueWidget.setRange(1, MAX_BAND_NUMBER)
self.bandLayout.addWidget(self.blueWidget)
[docs] def createComboBands(self, gdaldataset, parent):
"""
We have a dataset - create combo boxes with the band names
"""
self.bandLayout = QHBoxLayout()
self.redWidget = QComboBox(parent)
self.bandLayout.addWidget(self.redWidget)
self.greenWidget = QComboBox(parent)
self.bandLayout.addWidget(self.greenWidget)
self.blueWidget = QComboBox(parent)
self.bandLayout.addWidget(self.blueWidget)
self.populateComboFromDataset(self.redWidget, gdaldataset)
self.populateComboFromDataset(self.greenWidget, gdaldataset)
self.populateComboFromDataset(self.blueWidget, gdaldataset)
[docs] def populateComboFromDataset(self, combo, gdaldataset):
"""
Go through all the bands in the dataset and add a combo
item for each one. Set the current index to the currentBand
"""
for count in range(gdaldataset.RasterCount):
bandnum = count + 1
gdalband = gdaldataset.GetRasterBand(bandnum)
name = gdalband.GetDescription()
if name == '':
# make up a name so the user can still choose
name = 'Band %d' % bandnum
combo.addItem(name, bandnum)
[docs] @staticmethod
def getBandValue(widget):
"""
Depending on whether widget it a spinbox
or a combo box extract the current value for it.
"""
if isinstance(widget, QSpinBox):
value = widget.value()
else:
index = widget.currentIndex()
var = widget.itemData(index)
value = var
return value
[docs] def getStretch(self):
"""
Return a ViewerStretch object that reflects
the current state of the GUI
"""
obj = viewerstretch.ViewerStretch()
index = self.modeCombo.currentIndex()
obj.mode = self.modeCombo.itemData(index)
bands = []
value = self.getBandValue(self.redWidget)
bands.append(value)
if obj.mode == viewerstretch.VIEWER_MODE_RGB:
value = self.getBandValue(self.greenWidget)
bands.append(value)
value = self.getBandValue(self.blueWidget)
bands.append(value)
obj.setBands(tuple(bands))
if obj.mode == viewerstretch.VIEWER_MODE_PSEUDOCOLOR:
idx = self.rampCombo.currentIndex()
rampName = self.rampCombo.itemData(idx)
obj.setPseudoColor(str(rampName))
index = self.stretchCombo.currentIndex()
obj.stretchmode = self.stretchCombo.itemData(index)
if obj.stretchmode == viewerstretch.VIEWER_STRETCHMODE_STDDEV:
value = self.stretchParam1.value()
obj.setStdDevStretch(value)
elif obj.stretchmode == viewerstretch.VIEWER_STRETCHMODE_HIST:
histmin = self.stretchParam1.value()
histmax = self.stretchParam2.value()
obj.setHistStretch(histmin, histmax)
elif obj.stretchmode == viewerstretch.VIEWER_STRETCHMODE_LINEAR:
# need to do something cleverer here with the special value
minVal = self.stretchParam1.value()
if self.stretchParam1Stats.checkState() == Qt.Checked:
minVal = None
maxVal = self.stretchParam2.value()
if self.stretchParam2Stats.checkState() == Qt.Checked:
maxVal = None
obj.setLinearStretch(minVal, maxVal)
obj.setNoDataRGBA(self.nodataButton.getColorAsRGBATuple())
obj.setBackgroundRGBA(self.backgroundButton.getColorAsRGBATuple())
obj.setNaNRGBA(self.NaNButton.getColorAsRGBATuple())
return obj
[docs] def modeChanged(self, index):
"""
Called when user changed the mode.
Updates other GUI elements as needed
"""
mode = self.modeCombo.itemData(index)
greenredEnabled = (mode == viewerstretch.VIEWER_MODE_RGB)
self.greenWidget.setEnabled(greenredEnabled)
self.blueWidget.setEnabled(greenredEnabled)
if greenredEnabled:
self.redWidget.setToolTip("Red")
self.greenWidget.setToolTip("Green")
self.blueWidget.setToolTip("Blue")
else:
self.redWidget.setToolTip("Displayed Band")
self.greenWidget.setToolTip("")
self.blueWidget.setToolTip("")
if mode == viewerstretch.VIEWER_MODE_COLORTABLE:
# need to set stretch to none
self.stretchCombo.setCurrentIndex(0)
state = mode != viewerstretch.VIEWER_MODE_COLORTABLE
self.stretchCombo.setEnabled(state)
state = mode == viewerstretch.VIEWER_MODE_PSEUDOCOLOR
self.rampCombo.setEnabled(state)
[docs] def stretchChanged(self, index):
"""
Called when user changed the stretch.
Updates other GUI elements as needed
"""
stretchmode = self.stretchCombo.itemData(index)
if stretchmode == viewerstretch.VIEWER_STRETCHMODE_STDDEV:
self.stretchParam1.setEnabled(True)
self.stretchParam2.setEnabled(False)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1.setRange(0, 10)
self.stretchParam1.setSingleStep(0.1)
# always set back to this default
self.stretchParam1.setValue(viewerstretch.VIEWER_DEFAULT_STDDEV)
self.stretchParam1.setToolTip("Number of Standard Deviations")
self.stretchParam2.setToolTip("")
elif stretchmode == viewerstretch.VIEWER_STRETCHMODE_HIST:
self.stretchParam1.setEnabled(True)
self.stretchParam2.setEnabled(True)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1.setRange(0, 1)
self.stretchParam1.setSingleStep(0.005)
self.stretchParam1.setToolTip("Minimum Proportion of Histogram")
self.stretchParam2.setRange(0, 1)
self.stretchParam2.setSingleStep(0.005)
self.stretchParam2.setToolTip("Maximum Proportion of Histogram")
# set back to these defaults
self.stretchParam1.setValue(viewerstretch.VIEWER_DEFAULT_HISTMIN)
self.stretchParam2.setValue(viewerstretch.VIEWER_DEFAULT_HISTMAX)
elif stretchmode == viewerstretch.VIEWER_STRETCHMODE_LINEAR:
self.stretchParam1.setEnabled(True)
self.stretchParam2.setEnabled(True)
self.stretchParam1Stats.setEnabled(True)
self.stretchParam2Stats.setEnabled(True)
self.stretchParam1.setRange(-2**32, 2**32)
self.stretchParam1.setSingleStep(1)
self.stretchParam1.setToolTip("Minimum Value")
self.stretchParam2.setRange(-2**32, 2**32)
self.stretchParam2.setSingleStep(1)
self.stretchParam2.setToolTip("Maximum Value")
self.stretchParam1.setValue(0) # set back to these defaults
self.stretchParam2.setValue(0)
self.stretchParam1Stats.setCheckState(Qt.Checked)
self.stretchParam2Stats.setCheckState(Qt.Checked)
else:
self.stretchParam1.setEnabled(False)
self.stretchParam2.setEnabled(False)
self.stretchParam1Stats.setCheckState(Qt.Unchecked)
self.stretchParam2Stats.setCheckState(Qt.Unchecked)
self.stretchParam1Stats.setEnabled(False)
self.stretchParam2Stats.setEnabled(False)
self.stretchParam1.setToolTip("")
self.stretchParam2.setToolTip("")
RULE_DATA = (("Number of Bands Less than", viewerstretch.VIEWER_COMP_LT),
("Number of Bands Greater than", viewerstretch.VIEWER_COMP_GT),
("Number of Bands Equal to", viewerstretch.VIEWER_COMP_EQ))
[docs]class RuleLayout(QGridLayout):
"""
Layout that contains the 'rules'. These are
the number of bands, the comparison with the
number of bands and the check for a color table
"""
def __init__(self, parent, rule):
QGridLayout.__init__(self)
# the comaprison combo
self.compCombo = QComboBox(parent)
index = 0
for text, code in RULE_DATA:
self.compCombo.addItem(text, code)
if code == rule.comp:
self.compCombo.setCurrentIndex(index)
index += 1
self.addWidget(self.compCombo, 0, 0)
# the number of bands spinbox
self.numberBox = QSpinBox(parent)
self.numberBox.setRange(1, 100)
self.numberBox.setValue(rule.value)
self.addWidget(self.numberBox, 0, 1)
# the label for the color table rule
self.colorTableLabel = QLabel(parent)
self.colorTableLabel.setText("Color Table in Band")
self.addWidget(self.colorTableLabel, 1, 0)
# color table band spinbox
self.colorTableBox = QSpinBox(parent)
self.colorTableBox.setRange(0, 100)
self.colorTableBox.setSpecialValueText('No color table required')
if rule.ctband is None:
self.colorTableBox.setValue(0)
else:
self.colorTableBox.setValue(rule.ctband)
self.addWidget(self.colorTableBox, 1, 1)
[docs] def getRule(self):
"""
Return a StretchRule instance for the current GUI
settings
Note: the stretch field will be None
"""
index = self.compCombo.currentIndex()
comp = self.compCombo.itemData(index)
value = self.numberBox.value()
ctband = self.colorTableBox.value()
if ctband == 0:
ctband = None # no color table required
obj = viewerstretch.StretchRule(comp, value, ctband, None)
return obj
[docs]class StretchDefaultsDialog(QDialog):
"""
Dialog that contains a Tabs, each one describing a rule
and is a combination of RuleLayout and StretchLayout
"""
def __init__(self, parent):
QDialog.__init__(self, parent)
# create a tab widget with its tabs on the left
self.tabWidget = QTabWidget(self)
self.tabWidget.setTabPosition(QTabWidget.West)
# grab the rules from the setting
# this supplies some default rules if none
ruleList = self.fromSettings()
count = 1
# go through each rule
for rule in ruleList:
# create a widget for it
widget = self.createWidget(rule, rule.stretch)
# add the widget as a new tab
name = "Rule %d" % count
self.tabWidget.addTab(widget, name)
count += 1
# now sort out the rest of the dialog
self.mainLayout = QVBoxLayout(self)
self.mainLayout.addWidget(self.tabWidget)
# new and delete buttons
self.newBeforeButton = QPushButton(self)
self.newBeforeButton.setText("New Rule Before")
self.newBeforeButton.clicked.connect(self.onNewBefore)
self.newAfterButton = QPushButton(self)
self.newAfterButton.setText("New Rule After")
self.newAfterButton.clicked.connect(self.onNewAfter)
self.deleteRuleButton = QPushButton(self)
self.deleteRuleButton.setText("Delete This Rule")
if len(ruleList) <= 1:
self.deleteRuleButton.setEnabled(False)
self.deleteRuleButton.clicked.connect(self.onDelete)
self.newDeleteLayout = QHBoxLayout()
self.newDeleteLayout.addWidget(self.newBeforeButton)
self.newDeleteLayout.addWidget(self.newAfterButton)
self.newDeleteLayout.addWidget(self.deleteRuleButton)
self.mainLayout.addLayout(self.newDeleteLayout)
# ok and cancel buttons
self.okButton = QPushButton(self)
self.okButton.setText("OK")
self.okButton.setDefault(True)
self.okButton.clicked.connect(self.onOK)
self.cancelButton = QPushButton(self)
self.cancelButton.setText("Cancel")
self.cancelButton.clicked.connect(self.reject)
self.buttonLayout = QHBoxLayout()
self.buttonLayout.addWidget(self.okButton)
self.buttonLayout.addWidget(self.cancelButton)
self.mainLayout.addLayout(self.buttonLayout)
self.setLayout(self.mainLayout)
self.setWindowTitle("Default Stretch")
self.setSizeGripEnabled(True)
self.resize(600, 400)
[docs] @staticmethod
def fromSettings():
"""
Read the default stretch rules from the
settings and return a list of StretchRules.
Supplies a default set of rules if none found.
"""
settings = QSettings()
settings.beginGroup('Stretch')
ruleList = []
defaultRulesJSON = settings.value(DEFAULT_STRETCH_KEY)
if defaultRulesJSON is None or defaultRulesJSON == '':
# there isn't one, construct some defaults
stretch = viewerstretch.ViewerStretch()
# single band with color table
stretch.setColorTable()
stretch.setBands((1,))
# must be one band and band one must have a color table
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_EQ, 1, 1, stretch)
ruleList.append(rule)
# single band without color table
stretch.setGreyScale()
stretch.setStdDevStretch()
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_EQ, 1, None, stretch)
ruleList.append(rule)
# 2 bands
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_EQ, 2, None, stretch)
ruleList.append(rule)
# 3 bands
stretch.setRGB()
stretch.setBands((1, 2, 3))
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_EQ, 3, None, stretch)
ruleList.append(rule)
# < 6 bands
stretch.setBands((4, 3, 2))
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_LT, 6, None, stretch)
ruleList.append(rule)
# > 5 bands
stretch.setBands((5, 4, 2))
rule = viewerstretch.StretchRule(
viewerstretch.VIEWER_COMP_GT, 5, None, stretch)
ruleList.append(rule)
else:
# is a list of json strings
for string in json.loads(defaultRulesJSON):
# go through each one (which is itself a json string)
# and decode into a StretchRule
rule = viewerstretch.StretchRule.fromString(string)
ruleList.append(rule)
settings.endGroup()
return ruleList
[docs] def toSettings(self):
"""
Write the contents of the dialog as the
default rules to be remembered for next time.
"""
settings = QSettings()
settings.beginGroup('Stretch')
# go through each tab and turn
# rules into JSON string and append to list
defaultRulesList = []
nwidgets = self.tabWidget.count()
for index in range(nwidgets):
widget = self.tabWidget.widget(index)
stretch = widget.stretchLayout.getStretch()
rule = widget.ruleLayout.getRule()
rule.stretch = stretch
string = rule.toString()
defaultRulesList.append(string)
# turn list into a json string and write to settings
JSONstring = json.dumps(defaultRulesList)
settings.setValue(DEFAULT_STRETCH_KEY, JSONstring)
settings.endGroup()
[docs] def renumberTabs(self):
"""
A tab has been added or deleted so renumber
the tabs
"""
ntabs = self.tabWidget.count()
for index in range(ntabs):
name = "Rule %d" % (index + 1)
self.tabWidget.setTabText(index, name)
[docs] def onOK(self):
"""
OK button pressed. Save settings
"""
self.toSettings()
QDialog.accept(self)
[docs] def onNewBefore(self):
"""
The 'add new page before' button pressed.
Add a new page in with the rule/stretch
same as current page
"""
# get the current page and rule/stretch
currentWidget = self.tabWidget.currentWidget()
currentIndex = self.tabWidget.currentIndex()
rule = currentWidget.ruleLayout.getRule()
stretch = currentWidget.stretchLayout.getStretch()
# create a new tab
newWidget = self.createWidget(rule, stretch)
self.tabWidget.setUpdatesEnabled(False) # reduce flicker
self.tabWidget.insertTab(currentIndex, newWidget, "new rule")
self.deleteRuleButton.setEnabled(True)
self.renumberTabs() # make sure the numbers in order
self.tabWidget.setUpdatesEnabled(True) # reduce flicker
[docs] def onNewAfter(self):
"""
The 'add new page after' button pressed.
Add a new page in with the rule/stretch
same as current page
"""
# get the current page and rule/stretch
currentWidget = self.tabWidget.currentWidget()
currentIndex = self.tabWidget.currentIndex()
rule = currentWidget.ruleLayout.getRule()
stretch = currentWidget.stretchLayout.getStretch()
# create a new tab
newWidget = self.createWidget(rule, stretch)
self.tabWidget.setUpdatesEnabled(False) # reduce flicker
self.tabWidget.insertTab(currentIndex + 1, newWidget, "new rule")
self.deleteRuleButton.setEnabled(True)
self.renumberTabs() # make sure the numbers in order
self.tabWidget.setUpdatesEnabled(True) # reduce flicker
[docs] def onDelete(self):
"""
Delete the current page.
"""
currentIndex = self.tabWidget.currentIndex()
self.tabWidget.setUpdatesEnabled(False) # reduce flicker
self.tabWidget.removeTab(currentIndex)
if self.tabWidget.count() <= 1:
self.deleteRuleButton.setEnabled(False)
self.renumberTabs()
self.tabWidget.setUpdatesEnabled(True) # reduce flicker