Browse Source

Further improvements to GUI

tags/1.6.1
Trevor Irons 5 years ago
parent
commit
3e71430955
5 changed files with 1652 additions and 1451 deletions
  1. 89
    13
      akvo/gui/akvoGUI.py
  2. 1531
    1424
      akvo/gui/main.ui
  3. 29
    13
      akvo/gui/mydynamicmplcanvas.py
  4. 2
    0
      akvo/tressel/mrsurvey.py
  5. 1
    1
      setup.py

+ 89
- 13
akvo/gui/akvoGUI.py View File

172
         self.ui.plotGI.setEnabled(False) 
172
         self.ui.plotGI.setEnabled(False) 
173
         self.ui.plotGI.pressed.connect( self.plotGI )
173
         self.ui.plotGI.pressed.connect( self.plotGI )
174
  
174
  
175
+        # hide header info box 
176
+        #self.ui.headerFileBox.setVisible(False) 
177
+        self.ui.headerFileBox.clicked.connect( self.headerBoxShrink ) 
178
+        self.ui.headerBox2.setVisible(False) 
179
+
180
+        # Clean up the tab widget 
181
+        self.ui.actionPreprocessing.triggered.connect(self.addPreProc)
182
+        self.ui.actionModelling.triggered.connect(self.addModelling)
183
+        self.ui.actionInversion.triggered.connect(self.addInversion)
184
+
185
+        # tabs 
186
+        #self.ui.ProcTabs.tabCloseRequested.connect( self.closeTabs )
187
+        #self.ui.ProcTabs.tabBar().setTabButton(7, QtWidgets.QTabBar.RightSide,None) 
188
+        self.ui.ProcTabs.removeTab(4)    
189
+        self.ui.ProcTabs.removeTab(4)    
190
+        self.ui.ProcTabs.removeTab(4)    
191
+        self.ui.ProcTabs.removeTab(4)    
192
+        #self.ui.LoadTab.close(  ) 
193
+
175
         # Add progressbar to statusbar
194
         # Add progressbar to statusbar
176
         self.ui.barProgress =  QtWidgets.QProgressBar()
195
         self.ui.barProgress =  QtWidgets.QProgressBar()
177
         self.ui.statusbar.addPermanentWidget(self.ui.barProgress, 0);
196
         self.ui.statusbar.addPermanentWidget(self.ui.barProgress, 0);
181
         self.ui.mplwidget_navigator.setCanvas(self.ui.mplwidget)
200
         self.ui.mplwidget_navigator.setCanvas(self.ui.mplwidget)
182
         #self.ui.mplwidget_navigator_2.setCanvas(self.ui.mplwidget)
201
         #self.ui.mplwidget_navigator_2.setCanvas(self.ui.mplwidget)
183
 
202
 
203
+
184
         ##########################################################################
204
         ##########################################################################
185
         # Loop Table 
205
         # Loop Table 
186
         self.ui.loopTableWidget.setRowCount(80)       
206
         self.ui.loopTableWidget.setRowCount(80)       
231
                 self.ui.layerTableWidget.setItem(ir, ic, pCell)
251
                 self.ui.layerTableWidget.setItem(ir, ic, pCell)
232
         self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged) 
252
         self.ui.layerTableWidget.cellChanged.connect(self.sigmaCellChanged) 
233
 
253
 
