Skip to content
Snippets Groups Projects
plotstyling.py 10.8 KiB
Newer Older
import os

from qgis.core import *
from qgis.gui import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import numpy as np
from timeseriesviewer import *
from timeseriesviewer.utils import *

from timeseriesviewer.ui.widgets import loadUIFormClass
import pyqtgraph as pg
load = lambda p : loadUIFormClass(jp(DIR_UI,p))

MARKERSYMBOLS = [('o', u'Circle'),
                 ('t',u'Triangle Down'),
                 ('t1',u'Triangle Up'),
                 ('t2',u'Triangle Right'),
                 ('t3', u'Triangle Left'),
                 ('p',u'Pentagon'),
                 ('h', u'Hexagon'),
                 ('s',u'Star'),
                 ('+',u'Plus'),
                 ('d',u'Diamond'),
                 (None, u'No Symbol')
                 ]

PENSTYLES = [(Qt.SolidLine, '___'),
             (Qt.DashLine, '_ _ _'),
             (Qt.DotLine, '. . .'),
             (Qt.DashDotLine, '_ .'),
             (Qt.DashDotDotLine, '_ . .'),
             (Qt.NoPen, 'No Pen')]
Benjamin Jakimow's avatar
Benjamin Jakimow committed
class PlotStyle(QObject):
    def __init__(self, **kwds):
        plotStyle = kwds.get('plotStyle')
        if plotStyle: kwds.pop('plotStyle')
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        super(PlotStyle,self).__init__(**kwds)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        else:
            self.markerSymbol = MARKERSYMBOLS[0][0]
            self.markerSize = 10
            self.markerBrush = QBrush()
            self.markerBrush.setColor(Qt.green)
            self.markerBrush.setStyle(Qt.SolidPattern)

            self.backgroundColor = Qt.black

            self.markerPen = QPen()
            self.markerPen.setStyle(Qt.SolidLine)
            self.markerPen.setColor(Qt.white)

            self.linePen = QPen()
            self.linePen.setStyle(Qt.NoPen)
            self.linePen.setColor(QColor(74,75,75))

    def copyFrom(self, plotStyle):
        assert isinstance(plotStyle, PlotStyle)

        self.markerSymbol = plotStyle.markerSymbol
        self.markerBrush = QBrush(plotStyle.markerBrush)
        self.markerPen = QPen(plotStyle.markerPen)
        self.markerSize = plotStyle.markerSize
        self.backgroundColor = QColor(plotStyle.backgroundColor)
        self.linePen = QPen(plotStyle.linePen)
        s = ""
    def createIcon(self, size=None):

        if size is None:
            size = QSize(60,60)

        pm = QPixmap(size)
        pm.fill(self.backgroundColor)

        p = QPainter(pm)
        #draw the line
        p.setPen(self.linePen)
        p.drawLine(2, pm.height()-2, pm.width()-2, 2)
        p.translate(pm.width() / 2, pm.height() / 2)
        from pyqtgraph.graphicsItems.ScatterPlotItem import drawSymbol
        path = drawSymbol(p, self.markerSymbol, self.markerSize, self.markerPen, self.markerBrush)
        p.end()
        return QIcon(pm)



