easycoder 251004.1__py2.py3-none-any.whl → 251104.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 +1 -1
- easycoder/ec_classes.py +0 -4
- easycoder/ec_compiler.py +35 -7
- easycoder/ec_condition.py +1 -1
- easycoder/ec_core.py +53 -28
- easycoder/ec_handler.py +2 -2
- easycoder/ec_keyboard.py +13 -3
- easycoder/ec_program.py +2 -3
- easycoder/ec_pyside.py +187 -87
- {easycoder-251004.1.dist-info → easycoder-251104.1.dist-info}/METADATA +1 -1
- easycoder-251104.1.dist-info/RECORD +19 -0
- easycoder-251004.1.dist-info/RECORD +0 -19
- {easycoder-251004.1.dist-info → easycoder-251104.1.dist-info}/WHEEL +0 -0
- {easycoder-251004.1.dist-info → easycoder-251104.1.dist-info}/entry_points.txt +0 -0
- {easycoder-251004.1.dist-info → easycoder-251104.1.dist-info}/licenses/LICENSE +0 -0
easycoder/__init__.py
CHANGED
easycoder/ec_classes.py
CHANGED
|
@@ -16,7 +16,6 @@ class AssertionError:
|
|
|
16
16
|
def __init__(self, program, msg=None):
|
|
17
17
|
code = program.code[program.pc]
|
|
18
18
|
lino = code['lino']
|
|
19
|
-
script = program.script.lines[lino].strip()
|
|
20
19
|
message = f'Assertion Error in {program.name} at line {lino + 1}'
|
|
21
20
|
if msg != None:
|
|
22
21
|
message += f': {msg}'
|
|
@@ -58,8 +57,5 @@ class Token:
|
|
|
58
57
|
self.lino = lino
|
|
59
58
|
self.token = token
|
|
60
59
|
|
|
61
|
-
class Condition():
|
|
62
|
-
negate = False
|
|
63
|
-
|
|
64
60
|
class Object():
|
|
65
61
|
pass
|
easycoder/ec_compiler.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .ec_classes import
|
|
1
|
+
from .ec_classes import FatalError
|
|
2
2
|
from .ec_value import Value
|
|
3
3
|
from .ec_condition import Condition
|
|
4
4
|
|
|
@@ -18,9 +18,11 @@ class Compiler:
|
|
|
18
18
|
self.debugCompile = False
|
|
19
19
|
self.valueTypes = {}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
# Get the current code size. Used during compilation
|
|
22
|
+
def getCodeSize(self):
|
|
22
23
|
return len(self.program.code)
|
|
23
24
|
|
|
25
|
+
# Get the current index (the program counter)
|
|
24
26
|
def getIndex(self):
|
|
25
27
|
return self.index
|
|
26
28
|
|
|
@@ -39,6 +41,7 @@ class Compiler:
|
|
|
39
41
|
self.index += 1
|
|
40
42
|
return self.getToken()
|
|
41
43
|
|
|
44
|
+
# Peek ahead to see the next token without advancing the index
|
|
42
45
|
def peek(self):
|
|
43
46
|
try:
|
|
44
47
|
return self.tokens[self.index + 1].token
|
|
@@ -68,19 +71,23 @@ class Compiler:
|
|
|
68
71
|
self.index += 1
|
|
69
72
|
return self.condition.compileCondition()
|
|
70
73
|
|
|
74
|
+
# Test if the current token has a specified value
|
|
71
75
|
def tokenIs(self, value):
|
|
72
76
|
return self.getToken() == value
|
|
73
77
|
|
|
78
|
+
# Test if the next token has the specified value
|
|
74
79
|
def nextIs(self, value):
|
|
75
80
|
return self.nextToken() == value
|
|
76
81
|
|
|
82
|
+
# Get the command at a given pc in the code list
|
|
77
83
|
def getCommandAt(self, pc):
|
|
78
84
|
return self.program.code[pc]
|
|
79
85
|
|
|
80
86
|
# Add a command to the code list
|
|
81
|
-
def
|
|
87
|
+
def addCommand(self, command):
|
|
82
88
|
self.code.append(command)
|
|
83
89
|
|
|
90
|
+
# Test if the current token is a symbol
|
|
84
91
|
def isSymbol(self):
|
|
85
92
|
token = self.getToken()
|
|
86
93
|
try:
|
|
@@ -89,10 +96,12 @@ class Compiler:
|
|
|
89
96
|
return False
|
|
90
97
|
return True
|
|
91
98
|
|
|
99
|
+
# Test if the next token is a symbol
|
|
92
100
|
def nextIsSymbol(self):
|
|
93
101
|
self.next()
|
|
94
102
|
return self.isSymbol()
|
|
95
103
|
|
|
104
|
+
# Skip the next token if it matches the value given
|
|
96
105
|
def skip(self, token):
|
|
97
106
|
next = self.peek()
|
|
98
107
|
if type(token) == list:
|
|
@@ -102,21 +111,26 @@ class Compiler:
|
|
|
102
111
|
return
|
|
103
112
|
elif next == token: self.nextToken()
|
|
104
113
|
|
|
114
|
+
# Rewind to a given position in the code list
|
|
105
115
|
def rewindTo(self, index):
|
|
106
116
|
self.index = index
|
|
107
117
|
|
|
118
|
+
# Get source line number containing the current token
|
|
108
119
|
def getLino(self):
|
|
109
120
|
if self.index >= len(self.tokens):
|
|
110
121
|
return 0
|
|
111
122
|
return self.tokens[self.index].lino
|
|
112
123
|
|
|
124
|
+
# Issue a warning
|
|
113
125
|
def warning(self, message):
|
|
114
126
|
self.warnings.append(f'Warning at line {self.getLino() + 1} of {self.program.name}: {message}')
|
|
115
127
|
|
|
128
|
+
# Print all warnings
|
|
116
129
|
def showWarnings(self):
|
|
117
130
|
for warning in self.warnings:
|
|
118
131
|
print(warning)
|
|
119
132
|
|
|
133
|
+
# Get the symbol record for the current token (assumes it is a symbol name)
|
|
120
134
|
def getSymbolRecord(self):
|
|
121
135
|
token = self.getToken()
|
|
122
136
|
if not token in self.symbols:
|
|
@@ -128,18 +142,23 @@ class Compiler:
|
|
|
128
142
|
symbolRecord['used'] = True
|
|
129
143
|
return symbolRecord
|
|
130
144
|
|
|
145
|
+
# Add a value type
|
|
131
146
|
def addValueType(self):
|
|
132
147
|
self.valueTypes[self.getToken()] = True
|
|
133
148
|
|
|
149
|
+
# Test if a given value is in the value types list
|
|
134
150
|
def hasValue(self, type):
|
|
135
151
|
return type in self.valueTypes
|
|
136
152
|
|
|
153
|
+
# Compile a program label (a symbol ending with ':')
|
|
137
154
|
def compileLabel(self, command):
|
|
138
155
|
return self.compileSymbol(command, self.getToken())
|
|
139
156
|
|
|
157
|
+
# Compile a variable
|
|
140
158
|
def compileVariable(self, command, extra=None):
|
|
141
159
|
return self.compileSymbol(command, self.nextToken(), extra)
|
|
142
160
|
|
|
161
|
+
# Compile a symbol
|
|
143
162
|
def compileSymbol(self, command, name, extra=None):
|
|
144
163
|
try:
|
|
145
164
|
v = self.symbols[name]
|
|
@@ -148,7 +167,7 @@ class Compiler:
|
|
|
148
167
|
if v:
|
|
149
168
|
FatalError(self, f'Duplicate symbol name "{name}"')
|
|
150
169
|
return False
|
|
151
|
-
self.symbols[name] = self.
|
|
170
|
+
self.symbols[name] = self.getCodeSize()
|
|
152
171
|
command['program'] = self.program
|
|
153
172
|
command['type'] = 'symbol'
|
|
154
173
|
command['name'] = name
|
|
@@ -161,7 +180,7 @@ class Compiler:
|
|
|
161
180
|
command['locked'] = False
|
|
162
181
|
command['extra'] = extra
|
|
163
182
|
if 'keyword' in command: command['hasValue'] = self.hasValue(command['keyword'])
|
|
164
|
-
self.
|
|
183
|
+
self.addCommand(command)
|
|
165
184
|
return True
|
|
166
185
|
|
|
167
186
|
# Compile the current token
|
|
@@ -171,6 +190,10 @@ class Compiler:
|
|
|
171
190
|
# print(f'Compile {token}')
|
|
172
191
|
if not token:
|
|
173
192
|
return False
|
|
193
|
+
if len(self.code) == 0:
|
|
194
|
+
if self.program.parent == None and hasattr(self.program, 'usingGraphics'):
|
|
195
|
+
cmd = {'domain': 'graphics', 'keyword': 'init', 'debug': False}
|
|
196
|
+
self.code.append(cmd)
|
|
174
197
|
mark = self.getIndex()
|
|
175
198
|
for domain in self.program.getDomains():
|
|
176
199
|
handler = domain.keywordHandler(token)
|
|
@@ -195,7 +218,7 @@ class Compiler:
|
|
|
195
218
|
keyword = self.getToken()
|
|
196
219
|
if not keyword:
|
|
197
220
|
return False
|
|
198
|
-
|
|
221
|
+
# print(f'Compile keyword "{keyword}"')
|
|
199
222
|
if keyword.endswith(':'):
|
|
200
223
|
command = {}
|
|
201
224
|
command['domain'] = None
|
|
@@ -209,7 +232,7 @@ class Compiler:
|
|
|
209
232
|
self.index = index
|
|
210
233
|
while True:
|
|
211
234
|
token = self.tokens[self.index]
|
|
212
|
-
keyword = token.token
|
|
235
|
+
# keyword = token.token
|
|
213
236
|
if self.debugCompile: print(self.script.lines[token.lino])
|
|
214
237
|
# if keyword != 'else':
|
|
215
238
|
if self.compileOne() == True:
|
|
@@ -221,5 +244,10 @@ class Compiler:
|
|
|
221
244
|
else:
|
|
222
245
|
return False
|
|
223
246
|
|
|
247
|
+
# Compile fom the current location, stopping on any of a list of tokens
|
|
224
248
|
def compileFromHere(self, stopOn):
|
|
225
249
|
return self.compileFrom(self.getIndex(), stopOn)
|
|
250
|
+
|
|
251
|
+
# Compile from the start of the script
|
|
252
|
+
def compileFromStart(self):
|
|
253
|
+
return self.compileFrom(0, [])
|
easycoder/ec_condition.py
CHANGED
easycoder/ec_core.py
CHANGED
|
@@ -3,7 +3,7 @@ import numbers, base64, binascii, random, requests, paramiko
|
|
|
3
3
|
from copy import deepcopy
|
|
4
4
|
from psutil import Process
|
|
5
5
|
from datetime import datetime
|
|
6
|
-
from .ec_classes import FatalError, RuntimeWarning, RuntimeError, AssertionError, NoValueError, NoValueRuntimeError,
|
|
6
|
+
from .ec_classes import FatalError, RuntimeWarning, RuntimeError, AssertionError, NoValueError, NoValueRuntimeError, Object
|
|
7
7
|
from .ec_handler import Handler
|
|
8
8
|
from .ec_timestamp import getTimestamp
|
|
9
9
|
|
|
@@ -31,13 +31,13 @@ class Core(Handler):
|
|
|
31
31
|
cmd['keyword'] = 'gotoPC'
|
|
32
32
|
cmd['goto'] = 0
|
|
33
33
|
cmd['debug'] = False
|
|
34
|
-
skip = self.
|
|
34
|
+
skip = self.getCodeSize()
|
|
35
35
|
self.add(cmd)
|
|
36
36
|
# Process the 'or'
|
|
37
|
-
self.getCommandAt(orHere)['or'] = self.
|
|
37
|
+
self.getCommandAt(orHere)['or'] = self.getCodeSize()
|
|
38
38
|
self.compileOne()
|
|
39
39
|
# Fixup the skip
|
|
40
|
-
self.getCommandAt(skip)['goto'] = self.
|
|
40
|
+
self.getCommandAt(skip)['goto'] = self.getCodeSize()
|
|
41
41
|
|
|
42
42
|
#############################################################################
|
|
43
43
|
# Keyword handlers
|
|
@@ -323,7 +323,8 @@ class Core(Handler):
|
|
|
323
323
|
symbolRecord = self.getVariable(command['var'])
|
|
324
324
|
value = self.getSymbolValue(symbolRecord)
|
|
325
325
|
content = value['content']
|
|
326
|
-
content
|
|
326
|
+
if key >= 0 and key < len(content): del(content[key])
|
|
327
|
+
else: RuntimeError(self.program, f'Index {key} out of range')
|
|
327
328
|
value['content'] = content
|
|
328
329
|
self.putSymbolValue(symbolRecord, value)
|
|
329
330
|
return self.nextPC()
|
|
@@ -467,7 +468,7 @@ class Core(Handler):
|
|
|
467
468
|
if url != None:
|
|
468
469
|
command['url'] = url
|
|
469
470
|
command['or'] = None
|
|
470
|
-
get = self.
|
|
471
|
+
get = self.getCodeSize()
|
|
471
472
|
if self.peek() == 'timeout':
|
|
472
473
|
self.nextToken()
|
|
473
474
|
command['timeout'] = self.nextValue()
|
|
@@ -555,7 +556,7 @@ class Core(Handler):
|
|
|
555
556
|
command['condition'] = self.nextCondition()
|
|
556
557
|
self.add(command)
|
|
557
558
|
self.nextToken()
|
|
558
|
-
pcElse = self.
|
|
559
|
+
pcElse = self.getCodeSize()
|
|
559
560
|
cmd = {}
|
|
560
561
|
cmd['lino'] = command['lino']
|
|
561
562
|
cmd['domain'] = 'core'
|
|
@@ -568,7 +569,7 @@ class Core(Handler):
|
|
|
568
569
|
if self.peek() == 'else':
|
|
569
570
|
self.nextToken()
|
|
570
571
|
# Add a 'goto' to skip the 'else'
|
|
571
|
-
pcNext = self.
|
|
572
|
+
pcNext = self.getCodeSize()
|
|
572
573
|
cmd = {}
|
|
573
574
|
cmd['lino'] = command['lino']
|
|
574
575
|
cmd['domain'] = 'core'
|
|
@@ -577,15 +578,15 @@ class Core(Handler):
|
|
|
577
578
|
cmd['debug'] = False
|
|
578
579
|
self.add(cmd)
|
|
579
580
|
# Fixup the link to the 'else' branch
|
|
580
|
-
self.getCommandAt(pcElse)['goto'] = self.
|
|
581
|
+
self.getCommandAt(pcElse)['goto'] = self.getCodeSize()
|
|
581
582
|
# Process the 'else' branch
|
|
582
583
|
self.nextToken()
|
|
583
584
|
self.compileOne()
|
|
584
585
|
# Fixup the pcNext 'goto'
|
|
585
|
-
self.getCommandAt(pcNext)['goto'] = self.
|
|
586
|
+
self.getCommandAt(pcNext)['goto'] = self.getCodeSize()
|
|
586
587
|
else:
|
|
587
588
|
# We're already at the next command
|
|
588
|
-
self.getCommandAt(pcElse)['goto'] = self.
|
|
589
|
+
self.getCommandAt(pcElse)['goto'] = self.getCodeSize()
|
|
589
590
|
return True
|
|
590
591
|
|
|
591
592
|
def r_if(self, command):
|
|
@@ -604,7 +605,7 @@ class Core(Handler):
|
|
|
604
605
|
name = self.nextToken()
|
|
605
606
|
item = [keyword, name]
|
|
606
607
|
imports.append(item)
|
|
607
|
-
self.symbols[name] = self.
|
|
608
|
+
self.symbols[name] = self.getCodeSize()
|
|
608
609
|
variable = {}
|
|
609
610
|
variable['domain'] = None
|
|
610
611
|
variable['name'] = name
|
|
@@ -746,7 +747,7 @@ class Core(Handler):
|
|
|
746
747
|
else:
|
|
747
748
|
command['file'] = self.getValue()
|
|
748
749
|
command['or'] = None
|
|
749
|
-
load = self.
|
|
750
|
+
load = self.getCodeSize()
|
|
750
751
|
self.processOr(command, load)
|
|
751
752
|
return True
|
|
752
753
|
else:
|
|
@@ -915,7 +916,7 @@ class Core(Handler):
|
|
|
915
916
|
cmd['debug'] = False
|
|
916
917
|
self.add(cmd)
|
|
917
918
|
# Fixup the link
|
|
918
|
-
command['goto'] = self.
|
|
919
|
+
command['goto'] = self.getCodeSize()
|
|
919
920
|
return True
|
|
920
921
|
return False
|
|
921
922
|
|
|
@@ -1006,7 +1007,7 @@ class Core(Handler):
|
|
|
1006
1007
|
else:
|
|
1007
1008
|
command['result'] = None
|
|
1008
1009
|
command['or'] = None
|
|
1009
|
-
post = self.
|
|
1010
|
+
post = self.getCodeSize()
|
|
1010
1011
|
self.processOr(command, post)
|
|
1011
1012
|
return True
|
|
1012
1013
|
|
|
@@ -1105,7 +1106,7 @@ class Core(Handler):
|
|
|
1105
1106
|
FatalError(self.compiler, f'Symbol {symbolRecord["name"]} is not a value holder')
|
|
1106
1107
|
else:
|
|
1107
1108
|
command['or'] = None
|
|
1108
|
-
self.processOr(command, self.
|
|
1109
|
+
self.processOr(command, self.getCodeSize())
|
|
1109
1110
|
return True
|
|
1110
1111
|
else:
|
|
1111
1112
|
FatalError(self.compiler, f'Symbol {self.getToken()} is not a variable')
|
|
@@ -1273,7 +1274,7 @@ class Core(Handler):
|
|
|
1273
1274
|
else:
|
|
1274
1275
|
command['file'] = self.getValue()
|
|
1275
1276
|
command['or'] = None
|
|
1276
|
-
save = self.
|
|
1277
|
+
save = self.getCodeSize()
|
|
1277
1278
|
self.processOr(command, save)
|
|
1278
1279
|
return True
|
|
1279
1280
|
|
|
@@ -1768,12 +1769,17 @@ class Core(Handler):
|
|
|
1768
1769
|
self.program.importPlugin(f'{source}:{clazz}')
|
|
1769
1770
|
return True
|
|
1770
1771
|
return False
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1772
|
+
else:
|
|
1773
|
+
token = self.nextToken()
|
|
1774
|
+
if token in ['graphics', 'debugger']:
|
|
1775
|
+
if not hasattr(self.program, 'usingGraphics'):
|
|
1776
|
+
print('Loading graphics module')
|
|
1777
|
+
from .ec_pyside import Graphics
|
|
1778
|
+
self.program.graphics = Graphics
|
|
1779
|
+
self.program.useClass(Graphics)
|
|
1780
|
+
self.program.usingGraphics = True
|
|
1781
|
+
if token == 'debugger': self.program.debugging = True
|
|
1782
|
+
return True
|
|
1777
1783
|
return False
|
|
1778
1784
|
|
|
1779
1785
|
# Declare a general-purpose variable
|
|
@@ -1817,10 +1823,10 @@ class Core(Handler):
|
|
|
1817
1823
|
return None
|
|
1818
1824
|
# token = self.getToken()
|
|
1819
1825
|
command['condition'] = code
|
|
1820
|
-
test = self.
|
|
1826
|
+
test = self.getCodeSize()
|
|
1821
1827
|
self.add(command)
|
|
1822
1828
|
# Set up a goto for when the test fails
|
|
1823
|
-
fail = self.
|
|
1829
|
+
fail = self.getCodeSize()
|
|
1824
1830
|
cmd = {}
|
|
1825
1831
|
cmd['lino'] = command['lino']
|
|
1826
1832
|
cmd['domain'] = 'core'
|
|
@@ -1841,7 +1847,7 @@ class Core(Handler):
|
|
|
1841
1847
|
cmd['debug'] = False
|
|
1842
1848
|
self.add(cmd)
|
|
1843
1849
|
# Fixup the 'goto' on completion
|
|
1844
|
-
self.getCommandAt(fail)['goto'] = self.
|
|
1850
|
+
self.getCommandAt(fail)['goto'] = self.getCodeSize()
|
|
1845
1851
|
return True
|
|
1846
1852
|
|
|
1847
1853
|
def r_while(self, command):
|
|
@@ -2631,7 +2637,8 @@ class Core(Handler):
|
|
|
2631
2637
|
#############################################################################
|
|
2632
2638
|
# Compile a condition
|
|
2633
2639
|
def compileCondition(self):
|
|
2634
|
-
condition =
|
|
2640
|
+
condition = Object()
|
|
2641
|
+
condition.negate = False
|
|
2635
2642
|
|
|
2636
2643
|
token = self.getToken()
|
|
2637
2644
|
|
|
@@ -2655,7 +2662,14 @@ class Core(Handler):
|
|
|
2655
2662
|
path = self.nextValue()
|
|
2656
2663
|
condition.path = path
|
|
2657
2664
|
condition.type = 'exists'
|
|
2658
|
-
|
|
2665
|
+
self.skip('on')
|
|
2666
|
+
if self.nextIsSymbol():
|
|
2667
|
+
record = self.getSymbolRecord()
|
|
2668
|
+
if record['keyword'] == 'ssh':
|
|
2669
|
+
condition.type = 'sshExists'
|
|
2670
|
+
condition.target = record['name']
|
|
2671
|
+
token = self.nextToken()
|
|
2672
|
+
else: token = self.getToken()
|
|
2659
2673
|
if token == 'exists':
|
|
2660
2674
|
return condition
|
|
2661
2675
|
elif token == 'does':
|
|
@@ -2839,6 +2853,17 @@ class Core(Handler):
|
|
|
2839
2853
|
test = errormsg != None
|
|
2840
2854
|
return not test if condition.negate else test
|
|
2841
2855
|
|
|
2856
|
+
def c_sshExists(self, condition):
|
|
2857
|
+
path = self.getRuntimeValue(condition.path)
|
|
2858
|
+
ssh = self.getVariable(condition.target)
|
|
2859
|
+
sftp = ssh['sftp']
|
|
2860
|
+
try:
|
|
2861
|
+
with sftp.open(path, 'r') as remote_file: remote_file.read().decode()
|
|
2862
|
+
comparison = True
|
|
2863
|
+
except:
|
|
2864
|
+
comparison = False
|
|
2865
|
+
return not comparison if condition.negate else comparison
|
|
2866
|
+
|
|
2842
2867
|
def c_starts(self, condition):
|
|
2843
2868
|
value1 = self.getRuntimeValue(condition.value1)
|
|
2844
2869
|
value2 = self.getRuntimeValue(condition.value2)
|
easycoder/ec_handler.py
CHANGED
|
@@ -22,8 +22,8 @@ class Handler:
|
|
|
22
22
|
self.compileVariable = compiler.compileVariable
|
|
23
23
|
self.rewindTo = compiler.rewindTo
|
|
24
24
|
self.warning = compiler.warning
|
|
25
|
-
self.
|
|
26
|
-
self.add = compiler.
|
|
25
|
+
self.getCodeSize = compiler.getCodeSize
|
|
26
|
+
self.add = compiler.addCommand
|
|
27
27
|
self.getCommandAt = compiler.getCommandAt
|
|
28
28
|
self.compileOne = compiler.compileOne
|
|
29
29
|
self.compileFromHere = compiler.compileFromHere
|
easycoder/ec_keyboard.py
CHANGED
|
@@ -158,6 +158,8 @@ class KeyboardView(QVBoxLayout):
|
|
|
158
158
|
for row in rows:
|
|
159
159
|
self.addLayout(row)
|
|
160
160
|
|
|
161
|
+
###############################################################################
|
|
162
|
+
# VirtualKeyboard Class
|
|
161
163
|
class VirtualKeyboard(QStackedWidget):
|
|
162
164
|
def __init__(self, keyboardType, buttonHeight, receiver, onFinished):
|
|
163
165
|
super().__init__()
|
|
@@ -173,6 +175,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
173
175
|
self.addKeyboardLayout2()
|
|
174
176
|
self.addKeyboardLayout3()
|
|
175
177
|
|
|
178
|
+
###########################################################################
|
|
179
|
+
# Add the first keyboard layout (lowercase letters)
|
|
176
180
|
def addKeyboardLayout0(self):
|
|
177
181
|
rowList = []
|
|
178
182
|
|
|
@@ -214,7 +218,7 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
214
218
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickNumbers, None, 'img/numbers.png'),
|
|
215
219
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
216
220
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
|
|
217
|
-
KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, '
|
|
221
|
+
KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
|
|
218
222
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
|
|
219
223
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
220
224
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
|
|
@@ -228,6 +232,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
228
232
|
container.setLayout(keyboardView)
|
|
229
233
|
self.addWidget(container)
|
|
230
234
|
|
|
235
|
+
###########################################################################
|
|
236
|
+
# Add the second keyboard layout (uppercase letters)
|
|
231
237
|
def addKeyboardLayout1(self):
|
|
232
238
|
rowList = []
|
|
233
239
|
|
|
@@ -283,6 +289,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
283
289
|
container.setLayout(keyboardView)
|
|
284
290
|
self.addWidget(container)
|
|
285
291
|
|
|
292
|
+
###########################################################################
|
|
293
|
+
# Add the third keyboard layout (numbers and symbols)
|
|
286
294
|
def addKeyboardLayout2(self):
|
|
287
295
|
rowList = []
|
|
288
296
|
|
|
@@ -320,11 +328,11 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
320
328
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickLetters, None, 'img/letters.png'),
|
|
321
329
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
322
330
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
|
|
323
|
-
KeyboardButton(self.buttonHeight *
|
|
331
|
+
KeyboardButton(self.buttonHeight * 5.2, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
|
|
324
332
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
|
|
325
333
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
326
334
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
|
|
327
|
-
QSpacerItem(
|
|
335
|
+
QSpacerItem(10, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
328
336
|
])
|
|
329
337
|
rowList.append(row4)
|
|
330
338
|
|
|
@@ -334,6 +342,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
334
342
|
container.setLayout(keyboardView)
|
|
335
343
|
self.addWidget(container)
|
|
336
344
|
|
|
345
|
+
###########################################################################
|
|
346
|
+
# Add the fourth keyboard layout (additional symbols)
|
|
337
347
|
def addKeyboardLayout3(self):
|
|
338
348
|
rowList = []
|
|
339
349
|
|
easycoder/ec_program.py
CHANGED
|
@@ -34,9 +34,9 @@ class Program:
|
|
|
34
34
|
self.domainIndex = {}
|
|
35
35
|
self.name = '<anon>'
|
|
36
36
|
self.code = []
|
|
37
|
+
self.pc = 0
|
|
37
38
|
self.symbols = {}
|
|
38
39
|
self.onError = 0
|
|
39
|
-
self.pc = 0
|
|
40
40
|
self.debugStep = False
|
|
41
41
|
self.stack = []
|
|
42
42
|
self.script = Script(source)
|
|
@@ -48,7 +48,6 @@ class Program:
|
|
|
48
48
|
self.externalControl = False
|
|
49
49
|
self.ticker = 0
|
|
50
50
|
self.running = True
|
|
51
|
-
# self.start()
|
|
52
51
|
|
|
53
52
|
# This is called at 10msec intervals by the GUI code
|
|
54
53
|
def flushCB(self):
|
|
@@ -62,7 +61,7 @@ class Program:
|
|
|
62
61
|
module['child'] = self
|
|
63
62
|
startCompile = time.time()
|
|
64
63
|
self.tokenise(self.script)
|
|
65
|
-
if self.compiler.
|
|
64
|
+
if self.compiler.compileFromStart():
|
|
66
65
|
finishCompile = time.time()
|
|
67
66
|
s = len(self.script.lines)
|
|
68
67
|
t = len(self.script.tokens)
|
easycoder/ec_pyside.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import sys
|
|
2
2
|
from functools import partial
|
|
3
3
|
from .ec_handler import Handler
|
|
4
|
-
from .ec_classes import RuntimeError
|
|
4
|
+
from .ec_classes import RuntimeError, Object
|
|
5
5
|
from .ec_border import Border
|
|
6
6
|
from PySide6.QtCore import Qt, QTimer, Signal, QRect
|
|
7
7
|
from PySide6.QtGui import QPixmap, QPainter
|
|
@@ -26,6 +26,7 @@ from PySide6.QtWidgets import (
|
|
|
26
26
|
QSlider,
|
|
27
27
|
QSpinBox,
|
|
28
28
|
QTimeEdit,
|
|
29
|
+
QLayout,
|
|
29
30
|
QVBoxLayout,
|
|
30
31
|
QHBoxLayout,
|
|
31
32
|
QGridLayout,
|
|
@@ -67,13 +68,25 @@ class Graphics(Handler):
|
|
|
67
68
|
'combobox',
|
|
68
69
|
'widget'
|
|
69
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
|
|
70
87
|
|
|
71
88
|
def dialogTypes(self):
|
|
72
89
|
return ['confirm', 'lineedit', 'multiline', 'generic']
|
|
73
|
-
|
|
74
|
-
def getWidget(self, record):
|
|
75
|
-
if record['keyword'] in ['pushbutton']: return self.getSymbolContent(record)
|
|
76
|
-
else: return record['widget']
|
|
77
90
|
|
|
78
91
|
class ClickableLineEdit(QLineEdit):
|
|
79
92
|
clicked = Signal()
|
|
@@ -114,7 +127,7 @@ class Graphics(Handler):
|
|
|
114
127
|
# (2) add {widget} to {layout}
|
|
115
128
|
# (3) add stretch {widget} to {layout}
|
|
116
129
|
# (4) add stretch to {layout}
|
|
117
|
-
# (5) add spacer {size} to {layout}
|
|
130
|
+
# (5) add spacer [size] {size} to {layout}
|
|
118
131
|
# (6) add {widget} at {col} {row} in {grid layout}
|
|
119
132
|
def k_add(self, command):
|
|
120
133
|
def addToLayout():
|
|
@@ -146,6 +159,7 @@ class Graphics(Handler):
|
|
|
146
159
|
|
|
147
160
|
elif token == 'spacer':
|
|
148
161
|
self.nextToken()
|
|
162
|
+
self.skip('size')
|
|
149
163
|
command['widget'] = 'spacer'
|
|
150
164
|
command['size'] = self.nextValue()
|
|
151
165
|
self.skip('to')
|
|
@@ -186,19 +200,19 @@ class Graphics(Handler):
|
|
|
186
200
|
def r_add(self, command):
|
|
187
201
|
if 'value' in command:
|
|
188
202
|
value = self.getRuntimeValue(command['value'])
|
|
189
|
-
|
|
190
|
-
if
|
|
191
|
-
|
|
192
|
-
elif
|
|
193
|
-
if isinstance(value, list):
|
|
194
|
-
else:
|
|
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)
|
|
195
209
|
elif 'row' in command and 'col' in command:
|
|
196
210
|
layout = self.getVariable(command['layout'])['widget']
|
|
197
|
-
|
|
198
|
-
widget =
|
|
211
|
+
record = self.getVariable(command['widget'])
|
|
212
|
+
widget = self.getWidget(record)
|
|
199
213
|
row = self.getRuntimeValue(command['row'])
|
|
200
214
|
col = self.getRuntimeValue(command['col'])
|
|
201
|
-
if
|
|
215
|
+
if record['keyword'] == 'layout':
|
|
202
216
|
layout.addLayout(widget, row, col)
|
|
203
217
|
else:
|
|
204
218
|
layout.addWidget(widget, row, col)
|
|
@@ -272,8 +286,41 @@ class Graphics(Handler):
|
|
|
272
286
|
return False
|
|
273
287
|
|
|
274
288
|
def r_clear(self, command):
|
|
275
|
-
|
|
276
|
-
|
|
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
|
+
|
|
277
324
|
return self.nextPC()
|
|
278
325
|
|
|
279
326
|
# close {window}
|
|
@@ -370,17 +417,18 @@ class Graphics(Handler):
|
|
|
370
417
|
return True
|
|
371
418
|
|
|
372
419
|
def k_createPushbutton(self, command):
|
|
373
|
-
text = ''
|
|
374
420
|
while True:
|
|
375
421
|
token = self.peek()
|
|
376
422
|
if token == 'text':
|
|
377
423
|
self.nextToken()
|
|
378
|
-
text = self.nextValue()
|
|
424
|
+
command['text'] = self.nextValue()
|
|
425
|
+
elif token == 'icon':
|
|
426
|
+
self.nextToken()
|
|
427
|
+
command['icon'] = self.nextValue()
|
|
379
428
|
elif token == 'size':
|
|
380
429
|
self.nextToken()
|
|
381
430
|
command['size'] = self.nextValue()
|
|
382
431
|
else: break
|
|
383
|
-
command['text'] = text
|
|
384
432
|
self.add(command)
|
|
385
433
|
return True
|
|
386
434
|
|
|
@@ -562,19 +610,33 @@ class Graphics(Handler):
|
|
|
562
610
|
elif alignment == 'justify': label.setAlignment(Qt.AlignJustify)
|
|
563
611
|
if 'expand' in command:
|
|
564
612
|
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
|
565
|
-
record
|
|
613
|
+
self.setWidget(record, label)
|
|
566
614
|
return self.nextPC()
|
|
567
615
|
|
|
568
616
|
def r_createPushbutton(self, command, record):
|
|
569
|
-
text = self.getRuntimeValue(command['text'])
|
|
570
|
-
pushbutton = QPushButton(text)
|
|
571
|
-
pushbutton.setAccessibleName(text)
|
|
572
617
|
if 'size' in command:
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
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)
|
|
577
638
|
self.putSymbolValue(record, pushbutton)
|
|
639
|
+
self.setWidget(record, pushbutton)
|
|
578
640
|
return self.nextPC()
|
|
579
641
|
|
|
580
642
|
def r_createCheckBox(self, command, record):
|
|
@@ -596,7 +658,7 @@ class Graphics(Handler):
|
|
|
596
658
|
}
|
|
597
659
|
""")
|
|
598
660
|
checkbox.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
|
599
|
-
record
|
|
661
|
+
self.setWidget(record, checkbox)
|
|
600
662
|
return self.nextPC()
|
|
601
663
|
|
|
602
664
|
def r_createLineEdit(self, command, record):
|
|
@@ -607,7 +669,7 @@ class Graphics(Handler):
|
|
|
607
669
|
c = lineinput.contentsMargins()
|
|
608
670
|
w = fm.horizontalAdvance('x') * self.getRuntimeValue(command['size']) +m.left()+m.right()+c.left()+c.right()
|
|
609
671
|
lineinput.setMaximumWidth(w)
|
|
610
|
-
record
|
|
672
|
+
self.setWidget(record, lineinput)
|
|
611
673
|
return self.nextPC()
|
|
612
674
|
|
|
613
675
|
def r_createMultiLineEdit(self, command, record):
|
|
@@ -617,19 +679,19 @@ class Graphics(Handler):
|
|
|
617
679
|
charHeight = fontMetrics.height()
|
|
618
680
|
textinput.setFixedWidth(charWidth * self.getRuntimeValue(command['cols']))
|
|
619
681
|
textinput.setFixedHeight(charHeight * self.getRuntimeValue(command['rows']))
|
|
620
|
-
record
|
|
682
|
+
self.setWidget(record, textinput)
|
|
621
683
|
return self.nextPC()
|
|
622
684
|
|
|
623
685
|
def r_createListWidget(self, command, record):
|
|
624
|
-
record
|
|
686
|
+
self.setWidget(record, QListWidget())
|
|
625
687
|
return self.nextPC()
|
|
626
688
|
|
|
627
689
|
def r_createComboBox(self, command, record):
|
|
628
|
-
record
|
|
690
|
+
self.setWidget(record, QComboBox())
|
|
629
691
|
return self.nextPC()
|
|
630
692
|
|
|
631
693
|
def r_createWidget(self, command, record):
|
|
632
|
-
record
|
|
694
|
+
self.setWidget(record, QWidget())
|
|
633
695
|
return self.nextPC()
|
|
634
696
|
|
|
635
697
|
def r_createDialog(self, command, record):
|
|
@@ -757,12 +819,23 @@ class Graphics(Handler):
|
|
|
757
819
|
def r_group(self, command):
|
|
758
820
|
return self.nextPC()
|
|
759
821
|
|
|
760
|
-
#
|
|
761
|
-
def
|
|
762
|
-
if self.
|
|
763
|
-
self.
|
|
764
|
-
|
|
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
|
|
765
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):
|
|
766
839
|
|
|
767
840
|
def r_init(self, command):
|
|
768
841
|
self.app = QApplication(sys.argv)
|
|
@@ -770,7 +843,22 @@ class Graphics(Handler):
|
|
|
770
843
|
self.program.screenWidth = screen[0]
|
|
771
844
|
self.program.screenHeight = screen[1]
|
|
772
845
|
print(f'Screen: {self.program.screenWidth}x{self.program.screenHeight}')
|
|
773
|
-
return self.nextPC()
|
|
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()
|
|
774
862
|
|
|
775
863
|
# Declare a label variable
|
|
776
864
|
def k_label(self, command):
|
|
@@ -819,11 +907,11 @@ class Graphics(Handler):
|
|
|
819
907
|
# on tick
|
|
820
908
|
def k_on(self, command):
|
|
821
909
|
def setupOn():
|
|
822
|
-
command['goto'] = self.
|
|
910
|
+
command['goto'] = self.getCodeSize() + 2
|
|
823
911
|
self.add(command)
|
|
824
912
|
self.nextToken()
|
|
825
913
|
# Step over the click handler
|
|
826
|
-
pcNext = self.
|
|
914
|
+
pcNext = self.getCodeSize()
|
|
827
915
|
cmd = {}
|
|
828
916
|
cmd['domain'] = 'core'
|
|
829
917
|
cmd['lino'] = command['lino']
|
|
@@ -840,7 +928,7 @@ class Graphics(Handler):
|
|
|
840
928
|
cmd['debug'] = False
|
|
841
929
|
self.add(cmd)
|
|
842
930
|
# Fixup the goto
|
|
843
|
-
self.getCommandAt(pcNext)['goto'] = self.
|
|
931
|
+
self.getCommandAt(pcNext)['goto'] = self.getCodeSize()
|
|
844
932
|
|
|
845
933
|
token = self.nextToken()
|
|
846
934
|
command['type'] = token
|
|
@@ -860,11 +948,11 @@ class Graphics(Handler):
|
|
|
860
948
|
return True
|
|
861
949
|
elif token == 'tick':
|
|
862
950
|
command['tick'] = True
|
|
863
|
-
command['runOnTick'] = self.
|
|
951
|
+
command['runOnTick'] = self.getCodeSize() + 2
|
|
864
952
|
self.add(command)
|
|
865
953
|
self.nextToken()
|
|
866
954
|
# Step over the on tick action
|
|
867
|
-
pcNext = self.
|
|
955
|
+
pcNext = self.getCodeSize()
|
|
868
956
|
cmd = {}
|
|
869
957
|
cmd['domain'] = 'core'
|
|
870
958
|
cmd['lino'] = command['lino']
|
|
@@ -881,13 +969,13 @@ class Graphics(Handler):
|
|
|
881
969
|
cmd['debug'] = False
|
|
882
970
|
self.add(cmd)
|
|
883
971
|
# Fixup the goto
|
|
884
|
-
self.getCommandAt(pcNext)['goto'] = self.
|
|
972
|
+
self.getCommandAt(pcNext)['goto'] = self.getCodeSize()
|
|
885
973
|
return True
|
|
886
974
|
return False
|
|
887
975
|
|
|
888
976
|
def r_on(self, command):
|
|
889
977
|
def run(widget, record):
|
|
890
|
-
for i, w in enumerate(record['
|
|
978
|
+
for i, w in enumerate(record['widget']):
|
|
891
979
|
if w == widget:
|
|
892
980
|
record['index'] = i
|
|
893
981
|
self.run(command['goto'])
|
|
@@ -941,10 +1029,10 @@ class Graphics(Handler):
|
|
|
941
1029
|
record = self.getVariable(command['name'])
|
|
942
1030
|
if variant == 'current':
|
|
943
1031
|
if record['keyword'] == 'combobox':
|
|
944
|
-
widget = record
|
|
1032
|
+
widget = self.getWidget(record)
|
|
945
1033
|
widget.removeItem(widget.currentIndex())
|
|
946
1034
|
if record['keyword'] == 'listbox':
|
|
947
|
-
widget = record
|
|
1035
|
+
widget = self.getWidget(record)
|
|
948
1036
|
selectedItem = widget.currentItem()
|
|
949
1037
|
if selectedItem:
|
|
950
1038
|
row = widget.row(selectedItem)
|
|
@@ -969,7 +1057,7 @@ class Graphics(Handler):
|
|
|
969
1057
|
return False
|
|
970
1058
|
|
|
971
1059
|
def r_select(self, command):
|
|
972
|
-
widget = self.getVariable(command['widget'])
|
|
1060
|
+
widget = self.getWidget(self.getVariable(command['widget']))
|
|
973
1061
|
if 'index' in command:
|
|
974
1062
|
index = self.getRuntimeValue(command['index'])
|
|
975
1063
|
else:
|
|
@@ -1012,9 +1100,10 @@ class Graphics(Handler):
|
|
|
1012
1100
|
self.skip('to')
|
|
1013
1101
|
if self.nextIsSymbol():
|
|
1014
1102
|
record = self.getSymbolRecord()
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1103
|
+
if record['keyword'] == 'layout':
|
|
1104
|
+
command['layout'] = record['name']
|
|
1105
|
+
self.add(command)
|
|
1106
|
+
return True
|
|
1018
1107
|
elif token == 'spacing':
|
|
1019
1108
|
self.skip('of')
|
|
1020
1109
|
if self.nextIsSymbol():
|
|
@@ -1122,25 +1211,26 @@ class Graphics(Handler):
|
|
|
1122
1211
|
def r_set(self, command):
|
|
1123
1212
|
what = command['what']
|
|
1124
1213
|
if what == 'height':
|
|
1125
|
-
widget = self.getVariable(command['name'])
|
|
1214
|
+
widget = self.getWidget(self.getVariable(command['name']))
|
|
1126
1215
|
widget.setFixedHeight(self.getRuntimeValue(command['value']))
|
|
1127
1216
|
elif what == 'width':
|
|
1128
|
-
widget = self.getVariable(command['name'])
|
|
1217
|
+
widget = self.getWidget(self.getVariable(command['name']))
|
|
1129
1218
|
widget.setFixedWidth(self.getRuntimeValue(command['value']))
|
|
1130
1219
|
elif what == 'layout':
|
|
1131
|
-
|
|
1220
|
+
record = self.getVariable(command['layout'])
|
|
1221
|
+
layout = record['widget']
|
|
1132
1222
|
record = self.getVariable(command['name'])
|
|
1133
1223
|
keyword = record['keyword']
|
|
1134
1224
|
if keyword == 'window':
|
|
1135
1225
|
window = record['window']
|
|
1136
1226
|
container = QWidget()
|
|
1137
|
-
container.setLayout(
|
|
1227
|
+
container.setLayout(layout)
|
|
1138
1228
|
window.setCentralWidget(container)
|
|
1139
1229
|
elif keyword == 'widget':
|
|
1140
|
-
widget = record
|
|
1141
|
-
widget.setLayout(
|
|
1230
|
+
widget = self.getWidget(record)
|
|
1231
|
+
widget.setLayout(layout)
|
|
1142
1232
|
elif what == 'spacing':
|
|
1143
|
-
layout = self.getVariable(command['name'])
|
|
1233
|
+
layout = self.getWidget(self.getVariable(command['name']))
|
|
1144
1234
|
layout.setSpacing(self.getRuntimeValue(command['value']))
|
|
1145
1235
|
elif what == 'text':
|
|
1146
1236
|
record = self.getVariable(command['name'])
|
|
@@ -1158,7 +1248,7 @@ class Graphics(Handler):
|
|
|
1158
1248
|
record = self.getVariable(command['name'])
|
|
1159
1249
|
if record['keyword'] == 'checkbox':
|
|
1160
1250
|
state = self.getRuntimeValue(command['value'])
|
|
1161
|
-
record
|
|
1251
|
+
self.getWidget(record).setChecked(state)
|
|
1162
1252
|
elif what == 'alignment':
|
|
1163
1253
|
widget = self.getVariable(command['name'])['widget']
|
|
1164
1254
|
flags = command['value']
|
|
@@ -1197,6 +1287,7 @@ class Graphics(Handler):
|
|
|
1197
1287
|
|
|
1198
1288
|
# show {window}
|
|
1199
1289
|
# show {dialog}
|
|
1290
|
+
# show {widget}
|
|
1200
1291
|
# show {messagebox} giving {result}}
|
|
1201
1292
|
def k_show(self, command):
|
|
1202
1293
|
if self.nextIsSymbol():
|
|
@@ -1210,6 +1301,10 @@ class Graphics(Handler):
|
|
|
1210
1301
|
command['dialog'] = record['name']
|
|
1211
1302
|
self.add(command)
|
|
1212
1303
|
return True
|
|
1304
|
+
elif self.isWidget(keyword):
|
|
1305
|
+
command['name'] = record['name']
|
|
1306
|
+
self.add(command)
|
|
1307
|
+
return True
|
|
1213
1308
|
elif keyword == 'messagebox':
|
|
1214
1309
|
command['messagebox'] = record['name']
|
|
1215
1310
|
self.skip('giving')
|
|
@@ -1270,6 +1365,9 @@ class Graphics(Handler):
|
|
|
1270
1365
|
if dialog.exec() == QDialog.Accepted:
|
|
1271
1366
|
record['result'] = dialog.textEdit.toPlainText()
|
|
1272
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()
|
|
1273
1371
|
return self.nextPC()
|
|
1274
1372
|
|
|
1275
1373
|
# Start the graphics
|
|
@@ -1280,21 +1378,22 @@ class Graphics(Handler):
|
|
|
1280
1378
|
return False
|
|
1281
1379
|
|
|
1282
1380
|
def r_start(self, command):
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
timer
|
|
1294
|
-
timer.
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
self.app.
|
|
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()
|
|
1298
1397
|
|
|
1299
1398
|
# Declare a widget variable
|
|
1300
1399
|
def k_widget(self, command):
|
|
@@ -1364,38 +1463,38 @@ class Graphics(Handler):
|
|
|
1364
1463
|
symbolRecord = self.getVariable(symbolRecord['name'])
|
|
1365
1464
|
keyword = symbolRecord['keyword']
|
|
1366
1465
|
if keyword == 'pushbutton':
|
|
1367
|
-
pushbutton = self.
|
|
1466
|
+
pushbutton = self.getWidget(symbolRecord)
|
|
1368
1467
|
v = {}
|
|
1369
1468
|
v['type'] = 'text'
|
|
1370
1469
|
v['content'] = pushbutton.accessibleName()
|
|
1371
1470
|
return v
|
|
1372
1471
|
elif keyword == 'lineinput':
|
|
1373
|
-
lineinput = symbolRecord
|
|
1472
|
+
lineinput = self.getWidget(symbolRecord)
|
|
1374
1473
|
v = {}
|
|
1375
1474
|
v['type'] = 'text'
|
|
1376
1475
|
v['content'] = lineinput.displayText()
|
|
1377
1476
|
return v
|
|
1378
1477
|
elif keyword == 'multiline':
|
|
1379
|
-
multiline = symbolRecord
|
|
1478
|
+
multiline = self.getWidget(symbolRecord)
|
|
1380
1479
|
v = {}
|
|
1381
1480
|
v['type'] = 'text'
|
|
1382
1481
|
v['content'] = multiline.toPlainText()
|
|
1383
1482
|
return v
|
|
1384
1483
|
elif keyword == 'combobox':
|
|
1385
|
-
combobox = symbolRecord
|
|
1484
|
+
combobox = self.getWidget(symbolRecord)
|
|
1386
1485
|
v = {}
|
|
1387
1486
|
v['type'] = 'text'
|
|
1388
1487
|
v['content'] = combobox.currentText()
|
|
1389
1488
|
return v
|
|
1390
1489
|
elif keyword == 'listbox':
|
|
1391
|
-
listbox = symbolRecord
|
|
1490
|
+
listbox = self.getWidget(symbolRecord)
|
|
1392
1491
|
content = listbox.currentItem().text()
|
|
1393
1492
|
v = {}
|
|
1394
1493
|
v['type'] = 'text'
|
|
1395
1494
|
v['content'] = content
|
|
1396
1495
|
return v
|
|
1397
1496
|
elif keyword == 'checkbox':
|
|
1398
|
-
checkbox =
|
|
1497
|
+
checkbox =self.getWidget(symbolRecord)
|
|
1399
1498
|
content = checkbox.isChecked()
|
|
1400
1499
|
v = {}
|
|
1401
1500
|
v['type'] = 'boolean'
|
|
@@ -1412,7 +1511,7 @@ class Graphics(Handler):
|
|
|
1412
1511
|
def v_count(self, v):
|
|
1413
1512
|
record = self.getVariable(v['name'])
|
|
1414
1513
|
keyword = record['keyword']
|
|
1415
|
-
widget = record
|
|
1514
|
+
widget = self.getWidget(record)
|
|
1416
1515
|
if keyword in ['combobox', 'listbox']: content = widget.count()
|
|
1417
1516
|
value = {}
|
|
1418
1517
|
value['type'] = 'int'
|
|
@@ -1422,7 +1521,7 @@ class Graphics(Handler):
|
|
|
1422
1521
|
def v_current(self, v):
|
|
1423
1522
|
record = self.getVariable(v['name'])
|
|
1424
1523
|
keyword = record['keyword']
|
|
1425
|
-
widget = record
|
|
1524
|
+
widget = self.getWidget(record)
|
|
1426
1525
|
if keyword == 'listbox': content = widget.currentItem().text()
|
|
1427
1526
|
value = {}
|
|
1428
1527
|
value['type'] = 'text'
|
|
@@ -1432,8 +1531,9 @@ class Graphics(Handler):
|
|
|
1432
1531
|
#############################################################################
|
|
1433
1532
|
# Compile a condition
|
|
1434
1533
|
def compileCondition(self):
|
|
1435
|
-
condition =
|
|
1436
|
-
|
|
1534
|
+
condition = Object()
|
|
1535
|
+
condition.negate = False
|
|
1536
|
+
return None
|
|
1437
1537
|
|
|
1438
1538
|
#############################################################################
|
|
1439
1539
|
# Condition handlers
|
|
@@ -1442,4 +1542,4 @@ class Graphics(Handler):
|
|
|
1442
1542
|
# Force the application to exit
|
|
1443
1543
|
def force_exit(self):
|
|
1444
1544
|
QApplication.quit() # Gracefully close the application
|
|
1445
|
-
sys.exit(0) # Force a complete system exit
|
|
1545
|
+
sys.exit(0) # Force a complete system exit
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: easycoder
|
|
3
|
-
Version:
|
|
3
|
+
Version: 251104.1
|
|
4
4
|
Summary: Rapid scripting in English
|
|
5
5
|
Keywords: compiler,scripting,prototyping,programming,coding,python,low code,hypertalk,computer language,learn to code
|
|
6
6
|
Author-email: Graham Trott <gtanyware@gmail.com>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
easycoder/__init__.py,sha256=7ZoWrgGr2R_dOw69Yis1-y0u8zR8AAQ24gN0GpfM5rc,339
|
|
2
|
+
easycoder/close.png,sha256=3B9ueRNtEu9E4QNmZhdyC4VL6uqKvGmdfeFxIV9aO_Y,9847
|
|
3
|
+
easycoder/ec_border.py,sha256=KpOy0Jq8jI_6DYGo4jaFvoBP_jTIoAYWrmuHhl-FXA4,2355
|
|
4
|
+
easycoder/ec_classes.py,sha256=YGUiKnVN6T5scoeBmmGDQAtE8xJgaTHi0Exh9A7H2Y4,1750
|
|
5
|
+
easycoder/ec_compiler.py,sha256=2bdB7Bb4Cn_Uj7g0wjDn_gO0gQivqeaFellbgbAT2Hg,6587
|
|
6
|
+
easycoder/ec_condition.py,sha256=uamZrlW3Ej3R4bPDuduGB2f00M80Z1D0qV8muDx4Qfw,784
|
|
7
|
+
easycoder/ec_core.py,sha256=K89KR1z_clnubQgq_-L3SiTTRI4qs2ue1MhuUkB9xoU,100888
|
|
8
|
+
easycoder/ec_handler.py,sha256=doGCMXBCQxvSaD3omKMlXoR_LvQODxV7dZyoWafecyg,2336
|
|
9
|
+
easycoder/ec_keyboard.py,sha256=H8DhPT8-IvAIGgRxCs4qSaF_AQLaS6lxxtDteejbktM,19010
|
|
10
|
+
easycoder/ec_program.py,sha256=aPuZOYWFqGd1jsLDl5M5YmLu5LfFAewF9EZh6zHIbyM,10308
|
|
11
|
+
easycoder/ec_pyside.py,sha256=DwHMsk5kDBXg8feSbkyUinGWPO1a4uH-rcT3F9J4Aiw,58287
|
|
12
|
+
easycoder/ec_timestamp.py,sha256=myQnnF-mT31_1dpQKv2VEAu4BCcbypvMdzq7_DUi1xc,277
|
|
13
|
+
easycoder/ec_value.py,sha256=zgDJTJhIg3yOvmnnKIfccIizmIhGbtvL_ghLTL1T5fg,2516
|
|
14
|
+
easycoder/tick.png,sha256=OedASXJJTYvnza4J6Kv5m5lz6DrBfy667zX_WGgtbmM,9127
|
|
15
|
+
easycoder-251104.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
16
|
+
easycoder-251104.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
17
|
+
easycoder-251104.1.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
|
|
18
|
+
easycoder-251104.1.dist-info/METADATA,sha256=jWlzWZY1kVcRNkxMiIn6SGBsgK3UESTSnMhp8KlG064,6897
|
|
19
|
+
easycoder-251104.1.dist-info/RECORD,,
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
easycoder/__init__.py,sha256=q9lIBFHBsL7m8IFo13YFUlg_4clZurFfRFYX7kZnBCo,339
|
|
2
|
-
easycoder/close.png,sha256=3B9ueRNtEu9E4QNmZhdyC4VL6uqKvGmdfeFxIV9aO_Y,9847
|
|
3
|
-
easycoder/ec_border.py,sha256=KpOy0Jq8jI_6DYGo4jaFvoBP_jTIoAYWrmuHhl-FXA4,2355
|
|
4
|
-
easycoder/ec_classes.py,sha256=bejrby7mLHTeAQXhhz-1l8iv6LSbNSy30lW21KJKjXE,1832
|
|
5
|
-
easycoder/ec_compiler.py,sha256=LYwGNs8dcHKXI_nnu1sVFe1N36vjvylcUO_tX_bLjrk,5359
|
|
6
|
-
easycoder/ec_condition.py,sha256=YXvSBQKEzKGCcgUGo3Qp8iHolXmm2BpEm0NimSDszIM,785
|
|
7
|
-
easycoder/ec_core.py,sha256=VTAnhdLp3ftZ1tLPhovKX0PQ1CplmC9x17jH_DfrJsQ,99650
|
|
8
|
-
easycoder/ec_handler.py,sha256=ED08ULiOlZkcs4XHxAguvdPZw_dFXuwGDFLbFuo0kLs,2317
|
|
9
|
-
easycoder/ec_keyboard.py,sha256=ru-HdWolBMZJPyck2s72In9tXFeLJQSPtR1TpjmIo90,18350
|
|
10
|
-
easycoder/ec_program.py,sha256=srVDRlELMElvnkjxmREczUVPkvPXPvanZglN4hKreLI,10324
|
|
11
|
-
easycoder/ec_pyside.py,sha256=bnGwnlYyN-4KI4ECpocrgVx2uGO_9aDrDZNjT4AK7ak,54148
|
|
12
|
-
easycoder/ec_timestamp.py,sha256=myQnnF-mT31_1dpQKv2VEAu4BCcbypvMdzq7_DUi1xc,277
|
|
13
|
-
easycoder/ec_value.py,sha256=zgDJTJhIg3yOvmnnKIfccIizmIhGbtvL_ghLTL1T5fg,2516
|
|
14
|
-
easycoder/tick.png,sha256=OedASXJJTYvnza4J6Kv5m5lz6DrBfy667zX_WGgtbmM,9127
|
|
15
|
-
easycoder-251004.1.dist-info/entry_points.txt,sha256=JXAZbenl0TnsIft2FcGJbJ-4qoztVu2FuT8PFmWFexM,44
|
|
16
|
-
easycoder-251004.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
17
|
-
easycoder-251004.1.dist-info/WHEEL,sha256=Dyt6SBfaasWElUrURkknVFAZDHSTwxg3PaTza7RSbkY,100
|
|
18
|
-
easycoder-251004.1.dist-info/METADATA,sha256=O3CZb_23D8wHS9r_IMN0TLjZVRg1JMgq_SgOuxU6nb8,6897
|
|
19
|
-
easycoder-251004.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|