254
+    def closeTabs(self):
255
+        #self.ui.ProcTabs.removeTab(idx)    
256
+        self.ui.ProcTabs.clear( )    
257
+    
258
+    def addPreProc(self):
259
+        if self.ui.actionPreprocessing.isChecked(): 
260
+            self.ui.actionModelling.setChecked(False) 
261
+            self.ui.actionInversion.setChecked(False) 
262
+            self.ui.ProcTabs.clear( )    
263
+            self.ui.ProcTabs.insertTab( 0, self.ui.LoadTab, "Load" )    
264
+            self.ui.ProcTabs.insertTab( 1, self.ui.NCTab, "NC" )    
265
+            self.ui.ProcTabs.insertTab( 2, self.ui.QCTab, "QC" )    
266
+            self.ui.ProcTabs.insertTab( 3, self.ui.METATab, "META" )    
267
+            self.ui.ProcTabs.insertTab( 4, self.ui.LogTab, "Log" )    
268
+        else:
269
+            self.ui.ProcTabs.removeTab(0)    
270
+            self.ui.ProcTabs.removeTab(0)    
271
+            self.ui.ProcTabs.removeTab(0)    
272
+            self.ui.ProcTabs.removeTab(0)    
273
+    
274
+    def addModelling(self):
275
+        if self.ui.actionModelling.isChecked(): 
276
+            self.ui.actionPreprocessing.setChecked(False) 
277
+            self.ui.actionInversion.setChecked(False) 
278
+            self.ui.ProcTabs.clear( )    
279
+            self.ui.ProcTabs.insertTab( 0, self.ui.KernTab, "Kernel" )    
280
+            self.ui.ProcTabs.insertTab( 1, self.ui.ModelTab, "Modelling" )    
281
+            self.ui.ProcTabs.insertTab( 2, self.ui.LogTab, "Log" )    
282
+        else:
283
+            self.ui.ProcTabs.removeTab(0)    
284
+            self.ui.ProcTabs.removeTab(0)    
285
+    
286
+    def addInversion(self, idx):
287
+        if self.ui.actionInversion.isChecked(): 
288
+            self.ui.actionPreprocessing.setChecked(False) 
289
+            self.ui.actionModelling.setChecked(False) 
290
+            self.ui.ProcTabs.clear( )    
291
+            self.ui.ProcTabs.insertTab( 0, self.ui.InvertTab, "Inversion" )    
292
+            self.ui.ProcTabs.insertTab( 1, self.ui.AppraiseTab, "Appraisal" )    
293
+            self.ui.ProcTabs.insertTab( 2, self.ui.LogTab, "Log" )    
294
+        else:
295
+            self.ui.ProcTabs.removeTab(0)    
296
+            self.ui.ProcTabs.removeTab(0)    
297
+
298
+    def headerBoxShrink(self):
299
+        #self.ui.headerFileBox.setVisible(False)
300
+ 
301
+        if self.ui.headerFileBox.isChecked( ): 
302
+            #self.ui.headerFileBox.setMinimumSize(460,250) 
303
+            self.ui.headerBox2.setVisible(True) 
304
+        else:
305
+            #self.ui.headerFileBox.setMinimumSize(460,50) 
306
+            self.ui.headerBox2.setVisible(False) 
234
 
307
 
235
     def sigmaCellChanged(self):
308
     def sigmaCellChanged(self):
236
         self.ui.layerTableWidget.cellChanged.disconnect(self.sigmaCellChanged) 
309
         self.ui.layerTableWidget.cellChanged.disconnect(self.sigmaCellChanged) 
365
                 #pCell.setFlags( )
438
                 #pCell.setFlags( )
366
                 pCell.setBackground( QtGui.QColor("lightblue") )
439
                 pCell.setBackground( QtGui.QColor("lightblue") )
367
 
440
 
368
-
369
-            
370
- 
371
         self.plotLoops()
441
         self.plotLoops()
372
         self.ui.loopTableWidget.cellChanged.connect(self.loopCellChanged) 
442
         self.ui.loopTableWidget.cellChanged.connect(self.loopCellChanged) 
373
 
443
 
374
 
444
 
375
     def plotLoops(self):
445
     def plotLoops(self):
376
-               
377
-        #self.ui.mplwidget_3.fig.clear() 
378
-        self.ui.mplwidget_3.ax1.clear() 
379
-        self.ui.mplwidget_3.ax2.clear()
446
+
447
+        print("Plotting loopz")        
448
+       
449
+        self.ui.mplwidget.reAxH(1)
450
+        #self.ui.mplwidget.ax1.clear() 
451
+        #self.ui.mplwidget.ax2.clear()
380
         nor = dict()
452
         nor = dict()