class PlotStyleWidget(QWidget, load('plotstylewidget.ui')):
    sigPlotStyleChanged = pyqtSignal(PlotStyle)

    def __init__(self, title='<#>', parent=None):
        super(PlotStyleWidget, self).__init__(parent)
        self.setupUi(self)
        assert isinstance(self.plotWidget, pg.PlotWidget)

        self.mBlockUpdates = False
        #self.plotWidget.disableAutoRange()
        #self.plotWidget.setAspectLocked()
        self.plotWidget.setRange(xRange=[0,1], yRange=[0,1], update=True)
        self.plotWidget.setLimits(xMin=0, xMax=1, yMin=0, yMax=1)
        self.plotWidget.setMouseEnabled(x=False, y=False)

        for ax in self.plotWidget.plotItem.axes:
            self.plotWidget.plotItem.hideAxis(ax)
        #self.plotWidget.disableAutoRange()

        self.plotDataItem = self.plotWidget.plot(x=[0.1, 0.5, 0.9], y=[0.25, 0.9, 0.5])
        self.legend = pg.LegendItem((100,60), offset=(70,30))  # args are (size, offset)
        self.legend.setParentItem(self.plotDataItem.topLevelItem())   # Note we do NOT call plt.addItem in this case
        self.legend.hide()

        for t in MARKERSYMBOLS:
            self.cbMarkerSymbol.addItem(t[1], t[0])
        for t in PENSTYLES:
            self.cbMarkerPenStyle.addItem(t[1], t[0])
            self.cbLinePenStyle.addItem(t[1], t[0])

        #connect signals
        self.btnMarkerBrushColor.colorChanged.connect(self.refreshPreview)
        self.btnMarkerPenColor.colorChanged.connect(self.refreshPreview)
        self.btnLinePenColor.colorChanged.connect(self.refreshPreview)

        self.cbMarkerSymbol.currentIndexChanged.connect(self.refreshPreview)
        self.cbMarkerPenStyle.currentIndexChanged.connect(self.refreshPreview)
        self.cbLinePenStyle.currentIndexChanged.connect(self.refreshPreview)

        self.sbMarkerSize.valueChanged.connect(self.refreshPreview)
        self.sbMarkerPenWidth.valueChanged.connect(self.refreshPreview)
        self.sbLinePenWidth.valueChanged.connect(self.refreshPreview)


        self.setPlotStyle(PlotStyle())
        self.refreshPreview()

    def refreshPreview(self, *args):
        if not self.mBlockUpdates:
            print('DEBUG: REFRESH NOW')
            style = self.plotStyle()

            #todo: set style to style preview
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            pi.setSymbol(style.markerSymbol)
            pi.setSymbolSize(style.markerSize)
            pi.setSymbolBrush(style.markerBrush)
            pi.setSymbolPen(style.markerPen)
            pi.setPen(style.linePen)
            pi.update()
            self.plotWidget.update()
            self.sigPlotStyleChanged.emit(style)

    def _setComboBoxToValue(self, cb, value):
        assert isinstance(cb, QComboBox)
        for i in range(cb.count()):
            v = cb.itemData(i)
            if type(value) in [str, unicode]:
                v = str(v)
            if v == value:
                cb.setCurrentIndex(i)
                break
        s = ""
    def setPlotStyle(self, style):
        assert isinstance(style, PlotStyle)
        #set widget values
        self.mBlockUpdates = True
        self.sbMarkerSize.setValue(style.markerSize)
        self._setComboBoxToValue(self.cbMarkerSymbol, style.markerSymbol)
        assert isinstance(style.markerPen, QPen)
        assert isinstance(style.markerBrush, QBrush)
        assert isinstance(style.linePen, QPen)

        self.btnMarkerPenColor.setColor(style.markerPen.color())
        self._setComboBoxToValue(self.cbMarkerPenStyle, style.markerPen.style())
        self.sbMarkerPenWidth.setValue(style.markerPen.width())
        self.btnMarkerBrushColor.setColor(style.markerBrush.color())
        self.btnLinePenColor.setColor(style.linePen.color())
        self._setComboBoxToValue(self.cbLinePenStyle, style.linePen.style())

        self.sbLinePenWidth.setValue(style.linePen.width())

        self.mBlockUpdates = False

        self.refreshPreview()

    def plotStyleIcon(self):
        icon = QIcon()
        #todo: get plot preview as 60x60 icon
        return icon

    def plotStyle(self):
        style = PlotStyle()
        #read plotstyle values from widgets
        style.markerSize = self.sbMarkerSize.value()
        symbol = self.cbMarkerSymbol.itemData(self.cbMarkerSymbol.currentIndex())
        if isinstance(symbol, unicode):
            symbol = str(symbol)
        style.markerSymbol = symbol
        assert isinstance(style.markerPen, QPen)
        assert isinstance(style.markerBrush, QBrush)
        assert isinstance(style.linePen, QPen)

        style.markerPen = pg.mkPen(color=self.btnMarkerPenColor.color(),
                                   width=self.sbMarkerPenWidth.value(),
                                   style=self.cbMarkerPenStyle.itemData(self.cbMarkerPenStyle.currentIndex()))


        style.markerBrush.setColor(self.btnMarkerBrushColor.color())
        style.markerBrush.setColor(self.btnMarkerBrushColor.color())

        style.linePen = pg.mkPen(color=self.btnLinePenColor.color(),
                                 width=self.sbLinePenWidth.value(),
                                 style=self.cbLinePenStyle.itemData(self.cbLinePenStyle.currentIndex()))


