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