381
         eas = dict()
453
         eas = dict()
382
         dep = dict() 
454
         dep = dict() 
403
 
475
 
404
         for ii in nor.keys():            
476
         for ii in nor.keys():            
405
             try:    
477
             try:    
406
-                self.ui.mplwidget_3.ax1.plot(  np.array(nor[ii]), np.array(eas[ii])  )
478
+                self.ui.mplwidget.ax1.plot(  np.array(nor[ii]), np.array(eas[ii])  )
407
             except:
479
             except:
408
                 pass 
480
                 pass 
409
-        #self.ui.mplwidget_3.figure.axes().set
410
-        plt.gca().set_aspect('equal') #, adjustable='box')
411
-        self.ui.mplwidget_3.draw()
481
+        #self.ui.mplwidget.figure.axes().set
482
+        self.ui.mplwidget.ax1.set_aspect('equal') #, adjustable='box')
483
+        self.ui.mplwidget.draw()
412
 
484
 
413
     def about(self):
485
     def about(self):
414
         # TODO proper popup with info
486
         # TODO proper popup with info
469
         self.ui.lcdNumberNQ.setEnabled(True)
541
         self.ui.lcdNumberNQ.setEnabled(True)
470
 
542
 
471
         self.ui.headerFileBox.setEnabled(True)
543
         self.ui.headerFileBox.setEnabled(True)
544
+        self.ui.headerFileBox.setChecked( True )
545
+        self.ui.headerBox2.setVisible(True) 
472
         self.ui.inputRAWParametersBox.setEnabled(True)
546
         self.ui.inputRAWParametersBox.setEnabled(True)
473
         self.ui.loadDataPushButton.setEnabled(True)
547
         self.ui.loadDataPushButton.setEnabled(True)
474
          
548
          
706
         self.ui.lcdNumberNQ.setEnabled(True)
780
         self.ui.lcdNumberNQ.setEnabled(True)
707
 
781
 
708
         self.ui.headerFileBox.setEnabled(True)
782
         self.ui.headerFileBox.setEnabled(True)
783
+        self.ui.headerFileBox.setChecked( False )
784
+        #self.ui.headerBox2.setVisible(True) 
709
         self.ui.inputRAWParametersBox.setEnabled(True)
785
         self.ui.inputRAWParametersBox.setEnabled(True)
710
         self.ui.loadDataPushButton.setEnabled(True)
786
         self.ui.loadDataPushButton.setEnabled(True)
711
         
787
         
1249
     for ax in [ aw.ui.mplwidget ]: 
1325
     for ax in [ aw.ui.mplwidget ]: 
1250
         ax.fig.clear()
1326
         ax.fig.clear()
1251
         subplot = ax.fig.add_subplot(111)
1327
         subplot = ax.fig.add_subplot(111)
1252
-        ax.fig.patch.set_facecolor( None )
1253
-        ax.fig.patch.set_alpha( .0 )
1328
+        #ax.fig.patch.set_facecolor( None )
1329
+        #ax.fig.patch.set_alpha( .0 )
1254
         subplot.imshow(img) 
1330
         subplot.imshow(img) 
1255
         subplot.xaxis.set_major_locator(plt.NullLocator()) 
1331
         subplot.xaxis.set_major_locator(plt.NullLocator()) 
1256
         subplot.yaxis.set_major_locator(plt.NullLocator()) 
1332
         subplot.yaxis.set_major_locator(plt.NullLocator()) 

+ 1531
- 1424
akvo/gui/main.ui
File diff suppressed because it is too large
View File


+ 29
- 13
akvo/gui/mydynamicmplcanvas.py View File

17
     """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
17
     """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
18
     def __init__(self, parent=None, width=3, height=4, dpi=100):
18
     def __init__(self, parent=None, width=3, height=4, dpi=100):
19
         
19
         
20
-        self.fig = Figure(figsize=(width, height), dpi=dpi)
20
+        self.fig = Figure(figsize=(width, height), dpi=dpi, facecolor='darkgrey') # this fucking works...why?
21
+        #self.fig.patch.set_facecolor('blue')
21
         FigureCanvas.__init__(self, self.fig)