class PlotStyleButton(QPushButton):

Benjamin Jakimow's avatar
Benjamin Jakimow committed

    sigPlotStyleChanged = pyqtSignal(PlotStyle)

    def __init__(self, *args):
        super(PlotStyleButton, self).__init__(*args)
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        self.mInitialButtonSize = None
        self.setStyleSheet('* { padding: 0px; }')
        self.clicked.connect(self.showDialog)
        self.setPlotStyle(PlotStyle())
Benjamin Jakimow's avatar
Benjamin Jakimow committed


    def setPlotStyle(self, plotStyle):
            self._updateIcon()
            self.sigPlotStyleChanged.emit(self.mPlotStyle)
        style = PlotStyleDialog.getPlotStyle(plotStyle=self.mPlotStyle)
        if style:
            self.setPlotStyle(style)
    def resizeEvent(self, arg):
        self._updateIcon()

    def _updateIcon(self):
Benjamin Jakimow's avatar
Benjamin Jakimow committed
        if self.mInitialButtonSize is None:
            self.mInitialButtonSize = self.sizeHint()
            self.setIconSize(self.mInitialButtonSize)

        if self.mPlotStyle != None:
Benjamin Jakimow's avatar
Benjamin Jakimow committed
            s = self.mInitialButtonSize
            s = self.sizeHint()
            #s = QSize()
            icon = self.mPlotStyle.createIcon(self.mInitialButtonSize)
class PlotStyleDialog(QgsDialog):

    @staticmethod
    def getPlotStyle(*args, **kwds):
        """
        Opens a CrosshairDialog.
        :param args:
        :param kwds:
        :return: specified CrosshairStyle if accepted, else None
        """
        d = PlotStyleDialog(*args, **kwds)
        d.exec_()

        if d.result() == QDialog.Accepted:
        else:

            return None

    def __init__(self, parent=None, plotStyle=None, title='Specify Plot Style'):
        super(PlotStyleDialog, self).__init__(parent=parent , \
            buttons=QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.w = PlotStyleWidget(parent=self)
        self.setWindowTitle(title)
        self.btOk = QPushButton('Ok')
        self.btCancel = QPushButton('Cancel')
        buttonBar = QHBoxLayout()
        #buttonBar.addWidget(self.btCancel)
        #buttonBar.addWidget(self.btOk)
        l = self.layout()
        l.addWidget(self.w)
        l.addLayout(buttonBar)
        #self.setLayout(l)


    def plotStyle(self):
        return self.w.plotStyle()

    def setPlotStyle(self, plotStyle):
        assert isinstance(plotStyle, PlotStyle)
        self.w.setPlotStyle(plotStyle)



if __name__ == '__main__':
    import site, sys
    #add site-packages to sys.path as done by enmapboxplugin.py

    from timeseriesviewer import sandbox
    qgsApp = sandbox.initQgisEnvironment()
    btn = PlotStyleButton()
    btn.show()
    qgsApp.exec_()
    qgsApp.exitQgis()