semi working QT interface for postprocessing
This commit is contained in:
parent
28d2464aee
commit
7b9d1f172a
@ -721,7 +721,7 @@ class Survey(object):
|
||||
Used by plotAllPicks.
|
||||
'''
|
||||
import matplotlib.pyplot as plt
|
||||
plt.interactive(True)
|
||||
#plt.interactive(True)
|
||||
cm = plt.cm.jet
|
||||
if ax is None:
|
||||
print('Generating new plot...')
|
||||
@ -729,7 +729,7 @@ class Survey(object):
|
||||
ax = fig.add_subplot(111)
|
||||
sc = ax.scatter(dist, pick, cmap=cm, c=inkByVal, s=5,
|
||||
edgecolors='none', label=label)
|
||||
cbar = plt.colorbar(sc, fraction=0.05)
|
||||
cbar = fig.colorbar(sc, fraction=0.05)
|
||||
cbar.set_label(label)
|
||||
ax.set_xlabel('Distance [m]')
|
||||
ax.set_ylabel('Time [s]')
|
||||
@ -739,7 +739,8 @@ class Survey(object):
|
||||
sc = ax.scatter(dist, pick, cmap=cm, c=inkByVal, s=5,
|
||||
edgecolors='none', label=label)
|
||||
if cbar is not None:
|
||||
cbar = plt.colorbar(sc, cax=cbar.ax)
|
||||
cbar.ax.clear()
|
||||
cbar = ax.figure.colorbar(sc, cax=cbar.ax)
|
||||
cbar.set_label(label)
|
||||
ax.set_xlabel('Distance [m]')
|
||||
ax.set_ylabel('Time [s]')
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'asp3d_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:26 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'fmtomo_parameters_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:26 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'generate_seisarray_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:26 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'generate_survey_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:26 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'generate_survey_layout_minimal.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:27 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'picking_parameters_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:27 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'postprocessing_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:27 2016
|
||||
# Created: Wed Aug 10 14:11:08 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
@ -12,34 +12,13 @@ from PySide import QtCore, QtGui
|
||||
class Ui_postprocessing(object):
|
||||
def setupUi(self, postprocessing):
|
||||
postprocessing.setObjectName("postprocessing")
|
||||
postprocessing.resize(640, 480)
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout(postprocessing)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.verticalLayout = QtGui.QVBoxLayout()
|
||||
postprocessing.resize(663, 617)
|
||||
self.verticalLayout = QtGui.QVBoxLayout(postprocessing)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.gridLayout = QtGui.QGridLayout()
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.pushButton_rect = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.pushButton_rect.sizePolicy().hasHeightForWidth())
|
||||
self.pushButton_rect.setSizePolicy(sizePolicy)
|
||||
self.pushButton_rect.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_rect.setObjectName("pushButton_rect")
|
||||
self.horizontalLayout.addWidget(self.pushButton_rect)
|
||||
self.pushButton_poly = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.pushButton_poly.sizePolicy().hasHeightForWidth())
|
||||
self.pushButton_poly.setSizePolicy(sizePolicy)
|
||||
self.pushButton_poly.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_poly.setObjectName("pushButton_poly")
|
||||
self.horizontalLayout.addWidget(self.pushButton_poly)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1)
|
||||
self.horizontalLayout_2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.verticalLayout_3 = QtGui.QVBoxLayout()
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.label = QtGui.QLabel(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -49,7 +28,42 @@ class Ui_postprocessing(object):
|
||||
self.label.setMinimumSize(QtCore.QSize(0, 20))
|
||||
self.label.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
|
||||
self.verticalLayout_3.addWidget(self.label)
|
||||
self.horizontalLayout_4 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.pushButton_rect = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.pushButton_rect.sizePolicy().hasHeightForWidth())
|
||||
self.pushButton_rect.setSizePolicy(sizePolicy)
|
||||
self.pushButton_rect.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_rect.setObjectName("pushButton_rect")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_rect)
|
||||
self.pushButton_poly = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.pushButton_poly.sizePolicy().hasHeightForWidth())
|
||||
self.pushButton_poly.setSizePolicy(sizePolicy)
|
||||
self.pushButton_poly.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_poly.setObjectName("pushButton_poly")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_poly)
|
||||
self.pushButton_plot = QtGui.QPushButton(postprocessing)
|
||||
self.pushButton_plot.setCheckable(False)
|
||||
self.pushButton_plot.setDefault(False)
|
||||
self.pushButton_plot.setFlat(False)
|
||||
self.pushButton_plot.setObjectName("pushButton_plot")
|
||||
self.horizontalLayout_4.addWidget(self.pushButton_plot)
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout_4)
|
||||
self.horizontalLayout_2.addLayout(self.verticalLayout_3)
|
||||
self.line = QtGui.QFrame(postprocessing)
|
||||
self.line.setFrameShape(QtGui.QFrame.VLine)
|
||||
self.line.setFrameShadow(QtGui.QFrame.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.horizontalLayout_2.addWidget(self.line)
|
||||
self.verticalLayout_2 = QtGui.QVBoxLayout()
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.label_2 = QtGui.QLabel(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -59,9 +73,9 @@ class Ui_postprocessing(object):
|
||||
self.label_2.setMinimumSize(QtCore.QSize(0, 20))
|
||||
self.label_2.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 0, 1, 1, 1)
|
||||
self.horizontalLayout_3 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.verticalLayout_2.addWidget(self.label_2)
|
||||
self.horizontalLayout_5 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
||||
self.pushButton_snr = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -70,7 +84,7 @@ class Ui_postprocessing(object):
|
||||
self.pushButton_snr.setSizePolicy(sizePolicy)
|
||||
self.pushButton_snr.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_snr.setObjectName("pushButton_snr")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_snr)
|
||||
self.horizontalLayout_5.addWidget(self.pushButton_snr)
|
||||
self.pushButton_pe = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -79,7 +93,7 @@ class Ui_postprocessing(object):
|
||||
self.pushButton_pe.setSizePolicy(sizePolicy)
|
||||
self.pushButton_pe.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_pe.setObjectName("pushButton_pe")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_pe)
|
||||
self.horizontalLayout_5.addWidget(self.pushButton_pe)
|
||||
self.pushButton_spe = QtGui.QPushButton(postprocessing)
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -88,25 +102,23 @@ class Ui_postprocessing(object):
|
||||
self.pushButton_spe.setSizePolicy(sizePolicy)
|
||||
self.pushButton_spe.setMaximumSize(QtCore.QSize(16777215, 30))
|
||||
self.pushButton_spe.setObjectName("pushButton_spe")
|
||||
self.horizontalLayout_3.addWidget(self.pushButton_spe)
|
||||
self.gridLayout.addLayout(self.horizontalLayout_3, 1, 1, 1, 1)
|
||||
self.verticalLayout.addLayout(self.gridLayout)
|
||||
self.verticalLayout_2.addLayout(self.verticalLayout)
|
||||
self.horizontalLayout_5.addWidget(self.pushButton_spe)
|
||||
self.verticalLayout_2.addLayout(self.horizontalLayout_5)
|
||||
self.horizontalLayout_2.addLayout(self.verticalLayout_2)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.verticalLayout_plot = QtGui.QVBoxLayout()
|
||||
self.verticalLayout_plot.setObjectName("verticalLayout_plot")
|
||||
self.horizontalLayout_plot = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout_plot.setObjectName("horizontalLayout_plot")
|
||||
self.verticalLayout_plot.addLayout(self.horizontalLayout_plot)
|
||||
self.verticalLayout_2.addLayout(self.verticalLayout_plot)
|
||||
self.verticalLayout.addLayout(self.verticalLayout_plot)
|
||||
|
||||
self.retranslateUi(postprocessing)
|
||||
QtCore.QMetaObject.connectSlotsByName(postprocessing)
|
||||
|
||||
def retranslateUi(self, postprocessing):
|
||||
postprocessing.setWindowTitle(QtGui.QApplication.translate("postprocessing", "Postprocessing", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setText(QtGui.QApplication.translate("postprocessing", "Selection", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_rect.setText(QtGui.QApplication.translate("postprocessing", "Rectangle", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_poly.setText(QtGui.QApplication.translate("postprocessing", "Polygon", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label.setText(QtGui.QApplication.translate("postprocessing", "Selection", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_plot.setText(QtGui.QApplication.translate("postprocessing", "Plot", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label_2.setText(QtGui.QApplication.translate("postprocessing", "Color by", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_snr.setText(QtGui.QApplication.translate("postprocessing", "SNR", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.pushButton_pe.setText(QtGui.QApplication.translate("postprocessing", "PE", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'vtk_tools_layout.ui'
|
||||
#
|
||||
# Created: Tue Aug 9 11:40:27 2016
|
||||
# Created: Wed Aug 10 14:11:07 2016
|
||||
# by: pyside-uic 0.2.15 running on PySide 1.2.2
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
@ -14,6 +14,8 @@ from fmtomo_parameters_layout import Ui_fmtomo_parameters
|
||||
from vtk_tools_layout import Ui_vtk_tools
|
||||
from postprocessing_layout import Ui_postprocessing
|
||||
|
||||
from pylot.core.active.surveyPlotTools import regions
|
||||
|
||||
matplotlib.use('Qt4Agg')
|
||||
matplotlib.rcParams['backend.qt4']='PySide'
|
||||
|
||||
@ -602,27 +604,22 @@ class Postprocessing(object):
|
||||
def __init__(self, mainwindow, survey):
|
||||
self.mainwindow = mainwindow
|
||||
self.survey = survey
|
||||
self.init_dialog()
|
||||
self.start_dialog()
|
||||
self.init_widget()
|
||||
self.start_widget()
|
||||
|
||||
def init_dialog(self):
|
||||
def init_widget(self):
|
||||
qwidget = QtGui.QWidget()#
|
||||
ui = Ui_postprocessing()
|
||||
ui.setupUi(qwidget)
|
||||
self.ui = ui
|
||||
self.qwidget = qwidget
|
||||
self.initPlot()
|
||||
self.plot()
|
||||
#self.connectButtons()
|
||||
self.newPlot()
|
||||
self.connectButtons()
|
||||
self.region = regions(self.ax, self.cbar, self.survey, qt_interface = True)
|
||||
|
||||
def start_dialog(self):
|
||||
def start_widget(self):
|
||||
self.qwidget.show()
|
||||
# if self.qwidget.exec_():
|
||||
# #self.refresh_selection()
|
||||
# self.executed = True
|
||||
# else:
|
||||
# self.refresh_selection()
|
||||
# self.executed = False
|
||||
|
||||
def initPlot(self):
|
||||
self.figure = Figure()
|
||||
@ -631,18 +628,27 @@ class Postprocessing(object):
|
||||
self.toolbar = NavigationToolbar(self.canvas, self.mainwindow)
|
||||
self.ui.verticalLayout_plot.addWidget(self.toolbar)
|
||||
|
||||
def plot(self):
|
||||
survey = self.survey
|
||||
def newPlot(self):
|
||||
ax = self.figure.add_subplot(111)
|
||||
dist, pick, snrlog, pickerror, spe = survey.preparePlotAllPicks(plotRemoved = False)
|
||||
ax, cbar, sc = survey.createPlot(dist, pick, snrlog, '123', ax = ax, cbar = None)
|
||||
self.cbar = self.figure.colorbar(sc, fraction=0.05)
|
||||
self.ax = ax
|
||||
dists, picks, snrlog, pe, spe = self.survey.preparePlotAllPicks(plotRemoved = False)
|
||||
self.dists = dists
|
||||
self.picks = picks
|
||||
self.inkDict = {'snrlog': snrlog,
|
||||
'pe': pe,
|
||||
'spe': spe}
|
||||
|
||||
# def refresh_selection(self):
|
||||
# self.obsdir = self.ui.lineEdit_obs.text()
|
||||
# self.fstart = self.ui.fstart.text()
|
||||
# self.fend = self.ui.fend.text()
|
||||
ax, cbar, sc = self.survey.createPlot(dists, picks, snrlog, 'log10(SNR)', ax = ax, cbar = None)
|
||||
self.cbar = self.figure.colorbar(sc, ax = ax, fraction=0.05)
|
||||
self.ax = ax
|
||||
self.draw()
|
||||
|
||||
def refreshPlot(self, inkByVal = 'snrlog'):
|
||||
self.ax.clear()
|
||||
ax = self.ax
|
||||
ax, cbar, sc = self.survey.createPlot(self.dists, self.picks, self.inkDict[inkByVal],
|
||||
inkByVal, ax = ax, cbar = self.cbar)
|
||||
#self.cbar = self.figure.colorbar(sc, fraction=0.05)
|
||||
self.draw()
|
||||
|
||||
def update_survey(self, survey):
|
||||
self.survey = survey
|
||||
@ -650,8 +656,32 @@ class Postprocessing(object):
|
||||
def get_survey(self):
|
||||
return self.survey
|
||||
|
||||
# def connectButtons(self):
|
||||
# QtCore.QObject.connect(self.ui.pushButton_obs, QtCore.SIGNAL("clicked()"), self.chooseObsdir)
|
||||
def draw(self):
|
||||
self.canvas.draw()
|
||||
|
||||
def connectButtons(self):
|
||||
QtCore.QObject.connect(self.ui.pushButton_rect, QtCore.SIGNAL("clicked()"), self.chooseRect)
|
||||
QtCore.QObject.connect(self.ui.pushButton_poly, QtCore.SIGNAL("clicked()"), self.choosePoly)
|
||||
QtCore.QObject.connect(self.ui.pushButton_plot, QtCore.SIGNAL("clicked()"), self.plotPicks)
|
||||
QtCore.QObject.connect(self.ui.pushButton_snr, QtCore.SIGNAL("clicked()"), self.refrSNR)
|
||||
QtCore.QObject.connect(self.ui.pushButton_pe, QtCore.SIGNAL("clicked()"), self.refrPE)
|
||||
QtCore.QObject.connect(self.ui.pushButton_spe, QtCore.SIGNAL("clicked()"), self.refrSPE)
|
||||
|
||||
def chooseRect(self):
|
||||
self.region.chooseRectangles()
|
||||
|
||||
def choosePoly(self):
|
||||
self.region.choosePolygon()
|
||||
|
||||
def plotPicks(self):
|
||||
self.region.plotTracesInActiveRegions()
|
||||
|
||||
def refrSNR(self):
|
||||
self.refreshPlot('snrlog')
|
||||
|
||||
def refrPE(self):
|
||||
self.refreshPlot('pe')
|
||||
|
||||
def refrSPE(self):
|
||||
self.refreshPlot('spe')
|
||||
|
||||
# def chooseObsdir(self):
|
||||
# self.ui.lineEdit_obs.setText(browseDir('Choose observation directory.'))
|
||||
|
@ -29,7 +29,7 @@ class regions(object):
|
||||
|
||||
'''
|
||||
|
||||
def __init__(self, ax, cbar, survey):
|
||||
def __init__(self, ax, cbar, survey, qt_interface = False):
|
||||
self.ax = ax
|
||||
self.cbar = cbar
|
||||
self.cbv = 'log10SNR'
|
||||
@ -45,11 +45,12 @@ class regions(object):
|
||||
self._y1 = []
|
||||
self._polyx = []
|
||||
self._polyy = []
|
||||
self.buttons = {}
|
||||
self._allpicks = None
|
||||
self.shots_found = {}
|
||||
self.shots_for_deletion = {}
|
||||
self._generateList()
|
||||
if not qt_interface:
|
||||
self.buttons = {}
|
||||
self._addButtons()
|
||||
self.addTextfield()
|
||||
self.drawFigure()
|
||||
@ -525,4 +526,5 @@ class regions(object):
|
||||
if resetAxes == True:
|
||||
self.ax.set_xlim(self._xlim)
|
||||
self.ax.set_ylim(self._ylim)
|
||||
plt.draw()
|
||||
self.ax.figure.canvas.draw()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user