22
         FigureCanvas.__init__(self, self.fig)
22
 
23
 
23
         self.setParent(parent)
24
         self.setParent(parent)
33
 
34
 
34
     """A canvas that updates itself every second with a new plot."""
35
     """A canvas that updates itself every second with a new plot."""
35
     def __init__(self, *args, **kwargs):
36
     def __init__(self, *args, **kwargs):
36
-        
37
         MyMplCanvas.__init__(self, *args, **kwargs)
37
         MyMplCanvas.__init__(self, *args, **kwargs)
38
         self.ax1 = self.fig.add_axes([.125,.1,.725,.8])
38
         self.ax1 = self.fig.add_axes([.125,.1,.725,.8])
39
         self.ax2 = self.ax1.twinx() # fig.add_axes([.125,.1,.725,.8])
39
         self.ax2 = self.ax1.twinx() # fig.add_axes([.125,.1,.725,.8])
40
         self.compute_initial_figure()
40
         self.compute_initial_figure()
41
 
41
 
42
     def reAxH(self, num, shx=True, shy=True):
42
     def reAxH(self, num, shx=True, shy=True):
43
+        
44
+        try:
45
+            for ax in fig.axes:
46
+                self.fig.delaxes(ax)
47
+        except:
48
+            pass
43
         try:
49
         try:
44
             self.fig.clear()
50
             self.fig.clear()
45
         except:
51
         except:
46
             pass
52
             pass
53
+
47
         for n in range(num):
54
         for n in range(num):
48
             if n == 0:
55
             if n == 0:
49
-                self.ax1 = self.fig.add_subplot( 1, num, 1 )
56
+                self.ax1 = self.fig.add_subplot( 1, num, 1)
50
                 self.ax1.tick_params(axis='both', which='major', labelsize=8)
57
                 self.ax1.tick_params(axis='both', which='major', labelsize=8)
51
                 self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
58
                 self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
59
+                self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='x')  
52
                 self.ax1.yaxis.get_offset_text().set_size(8) 
60
                 self.ax1.yaxis.get_offset_text().set_size(8) 
61
+                self.ax1.xaxis.get_offset_text().set_size(8) 
53
             if n == 1:
62
             if n == 1:
54
-                self.ax2 = self.fig.add_subplot( 1, num, 2 )
63
+                self.ax2 = self.fig.add_subplot( 1, num, 2)
55
                 self.ax2.tick_params(axis='both', which='major', labelsize=8)
64
                 self.ax2.tick_params(axis='both', which='major', labelsize=8)
56
                 self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
65
                 self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
57
                 self.ax2.yaxis.get_offset_text().set_size(8) 
66
                 self.ax2.yaxis.get_offset_text().set_size(8) 
58
             if n == 2:
67
             if n == 2:
59
-                self.ax3 = self.fig.add_subplot( 1, num, 3 )
68
+                self.ax3 = self.fig.add_subplot( 1, num, 3) 
60
                 self.ax3.tick_params(axis='both', which='major', labelsize=8)
69
                 self.ax3.tick_params(axis='both', which='major', labelsize=8)
61
                 self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
70
                 self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
62
                 self.ax3.yaxis.get_offset_text().set_size(8) 
71
                 self.ax3.yaxis.get_offset_text().set_size(8) 
63
             if n == 3:
72
             if n == 3:
64
-                self.ax4 = self.fig.add_subplot( 1, num, 4 )
73
+                self.ax4 = self.fig.add_subplot( 1, num, 4) 
65
                 self.ax4.tick_params(axis='both', which='major', labelsize=8)
74
                 self.ax4.tick_params(axis='both', which='major', labelsize=8)
66
                 self.ax4.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
75
                 self.ax4.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
67
                 self.ax4.yaxis.get_offset_text().set_size(8) 
76
                 self.ax4.yaxis.get_offset_text().set_size(8) 
72
                 self.fig.delaxes(ax)
