easycoder 250118.1__py2.py3-none-any.whl → 251103.4__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
easycoder/ec_pyside.py ADDED
@@ -0,0 +1,1545 @@
1
+ import sys
2
+ from functools import partial
3
+ from .ec_handler import Handler
4
+ from .ec_classes import RuntimeError, Object
5
+ from .ec_border import Border
6
+ from PySide6.QtCore import Qt, QTimer, Signal, QRect
7
+ from PySide6.QtGui import QPixmap, QPainter
8
+ from PySide6.QtWidgets import (
9
+ QApplication,
10
+ QCheckBox,
11
+ QComboBox,
12
+ QDateEdit,
13
+ QDateTimeEdit,
14
+ QDial,
15
+ QDoubleSpinBox,
16
+ QFontComboBox,
17
+ QLabel,
18
+ QLCDNumber,
19
+ QLineEdit,
20
+ QPlainTextEdit,
21
+ QListWidget,
22
+ QMainWindow,
23
+ QProgressBar,
24
+ QPushButton,
25
+ QRadioButton,
26
+ QSlider,
27
+ QSpinBox,
28
+ QTimeEdit,
29
+ QLayout,
30
+ QVBoxLayout,
31
+ QHBoxLayout,
32
+ QGridLayout,
33
+ QStackedLayout,
34
+ QGroupBox,
35
+ QWidget,
36
+ QSpacerItem,
37
+ QSizePolicy,
38
+ QDialog,
39
+ QMessageBox,
40
+ QDialogButtonBox,
41
+ QGraphicsDropShadowEffect
42
+ )
43
+
44
+ class Graphics(Handler):
45
+
46
+ def __init__(self, compiler):
47
+ super().__init__(compiler)
48
+ self.blocked = False
49
+ self.runOnTick = 0
50
+ self.vkb = False
51
+
52
+ def getName(self):
53
+ return 'graphics'
54
+
55
+ def closeEvent(self):
56
+ print('window closed')
57
+
58
+ def isWidget(self, keyword):
59
+ return keyword in [
60
+ 'layout',
61
+ 'group',
62
+ 'label',
63
+ 'pushbutton',
64
+ 'checkbox',
65
+ 'lineinput',
66
+ 'multiline',
67
+ 'listbox',
68
+ 'combobox',
69
+ 'widget'
70
+ ]
71
+
72
+ def setWidget(self, record, widget):
73
+ if record['index'] >= record['elements']:
74
+ RuntimeError(self.program, f'Index out of range for widget {record["name"]}')
75
+ if not 'widget' in record:
76
+ record['widget'] = [None] * record['elements']
77
+ while len(record['widget']) < record['elements']:
78
+ record['widget'].append(None)
79
+ record['widget'][record['index']] = widget
80
+
81
+ def getWidget(self, record):
82
+ if 'widget' in record and record['widget'] != None:
83
+ if record['keyword'] in ['layout', 'group']: return record['widget']
84
+ return record['widget'][record['index']]
85
+ else:
86
+ return None
87
+
88
+ def dialogTypes(self):
89
+ return ['confirm', 'lineedit', 'multiline', 'generic']
90
+
91
+ class ClickableLineEdit(QLineEdit):
92
+ clicked = Signal()
93
+
94
+ def __init__(self):
95
+ super().__init__()
96
+ self.multiline = False
97
+ self.container = None
98
+
99
+ def setContainer(self, container):
100
+ self.container = container
101
+
102
+ def mousePressEvent(self, event):
103
+ self.clicked.emit()
104
+ super().mousePressEvent(event)
105
+ if self.container != None: self.container.setClickSource(self)
106
+
107
+ class ClickablePlainTextEdit(QPlainTextEdit):
108
+ clicked = Signal()
109
+
110
+ def __init__(self):
111
+ super().__init__()
112
+ self.multiline = True
113
+ self.container = None
114
+
115
+ def setContainer(self, container):
116
+ self.container = container
117
+
118
+ def mousePressEvent(self, event):
119
+ self.clicked.emit()
120
+ super().mousePressEvent(event)
121
+ if self.container != None: self.container.setClickSource(self)
122
+
123
+ #############################################################################
124
+ # Keyword handlers
125
+
126
+ # (1) add {value} to {widget}
127
+ # (2) add {widget} to {layout}
128
+ # (3) add stretch {widget} to {layout}
129
+ # (4) add stretch to {layout}
130
+ # (5) add spacer [size] {size} to {layout}
131
+ # (6) add {widget} at {col} {row} in {grid layout}
132
+ def k_add(self, command):
133
+ def addToLayout():
134
+ if self.nextIsSymbol():
135
+ record = self.getSymbolRecord()
136
+ if record['keyword'] in ['layout', 'group', 'element']:
137
+ command['layout'] = record['name']
138
+ self.add(command)
139
+ return True
140
+ return False
141
+
142
+ token = self.peek()
143
+ if token == 'stretch':
144
+ self.nextToken()
145
+ # It's either (3) or (4)
146
+ if self.nextIs('to'):
147
+ # (4)
148
+ command['stretch'] = False
149
+ command['widget'] = 'stretch'
150
+ return addToLayout()
151
+ if self.isSymbol():
152
+ # (3)
153
+ record = self.getSymbolRecord()
154
+ command['widget'] = record['name']
155
+ command['stretch'] = True
156
+ if self.nextIs('to'):
157
+ return addToLayout()
158
+ return False
159
+
160
+ elif token == 'spacer':
161
+ self.nextToken()
162
+ self.skip('size')
163
+ command['widget'] = 'spacer'
164
+ command['size'] = self.nextValue()
165
+ self.skip('to')
166
+ return addToLayout()
167
+
168
+ # Here it's either (1) or (2)
169
+ elif self.nextIsSymbol():
170
+ record = self.getSymbolRecord()
171
+ if record['extra'] == 'gui':
172
+ if self.isWidget(record['keyword']):
173
+ command['widget'] = record['name']
174
+ if self.peek() == 'to':
175
+ # (2)
176
+ record = self.getSymbolRecord()
177
+ self.nextToken()
178
+ return addToLayout()
179
+ elif self.peek() == 'at':
180
+ # (6)
181
+ self.nextToken()
182
+ command['row'] = self.nextValue()
183
+ command['col'] = self.nextValue()
184
+ self.skip('in')
185
+ return addToLayout()
186
+
187
+ else: return False
188
+ # (1)
189
+ value = self.getValue()
190
+ if value == None: return False
191
+ command['value'] = value
192
+ self.skip('to')
193
+ if self.nextIsSymbol():
194
+ record = self.getSymbolRecord()
195
+ command['widget'] = record['name']
196
+ self.add(command)
197
+ return True
198
+ return False
199
+
200
+ def r_add(self, command):
201
+ if 'value' in command:
202
+ value = self.getRuntimeValue(command['value'])
203
+ record = self.getVariable(command['widget'])
204
+ if record['keyword'] == 'listbox':
205
+ self.getWidget(record).addItem(value)
206
+ elif record['keyword'] == 'combobox':
207
+ if isinstance(value, list): record['widget'].addItems(value)
208
+ else: self.getWidget(record).addItem(value)
209
+ elif 'row' in command and 'col' in command:
210
+ layout = self.getVariable(command['layout'])['widget']
211
+ record = self.getVariable(command['widget'])
212
+ widget = self.getWidget(record)
213
+ row = self.getRuntimeValue(command['row'])
214
+ col = self.getRuntimeValue(command['col'])
215
+ if record['keyword'] == 'layout':
216
+ layout.addLayout(widget, row, col)
217
+ else:
218
+ layout.addWidget(widget, row, col)
219
+ else:
220
+ layoutRecord = self.getVariable(command['layout'])
221
+ widget = command['widget']
222
+ if widget == 'stretch':
223
+ self.getWidget(layoutRecord).addStretch()
224
+ elif widget == 'spacer':
225
+ self.getWidget(layoutRecord).addSpacing(self.getRuntimeValue(command['size']))
226
+ else:
227
+ widgetRecord = self.getVariable(widget)
228
+ layoutRecord = self.getVariable(command['layout'])
229
+ widget = self.getWidget(widgetRecord)
230
+ layout = layoutRecord['widget']
231
+ stretch = 'stretch' in command
232
+ if widgetRecord['keyword'] == 'layout':
233
+ if layoutRecord['keyword'] == 'group':
234
+ if widgetRecord['keyword'] == 'layout':
235
+ layout.setLayout(widget)
236
+ else:
237
+ RuntimeError(self.program, 'Can only add a layout to a group')
238
+ else:
239
+ if stretch: layout.addLayout(widget, stretch=1)
240
+ else: layout.addLayout(widget)
241
+ else:
242
+ if stretch: layout.addWidget(widget, stretch=1)
243
+ else: layout.addWidget(widget)
244
+ return self.nextPC()
245
+
246
+ # Center one window on another
247
+ # center {window2} on {window1}
248
+ def k_center(self, command):
249
+ if self.nextIsSymbol():
250
+ record = self.getSymbolRecord()
251
+ if record['keyword'] == 'window':
252
+ command['window2'] = record['name']
253
+ self.skip('on')
254
+ if self.nextIsSymbol():
255
+ record = self.getSymbolRecord()
256
+ if record['keyword'] == 'window':
257
+ command['window1'] = record['name']
258
+ self.add(command)
259
+ return True
260
+ return False
261
+
262
+ def r_center(self, command):
263
+ window1 = self.getVariable(command['window1'])['window']
264
+ window2 = self.getVariable(command['window2'])['window']
265
+ geo1 = window1.geometry()
266
+ geo2 = window2.geometry()
267
+ geo2.moveCenter(geo1.center())
268
+ window2.setGeometry(geo2)
269
+ return self.nextPC()
270
+
271
+ # Declare a checkbox variable
272
+ def k_checkbox(self, command):
273
+ return self.compileVariable(command, 'gui')
274
+
275
+ def r_checkbox(self, command):
276
+ return self.nextPC()
277
+
278
+ # clear {widget}
279
+ def k_clear(self, command):
280
+ if self.nextIsSymbol():
281
+ record = self.getSymbolRecord()
282
+ if self.isWidget(record['keyword']):
283
+ command['name'] = record['name']
284
+ self.add(command)
285
+ return True
286
+ return False
287
+
288
+ def r_clear(self, command):
289
+
290
+ def clearLayout(layout: QLayout) -> None:
291
+ if layout is None:
292
+ return
293
+ while layout.count() > 0:
294
+ item = layout.takeAt(0)
295
+ if item is None:
296
+ continue
297
+ widget = item.widget()
298
+ if widget is not None:
299
+ # Delete the widget
300
+ widget.deleteLater()
301
+ elif item.layout() is not None:
302
+ # Recursively clear sub-layout
303
+ clearLayout(item.layout())
304
+ item.layout().deleteLater()
305
+ # The QLayoutItem will be automatically cleaned up by Qt
306
+
307
+ def clearWidget(widget: QWidget) -> None:
308
+ if widget is None:
309
+ return
310
+ # Clear the layout first
311
+ layout = widget.layout()
312
+ if layout is not None:
313
+ clearLayout(layout)
314
+ layout.deleteLater()
315
+ # Clear any remaining child widgets
316
+ child_widgets = widget.findChildren(QWidget, "", Qt.FindDirectChildrenOnly)
317
+ for child in child_widgets:
318
+ child.deleteLater()
319
+
320
+ widget = self.getWidget(self.getVariable(command['name']))
321
+ clearWidget(widget)
322
+ return self.nextPC()
323
+
324
+ return self.nextPC()
325
+
326
+ # close {window}
327
+ def k_close(self, command):
328
+ if self.nextIsSymbol():
329
+ record = self.getSymbolRecord()
330
+ if record['keyword'] == 'window':
331
+ command['name'] = record['name']
332
+ self.add(command)
333
+ return True
334
+ return False
335
+
336
+ def r_close(self, command):
337
+ self.getVariable(command['name'])['window'].close()
338
+ return self.nextPC()
339
+
340
+ # Declare a combobox variable
341
+ def k_combobox(self, command):
342
+ return self.compileVariable(command, 'gui')
343
+
344
+ def r_combobox(self, command):
345
+ return self.nextPC()
346
+
347
+ # Create a window
348
+ def k_createWindow(self, command):
349
+ title = None
350
+ x = None
351
+ y = None
352
+ w = self.compileConstant(640)
353
+ h = self.compileConstant(480)
354
+ while True:
355
+ token = self.peek()
356
+ if token in ['title', 'at', 'size', 'layout']:
357
+ self.nextToken()
358
+ if token == 'title': title = self.nextValue()
359
+ elif token == 'at':
360
+ x = self.nextValue()
361
+ y = self.nextValue()
362
+ elif token == 'size':
363
+ w = self.nextValue()
364
+ h = self.nextValue()
365
+ elif token == 'layout':
366
+ if self.nextIsSymbol():
367
+ record = self.getSymbolRecord()
368
+ if record['keyword'] == 'layout':
369
+ command['layout'] = record['name']
370
+ else: return False
371
+ else: break
372
+ command['title'] = title
373
+ command['x'] = x
374
+ command['y'] = y
375
+ command['w'] = w
376
+ command['h'] = h
377
+ self.add(command)
378
+ return True
379
+
380
+ # Create a widget
381
+ def k_createLayout(self, command):
382
+ self.skip('type')
383
+ command['type'] = self.nextToken()
384
+ self.add(command)
385
+ return True
386
+
387
+ def k_createGroupBox(self, command):
388
+ if self.peek() == 'title':
389
+ self.nextToken()
390
+ title = self.nextValue()
391
+ else: title = ''
392
+ command['title'] = title
393
+ self.add(command)
394
+ return True
395
+
396
+ def k_createLabel(self, command):
397
+ text = self.compileConstant('')
398
+ while True:
399
+ token = self.peek()
400
+ if token == 'text':
401
+ self.nextToken()
402
+ text = self.nextValue()
403
+ elif token == 'size':
404
+ self.nextToken()
405
+ command['size'] = self.nextValue()
406
+ elif token == 'expand':
407
+ self.nextToken()
408
+ command['expand'] = True
409
+ elif token == 'align':
410
+ self.nextToken()
411
+ token = self.nextToken()
412
+ if token in ['left', 'right', 'center', 'centre', 'justify']:
413
+ command['align'] = token
414
+ else: break
415
+ command['text'] = text
416
+ self.add(command)
417
+ return True
418
+
419
+ def k_createPushbutton(self, command):
420
+ while True:
421
+ token = self.peek()
422
+ if token == 'text':
423
+ self.nextToken()
424
+ command['text'] = self.nextValue()
425
+ elif token == 'icon':
426
+ self.nextToken()
427
+ command['icon'] = self.nextValue()
428
+ elif token == 'size':
429
+ self.nextToken()
430
+ command['size'] = self.nextValue()
431
+ else: break
432
+ self.add(command)
433
+ return True
434
+
435
+ def k_createCheckBox(self, command):
436
+ if self.peek() == 'text':
437
+ self.nextToken()
438
+ text = self.nextValue()
439
+ else: text = self.compileConstant('')
440
+ command['text'] = text
441
+ self.add(command)
442
+ return True
443
+
444
+ def k_createLineEdit(self, command):
445
+ text = self.compileConstant('')
446
+ size = self.compileConstant(40)
447
+ while True:
448
+ token = self.peek()
449
+ if token == 'text':
450
+ self.nextToken()
451
+ text = self.nextValue()
452
+ elif token == 'size':
453
+ self.nextToken()
454
+ size = self.nextValue()
455
+ else: break;
456
+ command['size'] = size
457
+ command['text'] = text
458
+ self.add(command)
459
+ return True
460
+
461
+ def k_createMultiLineEdit(self, command):
462
+ cols = self.compileConstant(30)
463
+ rows = self.compileConstant(5)
464
+ while True:
465
+ next = self.peek()
466
+ if next == 'cols':
467
+ self.nextToken()
468
+ cols = self.nextValue()
469
+ elif next == 'rows':
470
+ self.nextToken()
471
+ rows = self.nextValue()
472
+ else: break;
473
+ command['cols'] = cols
474
+ command['rows'] = rows
475
+ self.add(command)
476
+ return True
477
+
478
+ def k_createWidget(self, command):
479
+ self.add(command)
480
+ return True
481
+
482
+ def k_createDialog(self, command):
483
+ if self.peek() == 'on':
484
+ self.nextToken()
485
+ if self.nextIsSymbol():
486
+ command['window'] = self.getSymbolRecord()['name']
487
+ else: command['window'] = None
488
+ while True:
489
+ if self.peek() == 'type':
490
+ self.nextToken()
491
+ dialogType = self.nextToken()
492
+ if dialogType in self.dialogTypes(): command['type'] = dialogType
493
+ else: return False
494
+ elif self.peek() == 'title':
495
+ self.nextToken()
496
+ command['title'] = self.nextValue()
497
+ elif self.peek() == 'prompt':
498
+ self.nextToken()
499
+ command['prompt'] = self.nextValue()
500
+ elif self.peek() == 'value':
501
+ self.nextToken()
502
+ command['value'] = self.nextValue()
503
+ elif self.peek() == 'with':
504
+ self.nextToken()
505
+ command['layout'] = self.nextToken()
506
+ else: break
507
+ if not 'title' in command: command['title'] = self.compileConstant('')
508
+ if not 'value' in command: command['value'] = self.compileConstant('')
509
+ if not 'prompt' in command: command['prompt'] = self.compileConstant('')
510
+ self.add(command)
511
+ return True
512
+
513
+ def k_createMessageBox(self, command):
514
+ if self.peek() == 'on':
515
+ self.nextToken()
516
+ if self.nextIsSymbol():
517
+ command['window'] = self.getSymbolRecord()['name']
518
+ else: command['window'] = None
519
+ style = 'question'
520
+ title = ''
521
+ message = ''
522
+ while True:
523
+ if self.peek() == 'style':
524
+ self.nextToken()
525
+ style = self.nextToken()
526
+ elif self.peek() == 'title':
527
+ self.nextToken()
528
+ title = self.nextValue()
529
+ elif self.peek() == 'message':
530
+ self.nextToken()
531
+ message = self.nextValue()
532
+ else: break
533
+ command['style'] = style
534
+ command['title'] = title
535
+ command['message'] = message
536
+ self.add(command)
537
+ return True
538
+
539
+ def k_create(self, command):
540
+ if self.nextIsSymbol():
541
+ record = self.getSymbolRecord()
542
+ command['name'] = record['name']
543
+ keyword = record['keyword']
544
+ if keyword == 'window': return self.k_createWindow(command)
545
+ elif keyword in ['listbox', 'combobox', 'widget']: return self.k_createWidget(command)
546
+ elif keyword == 'layout': return self.k_createLayout(command)
547
+ elif keyword == 'group': return self.k_createGroupBox(command)
548
+ elif keyword == 'label': return self.k_createLabel(command)
549
+ elif keyword == 'pushbutton': return self.k_createPushbutton(command)
550
+ elif keyword == 'checkbox': return self.k_createCheckBox(command)
551
+ elif keyword == 'lineinput': return self.k_createLineEdit(command)
552
+ elif keyword == 'multiline': return self.k_createMultiLineEdit(command)
553
+ elif keyword == 'dialog': return self.k_createDialog(command)
554
+ elif keyword == 'messagebox': return self.k_createMessageBox(command)
555
+ return False
556
+
557
+ def r_createWindow(self, command, record):
558
+ window = QMainWindow()
559
+ title = self.getRuntimeValue(command['title'])
560
+ if title == None: title = 'EasyCoder Main Window'
561
+ window.setWindowTitle(title)
562
+ w = self.getRuntimeValue(command['w'])
563
+ h = self.getRuntimeValue(command['h'])
564
+ x = command['x']
565
+ y = command['y']
566
+ if hasattr(self.program, 'screenWidth'): screenWidth = self.program.screenWidth
567
+ else: screenWidth = self.program.parent.program.screenWidth
568
+ if hasattr(self.program, 'screenHeight'): screenHeight = self.program.screenHeight
569
+ else: screenHeight = self.program.parent.program.screenHeight
570
+ if x == None: x = (screenWidth - w) / 2
571
+ else: x = self.getRuntimeValue(x)
572
+ if y == None: y = (screenHeight - h) / 2
573
+ else: y = self.getRuntimeValue(x)
574
+ window.setGeometry(x, y, w, h)
575
+ record['window'] = window
576
+ return self.nextPC()
577
+
578
+ def r_createLayout(self, command, record):
579
+ layoutType = command['type']
580
+ if layoutType == 'QHBoxLayout': layout = QHBoxLayout()
581
+ elif layoutType == 'QGridLayout': layout = QGridLayout()
582
+ elif layoutType == 'QStackedLayout': layout = QStackedLayout()
583
+ else: layout = QVBoxLayout()
584
+ layout.setContentsMargins(5,0,5,0)
585
+ record['widget'] = layout
586
+ return self.nextPC()
587
+
588
+ def r_createGroupBox(self, command, record):
589
+ group = QGroupBox(self.getRuntimeValue(command['title']))
590
+ group.setAlignment(Qt.AlignLeft)
591
+ record['widget'] = group
592
+ return self.nextPC()
593
+
594
+ def r_createLabel(self, command, record):
595
+ label = QLabel(str(self.getRuntimeValue(command['text'])))
596
+ label.setStyleSheet("""
597
+ background-color: transparent;
598
+ border: none;
599
+ """)
600
+ if 'size' in command:
601
+ fm = label.fontMetrics()
602
+ c = label.contentsMargins()
603
+ w = fm.horizontalAdvance('m') * self.getRuntimeValue(command['size']) +c.left()+c.right()
604
+ label.setMaximumWidth(w)
605
+ if 'align' in command:
606
+ alignment = command['align']
607
+ if alignment == 'left': label.setAlignment(Qt.AlignLeft)
608
+ elif alignment == 'right': label.setAlignment(Qt.AlignRight)
609
+ elif alignment in ['center', 'centre']: label.setAlignment(Qt.AlignHCenter)
610
+ elif alignment == 'justify': label.setAlignment(Qt.AlignJustify)
611
+ if 'expand' in command:
612
+ label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
613
+ self.setWidget(record, label)
614
+ return self.nextPC()
615
+
616
+ def r_createPushbutton(self, command, record):
617
+ if 'size' in command:
618
+ size = self.getRuntimeValue(command['size'])
619
+ else: size = None
620
+ if 'icon' in command:
621
+ iconPath = self.getRuntimeValue(command['icon'])
622
+ pixmap = QPixmap(iconPath)
623
+ if pixmap.isNull():
624
+ RuntimeError(self.program, f'Icon not found: {iconPath}')
625
+ icon = pixmap.scaledToHeight(size if size != None else 24, Qt.SmoothTransformation)
626
+ pushbutton = QPushButton()
627
+ pushbutton.setIcon(icon)
628
+ pushbutton.setIconSize(icon.size())
629
+ elif 'text' in command:
630
+ text = self.getRuntimeValue(command['text'])
631
+ pushbutton = QPushButton(text)
632
+ pushbutton.setAccessibleName(text)
633
+ if size != None:
634
+ fm = pushbutton.fontMetrics()
635
+ c = pushbutton.contentsMargins()
636
+ w = fm.horizontalAdvance('m') * self.getRuntimeValue(command['size']) + c.left()+c.right()
637
+ pushbutton.setMaximumWidth(w)
638
+ self.putSymbolValue(record, pushbutton)
639
+ self.setWidget(record, pushbutton)
640
+ return self.nextPC()
641
+
642
+ def r_createCheckBox(self, command, record):
643
+ checkbox = QCheckBox(self.getRuntimeValue(command['text']))
644
+ checkbox.setStyleSheet("""
645
+ QCheckBox::indicator {
646
+ border: 1px solid black;
647
+ border-radius: 3px;
648
+ background: white;
649
+ width: 16px;
650
+ height: 16px;
651
+ }
652
+ QCheckBox::indicator:checked {
653
+ background: #0078d7;
654
+ }
655
+ QCheckBox {
656
+ border: none;
657
+ background: transparent;
658
+ }
659
+ """)
660
+ checkbox.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
661
+ self.setWidget(record, checkbox)
662
+ return self.nextPC()
663
+
664
+ def r_createLineEdit(self, command, record):
665
+ lineinput = self.ClickableLineEdit()
666
+ lineinput.setText(self.getRuntimeValue(command['text']))
667
+ fm = lineinput.fontMetrics()
668
+ m = lineinput.textMargins()
669
+ c = lineinput.contentsMargins()
670
+ w = fm.horizontalAdvance('x') * self.getRuntimeValue(command['size']) +m.left()+m.right()+c.left()+c.right()
671
+ lineinput.setMaximumWidth(w)
672
+ self.setWidget(record, lineinput)
673
+ return self.nextPC()
674
+
675
+ def r_createMultiLineEdit(self, command, record):
676
+ textinput = self.ClickablePlainTextEdit()
677
+ fontMetrics = textinput.fontMetrics()
678
+ charWidth = fontMetrics.horizontalAdvance('x')
679
+ charHeight = fontMetrics.height()
680
+ textinput.setFixedWidth(charWidth * self.getRuntimeValue(command['cols']))
681
+ textinput.setFixedHeight(charHeight * self.getRuntimeValue(command['rows']))
682
+ self.setWidget(record, textinput)
683
+ return self.nextPC()
684
+
685
+ def r_createListWidget(self, command, record):
686
+ self.setWidget(record, QListWidget())
687
+ return self.nextPC()
688
+
689
+ def r_createComboBox(self, command, record):
690
+ self.setWidget(record, QComboBox())
691
+ return self.nextPC()
692
+
693
+ def r_createWidget(self, command, record):
694
+ self.setWidget(record, QWidget())
695
+ return self.nextPC()
696
+
697
+ def r_createDialog(self, command, record):
698
+
699
+ class ECDialog(QDialog):
700
+ def __init__(self, parent, record):
701
+ super().__init__(parent)
702
+ self.record = record
703
+
704
+ def showEvent(self, event):
705
+ super().showEvent(event)
706
+ QTimer.singleShot(100, self.afterShown)
707
+
708
+ def afterShown(self):
709
+ if 'action' in self.record: self.record['action']()
710
+
711
+ win = command['window']
712
+ if win != None:
713
+ win = self.getVariable(win)['window']
714
+ dialog = ECDialog(win, record)
715
+ dialogType = command['type'].lower()
716
+ dialog.dialogType = dialogType
717
+ mainLayout = QVBoxLayout(dialog)
718
+ if dialogType == 'generic':
719
+ dialog.setFixedWidth(500)
720
+ dialog.setFixedHeight(500)
721
+ dialog.setWindowFlags(Qt.FramelessWindowHint)
722
+ dialog.setModal(True)
723
+ dialog.setStyleSheet('background-color: white;border:1px solid black;')
724
+
725
+ border = Border()
726
+ border.tickClicked.connect(dialog.accept)
727
+ border.closeClicked.connect(dialog.reject)
728
+ mainLayout.addWidget(border)
729
+ if 'layout' in command:
730
+ layout = self.getVariable(command['layout'])['widget']
731
+ mainLayout.addLayout(layout)
732
+ dialog.setLayout(mainLayout)
733
+ else:
734
+ dialog.setWindowTitle(self.getRuntimeValue(command['title']))
735
+ prompt = self.getRuntimeValue(command['prompt'])
736
+ if dialogType == 'confirm':
737
+ mainLayout.addWidget(QLabel(prompt))
738
+ elif dialogType == 'lineedit':
739
+ mainLayout.addWidget(QLabel(prompt))
740
+ dialog.lineEdit = self.ClickableLineEdit(dialog)
741
+ dialog.value = self.getRuntimeValue(command['value'])
742
+ dialog.lineEdit.setText(dialog.value)
743
+ mainLayout.addWidget(dialog.lineEdit)
744
+ elif dialogType == 'multiline':
745
+ mainLayout.addWidget(QLabel(prompt))
746
+ dialog.textEdit = self.ClickablePlainTextEdit(self)
747
+ dialog.textEdit.setText(dialog.value)
748
+ mainLayout.addWidget(dialog.textEdit)
749
+ buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
750
+ buttonBox.accepted.connect(dialog.accept)
751
+ buttonBox.rejected.connect(dialog.reject)
752
+ mainLayout.addWidget(buttonBox, alignment=Qt.AlignHCenter)
753
+ record['dialog'] = dialog
754
+ return self.nextPC()
755
+
756
+ # Creates a message box but doesn't run it
757
+ def r_createMessageBox(self, command, record):
758
+ data = {}
759
+ data['window'] = command['window']
760
+ data['style'] = command['style']
761
+ data['title'] = self.getRuntimeValue(command['title'])
762
+ data['message'] = self.getRuntimeValue(command['message'])
763
+ record['data'] = data
764
+ return self.nextPC()
765
+
766
+ def r_create(self, command):
767
+ record = self.getVariable(command['name'])
768
+ keyword = record['keyword']
769
+ if keyword == 'window': return self.r_createWindow(command, record)
770
+ elif keyword == 'layout': return self.r_createLayout(command, record)
771
+ elif keyword == 'group': return self.r_createGroupBox(command, record)
772
+ elif keyword == 'label': return self.r_createLabel(command, record)
773
+ elif keyword == 'pushbutton': return self.r_createPushbutton(command, record)
774
+ elif keyword == 'checkbox': return self.r_createCheckBox(command, record)
775
+ elif keyword == 'lineinput': return self.r_createLineEdit(command, record)
776
+ elif keyword == 'multiline': return self.r_createMultiLineEdit(command, record)
777
+ elif keyword == 'listbox': return self.r_createListWidget(command, record)
778
+ elif keyword == 'combobox': return self.r_createComboBox(command, record)
779
+ elif keyword == 'widget': return self.r_createWidget(command, record)
780
+ elif keyword == 'dialog': return self.r_createDialog(command, record)
781
+ elif keyword == 'messagebox': return self.r_createMessageBox(command, record)
782
+ return None
783
+
784
+ # Declare a dialog variable
785
+ def k_dialog(self, command):
786
+ return self.compileVariable(command, 'gui')
787
+
788
+ def r_dialog(self, command):
789
+ return self.nextPC()
790
+
791
+ # Disable a widget
792
+ def k_disable(self, command):
793
+ if self.nextIsSymbol():
794
+ command['name'] = self.getSymbolRecord()['name']
795
+ self.add(command)
796
+ return True
797
+ return False
798
+
799
+ def r_disable(self, command):
800
+ self.getWidget(self.getVariable(command['name'])).setEnabled(False)
801
+ return self.nextPC()
802
+
803
+ # Enable a widget
804
+ def k_enable(self, command):
805
+ if self.nextIsSymbol():
806
+ command['name'] = self.getSymbolRecord()['name']
807
+ self.add(command)
808
+ return True
809
+ return False
810
+
811
+ def r_enable(self, command):
812
+ self.getWidget(self.getVariable(command['name'])).setEnabled(True)
813
+ return self.nextPC()
814
+
815
+ # Create a group box
816
+ def k_group(self, command):
817
+ return self.compileVariable(command, 'gui')
818
+
819
+ def r_group(self, command):
820
+ return self.nextPC()
821
+
822
+ # hide {widget}
823
+ def k_hide(self, command):
824
+ if self.nextIsSymbol():
825
+ record = self.getSymbolRecord()
826
+ if self.isWidget(record['keyword']):
827
+ command['widget'] = record['name']
828
+ self.add(command)
829
+ return True
830
+ return False
831
+
832
+ def r_hide(self, command):
833
+ record = self.getVariable(command['widget'])
834
+ if 'widget' in record: self.getWidget(record).hide()
835
+ return self.nextPC()
836
+
837
+ # Initialize the graphics environment
838
+ # Unused: def k_init(self, command):
839
+
840
+ def r_init(self, command):
841
+ self.app = QApplication(sys.argv)
842
+ screen = QApplication.screens()[0].size().toTuple()
843
+ self.program.screenWidth = screen[0]
844
+ self.program.screenHeight = screen[1]
845
+ print(f'Screen: {self.program.screenWidth}x{self.program.screenHeight}')
846
+ # return self.nextPC()
847
+ def on_last_window_closed():
848
+ self.program.kill()
849
+ def init():
850
+ self.program.flush(self.nextPC())
851
+ def flush():
852
+ if not self.blocked:
853
+ if self.runOnTick != 0:
854
+ self.program.run(self.runOnTick)
855
+ self.program.flushCB()
856
+ timer = QTimer()
857
+ timer.timeout.connect(flush)
858
+ timer.start(10)
859
+ QTimer.singleShot(500, init)
860
+ self.app.lastWindowClosed.connect(on_last_window_closed)
861
+ self.app.exec()
862
+
863
+ # Declare a label variable
864
+ def k_label(self, command):
865
+ return self.compileVariable(command, 'gui')
866
+
867
+ def r_label(self, command):
868
+ return self.nextPC()
869
+
870
+ # Declare a layout variable
871
+ def k_layout(self, command):
872
+ return self.compileVariable(command, 'gui')
873
+
874
+ def r_layout(self, command):
875
+ return self.nextPC()
876
+
877
+ # Declare a line input variable
878
+ def k_lineinput(self, command):
879
+ return self.compileVariable(command, 'gui')
880
+
881
+ def r_lineinput(self, command):
882
+ return self.nextPC()
883
+
884
+ # Declare a listbox input variable
885
+ def k_listbox(self, command):
886
+ return self.compileVariable(command, 'gui')
887
+
888
+ def r_listbox(self, command):
889
+ return self.nextPC()
890
+
891
+ # Declare a messagebox variable
892
+ def k_messagebox(self, command):
893
+ return self.compileVariable(command)
894
+
895
+ def r_messagebox(self, command):
896
+ return self.nextPC()
897
+
898
+ # Declare a multiline input variable
899
+ def k_multiline(self, command):
900
+ return self.compileVariable(command, 'gui')
901
+
902
+ def r_multiline(self, command):
903
+ return self.nextPC()
904
+
905
+ # on click {pushbutton}/{lineinput}/{multiline}
906
+ # on select {combobox}/{listbox}
907
+ # on tick
908
+ def k_on(self, command):
909
+ def setupOn():
910
+ command['goto'] = self.getPC() + 2
911
+ self.add(command)
912
+ self.nextToken()
913
+ # Step over the click handler
914
+ pcNext = self.getPC()
915
+ cmd = {}
916
+ cmd['domain'] = 'core'
917
+ cmd['lino'] = command['lino']
918
+ cmd['keyword'] = 'gotoPC'
919
+ cmd['goto'] = 0
920
+ cmd['debug'] = False
921
+ self.add(cmd)
922
+ # This is the click handler
923
+ self.compileOne()
924
+ cmd = {}
925
+ cmd['domain'] = 'core'
926
+ cmd['lino'] = command['lino']
927
+ cmd['keyword'] = 'stop'
928
+ cmd['debug'] = False
929
+ self.add(cmd)
930
+ # Fixup the goto
931
+ self.getCommandAt(pcNext)['goto'] = self.getPC()
932
+
933
+ token = self.nextToken()
934
+ command['type'] = token
935
+ if token == 'click':
936
+ if self.nextIsSymbol():
937
+ record = self.getSymbolRecord()
938
+ if record['keyword'] in ['pushbutton', 'lineinput', 'multiline']:
939
+ command['name'] = record['name']
940
+ setupOn()
941
+ return True
942
+ elif token == 'select':
943
+ if self.nextIsSymbol():
944
+ record = self.getSymbolRecord()
945
+ if record['keyword'] in ['combobox', 'listbox']:
946
+ command['name'] = record['name']
947
+ setupOn()
948
+ return True
949
+ elif token == 'tick':
950
+ command['tick'] = True
951
+ command['runOnTick'] = self.getPC() + 2
952
+ self.add(command)
953
+ self.nextToken()
954
+ # Step over the on tick action
955
+ pcNext = self.getPC()
956
+ cmd = {}
957
+ cmd['domain'] = 'core'
958
+ cmd['lino'] = command['lino']
959
+ cmd['keyword'] = 'gotoPC'
960
+ cmd['goto'] = 0
961
+ cmd['debug'] = False
962
+ self.add(cmd)
963
+ # This is the on tick handler
964
+ self.compileOne()
965
+ cmd = {}
966
+ cmd['domain'] = 'core'
967
+ cmd['lino'] = command['lino']
968
+ cmd['keyword'] = 'stop'
969
+ cmd['debug'] = False
970
+ self.add(cmd)
971
+ # Fixup the goto
972
+ self.getCommandAt(pcNext)['goto'] = self.getPC()
973
+ return True
974
+ return False
975
+
976
+ def r_on(self, command):
977
+ def run(widget, record):
978
+ for i, w in enumerate(record['widget']):
979
+ if w == widget:
980
+ record['index'] = i
981
+ self.run(command['goto'])
982
+ return
983
+
984
+ if command['type'] == 'tick':
985
+ self.runOnTick = command['runOnTick']
986
+ else:
987
+ record = self.getVariable(command['name'])
988
+ widget = self.getWidget(record)
989
+ keyword = record['keyword']
990
+ if keyword == 'pushbutton':
991
+ handler = partial(run, widget, record)
992
+ widget.clicked.connect(handler)
993
+ elif keyword == 'combobox':
994
+ widget.currentIndexChanged.connect(lambda: self.run(command['goto']))
995
+ elif keyword == 'listbox':
996
+ widget.itemClicked.connect(lambda: self.run(command['goto']))
997
+ return self.nextPC()
998
+
999
+ # Declare a pushbutton variable
1000
+ def k_pushbutton(self, command):
1001
+ return self.compileVariable(command, 'gui')
1002
+
1003
+ def r_pushbutton(self, command):
1004
+ return self.nextPC()
1005
+
1006
+ # remove [the] [current/selected] [item] [from/in] {combobox}/{listbox}
1007
+ def k_remove(self, command):
1008
+ command['variant'] = None
1009
+ self.skip('the')
1010
+ self.skip(['current', 'selected'])
1011
+ self.skip('item')
1012
+ self.skip(['from', 'in'])
1013
+ if self.nextIsSymbol():
1014
+ record = self.getSymbolRecord()
1015
+ if record['keyword'] == 'combobox':
1016
+ command['variant'] = 'current'
1017
+ command['name'] = record['name']
1018
+ self.add(command)
1019
+ return True
1020
+ elif record['keyword'] == 'listbox':
1021
+ command['variant'] = 'current'
1022
+ command['name'] = record['name']
1023
+ self.add(command)
1024
+ return True
1025
+ return False
1026
+
1027
+ def r_remove(self, command):
1028
+ variant = command['variant']
1029
+ record = self.getVariable(command['name'])
1030
+ if variant == 'current':
1031
+ if record['keyword'] == 'combobox':
1032
+ widget = self.getWidget(record)
1033
+ widget.removeItem(widget.currentIndex())
1034
+ if record['keyword'] == 'listbox':
1035
+ widget = self.getWidget(record)
1036
+ selectedItem = widget.currentItem()
1037
+ if selectedItem:
1038
+ row = widget.row(selectedItem)
1039
+ widget.takeItem(row)
1040
+ return self.nextPC()
1041
+
1042
+ # select index {n} [of] {combobox]}
1043
+ # select {name} [in] {combobox}
1044
+ def k_select(self, command):
1045
+ if self.nextIs('index'):
1046
+ command['index'] = self.nextValue()
1047
+ self.skip('of')
1048
+ else:
1049
+ command['name'] = self.getValue()
1050
+ self.skip('in')
1051
+ if self.nextIsSymbol():
1052
+ record = self.getSymbolRecord()
1053
+ if record['keyword'] == 'combobox':
1054
+ command['widget'] = record['name']
1055
+ self.add(command)
1056
+ return True
1057
+ return False
1058
+
1059
+ def r_select(self, command):
1060
+ widget = self.getWidget(self.getVariable(command['widget']))
1061
+ if 'index' in command:
1062
+ index = self.getRuntimeValue(command['index'])
1063
+ else:
1064
+ name = self.getRuntimeValue(command['name'])
1065
+ index = widget.findText(name, Qt.MatchFixedString)
1066
+ if index >= 0:
1067
+ widget.setCurrentIndex(index)
1068
+ return self.nextPC()
1069
+
1070
+ # set [the] width/height [of] {widget} [to] {value}
1071
+ # set [the] layout of {window}/{widget} to {layout}
1072
+ # set [the] spacing of {layout} to {value}
1073
+ # set [the] text [of] {label}/{button}/{lineinput}/{multiline} [to] {text}
1074
+ # set [the] color [of] {label}/{button}/{lineinput}/{multiline} [to] {color}
1075
+ # set [the] state [of] {checkbox} [to] {state}
1076
+ # set [the] style of {widget} to {style}
1077
+ # set {listbox} to {list}
1078
+ # set blocked true/false
1079
+ def k_set(self, command):
1080
+ self.skip('the')
1081
+ token = self.nextToken()
1082
+ command['what'] = token
1083
+ if token in ['width', 'height']:
1084
+ self.skip('of')
1085
+ if self.nextIsSymbol():
1086
+ record = self.getSymbolRecord()
1087
+ if record['extra'] == 'gui':
1088
+ command['name'] = record['name']
1089
+ self.skip('to')
1090
+ command['value'] = self.nextValue()
1091
+ self.add(command)
1092
+ return True
1093
+ elif token == 'layout':
1094
+ self.skip('of')
1095
+ if self.nextIsSymbol():
1096
+ record = self.getSymbolRecord()
1097
+ keyword = record['keyword']
1098
+ if keyword in ['window', 'widget']:
1099
+ command['name'] = record['name']
1100
+ self.skip('to')
1101
+ if self.nextIsSymbol():
1102
+ record = self.getSymbolRecord()
1103
+ if record['keyword'] == 'layout':
1104
+ command['layout'] = record['name']
1105
+ self.add(command)
1106
+ return True
1107
+ elif token == 'spacing':
1108
+ self.skip('of')
1109
+ if self.nextIsSymbol():
1110
+ record = self.getSymbolRecord()
1111
+ if record['keyword'] == 'layout':
1112
+ command['name'] = record['name']
1113
+ self.skip('to')
1114
+ command['value'] = self.nextValue()
1115
+ self.add(command)
1116
+ return True
1117
+ elif token == 'text':
1118
+ self.skip('of')
1119
+ if self.nextIsSymbol():
1120
+ record = self.getSymbolRecord()
1121
+ if record['keyword'] in ['label', 'pushbutton', 'lineinput', 'multiline', 'element']:
1122
+ command['name'] = record['name']
1123
+ self.skip('to')
1124
+ command['value'] = self.nextValue()
1125
+ self.add(command)
1126
+ return True
1127
+ elif token == 'state':
1128
+ self.skip('of')
1129
+ if self.nextIsSymbol():
1130
+ record = self.getSymbolRecord()
1131
+ if record['keyword'] == 'checkbox':
1132
+ command['name'] = record['name']
1133
+ self.skip('to')
1134
+ if self.peek() == 'checked':
1135
+ command['value'] = self.compileConstant(True)
1136
+ self.nextToken()
1137
+ elif self.peek() == 'unchecked':
1138
+ command['value'] = self.compileConstant(False)
1139
+ self.nextToken()
1140
+ else: command['value'] = self.nextValue()
1141
+ self.add(command)
1142
+ return True
1143
+ elif token == 'style':
1144
+ self.skip('of')
1145
+ if self.nextIsSymbol():
1146
+ record = self.getSymbolRecord()
1147
+ if record['extra'] == 'gui':
1148
+ command['name'] = record['name']
1149
+ self.skip('to')
1150
+ command['value'] = self.nextValue()
1151
+ self.add(command)
1152
+ return True
1153
+ elif token == 'alignment':
1154
+ self.skip('of')
1155
+ if self.nextIsSymbol():
1156
+ record = self.getSymbolRecord()
1157
+ if record['extra'] == 'gui':
1158
+ command['name'] = record['name']
1159
+ self.skip('to')
1160
+ flags = []
1161
+ while self.peek() in ['left', 'hcenter', 'right', 'top', 'vcenter', 'bottom', 'center']:
1162
+ flags.append(self.nextToken())
1163
+ command['value'] = flags
1164
+ self.add(command)
1165
+ return True
1166
+ elif token == 'style':
1167
+ self.skip('of')
1168
+ if self.nextIsSymbol():
1169
+ record = self.getSymbolRecord()
1170
+ if record['keyword'] == 'label':
1171
+ command['name'] = record['name']
1172
+ self.skip('to')
1173
+ command['value'] = self.nextValue()
1174
+ self.add(command)
1175
+ return True
1176
+ elif token == 'color':
1177
+ self.skip('of')
1178
+ if self.nextIsSymbol():
1179
+ record = self.getSymbolRecord()
1180
+ if record['keyword'] == 'label':
1181
+ command['name'] = record['name']
1182
+ self.skip('to')
1183
+ command['value'] = self.nextValue()
1184
+ self.add(command)
1185
+ return True
1186
+ elif token == 'background':
1187
+ self.skip('color')
1188
+ self.skip('of')
1189
+ if self.nextIsSymbol():
1190
+ record = self.getSymbolRecord()
1191
+ if record['keyword'] in ['label', 'pushbutton', 'lineinput', 'multiline']:
1192
+ command['name'] = record['name']
1193
+ self.skip('to')
1194
+ command['value'] = self.nextValue()
1195
+ self.add(command)
1196
+ return True
1197
+ elif token == 'blocked':
1198
+ self.blocked = True if self.nextToken() == 'true' else False
1199
+ return True
1200
+ elif self.isSymbol():
1201
+ record = self.getSymbolRecord()
1202
+ if record['keyword'] == 'listbox':
1203
+ command['what'] = 'listbox'
1204
+ command['name'] = record['name']
1205
+ self.skip('to')
1206
+ command['value'] = self.nextValue()
1207
+ self.add(command)
1208
+ return True
1209
+ return False
1210
+
1211
+ def r_set(self, command):
1212
+ what = command['what']
1213
+ if what == 'height':
1214
+ widget = self.getWidget(self.getVariable(command['name']))
1215
+ widget.setFixedHeight(self.getRuntimeValue(command['value']))
1216
+ elif what == 'width':
1217
+ widget = self.getWidget(self.getVariable(command['name']))
1218
+ widget.setFixedWidth(self.getRuntimeValue(command['value']))
1219
+ elif what == 'layout':
1220
+ record = self.getVariable(command['layout'])
1221
+ layout = record['widget']
1222
+ record = self.getVariable(command['name'])
1223
+ keyword = record['keyword']
1224
+ if keyword == 'window':
1225
+ window = record['window']
1226
+ container = QWidget()
1227
+ container.setLayout(layout)
1228
+ window.setCentralWidget(container)
1229
+ elif keyword == 'widget':
1230
+ widget = self.getWidget(record)
1231
+ widget.setLayout(layout)
1232
+ elif what == 'spacing':
1233
+ layout = self.getWidget(self.getVariable(command['name']))
1234
+ layout.setSpacing(self.getRuntimeValue(command['value']))
1235
+ elif what == 'text':
1236
+ record = self.getVariable(command['name'])
1237
+ widget = self.getWidget(record)
1238
+ text = self.getRuntimeValue(command['value'])
1239
+ keyword = record['keyword']
1240
+ setText = getattr(widget, "setText", None)
1241
+ if callable(setText):
1242
+ widget.setText(text)
1243
+ elif keyword == 'multiline':
1244
+ widget.setPlainText(text)
1245
+ if record['keyword'] == 'pushbutton':
1246
+ widget.setAccessibleName(text)
1247
+ elif what == 'state':
1248
+ record = self.getVariable(command['name'])
1249
+ if record['keyword'] == 'checkbox':
1250
+ state = self.getRuntimeValue(command['value'])
1251
+ self.getWidget(record).setChecked(state)
1252
+ elif what == 'alignment':
1253
+ widget = self.getVariable(command['name'])['widget']
1254
+ flags = command['value']
1255
+ alignment = 0
1256
+ for flag in flags:
1257
+ if flag == 'left': alignment |= Qt.AlignLeft
1258
+ elif flag == 'hcenter': alignment |= Qt.AlignHCenter
1259
+ elif flag == 'right': alignment |= Qt.AlignRight
1260
+ elif flag == 'top': alignment |= Qt.AlignTop
1261
+ elif flag == 'vcenter': alignment |= Qt.AlignVCenter
1262
+ elif flag == 'bottom': alignment |= Qt.AlignBottom
1263
+ elif flag == 'center': alignment |= Qt.AlignCenter
1264
+ widget.setAlignment(alignment)
1265
+ elif what == 'style':
1266
+ record = self.getVariable(command['name'])
1267
+ widget = self.getWidget(record)
1268
+ styles = self.getRuntimeValue(command['value'])
1269
+ widget.setStyleSheet(styles)
1270
+ elif what == 'color':
1271
+ record = self.getVariable(command['name'])
1272
+ widget = self.getWidget(record)
1273
+ color = self.getRuntimeValue(command['value'])
1274
+ widget.setStyleSheet(f"color: {color};")
1275
+ elif what == 'background-color':
1276
+ record = self.getVariable(command['name'])
1277
+ widget = self.getWidget(record)
1278
+ bg_color = self.getRuntimeValue(command['value'])
1279
+ widget.setStyleSheet(f"background-color: {bg_color};")
1280
+ elif what == 'listbox':
1281
+ record = self.getVariable(command['name'])
1282
+ widget = self.getWidget(record)
1283
+ value = self.getRuntimeValue(command['value'])
1284
+ widget.clear()
1285
+ widget.addItems(value)
1286
+ return self.nextPC()
1287
+
1288
+ # show {window}
1289
+ # show {dialog}
1290
+ # show {widget}
1291
+ # show {messagebox} giving {result}}
1292
+ def k_show(self, command):
1293
+ if self.nextIsSymbol():
1294
+ record = self.getSymbolRecord()
1295
+ keyword = record['keyword']
1296
+ if keyword == 'window':
1297
+ command['window'] = record['name']
1298
+ self.add(command)
1299
+ return True
1300
+ elif keyword == 'dialog':
1301
+ command['dialog'] = record['name']
1302
+ self.add(command)
1303
+ return True
1304
+ elif self.isWidget(keyword):
1305
+ command['name'] = record['name']
1306
+ self.add(command)
1307
+ return True
1308
+ elif keyword == 'messagebox':
1309
+ command['messagebox'] = record['name']
1310
+ self.skip('giving')
1311
+ if self.nextIsSymbol():
1312
+ command['result'] = self.getSymbolRecord()['name']
1313
+ self.add(command)
1314
+ return True
1315
+ return False
1316
+
1317
+ def r_show(self, command):
1318
+ if 'messagebox' in command:
1319
+ data = self.getVariable(command['messagebox'])['data']
1320
+ symbolRecord = self.getVariable(command['result'])
1321
+ window = self.getVariable(data['window'])['window']
1322
+ style = data['style']
1323
+ title = data['title']
1324
+ message = data['message']
1325
+ if style == 'question':
1326
+ choice = QMessageBox.question(window, title, message)
1327
+ result = 'Yes' if choice == QMessageBox.Yes else 'No'
1328
+ elif style == 'yesnocancel':
1329
+ choice = QMessageBox.question(
1330
+ window,
1331
+ title,
1332
+ message,
1333
+ QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel
1334
+ )
1335
+ if choice == QMessageBox.Yes:
1336
+ result = 'Yes'
1337
+ elif choice == QMessageBox.No:
1338
+ result = 'No'
1339
+ else:
1340
+ result = 'Cancel'
1341
+ elif style == 'warning':
1342
+ choice = QMessageBox.warning(window, title, message)
1343
+ if choice == QMessageBox.Ok: result = 'OK'
1344
+ else: result = ''
1345
+ else: result = 'Cancel'
1346
+ v = {}
1347
+ v['type'] = 'text'
1348
+ v['content'] = result
1349
+ self.putSymbolValue(symbolRecord, v)
1350
+ elif 'window' in command:
1351
+ window = self.getVariable(command['window'])['window']
1352
+ window.show()
1353
+ elif 'dialog' in command:
1354
+ record = self.getVariable(command['dialog'])
1355
+ dialog = record['dialog']
1356
+ if dialog.dialogType == 'generic':
1357
+ record['result'] = dialog.exec()
1358
+ elif dialog.dialogType == 'confirm':
1359
+ record['result'] = True if dialog.exec() == QDialog.Accepted else False
1360
+ elif dialog.dialogType == 'lineedit':
1361
+ if dialog.exec() == QDialog.Accepted:
1362
+ record['result'] = dialog.lineEdit.text()
1363
+ else: record['result'] = dialog.value
1364
+ elif dialog.dialogType == 'multiline':
1365
+ if dialog.exec() == QDialog.Accepted:
1366
+ record['result'] = dialog.textEdit.toPlainText()
1367
+ else: record['result'] = dialog.value
1368
+ elif 'name' in command:
1369
+ record = self.getVariable(command['name'])
1370
+ if 'widget' in record: self.getWidget(record).show()
1371
+ return self.nextPC()
1372
+
1373
+ # Start the graphics
1374
+ def k_start(self, command):
1375
+ if self.nextIs('graphics'):
1376
+ self.add(command)
1377
+ return True
1378
+ return False
1379
+
1380
+ def r_start(self, command):
1381
+ return self.nextPC()
1382
+ # def on_last_window_closed():
1383
+ # self.program.kill()
1384
+ # def init():
1385
+ # self.program.flush(self.nextPC())
1386
+ # def flush():
1387
+ # if not self.blocked:
1388
+ # if self.runOnTick != 0:
1389
+ # self.program.run(self.runOnTick)
1390
+ # self.program.flushCB()
1391
+ # timer = QTimer()
1392
+ # timer.timeout.connect(flush)
1393
+ # timer.start(10)
1394
+ # QTimer.singleShot(500, init)
1395
+ # self.app.lastWindowClosed.connect(on_last_window_closed)
1396
+ # self.app.exec()
1397
+
1398
+ # Declare a widget variable
1399
+ def k_widget(self, command):
1400
+ return self.compileVariable(command, 'gui')
1401
+
1402
+ def r_widget(self, command):
1403
+ return self.nextPC()
1404
+
1405
+ # Declare a window variable
1406
+ def k_window(self, command):
1407
+ return self.compileVariable(command)
1408
+
1409
+ def r_window(self, command):
1410
+ return self.nextPC()
1411
+
1412
+ #############################################################################
1413
+ # Compile a value in this domain
1414
+ def compileValue(self):
1415
+ value = {}
1416
+ value['domain'] = self.getName()
1417
+ token = self.getToken()
1418
+ if self.isSymbol():
1419
+ record = self.getSymbolRecord()
1420
+ if record['extra'] == 'gui':
1421
+ if self.isWidget(record['keyword']):
1422
+ value['name'] = token
1423
+ value['type'] = 'symbol'
1424
+ return value
1425
+
1426
+ else:
1427
+ if self.tokenIs('the'): token = self.nextToken()
1428
+ if token == 'count':
1429
+ self.skip('of')
1430
+ if self.nextIsSymbol():
1431
+ value['type'] = 'symbol'
1432
+ record = self.getSymbolRecord()
1433
+ keyword = record['keyword']
1434
+ if keyword in ['combobox', 'listbox']:
1435
+ value['type'] = 'count'
1436
+ value['name'] = record['name']
1437
+ return value
1438
+
1439
+ elif token == 'current':
1440
+ self.skip('item')
1441
+ self.skip('in')
1442
+ if self.nextIsSymbol():
1443
+ value['type'] = 'symbol'
1444
+ record = self.getSymbolRecord()
1445
+ keyword = record['keyword']
1446
+ if keyword == 'listbox':
1447
+ value['type'] = 'current'
1448
+ value['name'] = record['name']
1449
+ return value
1450
+
1451
+ return None
1452
+
1453
+ #############################################################################
1454
+ # Modify a value or leave it unchanged.
1455
+ def modifyValue(self, value):
1456
+ return value
1457
+
1458
+ #############################################################################
1459
+ # Value handlers
1460
+
1461
+ # This is used by the expression evaluator to get the value of a symbol
1462
+ def v_symbol(self, symbolRecord):
1463
+ symbolRecord = self.getVariable(symbolRecord['name'])
1464
+ keyword = symbolRecord['keyword']
1465
+ if keyword == 'pushbutton':
1466
+ pushbutton = self.getWidget(symbolRecord)
1467
+ v = {}
1468
+ v['type'] = 'text'
1469
+ v['content'] = pushbutton.accessibleName()
1470
+ return v
1471
+ elif keyword == 'lineinput':
1472
+ lineinput = self.getWidget(symbolRecord)
1473
+ v = {}
1474
+ v['type'] = 'text'
1475
+ v['content'] = lineinput.displayText()
1476
+ return v
1477
+ elif keyword == 'multiline':
1478
+ multiline = self.getWidget(symbolRecord)
1479
+ v = {}
1480
+ v['type'] = 'text'
1481
+ v['content'] = multiline.toPlainText()
1482
+ return v
1483
+ elif keyword == 'combobox':
1484
+ combobox = self.getWidget(symbolRecord)
1485
+ v = {}
1486
+ v['type'] = 'text'
1487
+ v['content'] = combobox.currentText()
1488
+ return v
1489
+ elif keyword == 'listbox':
1490
+ listbox = self.getWidget(symbolRecord)
1491
+ content = listbox.currentItem().text()
1492
+ v = {}
1493
+ v['type'] = 'text'
1494
+ v['content'] = content
1495
+ return v
1496
+ elif keyword == 'checkbox':
1497
+ checkbox =self.getWidget(symbolRecord)
1498
+ content = checkbox.isChecked()
1499
+ v = {}
1500
+ v['type'] = 'boolean'
1501
+ v['content'] = content
1502
+ return v
1503
+ elif keyword == 'dialog':
1504
+ content = symbolRecord['result']
1505
+ v = {}
1506
+ v['type'] = 'text'
1507
+ v['content'] = content
1508
+ return v
1509
+ return None
1510
+
1511
+ def v_count(self, v):
1512
+ record = self.getVariable(v['name'])
1513
+ keyword = record['keyword']
1514
+ widget = self.getWidget(record)
1515
+ if keyword in ['combobox', 'listbox']: content = widget.count()
1516
+ value = {}
1517
+ value['type'] = 'int'
1518
+ value['content'] = content
1519
+ return value
1520
+
1521
+ def v_current(self, v):
1522
+ record = self.getVariable(v['name'])
1523
+ keyword = record['keyword']
1524
+ widget = self.getWidget(record)
1525
+ if keyword == 'listbox': content = widget.currentItem().text()
1526
+ value = {}
1527
+ value['type'] = 'text'
1528
+ value['content'] = content
1529
+ return value
1530
+
1531
+ #############################################################################
1532
+ # Compile a condition
1533
+ def compileCondition(self):
1534
+ condition = Object()
1535
+ condition.negate = False
1536
+ return None
1537
+
1538
+ #############################################################################
1539
+ # Condition handlers
1540
+
1541
+ #############################################################################
1542
+ # Force the application to exit
1543
+ def force_exit(self):
1544
+ QApplication.quit() # Gracefully close the application
1545
+ sys.exit(0) # Force a complete system exit