81
                 self.fig.delaxes(ax)
73
         except:
82
         except:
74
             pass
83
             pass
75
-
76
         try:
84
         try:
77
             self.fig.clear()
85
             self.fig.clear()
78
         except:
86
         except:
80
         
88
         
81
         for n in range(num):
89
         for n in range(num):
82
             if n == 0:
90
             if n == 0:
83
-                self.ax1 = self.fig.add_subplot( 2, num, 1 )
91
+                self.ax1 = self.fig.add_subplot( 2, num, 1)
84
                 self.ax1.tick_params(axis='both', which='major', labelsize=8)
92
                 self.ax1.tick_params(axis='both', which='major', labelsize=8)
85
                 self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
93
                 self.ax1.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
86
                 self.ax1.yaxis.get_offset_text().set_size(8) 
94
                 self.ax1.yaxis.get_offset_text().set_size(8) 
87
-                self.ax21 = self.fig.add_subplot( 2, num, num+1 )
95
+                self.ax21 = self.fig.add_subplot( 2, num, num+1)
88
                 self.ax21.tick_params(axis='both', which='major', labelsize=8)
96
                 self.ax21.tick_params(axis='both', which='major', labelsize=8)
89
                 self.ax21.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
97
                 self.ax21.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
90
                 self.ax21.yaxis.get_offset_text().set_size(8) 
98
                 self.ax21.yaxis.get_offset_text().set_size(8) 
91
             if n == 1:
99
             if n == 1:
92
-                self.ax2 = self.fig.add_subplot( 2, num, 2, sharex=self.ax1, sharey=self.ax1 )
100
+                self.ax2 = self.fig.add_subplot( 2, num, 2, sharex=self.ax1, sharey=self.ax1)
93
                 self.ax2.tick_params(axis='both', which='major', labelsize=8)
101
                 self.ax2.tick_params(axis='both', which='major', labelsize=8)
94
                 self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
102
                 self.ax2.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
95
                 self.ax2.yaxis.get_offset_text().set_size(8) 
103
                 self.ax2.yaxis.get_offset_text().set_size(8) 
96
-                self.ax22 = self.fig.add_subplot( 2, num, num+2, sharex=self.ax21, sharey=self.ax21 )
104
+                self.ax22 = self.fig.add_subplot( 2, num, num+2, sharex=self.ax21, sharey=self.ax21)
97
                 self.ax22.tick_params(axis='both', which='major', labelsize=8)
105
                 self.ax22.tick_params(axis='both', which='major', labelsize=8)
98
                 self.ax22.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
106
                 self.ax22.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
99
                 self.ax22.yaxis.get_offset_text().set_size(8) 
107
                 self.ax22.yaxis.get_offset_text().set_size(8) 
100
             if n == 2:
108
             if n == 2:
101
-                self.ax3 = self.fig.add_subplot( 2, num, 3, sharex=self.ax1, sharey=self.ax1 )
109
+                self.ax3 = self.fig.add_subplot( 2, num, 3, sharex=self.ax1, sharey=self.ax1)
102
                 self.ax3.tick_params(axis='both', which='major', labelsize=8)
110
                 self.ax3.tick_params(axis='both', which='major', labelsize=8)
103
                 self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
111
                 self.ax3.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
104
                 self.ax3.yaxis.get_offset_text().set_size(8) 
112
                 self.ax3.yaxis.get_offset_text().set_size(8) 
105
-                self.ax23 = self.fig.add_subplot( 2, num, num+3, sharex=self.ax21, sharey=self.ax21 )
113
+                self.ax23 = self.fig.add_subplot( 2, num, num+3, sharex=self.ax21, sharey=self.ax21)
106
                 self.ax23.tick_params(axis='both', which='major', labelsize=8)
114
                 self.ax23.tick_params(axis='both', which='major', labelsize=8)
107
                 self.ax23.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
115
                 self.ax23.ticklabel_format(style='sci', scilimits=(0,0), axis='y')  
108
                 self.ax23.yaxis.get_offset_text().set_size(8) 
116
                 self.ax23.yaxis.get_offset_text().set_size(8) 
176
         except:
184
         except:
177
             pass
185
             pass
178
 
186
 
187
+        #self.fig.patch.set_facecolor('red')
179
         self.ax1 = self.fig.add_subplot(211)
188
         self.ax1 = self.fig.add_subplot(211)
180
         if shx and shy:
189
         if shx and shy:
181
             self.ax2 = self.fig.add_subplot(212, sharex=self.ax1, sharey=self.ax1)
190
             self.ax2 = self.fig.add_subplot(212, sharex=self.ax1, sharey=self.ax1)
232
 
241
 
233
         self.ax3 = self.ax1.twinx()
242
         self.ax3 = self.ax1.twinx()
234
 
243
 
244
+        #self.ax1.set_facecolor('red')
245
+        #self.ax2.set_facecolor('red')
246
+        #self.ax3.set_facecolor('red')
247
+        #self.fig.set_facecolor('red')
248
+        #self.fig.set_edgecolor('red')
249
+        #self.ax1.set_axis_bgcolor('green')
250
+
235
         self.ax1.tick_params(axis='both', which='major', labelsize=8)
251
         self.ax1.tick_params(axis='both', which='major', labelsize=8)
236
         self.ax2.tick_params(axis='both', which='major', labelsize=8)
252
         self.ax2.tick_params(axis='both', which='major', labelsize=8)
237
         self.ax3.tick_params(axis='both', which='major', labelsize=8)
253
         self.ax3.tick_params(axis='both', which='major', labelsize=8)

+ 2
- 0
akvo/tressel/mrsurvey.py View File

2216
         #    results = pool.starmap( loadGMRBinaryFID, zip(itertools.repeat(self), fnames, info ) ) # zip(np.tile(vc, (ns, 1)), np.tile(vgc, (ns,1)), itertools.repeat(sys.argv[1]), itertools.repeat(sys.argv[2]), EPS_CMR))
2216
         #    results = pool.starmap( loadGMRBinaryFID, zip(itertools.repeat(self), fnames, info ) ) # zip(np.tile(vc, (ns, 1)), np.tile(vgc, (ns,1)), itertools.repeat(sys.argv[1]), itertools.repeat(sys.argv[2]), EPS_CMR))
2217
 
2217
 
2218
         # Plotting
2218
         # Plotting
2219
+
2219
         if plot: 
2220
         if plot: 
2220
             iistack = 0
2221
             iistack = 0
2221
             for istack in procStacks:
2222
             for istack in procStacks:
2223
                     canvas.ax1.clear()
2224
                     canvas.ax1.clear()
2224
                     canvas.ax2.clear()
2225
                     canvas.ax2.clear()
2225
                     canvas.ax3.clear()
2226
                     canvas.ax3.clear()
2227
+                    #canvas.fig.patch.set_facecolor('blue')
2226
                            
2228
                            
2227
                     for ichan in chan:
2229
                     for ichan in chan:
2228
                         canvas.ax1.plot(self.DATADICT["Pulse 1"]["PULSE_TIMES"], self.DATADICT["Pulse 1"]["CURRENT"][ipm][istack] , color='black')
2230
                         canvas.ax1.plot(self.DATADICT["Pulse 1"]["PULSE_TIMES"], self.DATADICT["Pulse 1"]["CURRENT"][ipm][istack] , color='black')

+ 1
- 1
setup.py View File

17
         build_py.run(self)
17
         build_py.run(self)
18
 
18
 
19
 setup(name='Akvo',
19
 setup(name='Akvo',
20
-      version='1.0.6',
20
+      version='1.0.7',
21
       description='Surface nuclear magnetic resonance workbench',
21
       description='Surface nuclear magnetic resonance workbench',
22
       author='Trevor P. Irons',
22
       author='Trevor P. Irons',
23
       author_email='Trevor.Irons@lemmasoftware.org',
23
       author_email='Trevor.Irons@lemmasoftware.org',

Loading…
Cancel
Save